ClientEventReceive and BytesAvailable

I’m updating the TDI interface in our FSD to use ClientEventReceive()
for our TCP receive interface instead of just always posting
a TDI_RECEIVE, and am having problems on XP SP1.

I know this issues has been dealt with in the past and I
looked through the archives multiple times, and have
read through Maxim Shatskih’s replies on the subject – they
have been helpful, but I’m still running into a problem
and need help from those who have more patience with the
TDI than I do.

I have both a ClientEventReceive and it’s chained counterpart.
As long as BytesAvailable == BytesIndicated in ClientEventReceive
everything seems to work fine.

First off, what (or why?) causes BytesAvailable > BytesIndicated?
Isn’t this a tease? It seems that regardless of what I return
to the TDI (tcp), I end up in a situation where I get no
more data after returning STATUS_MORE_PROCESSING_REQUIRED.

I’ve tried setting *BytesTaken to both BytesAvailable and BytesIndicated
in this case – which should it be?

I’ve tried sending back an IRP/MDL built with TdiBuildReceive()
directly via IoCallDriver from the event handler with no luck.

I’ve tried to send back an IRP/MDL via *IoRequestPacket,
where after setting my completion routine in the current stack
location, I set the params like TdiBuildReceive() in the next
stack location. The buffer length in the MDL is set to the remaining
(ie, BytesAvailable - BytesIndicated). Is this correct?

It also seems like whatever buffer I hand back to the TDI has
to be pinned/locked, as if I don’t ProbeAndLockPages on it,
TCP barfs as it tries to unlock some pages. I wouldn’t have
thought I needed to ProbeAndLock a nonpaged pool buffer – is
it that the TDI is confused by what I sent back?

Any hints on how to correctly respond when BytesAvailable !=
BytesIndicated would be sincerely appreciated!

Thanks.

The *BytesTaken should set to BytesIndicated. I have done this for udp. I
thnik it is about the same for tcp.

You also need to advance the irp’s stack before return
STATUS_MORE_PROCESSING_REQUIRED since you are not calling IoCallDriver
directly here.

Hope this will help.

Lin

“Peter Lawthers” wrote in message news:xxxxx@ntfsd…
> I’m updating the TDI interface in our FSD to use ClientEventReceive()
> for our TCP receive interface instead of just always posting
> a TDI_RECEIVE, and am having problems on XP SP1.
>
> I know this issues has been dealt with in the past and I
> looked through the archives multiple times, and have
> read through Maxim Shatskih’s replies on the subject – they
> have been helpful, but I’m still running into a problem
> and need help from those who have more patience with the
> TDI than I do.
>
> I have both a ClientEventReceive and it’s chained counterpart.
> As long as BytesAvailable == BytesIndicated in ClientEventReceive
> everything seems to work fine.
>
> First off, what (or why?) causes BytesAvailable > BytesIndicated?
> Isn’t this a tease? It seems that regardless of what I return
> to the TDI (tcp), I end up in a situation where I get no
> more data after returning STATUS_MORE_PROCESSING_REQUIRED.
>
> I’ve tried setting *BytesTaken to both BytesAvailable and BytesIndicated
> in this case – which should it be?
>
> I’ve tried sending back an IRP/MDL built with TdiBuildReceive()
> directly via IoCallDriver from the event handler with no luck.
>
> I’ve tried to send back an IRP/MDL via *IoRequestPacket,
> where after setting my completion routine in the current stack
> location, I set the params like TdiBuildReceive() in the next
> stack location. The buffer length in the MDL is set to the remaining
> (ie, BytesAvailable - BytesIndicated). Is this correct?
>
> It also seems like whatever buffer I hand back to the TDI has
> to be pinned/locked, as if I don’t ProbeAndLockPages on it,
> TCP barfs as it tries to unlock some pages. I wouldn’t have
> thought I needed to ProbeAndLock a nonpaged pool buffer – is
> it that the TDI is confused by what I sent back?
>
> Any hints on how to correctly respond when BytesAvailable !=
> BytesIndicated would be sincerely appreciated!
>
> Thanks.
>
>

It’s been a while when I did this, but if remember correctly
BytesAvailable > BytesIndicated takes place when the transport driver
accumulates the received packet in the chain of MDLs (NDIS_BUFFERs), so
it indicates
only the buffer represented by the first MDL to your callback. At this
point you have a chance to inspect
the indicated header, and if you want to get the rest, you should

(1) allocate the IRP and init it with TdiBuildReceive(), (2)
IoSetNextIrpStackLocation(irp), (3) save this irp *IoRequestPacket=irp;
and return STATUS_MORE_PROCESSING_REQUIRED.
I think if you set *BytesTaken=0, then the entire received packet will
transefered into the MDL used by your IRP on its completion.

  • Vitaly

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Peter Lawthers
Sent: Wednesday, March 03, 2004 11:59 AM
To: Windows File Systems Devs Interest List
Subject: [ntfsd] ClientEventReceive and BytesAvailable

I’m updating the TDI interface in our FSD to use ClientEventReceive()
for our TCP receive interface instead of just always posting a
TDI_RECEIVE, and am having problems on XP SP1.

I know this issues has been dealt with in the past and I
looked through the archives multiple times, and have
read through Maxim Shatskih’s replies on the subject – they have been
helpful, but I’m still running into a problem and need help from those
who have more patience with the TDI than I do.

I have both a ClientEventReceive and it’s chained counterpart. As long
as BytesAvailable == BytesIndicated in ClientEventReceive everything
seems to work fine.

First off, what (or why?) causes BytesAvailable > BytesIndicated? Isn’t
this a tease? It seems that regardless of what I return to the TDI
(tcp), I end up in a situation where I get no more data after returning
STATUS_MORE_PROCESSING_REQUIRED.

I’ve tried setting *BytesTaken to both BytesAvailable and BytesIndicated
in this case – which should it be?

I’ve tried sending back an IRP/MDL built with TdiBuildReceive() directly
via IoCallDriver from the event handler with no luck.

I’ve tried to send back an IRP/MDL via *IoRequestPacket,
where after setting my completion routine in the current stack location,
I set the params like TdiBuildReceive() in the next stack location. The
buffer length in the MDL is set to the remaining (ie, BytesAvailable -
BytesIndicated). Is this correct?

It also seems like whatever buffer I hand back to the TDI has to be
pinned/locked, as if I don’t ProbeAndLockPages on it, TCP barfs as it
tries to unlock some pages. I wouldn’t have thought I needed to
ProbeAndLock a nonpaged pool buffer – is it that the TDI is confused by
what I sent back?

Any hints on how to correctly respond when BytesAvailable !=
BytesIndicated would be sincerely appreciated!

Thanks.


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@relicore.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

> First off, what (or why?) causes BytesAvailable > BytesIndicated?

Discontiguous packet.

BytesIndicated is the length of the 1st contiguous chunk (first NDIS_BUFFER in
the packet minus the TCP/IP headers), and BytesAvailable is the total packet
length.

to the TDI (tcp), I end up in a situation where I get no
more data after returning STATUS_MORE_PROCESSING_REQUIRED.

I can shamelessly :slight_smile: suggest purchasing our (StorageCraft’s) kernel sockets
library as a sample code for a TDI client. It is rather well-debugged and
tested under load.

I’ve tried sending back an IRP/MDL built with TdiBuildReceive()
directly via IoCallDriver from the event handler with no luck.

Correct way. Do not forget to call IoSetNextIrpStackLocation on this IRP.

It also seems like whatever buffer I hand back to the TDI has
to be pinned/locked, as if I don’t ProbeAndLockPages on it,

Any MDL which crosses the module boundary must be locked (or have
MmBuildMdlForNonPagedPool called on them). This is a law. Unlocked MDLs are
just “not completely built”.

Any hints on how to correctly respond when BytesAvailable !=
BytesIndicated would be sincerely appreciated!

Return the IRP via *IoRequestPacket.

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