Puzzling problem in tdi-filter, TDI_SEND and TDI_EVENT_RECEIVE

Hi,
i’ve the following weird problem : in my tdi filter i handle client
event TDI_EVENT_RECEIVE (among the others) to capture network data.
Also, i need to parse data in TDI_SEND handler to do some matching (ie:
for http connection, i log the connection only if the http GET request
matches my url-list). So i send down every TDI_SEND request and do the
compare stuff in the completion routine for the TDI_SEND ioctl, deciding
there if the connection must be logged or not (i mantain a flag for that
in a structure which is unique for every connection).

What happens is that, after decided in the TDI_SEND completion to not
log a connection, i noticed some connections which should not be logged
by my filter still had that “log this” flag enabled when they reached
the TDI_EVENT_RECEIVE client handler.

I investigated a bit, and i noticed that sometimes the TDI_EVENT_RECEIVE
handler is called after the TDI_SEND is passed down to the lower driver
but *before* the TDI_SEND completion routine (so my “do not log” flag is
not set yet). I noticed this behaviour on w2k(sp4), on xp it works fine.

Isn’t that puzzling ? Shouldn’t a “receive” be called after a “send”
(after its completion,specifically) for the same connection ?

Regards,
Valerio

> Isn’t that puzzling ? Shouldn’t a “receive” be called after a “send”

(after its completion,specifically) for the same connection ?

Not so.

TCP completes TDI_SEND at the moment when all ACKs arrived for a data portion.
The ACK is usually carried in the header of the same packet which carries the
response data. More so. If the incoming packet should trigger both receive and
send completion, then receive is called first.

So, in a “request-response” pattern like HTTP you will have:

TDI_SEND request
(processing inside the webserver)
(webserver prints the response header, webserver’s TCP uses this packet to
carry the ACK for the request)
(the packet arrives to a client)
ClientEventReceive for response header
TDI_SEND completion.

This is normal. First, you will get the response, and only then the send
completion for a request. I observed the same pattern in some iSCSI-like code
of mine.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

Maxim S. Shatskih wrote:

>Isn’t that puzzling ? Shouldn’t a “receive” be called after a “send”
>(after its completion,specifically) for the same connection ?

Not so.

TCP completes TDI_SEND at the moment when all ACKs arrived for a data portion.
The ACK is usually carried in the header of the same packet which carries the
response data. More so. If the incoming packet should trigger both receive and
send completion, then receive is called first.

So, in a “request-response” pattern like HTTP you will have:

TDI_SEND request
(processing inside the webserver)
(webserver prints the response header, webserver’s TCP uses this packet to
carry the ACK for the request)
(the packet arrives to a client)
ClientEventReceive for response header
TDI_SEND completion.

This is normal. First, you will get the response, and only then the send
completion for a request. I observed the same pattern in some iSCSI-like code
of mine.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

Hi Max, thanx for the reply.

Uhm … it sounds really weird to me. Why so in windows xp it works as
i’d logically expect ?

Like, i request pippo.html from my browser. So logically it should be :
TDI_SEND -> in TDI_SEND Completion i can parse the request buffer “GET
/pippo.html HTTP/1.1 bla bla bla” -> ClientEventReceive and the rest.

Anyway, surely you know what you’re saying better than me ehhehe… So i
'd need some tips on how can i actually implement what i need (parse the
TDI_SEND buffer and make some decision,stopping receives on the
connections not matching my filter).

Any idea ?

Valerio

>Uhm … it sounds really weird to me. Why so in windows xp it works as

i’d logically expect ?

All Windows I know behave this way.

Like, i request pippo.html from my browser. So logically it should be :
TDI_SEND -> in TDI_SEND Completion i can parse the request buffer “GET
/pippo.html HTTP/1.1 bla bla bla” -> ClientEventReceive and the rest.

You can. But the response data from the webserver will arrive earlier then send
completion.

Your code must not depend on send completions. The only thing you can do in
send completion is to clean up the resources occupied for send. You must not
treat it as an event which says something.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com