Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2080 lines
76 KiB

  1. /********************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1990-2000 **/
  4. /********************************************************************/
  5. /* :ts=4 */
  6. //** TCPDELIV.C - TCP deliver data code.
  7. //
  8. // This file contains the code for delivering data to the user, including
  9. // putting data into recv. buffers and calling indication handlers.
  10. //
  11. #include "precomp.h"
  12. #include "addr.h"
  13. #include "tcp.h"
  14. #include "tcb.h"
  15. #include "tcprcv.h"
  16. #include "tcpsend.h"
  17. #include "tcpconn.h"
  18. #include "tcpdeliv.h"
  19. #include "tlcommon.h"
  20. #include "tcpipbuf.h"
  21. #include "pplasl.h"
  22. #include "mdl2ndis.h"
  23. extern TCPConnBlock **ConnTable;
  24. extern HANDLE TcpRequestPool;
  25. extern BOOLEAN
  26. PutOnRAQ(TCB * RcvTCB, TCPRcvInfo * RcvInfo, IPRcvBuf * RcvBuf, uint Size);
  27. NTSTATUS
  28. TCPPrepareIrpForCancel(
  29. PTCP_CONTEXT TcpContext,
  30. PIRP Irp,
  31. PDRIVER_CANCEL CancelRoutine
  32. );
  33. ULONG
  34. TCPGetMdlChainByteCount(
  35. PMDL Mdl
  36. );
  37. NTSTATUS
  38. TCPDataRequestComplete(
  39. void *Context,
  40. unsigned int Status,
  41. unsigned int ByteCount
  42. );
  43. VOID
  44. TCPCancelRequest(
  45. PDEVICE_OBJECT Device,
  46. PIRP Irp
  47. );
  48. VOID
  49. CompleteRcvs(TCB * CmpltTCB);
  50. #if DBG
  51. ULONG DbgChainedRcvPends;
  52. ULONG DbgChainedRcvNonPends;
  53. ULONG DbgRegularRcv;
  54. #endif
  55. //* FreeRcvReq - Free a rcv request structure.
  56. //
  57. // Called to free a rcv request structure.
  58. //
  59. // Input: FreedReq - Rcv request structure to be freed.
  60. //
  61. // Returns: Nothing.
  62. //
  63. __inline
  64. VOID
  65. FreeRcvReq(TCPRcvReq * Request)
  66. {
  67. CTEStructAssert(Request, trr);
  68. PplFree(TcpRequestPool, Request);
  69. }
  70. //* GetRcvReq - Get a recv. request structure.
  71. //
  72. // Called to get a rcv. request structure.
  73. //
  74. // Input: Nothing.
  75. //
  76. // Returns: Pointer to RcvReq structure, or NULL if none.
  77. //
  78. __inline
  79. TCPRcvReq *
  80. GetRcvReq(VOID)
  81. {
  82. TCPRcvReq *Request;
  83. LOGICAL FromList;
  84. Request = PplAllocate(TcpRequestPool, &FromList);
  85. if (Request) {
  86. #if DBG
  87. Request->trr_sig = trr_signature;
  88. #endif
  89. }
  90. return Request;
  91. }
  92. //* FindLastBuffer - Find the last buffer in a chain.
  93. //
  94. // A utility routine to find the last buffer in an rb chain.
  95. //
  96. // Input: Buf - Pointer to RB chain.
  97. //
  98. // Returns: Pointer to last buf in chain.
  99. //
  100. IPRcvBuf *
  101. FindLastBuffer(IPRcvBuf * Buf)
  102. {
  103. ASSERT(Buf != NULL);
  104. while (Buf->ipr_next != NULL)
  105. Buf = Buf->ipr_next;
  106. return Buf;
  107. }
  108. //* FreePartialRB - Free part of an RB chain.
  109. //
  110. // Called to adjust an free part of an RB chain. We walk down the chain,
  111. // trying to free buffers.
  112. //
  113. // Input: RB - RB chain to be adjusted.
  114. // Size - Size in bytes to be freed.
  115. //
  116. // Returns: Pointer to adjusted RB chain.
  117. //
  118. IPRcvBuf *
  119. FreePartialRB(IPRcvBuf * RB, uint Size)
  120. {
  121. while (Size != 0) {
  122. IPRcvBuf *TempBuf;
  123. ASSERT(RB != NULL);
  124. if (Size >= RB->ipr_size) {
  125. Size -= RB->ipr_size;
  126. TempBuf = RB;
  127. RB = RB->ipr_next;
  128. if (TempBuf->ipr_owner == IPR_OWNER_TCP)
  129. FreeTcpIpr(TempBuf);
  130. } else {
  131. RB->ipr_size -= Size;
  132. RB->ipr_buffer += Size;
  133. break;
  134. }
  135. }
  136. ASSERT(RB != NULL);
  137. return RB;
  138. }
  139. //* CopyRBChain - Copy a chain of IP rcv buffers.
  140. //
  141. // Called to copy a chain of IP rcv buffers. We don't copy a buffer if it's
  142. // already owner by TCP. We assume that all non-TCP owned buffers start
  143. // before any TCP owner buffers, so we quit when we copy to a TCP owner buffer.
  144. //
  145. // Input: OrigBuf - Buffer chain to copy from.
  146. // LastBuf - Where to return pointer to last buffer in
  147. // chain.
  148. // Size - Maximum size in bytes to copy.
  149. //
  150. // Returns: Pointer to new buffer chain.
  151. //
  152. IPRcvBuf *
  153. CopyRBChain(IPRcvBuf * OrigBuf, IPRcvBuf ** LastBuf, uint Size)
  154. {
  155. IPRcvBuf *FirstBuf, *EndBuf;
  156. uint BytesToCopy;
  157. ASSERT(OrigBuf != NULL);
  158. ASSERT(Size > 0);
  159. if (OrigBuf->ipr_owner != IPR_OWNER_TCP) {
  160. BytesToCopy = MIN(Size, OrigBuf->ipr_size);
  161. FirstBuf = AllocTcpIpr(BytesToCopy, 'BPCT');
  162. if (FirstBuf != NULL) {
  163. EndBuf = FirstBuf;
  164. RtlCopyMemory(FirstBuf->ipr_buffer, OrigBuf->ipr_buffer,
  165. BytesToCopy);
  166. Size -= BytesToCopy;
  167. OrigBuf = OrigBuf->ipr_next;
  168. while (OrigBuf != NULL && OrigBuf->ipr_owner != IPR_OWNER_TCP
  169. && Size != 0) {
  170. IPRcvBuf *NewBuf;
  171. BytesToCopy = MIN(Size, OrigBuf->ipr_size);
  172. NewBuf = AllocTcpIpr(BytesToCopy, 'BPCT');
  173. if (NewBuf != NULL) {
  174. RtlCopyMemory(NewBuf->ipr_buffer, OrigBuf->ipr_buffer,
  175. BytesToCopy);
  176. EndBuf->ipr_next = NewBuf;
  177. EndBuf = NewBuf;
  178. Size -= BytesToCopy;
  179. OrigBuf = OrigBuf->ipr_next;
  180. } else {
  181. FreeRBChain(FirstBuf);
  182. return NULL;
  183. }
  184. }
  185. EndBuf->ipr_next = OrigBuf;
  186. } else
  187. return NULL;
  188. } else {
  189. FirstBuf = OrigBuf;
  190. EndBuf = OrigBuf;
  191. if (Size < OrigBuf->ipr_size)
  192. OrigBuf->ipr_size = Size;
  193. Size -= OrigBuf->ipr_size;
  194. }
  195. // Now walk down the chain, until we run out of
  196. // Size. At this point, Size is the bytes left to 'copy' (it may be 0),
  197. // and the sizes in buffers FirstBuf...EndBuf are correct.
  198. while (Size != 0) {
  199. EndBuf = EndBuf->ipr_next;
  200. ASSERT(EndBuf != NULL);
  201. if (Size < EndBuf->ipr_size)
  202. EndBuf->ipr_size = Size;
  203. Size -= EndBuf->ipr_size;
  204. }
  205. // If there's anything left in the chain, free it now.
  206. if (EndBuf->ipr_next != NULL) {
  207. FreeRBChain(EndBuf->ipr_next);
  208. EndBuf->ipr_next = NULL;
  209. }
  210. *LastBuf = EndBuf;
  211. return FirstBuf;
  212. }
  213. //* PendData - Pend incoming data to a client.
  214. //
  215. // Called when we need to buffer data for a client because there's no receive
  216. // down and we can't indicate.
  217. //
  218. // The TCB lock is held throughout this procedure. If this is to be changed,
  219. // make sure consistency of tcb_pendingcnt is preserved. This routine is
  220. // always called at DPC level.
  221. //
  222. // Input: RcvTCB - TCB on which to receive the data.
  223. // RcvFlags - TCP flags for the incoming packet.
  224. // InBuffer - Input buffer of packet.
  225. // Size - Size in bytes of data in InBuffer.
  226. //
  227. // Returns: Number of bytes of data taken.
  228. //
  229. uint
  230. PendData(TCB * RcvTCB, uint RcvFlags, IPRcvBuf * InBuffer, uint Size)
  231. {
  232. IPRcvBuf *NewBuf, *LastBuf;
  233. CTEStructAssert(RcvTCB, tcb);
  234. ASSERT(Size > 0);
  235. ASSERT(InBuffer != NULL);
  236. ASSERT(RcvTCB->tcb_refcnt != 0);
  237. ASSERT(RcvTCB->tcb_fastchk & TCP_FLAG_IN_RCV);
  238. //ASSERT(RcvTCB->tcb_currcv == NULL);
  239. ASSERT(RcvTCB->tcb_rcvhndlr == PendData);
  240. CheckRBList(RcvTCB->tcb_pendhead, RcvTCB->tcb_pendingcnt);
  241. NewBuf = CopyRBChain(InBuffer, &LastBuf, Size);
  242. if (NewBuf != NULL) {
  243. // We have a duplicate chain. Put it on the end of the
  244. // pending q.
  245. if (RcvTCB->tcb_pendhead == NULL) {
  246. RcvTCB->tcb_pendhead = NewBuf;
  247. RcvTCB->tcb_pendtail = LastBuf;
  248. } else {
  249. RcvTCB->tcb_pendtail->ipr_next = NewBuf;
  250. RcvTCB->tcb_pendtail = LastBuf;
  251. }
  252. RcvTCB->tcb_pendingcnt += Size;
  253. } else {
  254. FreeRBChain(InBuffer);
  255. Size = 0;
  256. }
  257. CheckRBList(RcvTCB->tcb_pendhead, RcvTCB->tcb_pendingcnt);
  258. return Size;
  259. }
  260. //* BufferData - Put incoming data into client's buffer.
  261. //
  262. // Called when we believe we have a buffer into which we can put data. We put
  263. // it in there, and if we've filled the buffer or the incoming data has the
  264. // push flag set we'll mark the TCB to return the buffer. Otherwise we'll
  265. // get out and return the data later.
  266. //
  267. // In NT, this routine is called with the TCB lock held, and holds it for
  268. // the duration of the call. This is important to ensure consistency of
  269. // the tcb_pendingcnt field. If we need to change this to free the lock
  270. // partway through, make sure to take this into account. In particular,
  271. // TdiReceive zeros pendingcnt before calling this routine, and this routine
  272. // may update it. If the lock is freed in here there would be a window where
  273. // we really do have pending data, but it's not on the list or reflected in
  274. // pendingcnt. This could mess up our windowing computations, and we'd have
  275. // to be careful not to end up with more data pending than our window allows.
  276. //
  277. // Input: RcvTCB - TCB on which to receive the data.
  278. // RcvFlags - TCP rcv flags for the incoming packet.
  279. // InBuffer - Input buffer of packet.
  280. // Size - Size in bytes of data in InBuffer.
  281. //
  282. // Returns: Number of bytes of data taken.
  283. //
  284. uint
  285. BufferData(TCB * RcvTCB, uint RcvFlags, IPRcvBuf * InBuffer, uint Size)
  286. {
  287. uchar *DestPtr; // Destination pointer.
  288. uchar *SrcPtr; // Src pointer.
  289. uint SrcSize, DestSize = 0; // Sizes of current source and
  290. // destination buffers.
  291. uint Copied; // Total bytes to copy.
  292. uint BytesToCopy; // Bytes of data to copy this time.
  293. TCPRcvReq *DestReq; // Current receive request.
  294. IPRcvBuf *SrcBuf; // Current source buffer.
  295. PNDIS_BUFFER DestBuf; // Current receive buffer.
  296. uint RcvCmpltd;
  297. uint Flags;
  298. CTEStructAssert(RcvTCB, tcb);
  299. ASSERT(Size > 0);
  300. ASSERT(InBuffer != NULL);
  301. ASSERT(RcvTCB->tcb_refcnt != 0);
  302. ASSERT(RcvTCB->tcb_rcvhndlr == BufferData);
  303. // In order to copy the received data to the application's buffers,
  304. // we now need to map those buffers into the system's address space.
  305. // Rather than attempting to map them below, where the going gets rough,
  306. // we do it up-front where errors may be more readily handled.
  307. //
  308. // N.B. We map one buffer beyond what we need, since the code below
  309. // will update the current receive-request to point beyond the data copied.
  310. Copied = 0;
  311. for (DestReq = RcvTCB->tcb_currcv; DestReq; DestReq = DestReq->trr_next) {
  312. uint DestAvail = DestReq->trr_size - DestReq->trr_amt;
  313. for (DestBuf = DestReq->trr_buffer, DestSize = DestReq->trr_offset;
  314. DestBuf && DestAvail && Copied < Size;
  315. DestBuf = NDIS_BUFFER_LINKAGE(DestBuf), DestSize = 0) {
  316. if (!TcpipBufferVirtualAddress(DestBuf, NormalPagePriority)) {
  317. return 0;
  318. }
  319. DestSize = MIN(NdisBufferLength(DestBuf) - DestSize, DestAvail);
  320. DestAvail -= DestSize;
  321. Copied += DestSize;
  322. }
  323. if (Copied >= Size) {
  324. // We've mapped the space into which we'll copy;
  325. // now map the space immediately beyond that.
  326. if (DestAvail) {
  327. // We believe space remains in the current receive-request;
  328. // DestBuf should point to the current buffer.
  329. ASSERT(DestBuf);
  330. } else if ((DestReq = DestReq->trr_next) != NULL) {
  331. // No more space in that receive-request, but there's another;
  332. // Move to this next one, and map the start of that.
  333. DestBuf = DestReq->trr_buffer;
  334. } else {
  335. break;
  336. }
  337. if (!TcpipBufferVirtualAddress(DestBuf, NormalPagePriority)) {
  338. return 0;
  339. }
  340. break;
  341. }
  342. }
  343. Copied = 0;
  344. RcvCmpltd = 0;
  345. DestReq = RcvTCB->tcb_currcv;
  346. ASSERT(DestReq != NULL);
  347. CTEStructAssert(DestReq, trr);
  348. DestBuf = DestReq->trr_buffer;
  349. DestSize = MIN(NdisBufferLength(DestBuf) - DestReq->trr_offset,
  350. DestReq->trr_size - DestReq->trr_amt);
  351. DestPtr = (uchar *) NdisBufferVirtualAddress(DestBuf) + DestReq->trr_offset;
  352. SrcBuf = InBuffer;
  353. SrcSize = SrcBuf->ipr_size;
  354. SrcPtr = SrcBuf->ipr_buffer;
  355. Flags = (RcvFlags & TCP_FLAG_PUSH) ? TRR_PUSHED : 0;
  356. RcvCmpltd = Flags;
  357. DestReq->trr_flags |= Flags;
  358. do {
  359. BytesToCopy = MIN(Size - Copied, MIN(SrcSize, DestSize));
  360. RtlCopyMemory(DestPtr, SrcPtr, BytesToCopy);
  361. Copied += BytesToCopy;
  362. DestReq->trr_amt += BytesToCopy;
  363. // Update our source pointers.
  364. if ((SrcSize -= BytesToCopy) == 0) {
  365. IPRcvBuf *TempBuf;
  366. // We've copied everything in this buffer.
  367. TempBuf = SrcBuf;
  368. SrcBuf = SrcBuf->ipr_next;
  369. if (Size != Copied) {
  370. ASSERT(SrcBuf != NULL);
  371. SrcSize = SrcBuf->ipr_size;
  372. SrcPtr = SrcBuf->ipr_buffer;
  373. }
  374. if (TempBuf->ipr_owner == IPR_OWNER_TCP)
  375. FreeTcpIpr(TempBuf);
  376. } else
  377. SrcPtr += BytesToCopy;
  378. // Now check the destination pointer, and update it if we need to.
  379. if ((DestSize -= BytesToCopy) == 0) {
  380. uint DestAvail;
  381. // Exhausted this buffer. See if there's another one.
  382. DestAvail = DestReq->trr_size - DestReq->trr_amt;
  383. DestBuf = NDIS_BUFFER_LINKAGE(DestBuf);
  384. if (DestBuf != NULL && (DestAvail != 0)) {
  385. // Have another buffer in the chain. Update things.
  386. DestSize = MIN(NdisBufferLength(DestBuf), DestAvail);
  387. DestPtr = (uchar *) NdisBufferVirtualAddress(DestBuf);
  388. } else {
  389. // No more buffers in the chain. See if we have another buffer
  390. // on the list.
  391. DestReq->trr_flags |= TRR_PUSHED;
  392. // If we've been told there's to be no back traffic, get an ACK
  393. // going right away.
  394. if (DestReq->trr_flags & TDI_RECEIVE_NO_RESPONSE_EXP)
  395. DelayAction(RcvTCB, NEED_ACK);
  396. RcvCmpltd = TRUE;
  397. DestReq = DestReq->trr_next;
  398. if (DestReq != NULL) {
  399. DestBuf = DestReq->trr_buffer;
  400. DestSize = MIN(NdisBufferLength(DestBuf), DestReq->trr_size);
  401. DestPtr = (uchar *) NdisBufferVirtualAddress(DestBuf);
  402. // If we have more to put into here, set the flags.
  403. if (Copied != Size)
  404. DestReq->trr_flags |= Flags;
  405. } else {
  406. // All out of buffer space. Reset the data handler pointer.
  407. break;
  408. }
  409. }
  410. } else
  411. // Current buffer not empty yet.
  412. DestPtr += BytesToCopy;
  413. // If we've copied all that we need to, we're done.
  414. } while (Copied != Size);
  415. // We've finished copying, and have a few more things to do. We need to
  416. // update the current rcv. pointer and possibly the offset in the
  417. // recv. request. If we need to complete any receives we have to schedule
  418. // that. If there's any data we couldn't copy we'll need to dispose of
  419. // it.
  420. RcvTCB->tcb_currcv = DestReq;
  421. if (DestReq != NULL) {
  422. DestReq->trr_buffer = DestBuf;
  423. DestReq->trr_offset = (uint) (DestPtr - (uchar *) NdisBufferVirtualAddress(DestBuf));
  424. RcvTCB->tcb_rcvhndlr = BufferData;
  425. } else
  426. RcvTCB->tcb_rcvhndlr = PendData;
  427. RcvTCB->tcb_indicated -= MIN(Copied, RcvTCB->tcb_indicated);
  428. if (Size != Copied) {
  429. IPRcvBuf *NewBuf, *LastBuf;
  430. ASSERT(DestReq == NULL);
  431. RcvTCB->tcb_moreflag = 1;
  432. // We have data to dispose of. Update the first buffer of the chain
  433. // with the current src pointer and size, and copy it.
  434. ASSERT(SrcSize <= SrcBuf->ipr_size);
  435. ASSERT(
  436. ((uint) (SrcPtr - SrcBuf->ipr_buffer)) ==
  437. (SrcBuf->ipr_size - SrcSize)
  438. );
  439. SrcBuf->ipr_buffer = SrcPtr;
  440. SrcBuf->ipr_size = SrcSize;
  441. NewBuf = CopyRBChain(SrcBuf, &LastBuf, Size - Copied);
  442. if (NewBuf != NULL) {
  443. // We managed to copy the buffer. Push it on the pending queue.
  444. if (RcvTCB->tcb_pendhead == NULL) {
  445. RcvTCB->tcb_pendhead = NewBuf;
  446. RcvTCB->tcb_pendtail = LastBuf;
  447. } else {
  448. LastBuf->ipr_next = RcvTCB->tcb_pendhead;
  449. RcvTCB->tcb_pendhead = NewBuf;
  450. }
  451. RcvTCB->tcb_pendingcnt += Size - Copied;
  452. Copied = Size;
  453. CheckRBList(RcvTCB->tcb_pendhead, RcvTCB->tcb_pendingcnt);
  454. } else
  455. FreeRBChain(SrcBuf);
  456. } else {
  457. // We copied Size bytes, but the chain could be longer than that. Free
  458. // it if we need to.
  459. if (SrcBuf != NULL)
  460. FreeRBChain(SrcBuf);
  461. }
  462. if (RcvCmpltd != 0) {
  463. DelayAction(RcvTCB, NEED_RCV_CMPLT);
  464. } else {
  465. //instrumentation to catch conreq null in tcb.c
  466. // ASSERT(DestReq);
  467. // ASSERT(DestReq->trr_amt);
  468. // RcvTCB->tcb_lastreq = DestReq;
  469. START_TCB_TIMER_R(RcvTCB, PUSH_TIMER, PUSH_TO);
  470. }
  471. return Copied;
  472. }
  473. //* IndicateData - Indicate incoming data to a client.
  474. //
  475. // Called when we need to indicate data to an upper layer client. We'll pass
  476. // up a pointer to whatever we have available, and the client may take some
  477. // or all of it.
  478. //
  479. // Input: RcvTCB - TCB on which to receive the data.
  480. // RcvFlags - TCP rcv flags for the incoming packet.
  481. // InBuffer - Input buffer of packet.
  482. // Size - Size in bytes of data in InBuffer.
  483. //
  484. // Returns: Number of bytes of data taken.
  485. //
  486. uint
  487. IndicateData(TCB * RcvTCB, uint RcvFlags, IPRcvBuf * InBuffer, uint Size)
  488. {
  489. TDI_STATUS Status;
  490. PRcvEvent Event;
  491. PVOID EventContext, ConnContext;
  492. uint BytesTaken = 0;
  493. #if MILLEN
  494. EventRcvBuffer ERB;
  495. #else // MILLEN
  496. EventRcvBuffer *ERB = NULL;
  497. PTDI_REQUEST_KERNEL_RECEIVE RequestInformation;
  498. PIO_STACK_LOCATION IrpSp;
  499. #endif // !MILLEN
  500. TCPRcvReq *RcvReq;
  501. IPRcvBuf *NewBuf;
  502. ulong IndFlags;
  503. #if TRACE_EVENT
  504. PTDI_DATA_REQUEST_NOTIFY_ROUTINE CPCallBack;
  505. WMIData WMIInfo;
  506. #endif
  507. IPRcvBuf *LastBuf;
  508. DEBUGMSG(DBG_TRACE && DBG_TDI, (DTEXT("+IndicateData\n")));
  509. CTEStructAssert(RcvTCB, tcb);
  510. ASSERT(Size > 0);
  511. ASSERT(InBuffer != NULL);
  512. ASSERT(RcvTCB->tcb_refcnt != 0);
  513. ASSERT(RcvTCB->tcb_fastchk & TCP_FLAG_IN_RCV);
  514. ASSERT(RcvTCB->tcb_rcvind != NULL);
  515. ASSERT(RcvTCB->tcb_rcvhead == NULL);
  516. ASSERT(RcvTCB->tcb_rcvhndlr == IndicateData);
  517. Event = RcvTCB->tcb_rcvind;
  518. EventContext = RcvTCB->tcb_ricontext;
  519. ConnContext = RcvTCB->tcb_conncontext;
  520. if (Size < InBuffer->ipr_size) {
  521. uint NewRcvWin;
  522. NewRcvWin = RcvWin(RcvTCB);
  523. Size = MIN(InBuffer->ipr_size, NewRcvWin);
  524. }
  525. RcvTCB->tcb_indicated = Size;
  526. RcvTCB->tcb_flags |= IN_RCV_IND;
  527. IF_TCPDBG(TCP_DEBUG_RECEIVE) {
  528. TCPTRACE((
  529. "Indicating %lu bytes, %lu available\n",
  530. InBuffer->ipr_size, Size
  531. ));
  532. }
  533. #if TCP_FLAG_PUSH >= TDI_RECEIVE_ENTIRE_MESSAGE
  534. IndFlags = TDI_RECEIVE_COPY_LOOKAHEAD | TDI_RECEIVE_NORMAL |
  535. TDI_RECEIVE_AT_DISPATCH_LEVEL |
  536. ((RcvFlags & TCP_FLAG_PUSH) >>
  537. ((TCP_FLAG_PUSH / TDI_RECEIVE_ENTIRE_MESSAGE) - 1));
  538. #else
  539. IndFlags = TDI_RECEIVE_COPY_LOOKAHEAD | TDI_RECEIVE_NORMAL |
  540. TDI_RECEIVE_AT_DISPATCH_LEVEL |
  541. ((RcvFlags & TCP_FLAG_PUSH) <<
  542. ((TDI_RECEIVE_ENTIRE_MESSAGE / TCP_FLAG_PUSH) - 1));
  543. #endif
  544. #if DBG
  545. DbgRegularRcv++;
  546. #endif
  547. if (InBuffer->ipr_pMdl && RcvTCB->tcb_chainedrcvind) {
  548. PChainedRcvEvent ChainedEvent = RcvTCB->tcb_chainedrcvind;
  549. CTEFreeLockFromDPC(&RcvTCB->tcb_lock, NULL);
  550. ASSERT(InBuffer->ipr_size == Size);
  551. Status = (*ChainedEvent) (RcvTCB->tcb_chainedrcvcontext, ConnContext,
  552. IndFlags, InBuffer->ipr_size, InBuffer->ipr_RcvOffset,
  553. InBuffer->ipr_pMdl, InBuffer->ipr_RcvContext);
  554. #if TRACE_EVENT
  555. CPCallBack = TCPCPHandlerRoutine;
  556. if ((CPCallBack != NULL) && (Size > 0)) {
  557. ulong GroupType;
  558. WMIInfo.wmi_destaddr = RcvTCB->tcb_daddr;
  559. WMIInfo.wmi_destport = RcvTCB->tcb_dport;
  560. WMIInfo.wmi_srcaddr = RcvTCB->tcb_saddr;
  561. WMIInfo.wmi_srcport = RcvTCB->tcb_sport;
  562. WMIInfo.wmi_size = Size;
  563. WMIInfo.wmi_context = RcvTCB->tcb_cpcontext;
  564. GroupType = EVENT_TRACE_GROUP_TCPIP + EVENT_TRACE_TYPE_RECEIVE;
  565. (*CPCallBack) (GroupType, (PVOID) &WMIInfo, sizeof(WMIInfo), NULL);
  566. }
  567. #endif
  568. if (Status == STATUS_PENDING) {
  569. *InBuffer->ipr_pClientCnt = 1; //indicate to the ndis that
  570. #if DBG
  571. DbgChainedRcvPends++;
  572. #endif
  573. } else if (Status == TDI_SUCCESS) {
  574. *InBuffer->ipr_pClientCnt = 0;
  575. #if DBG
  576. DbgChainedRcvNonPends++;
  577. #endif
  578. }
  579. CTEGetLockAtDPC(&RcvTCB->tcb_lock, NULL);
  580. RcvTCB->tcb_indicated = 0;
  581. RcvTCB->tcb_flags &= ~IN_RCV_IND;
  582. if (Status == TDI_NOT_ACCEPTED) {
  583. BytesTaken = 0;
  584. if ((RcvTCB->tcb_rcvhead != NULL) && (RcvTCB->tcb_currcv != NULL)) {
  585. RcvTCB->tcb_rcvhndlr = BufferData;
  586. //ASSERT(RcvTCB->tcb_rcvhndlr == BufferData);
  587. BytesTaken += BufferData(RcvTCB, RcvFlags, InBuffer,
  588. Size - BytesTaken);
  589. } else {
  590. // Need to copy the chain and pend the data.
  591. RcvTCB->tcb_rcvhndlr = PendData;
  592. NewBuf = CopyRBChain(InBuffer, &LastBuf, Size - BytesTaken);
  593. if (NewBuf != NULL) {
  594. // We have a duplicate chain. Push it on the front of the
  595. // pending q.
  596. if (RcvTCB->tcb_pendhead == NULL) {
  597. RcvTCB->tcb_pendhead = NewBuf;
  598. RcvTCB->tcb_pendtail = LastBuf;
  599. } else {
  600. LastBuf->ipr_next = RcvTCB->tcb_pendhead;
  601. RcvTCB->tcb_pendhead = NewBuf;
  602. }
  603. RcvTCB->tcb_pendingcnt += Size - BytesTaken;
  604. BytesTaken = Size;
  605. RcvTCB->tcb_moreflag = 3;
  606. } else {
  607. FreeRBChain(InBuffer);
  608. }
  609. }
  610. return BytesTaken;
  611. }
  612. return Size;
  613. }
  614. if (!Event) {
  615. // This is to safeguard against a timing window between the
  616. // time NEED_RST is set and the tcb gets closed.
  617. FreeRBChain(InBuffer);
  618. return 0;
  619. }
  620. RcvReq = GetRcvReq();
  621. if (RcvReq != NULL) {
  622. // The indicate handler is saved in the TCB. Just call up into it.
  623. CTEFreeLockFromDPC(&RcvTCB->tcb_lock, NULL);
  624. Status = (*Event) (EventContext, ConnContext,
  625. IndFlags, InBuffer->ipr_size, Size, &BytesTaken,
  626. InBuffer->ipr_buffer, &ERB);
  627. IF_TCPDBG(TCP_DEBUG_RECEIVE) {
  628. TCPTRACE(("%lu bytes taken, status %lx\n", BytesTaken, Status));
  629. }
  630. // See what the client did. If the return status is MORE_PROCESSING,
  631. // we've been given a buffer. In that case put it on the front of the
  632. // buffer queue, and if all the data wasn't taken go ahead and copy
  633. // it into the new buffer chain.
  634. //
  635. // Note that the size and buffer chain we're concerned with here is
  636. // the one that we passed to the client. Since we're in a rcv. handler,
  637. // any data that has come in would have been put on the reassembly
  638. // queue.
  639. #if TRACE_EVENT
  640. CPCallBack = TCPCPHandlerRoutine;
  641. if ((CPCallBack != NULL) && (BytesTaken > 0)) {
  642. ulong GroupType;
  643. WMIInfo.wmi_destaddr = RcvTCB->tcb_daddr;
  644. WMIInfo.wmi_destport = RcvTCB->tcb_dport;
  645. WMIInfo.wmi_srcaddr = RcvTCB->tcb_saddr;
  646. WMIInfo.wmi_srcport = RcvTCB->tcb_sport;
  647. WMIInfo.wmi_size = BytesTaken;
  648. WMIInfo.wmi_context = RcvTCB->tcb_cpcontext;
  649. GroupType = EVENT_TRACE_GROUP_TCPIP + EVENT_TRACE_TYPE_RECEIVE;
  650. (*CPCallBack) (GroupType, (PVOID)&WMIInfo, sizeof(WMIInfo), NULL);
  651. }
  652. #endif
  653. if (Status == TDI_MORE_PROCESSING) {
  654. #if !MILLEN
  655. ASSERT(ERB != NULL);
  656. IrpSp = IoGetCurrentIrpStackLocation(ERB);
  657. Status = TCPPrepareIrpForCancel(
  658. (PTCP_CONTEXT) IrpSp->FileObject->FsContext,
  659. ERB,
  660. TCPCancelRequest
  661. );
  662. if (NT_SUCCESS(Status)) {
  663. PNDIS_BUFFER pNdisBuffer;
  664. Status = ConvertMdlToNdisBuffer(ERB, ERB->MdlAddress, &pNdisBuffer);
  665. ASSERT(Status == TDI_SUCCESS);
  666. RequestInformation = (PTDI_REQUEST_KERNEL_RECEIVE)
  667. & (IrpSp->Parameters);
  668. RcvReq->trr_rtn = TCPDataRequestComplete;
  669. RcvReq->trr_context = ERB;
  670. RcvReq->trr_buffer = pNdisBuffer;
  671. RcvReq->trr_size = RequestInformation->ReceiveLength;
  672. RcvReq->trr_uflags = (ushort *)
  673. & (RequestInformation->ReceiveFlags);
  674. RcvReq->trr_flags = (uint) (RequestInformation->ReceiveFlags);
  675. RcvReq->trr_offset = 0;
  676. RcvReq->trr_amt = 0;
  677. #else // !MILLEN
  678. if (1) {
  679. RcvReq->trr_rtn = ERB.erb_rtn;
  680. RcvReq->trr_context = ERB.erb_context;
  681. RcvReq->trr_buffer = ERB.erb_buffer;
  682. RcvReq->trr_size = ERB.erb_size;
  683. RcvReq->trr_uflags = ERB.erb_flags;
  684. CTEAssert(ERB.erb_flags != NULL);
  685. RcvReq->trr_flags = (uint) (*ERB.erb_flags);
  686. RcvReq->trr_offset = 0;
  687. RcvReq->trr_amt = 0;
  688. #endif // MILLEN
  689. CTEGetLockAtDPC(&RcvTCB->tcb_lock, NULL);
  690. RcvTCB->tcb_flags &= ~IN_RCV_IND;
  691. ASSERT(RcvTCB->tcb_rcvhndlr == IndicateData);
  692. // Push him on the front of the rcv. queue.
  693. ASSERT((RcvTCB->tcb_currcv == NULL) ||
  694. (RcvTCB->tcb_currcv->trr_amt == 0));
  695. if (RcvTCB->tcb_rcvhead == NULL) {
  696. RcvTCB->tcb_rcvhead = RcvReq;
  697. RcvTCB->tcb_rcvtail = RcvReq;
  698. RcvReq->trr_next = NULL;
  699. } else {
  700. RcvReq->trr_next = RcvTCB->tcb_rcvhead;
  701. RcvTCB->tcb_rcvhead = RcvReq;
  702. }
  703. RcvTCB->tcb_currcv = RcvReq;
  704. RcvTCB->tcb_rcvhndlr = BufferData;
  705. ASSERT(BytesTaken <= Size);
  706. RcvTCB->tcb_indicated -= BytesTaken;
  707. if ((Size -= BytesTaken) != 0) {
  708. RcvTCB->tcb_moreflag = 2;
  709. // Not everything was taken. Adjust the buffer chain to point
  710. // beyond what was taken.
  711. InBuffer = FreePartialRB(InBuffer, BytesTaken);
  712. ASSERT(InBuffer != NULL);
  713. // We've adjusted the buffer chain. Call the BufferData
  714. // handler.
  715. BytesTaken += BufferData(RcvTCB, RcvFlags, InBuffer, Size);
  716. } else {
  717. // All of the data was taken. Free the buffer chain.
  718. FreeRBChain(InBuffer);
  719. }
  720. return BytesTaken;
  721. #if !MILLEN
  722. } else {
  723. //
  724. // The IRP was cancelled before it was handed back to us.
  725. // We'll pretend we never saw it. TCPPrepareIrpForCancel
  726. // already completed it. The client may have taken data,
  727. // so we will act as if success was returned.
  728. //
  729. ERB = NULL;
  730. Status = TDI_SUCCESS;
  731. #endif // !MILLEN
  732. }
  733. }
  734. CTEGetLockAtDPC(&RcvTCB->tcb_lock, NULL);
  735. RcvTCB->tcb_flags &= ~IN_RCV_IND;
  736. // Status is not more processing. If it's not SUCCESS, the client
  737. // didn't take any of the data. In either case we now need to
  738. // see if all of the data was taken. If it wasn't, we'll try and
  739. // push it onto the front of the pending queue.
  740. FreeRcvReq(RcvReq); // This won't be needed.
  741. if (Status == TDI_NOT_ACCEPTED)
  742. BytesTaken = 0;
  743. ASSERT(BytesTaken <= Size);
  744. RcvTCB->tcb_indicated -= BytesTaken;
  745. ASSERT(RcvTCB->tcb_rcvhndlr == IndicateData);
  746. // Check to see if a rcv. buffer got posted during the indication.
  747. // If it did, reset the recv. handler now.
  748. if (RcvTCB->tcb_rcvhead != NULL)
  749. RcvTCB->tcb_rcvhndlr = BufferData;
  750. // See if all of the data was taken.
  751. if (BytesTaken == Size) {
  752. ASSERT(RcvTCB->tcb_indicated == 0);
  753. FreeRBChain(InBuffer);
  754. return BytesTaken; // It was all taken.
  755. }
  756. // It wasn't all taken. Adjust for what was taken, and push
  757. // on the front of the pending queue. We also need to check to
  758. // see if a receive buffer got posted during the indication. This
  759. // would be weird, but not impossible.
  760. InBuffer = FreePartialRB(InBuffer, BytesTaken);
  761. if (RcvTCB->tcb_rcvhead == NULL) {
  762. RcvTCB->tcb_rcvhndlr = PendData;
  763. NewBuf = CopyRBChain(InBuffer, &LastBuf, Size - BytesTaken);
  764. if (NewBuf != NULL) {
  765. // We have a duplicate chain. Push it on the front of the
  766. // pending q.
  767. if (RcvTCB->tcb_pendhead == NULL) {
  768. RcvTCB->tcb_pendhead = NewBuf;
  769. RcvTCB->tcb_pendtail = LastBuf;
  770. } else {
  771. LastBuf->ipr_next = RcvTCB->tcb_pendhead;
  772. RcvTCB->tcb_pendhead = NewBuf;
  773. }
  774. RcvTCB->tcb_pendingcnt += Size - BytesTaken;
  775. BytesTaken = Size;
  776. RcvTCB->tcb_moreflag = 3;
  777. } else {
  778. FreeRBChain(InBuffer);
  779. }
  780. return BytesTaken;
  781. } else {
  782. // Just great. There's now a rcv. buffer on the TCB. Call the
  783. // BufferData handler now.
  784. ASSERT(RcvTCB->tcb_rcvhndlr == BufferData);
  785. BytesTaken += BufferData(RcvTCB, RcvFlags, InBuffer,
  786. Size - BytesTaken);
  787. return BytesTaken;
  788. }
  789. } else {
  790. // Couldn't get a recv. request. We must be really low on resources,
  791. // so just bail out now.
  792. FreeRBChain(InBuffer);
  793. return 0;
  794. }
  795. DEBUGMSG(DBG_TRACE && DBG_TDI, (DTEXT("-IndicateData\n")));
  796. }
  797. //* IndicatePendingData - Indicate pending data to a client.
  798. //
  799. // Called when we need to indicate pending data to an upper layer client,
  800. // usually because data arrived when we were in a state that it couldn't
  801. // be indicated.
  802. //
  803. // Many of the comments in the BufferData header about the consistency of
  804. // tcb_pendingcnt apply here also.
  805. //
  806. // Input: RcvTCB - TCB on which to indicate the data.
  807. // RcvReq - Rcv. req. to use to indicate it.
  808. //
  809. // Returns: Nothing.
  810. //
  811. void
  812. IndicatePendingData(TCB *RcvTCB, TCPRcvReq *RcvReq, CTELockHandle TCBHandle)
  813. {
  814. TDI_STATUS Status;
  815. PRcvEvent Event;
  816. PVOID EventContext, ConnContext;
  817. #if !MILLEN
  818. EventRcvBuffer *ERB = NULL;
  819. PTDI_REQUEST_KERNEL_RECEIVE RequestInformation;
  820. PIO_STACK_LOCATION IrpSp;
  821. #else // !MILLEN
  822. EventRcvBuffer ERB;
  823. #endif // MILLEN
  824. IPRcvBuf *NewBuf;
  825. uint Size;
  826. uint BytesIndicated;
  827. uint BytesAvailable;
  828. uint BytesTaken = 0;
  829. uchar *DataBuffer;
  830. CTEStructAssert(RcvTCB, tcb);
  831. ASSERT(RcvTCB->tcb_refcnt != 0);
  832. ASSERT(RcvTCB->tcb_rcvind != NULL);
  833. ASSERT(RcvTCB->tcb_rcvhead == NULL);
  834. ASSERT(RcvTCB->tcb_pendingcnt != 0);
  835. ASSERT(RcvReq != NULL);
  836. for (;;) {
  837. ASSERT(RcvTCB->tcb_rcvhndlr == PendData);
  838. // The indicate handler is saved in the TCB. Just call up into it.
  839. Event = RcvTCB->tcb_rcvind;
  840. EventContext = RcvTCB->tcb_ricontext;
  841. ConnContext = RcvTCB->tcb_conncontext;
  842. BytesIndicated = RcvTCB->tcb_pendhead->ipr_size;
  843. BytesAvailable = RcvTCB->tcb_pendingcnt;
  844. DataBuffer = RcvTCB->tcb_pendhead->ipr_buffer;
  845. RcvTCB->tcb_indicated = RcvTCB->tcb_pendingcnt;
  846. RcvTCB->tcb_flags |= IN_RCV_IND;
  847. RcvTCB->tcb_moreflag = 0;
  848. CTEFreeLock(&RcvTCB->tcb_lock, TCBHandle);
  849. IF_TCPDBG(TCPDebug & TCP_DEBUG_RECEIVE) {
  850. TCPTRACE((
  851. "Indicating pending %d bytes, %d available\n",
  852. RcvTCB->tcb_pendhead->ipr_size, RcvTCB->tcb_pendingcnt
  853. ));
  854. }
  855. Status = (*Event) (EventContext, ConnContext,
  856. TDI_RECEIVE_COPY_LOOKAHEAD | TDI_RECEIVE_NORMAL |
  857. TDI_RECEIVE_ENTIRE_MESSAGE,
  858. BytesIndicated, BytesAvailable, &BytesTaken,
  859. DataBuffer, &ERB);
  860. IF_TCPDBG(TCPDebug & TCP_DEBUG_RECEIVE) {
  861. TCPTRACE(("%d bytes taken\n", BytesTaken));
  862. }
  863. // See what the client did. If the return status is MORE_PROCESSING,
  864. // we've been given a buffer. In that case put it on the front of the
  865. // buffer queue, and if all the data wasn't taken go ahead and copy
  866. // it into the new buffer chain.
  867. if (Status == TDI_MORE_PROCESSING) {
  868. #if !MILLEN
  869. IF_TCPDBG(TCP_DEBUG_RECEIVE) {
  870. TCPTRACE(("more processing on receive\n"));
  871. }
  872. ASSERT(ERB != NULL);
  873. IrpSp = IoGetCurrentIrpStackLocation(ERB);
  874. Status = TCPPrepareIrpForCancel(
  875. (PTCP_CONTEXT) IrpSp->FileObject->FsContext,
  876. ERB,
  877. TCPCancelRequest
  878. );
  879. if (NT_SUCCESS(Status)) {
  880. PNDIS_BUFFER pNdisBuffer;
  881. Status = ConvertMdlToNdisBuffer(ERB, ERB->MdlAddress, &pNdisBuffer);
  882. ASSERT(Status == TDI_SUCCESS);
  883. RequestInformation = (PTDI_REQUEST_KERNEL_RECEIVE)
  884. & (IrpSp->Parameters);
  885. RcvReq->trr_rtn = TCPDataRequestComplete;
  886. RcvReq->trr_context = ERB;
  887. RcvReq->trr_buffer = pNdisBuffer;
  888. RcvReq->trr_size = RequestInformation->ReceiveLength;
  889. RcvReq->trr_uflags = (ushort *)
  890. & (RequestInformation->ReceiveFlags);
  891. RcvReq->trr_flags = (uint) (RequestInformation->ReceiveFlags);
  892. RcvReq->trr_offset = 0;
  893. RcvReq->trr_amt = 0;
  894. #else // !MILLEN
  895. if (1) {
  896. RcvReq->trr_rtn = ERB.erb_rtn;
  897. RcvReq->trr_context = ERB.erb_context;
  898. RcvReq->trr_buffer = ERB.erb_buffer;
  899. RcvReq->trr_size = ERB.erb_size;
  900. RcvReq->trr_uflags = ERB.erb_flags;
  901. RcvReq->trr_flags = (uint) (*ERB.erb_flags);
  902. RcvReq->trr_offset = 0;
  903. RcvReq->trr_amt = 0;
  904. #endif // MILLLEN
  905. CTEGetLock(&RcvTCB->tcb_lock, &TCBHandle);
  906. RcvTCB->tcb_flags &= ~IN_RCV_IND;
  907. // Push him on the front of the rcv. queue.
  908. ASSERT((RcvTCB->tcb_currcv == NULL) ||
  909. (RcvTCB->tcb_currcv->trr_amt == 0));
  910. if (RcvTCB->tcb_rcvhead == NULL) {
  911. RcvTCB->tcb_rcvhead = RcvReq;
  912. RcvTCB->tcb_rcvtail = RcvReq;
  913. RcvReq->trr_next = NULL;
  914. } else {
  915. RcvReq->trr_next = RcvTCB->tcb_rcvhead;
  916. RcvTCB->tcb_rcvhead = RcvReq;
  917. }
  918. RcvTCB->tcb_currcv = RcvReq;
  919. RcvTCB->tcb_rcvhndlr = BufferData;
  920. // Have to pick up the new size and pointers now, since things could
  921. // have changed during the upcall.
  922. Size = RcvTCB->tcb_pendingcnt;
  923. NewBuf = RcvTCB->tcb_pendhead;
  924. RcvTCB->tcb_pendingcnt = 0;
  925. RcvTCB->tcb_pendhead = NULL;
  926. ASSERT(BytesTaken <= Size);
  927. RcvTCB->tcb_indicated -= BytesTaken;
  928. if ((Size -= BytesTaken) != 0) {
  929. RcvTCB->tcb_moreflag = 4;
  930. // Not everything was taken. Adjust the buffer chain to point
  931. // beyond what was taken.
  932. NewBuf = FreePartialRB(NewBuf, BytesTaken);
  933. ASSERT(NewBuf != NULL);
  934. // We've adjusted the buffer chain. Call the BufferData
  935. // handler.
  936. (void)BufferData(RcvTCB, TCP_FLAG_PUSH, NewBuf, Size);
  937. CTEFreeLock(&RcvTCB->tcb_lock, TCBHandle);
  938. } else {
  939. // All of the data was taken. Free the buffer chain. Since
  940. // we were passed a buffer chain which we put on the head of
  941. // the list, leave the rcvhandler pointing at BufferData.
  942. ASSERT(RcvTCB->tcb_rcvhndlr == BufferData);
  943. ASSERT(RcvTCB->tcb_indicated == 0);
  944. ASSERT(RcvTCB->tcb_rcvhead != NULL);
  945. CTEFreeLock(&RcvTCB->tcb_lock, TCBHandle);
  946. FreeRBChain(NewBuf);
  947. }
  948. return;
  949. #if !MILLEN
  950. } else {
  951. //
  952. // The IRP was cancelled before it was handed back to us.
  953. // We'll pretend we never saw it. TCPPrepareIrpForCancel
  954. // already completed it. The client may have taken data,
  955. // so we will act as if success was returned.
  956. //
  957. ERB = NULL;
  958. Status = TDI_SUCCESS;
  959. #endif // !MILLEN
  960. }
  961. }
  962. CTEGetLock(&RcvTCB->tcb_lock, &TCBHandle);
  963. RcvTCB->tcb_flags &= ~IN_RCV_IND;
  964. // Status is not more processing. If it's not SUCCESS, the client
  965. // didn't take any of the data. In either case we now need to
  966. // see if all of the data was taken. If it wasn't, we're done.
  967. if (Status == TDI_NOT_ACCEPTED)
  968. BytesTaken = 0;
  969. ASSERT(RcvTCB->tcb_rcvhndlr == PendData);
  970. RcvTCB->tcb_indicated -= BytesTaken;
  971. Size = RcvTCB->tcb_pendingcnt;
  972. NewBuf = RcvTCB->tcb_pendhead;
  973. ASSERT(BytesTaken <= Size);
  974. // See if all of the data was taken.
  975. if (BytesTaken == Size) {
  976. // It was all taken. Zap the pending data information.
  977. RcvTCB->tcb_pendingcnt = 0;
  978. RcvTCB->tcb_pendhead = NULL;
  979. ASSERT(RcvTCB->tcb_indicated == 0);
  980. if (RcvTCB->tcb_rcvhead == NULL) {
  981. if (RcvTCB->tcb_rcvind != NULL)
  982. RcvTCB->tcb_rcvhndlr = IndicateData;
  983. } else
  984. RcvTCB->tcb_rcvhndlr = BufferData;
  985. CTEFreeLock(&RcvTCB->tcb_lock, TCBHandle);
  986. FreeRBChain(NewBuf);
  987. break;
  988. }
  989. // It wasn't all taken. Adjust for what was taken, We also need to check
  990. // to see if a receive buffer got posted during the indication. This
  991. // would be weird, but not impossible.
  992. NewBuf = FreePartialRB(NewBuf, BytesTaken);
  993. ASSERT(RcvTCB->tcb_rcvhndlr == PendData);
  994. RcvTCB->tcb_moreflag = 5;
  995. if (RcvTCB->tcb_rcvhead == NULL) {
  996. RcvTCB->tcb_pendhead = NewBuf;
  997. RcvTCB->tcb_pendingcnt -= BytesTaken;
  998. if (RcvTCB->tcb_indicated != 0 || RcvTCB->tcb_rcvind == NULL) {
  999. CTEFreeLock(&RcvTCB->tcb_lock, TCBHandle);
  1000. break;
  1001. }
  1002. // From here, we'll loop around and indicate the new data that
  1003. // presumably came in during the previous indication.
  1004. } else {
  1005. // Just great. There's now a rcv. buffer on the TCB. Call the
  1006. // BufferData handler now.
  1007. RcvTCB->tcb_rcvhndlr = BufferData;
  1008. RcvTCB->tcb_pendingcnt = 0;
  1009. RcvTCB->tcb_pendhead = NULL;
  1010. BytesTaken += BufferData(RcvTCB, TCP_FLAG_PUSH, NewBuf,
  1011. Size - BytesTaken);
  1012. CTEFreeLock(&RcvTCB->tcb_lock, TCBHandle);
  1013. break;
  1014. }
  1015. } // for (;;)
  1016. FreeRcvReq(RcvReq); // This isn't needed anymore.
  1017. }
  1018. //* DeliverUrgent - Deliver urgent data to a client.
  1019. //
  1020. // Called to deliver urgent data to a client. We assume the input
  1021. // urgent data is in a buffer we can keep. The buffer can be NULL, in
  1022. // which case we'll just look on the urgent pending queue for data.
  1023. //
  1024. // Input: RcvTCB - TCB to deliver on.
  1025. // RcvBuf - RcvBuffer for urgent data.
  1026. // Size - Number of bytes of urgent data to deliver.
  1027. //
  1028. // Returns: Nothing.
  1029. //
  1030. void
  1031. DeliverUrgent(TCB * RcvTCB, IPRcvBuf * RcvBuf, uint Size,
  1032. CTELockHandle * TCBHandle)
  1033. {
  1034. CTELockHandle AOHandle, AOTblHandle, ConnHandle;
  1035. TCPRcvReq *RcvReq, *PrevReq;
  1036. uint BytesTaken = 0;
  1037. IPRcvBuf *LastBuf;
  1038. #if !MILLEN
  1039. EventRcvBuffer *ERB;
  1040. #else // !MILLEN
  1041. EventRcvBuffer ERB;
  1042. #endif // MILLEN
  1043. #if TRACE_EVENT
  1044. PTDI_DATA_REQUEST_NOTIFY_ROUTINE CPCallBack;
  1045. WMIData WMIInfo;
  1046. #endif
  1047. PRcvEvent ExpRcv;
  1048. PVOID ExpRcvContext;
  1049. PVOID ConnContext;
  1050. TDI_STATUS Status;
  1051. CTEStructAssert(RcvTCB, tcb);
  1052. ASSERT(RcvTCB->tcb_refcnt != 0);
  1053. CheckRBList(RcvTCB->tcb_urgpending, RcvTCB->tcb_urgcnt);
  1054. // See if we have new data, or are processing old data.
  1055. if (RcvBuf != NULL) {
  1056. // We have new data. If the pending queue is not NULL, or we're already
  1057. // in this routine, just put the buffer on the end of the queue.
  1058. if (RcvTCB->tcb_urgpending != NULL || (RcvTCB->tcb_flags & IN_DELIV_URG)) {
  1059. IPRcvBuf *PrevRcvBuf;
  1060. // Put him on the end of the queue.
  1061. PrevRcvBuf = STRUCT_OF(IPRcvBuf, &RcvTCB->tcb_urgpending, ipr_next);
  1062. while (PrevRcvBuf->ipr_next != NULL)
  1063. PrevRcvBuf = PrevRcvBuf->ipr_next;
  1064. PrevRcvBuf->ipr_next = RcvBuf;
  1065. RcvTCB->tcb_urgcnt += Size;
  1066. return;
  1067. }
  1068. } else {
  1069. // The input buffer is NULL. See if we have existing data, or are in
  1070. // this routine. If we have no existing data or are in this routine
  1071. // just return.
  1072. if (RcvTCB->tcb_urgpending == NULL ||
  1073. (RcvTCB->tcb_flags & IN_DELIV_URG)) {
  1074. return;
  1075. } else {
  1076. RcvBuf = RcvTCB->tcb_urgpending;
  1077. Size = RcvTCB->tcb_urgcnt;
  1078. RcvTCB->tcb_urgpending = NULL;
  1079. RcvTCB->tcb_urgcnt = 0;
  1080. }
  1081. }
  1082. ASSERT(RcvBuf != NULL);
  1083. ASSERT(!(RcvTCB->tcb_flags & IN_DELIV_URG));
  1084. // We know we have data to deliver, and we have a pointer and a size.
  1085. // Go into a loop, trying to deliver the data. On each iteration, we'll
  1086. // try to find a buffer for the data. If we find one, we'll copy and
  1087. // complete it right away. Otherwise we'll try and indicate it. If we
  1088. // can't indicate it, we'll put it on the pending queue and leave.
  1089. RcvTCB->tcb_flags |= IN_DELIV_URG;
  1090. RcvTCB->tcb_slowcount++;
  1091. RcvTCB->tcb_fastchk |= TCP_FLAG_SLOW;
  1092. CheckTCBRcv(RcvTCB);
  1093. do {
  1094. CheckRBList(RcvTCB->tcb_urgpending, RcvTCB->tcb_urgcnt);
  1095. BytesTaken = 0;
  1096. // First check the expedited queue.
  1097. if ((RcvReq = RcvTCB->tcb_exprcv) != NULL)
  1098. RcvTCB->tcb_exprcv = RcvReq->trr_next;
  1099. else {
  1100. // Nothing in the expedited rcv. queue. Walk down the ordinary
  1101. // receive queue, looking for a buffer that we can steal.
  1102. PrevReq = STRUCT_OF(TCPRcvReq, &RcvTCB->tcb_rcvhead, trr_next);
  1103. RcvReq = PrevReq->trr_next;
  1104. while (RcvReq != NULL) {
  1105. CTEStructAssert(RcvReq, trr);
  1106. if (RcvReq->trr_flags & TDI_RECEIVE_EXPEDITED) {
  1107. // This is a candidate.
  1108. if (RcvReq->trr_amt == 0) {
  1109. ASSERT(RcvTCB->tcb_rcvhndlr == BufferData);
  1110. // And he has nothing currently in him. Pull him
  1111. // out of the queue.
  1112. if (RcvTCB->tcb_rcvtail == RcvReq) {
  1113. if (RcvTCB->tcb_rcvhead == RcvReq)
  1114. RcvTCB->tcb_rcvtail = NULL;
  1115. else
  1116. RcvTCB->tcb_rcvtail = PrevReq;
  1117. }
  1118. PrevReq->trr_next = RcvReq->trr_next;
  1119. if (RcvTCB->tcb_currcv == RcvReq) {
  1120. RcvTCB->tcb_currcv = RcvReq->trr_next;
  1121. if (RcvTCB->tcb_currcv == NULL) {
  1122. // We've taken the last receive from the list.
  1123. // Reset the rcvhndlr.
  1124. if (RcvTCB->tcb_rcvind != NULL &&
  1125. RcvTCB->tcb_indicated == 0)
  1126. RcvTCB->tcb_rcvhndlr = IndicateData;
  1127. else
  1128. RcvTCB->tcb_rcvhndlr = PendData;
  1129. }
  1130. }
  1131. break;
  1132. }
  1133. }
  1134. PrevReq = RcvReq;
  1135. RcvReq = PrevReq->trr_next;
  1136. }
  1137. }
  1138. // We've done our best to get a buffer. If we got one, copy into it
  1139. // now, and complete the request.
  1140. if (RcvReq != NULL) {
  1141. // Got a buffer.
  1142. CTEFreeLock(&RcvTCB->tcb_lock, *TCBHandle);
  1143. BytesTaken = CopyRcvToNdis(RcvBuf, RcvReq->trr_buffer, Size, 0, 0);
  1144. #if TRACE_EVENT
  1145. CPCallBack = TCPCPHandlerRoutine;
  1146. if (CPCallBack != NULL) {
  1147. ulong GroupType;
  1148. WMIInfo.wmi_destaddr = RcvTCB->tcb_daddr;
  1149. WMIInfo.wmi_destport = RcvTCB->tcb_dport;
  1150. WMIInfo.wmi_srcaddr = RcvTCB->tcb_saddr;
  1151. WMIInfo.wmi_srcport = RcvTCB->tcb_sport;
  1152. WMIInfo.wmi_size = BytesTaken;
  1153. WMIInfo.wmi_context = RcvTCB->tcb_cpcontext;
  1154. GroupType = EVENT_TRACE_GROUP_TCPIP + EVENT_TRACE_TYPE_RECEIVE;
  1155. (*CPCallBack) (GroupType, (PVOID) &WMIInfo, sizeof(WMIInfo), NULL);
  1156. }
  1157. #endif
  1158. (*RcvReq->trr_rtn) (RcvReq->trr_context, TDI_SUCCESS, BytesTaken);
  1159. FreeRcvReq(RcvReq);
  1160. CTEGetLock(&RcvTCB->tcb_lock, TCBHandle);
  1161. RcvTCB->tcb_urgind -= MIN(RcvTCB->tcb_urgind, BytesTaken);
  1162. } else {
  1163. // No posted buffer. If we can indicate, do so.
  1164. if (RcvTCB->tcb_urgind == 0) {
  1165. TCPConn *Conn;
  1166. // See if he has an expedited rcv handler.
  1167. ConnContext = RcvTCB->tcb_conncontext;
  1168. CTEFreeLock(&RcvTCB->tcb_lock, *TCBHandle);
  1169. CTEGetLock(&AddrObjTableLock.Lock, &AOTblHandle);
  1170. CTEGetLockAtDPC(&((ConnTable[CONN_BLOCKID(RcvTCB->tcb_connid)])->cb_lock), &ConnHandle);
  1171. #if DBG
  1172. ConnTable[CONN_BLOCKID(RcvTCB->tcb_connid)]->line = (uint) __LINE__;
  1173. ConnTable[CONN_BLOCKID(RcvTCB->tcb_connid)]->module = (uchar *) __FILE__;
  1174. #endif
  1175. //CTEGetLock(&ConnTableLock, &ConnHandle);
  1176. CTEGetLock(&RcvTCB->tcb_lock, TCBHandle);
  1177. if ((Conn = RcvTCB->tcb_conn) != NULL) {
  1178. CTEStructAssert(Conn, tc);
  1179. ASSERT(Conn->tc_tcb == RcvTCB);
  1180. CTEFreeLock(&RcvTCB->tcb_lock, *TCBHandle);
  1181. if (Conn->tc_ao != NULL) {
  1182. AddrObj *AO;
  1183. AO = Conn->tc_ao;
  1184. CTEGetLock(&AO->ao_lock, &AOHandle);
  1185. if (AO_VALID(AO) && (ExpRcv = AO->ao_exprcv) != NULL) {
  1186. ExpRcvContext = AO->ao_exprcvcontext;
  1187. CTEFreeLock(&AO->ao_lock, AOHandle);
  1188. // We're going to indicate.
  1189. RcvTCB->tcb_urgind = Size;
  1190. ASSERT(Conn->tc_ConnBlock == ConnTable[CONN_BLOCKID(RcvTCB->tcb_connid)]);
  1191. CTEFreeLockFromDPC(&(Conn->tc_ConnBlock->cb_lock), ConnHandle);
  1192. CTEFreeLock(&AddrObjTableLock.Lock, AOTblHandle);
  1193. Status = (*ExpRcv) (ExpRcvContext, ConnContext,
  1194. TDI_RECEIVE_COPY_LOOKAHEAD |
  1195. TDI_RECEIVE_ENTIRE_MESSAGE |
  1196. TDI_RECEIVE_EXPEDITED,
  1197. RcvBuf->ipr_size, Size, &BytesTaken,
  1198. RcvBuf->ipr_buffer, &ERB);
  1199. CTEGetLock(&RcvTCB->tcb_lock, TCBHandle);
  1200. // See what he did with it.
  1201. if (Status == TDI_MORE_PROCESSING) {
  1202. uint CopySize;
  1203. // He gave us a buffer.
  1204. if (BytesTaken == Size) {
  1205. // He gave us a buffer, but took all of
  1206. // it. We'll just return it to him.
  1207. CopySize = 0;
  1208. } else {
  1209. // We have some data to copy in.
  1210. RcvBuf = FreePartialRB(RcvBuf, BytesTaken);
  1211. #if !MILLEN
  1212. CopySize = CopyRcvToMdl(RcvBuf,
  1213. ERB->MdlAddress,
  1214. TCPGetMdlChainByteCount(ERB->MdlAddress),
  1215. 0, 0);
  1216. #else //!MILLEN
  1217. CopySize = CopyRcvToNdis(RcvBuf,
  1218. ERB.erb_buffer,
  1219. ERB.erb_size,
  1220. 0, 0);
  1221. #endif // MILLEN
  1222. }
  1223. BytesTaken += CopySize;
  1224. RcvTCB->tcb_urgind -= MIN(RcvTCB->tcb_urgind,
  1225. BytesTaken);
  1226. CTEFreeLock(&RcvTCB->tcb_lock, *TCBHandle);
  1227. #if !MILLEN
  1228. ERB->IoStatus.Status = TDI_SUCCESS;
  1229. ERB->IoStatus.Information = CopySize;
  1230. IoCompleteRequest(ERB, 2);
  1231. #else // !MILLEN
  1232. (*ERB.erb_rtn) (ERB.erb_context, TDI_SUCCESS,
  1233. CopySize);
  1234. #endif // MILLEN
  1235. CTEGetLock(&RcvTCB->tcb_lock, TCBHandle);
  1236. } else {
  1237. // No buffer to deal with.
  1238. if (Status == TDI_NOT_ACCEPTED)
  1239. BytesTaken = 0;
  1240. RcvTCB->tcb_urgind -= MIN(RcvTCB->tcb_urgind,
  1241. BytesTaken);
  1242. }
  1243. goto checksize;
  1244. } else // No rcv. handler.
  1245. CTEFreeLock(&AO->ao_lock, AOHandle);
  1246. }
  1247. // Conn->tc_ao == NULL.
  1248. ASSERT(Conn->tc_ConnBlock == ConnTable[CONN_BLOCKID(RcvTCB->tcb_connid)]);
  1249. CTEFreeLockFromDPC(&(Conn->tc_ConnBlock->cb_lock), ConnHandle);
  1250. //CTEFreeLock(&ConnTableLock, ConnHandle);
  1251. CTEFreeLock(&AddrObjTableLock.Lock, AOTblHandle);
  1252. CTEGetLock(&RcvTCB->tcb_lock, TCBHandle);
  1253. } else {
  1254. // RcvTCB has invalid index.
  1255. //CTEFreeLock(&ConnTableLock, *TCBHandle);
  1256. CTEFreeLockFromDPC(&((ConnTable[CONN_BLOCKID(RcvTCB->tcb_connid)])->cb_lock), ConnHandle);
  1257. CTEFreeLock(&AddrObjTableLock.Lock, AOTblHandle);
  1258. *TCBHandle = AOTblHandle;
  1259. }
  1260. }
  1261. // For whatever reason we couldn't indicate the data. At this point
  1262. // we hold the lock on the TCB. Push the buffer onto the pending
  1263. // queue and return.
  1264. CheckRBList(RcvTCB->tcb_urgpending, RcvTCB->tcb_urgcnt);
  1265. LastBuf = FindLastBuffer(RcvBuf);
  1266. LastBuf->ipr_next = RcvTCB->tcb_urgpending;
  1267. RcvTCB->tcb_urgpending = RcvBuf;
  1268. RcvTCB->tcb_urgcnt += Size;
  1269. break;
  1270. }
  1271. checksize:
  1272. // See how much we took. If we took it all, check the pending queue.
  1273. // At this point, we should hold the lock on the TCB.
  1274. if (Size == BytesTaken) {
  1275. // Took it all.
  1276. FreeRBChain(RcvBuf);
  1277. RcvBuf = RcvTCB->tcb_urgpending;
  1278. Size = RcvTCB->tcb_urgcnt;
  1279. } else {
  1280. // We didn't manage to take it all. Free what we did take,
  1281. // and then merge with the pending queue.
  1282. RcvBuf = FreePartialRB(RcvBuf, BytesTaken);
  1283. Size = Size - BytesTaken + RcvTCB->tcb_urgcnt;
  1284. if (RcvTCB->tcb_urgpending != NULL) {
  1285. // Find the end of the current RcvBuf chain, so we can
  1286. // merge.
  1287. LastBuf = FindLastBuffer(RcvBuf);
  1288. LastBuf->ipr_next = RcvTCB->tcb_urgpending;
  1289. }
  1290. }
  1291. RcvTCB->tcb_urgpending = NULL;
  1292. RcvTCB->tcb_urgcnt = 0;
  1293. } while (RcvBuf != NULL);
  1294. CheckRBList(RcvTCB->tcb_urgpending, RcvTCB->tcb_urgcnt);
  1295. RcvTCB->tcb_flags &= ~IN_DELIV_URG;
  1296. if (--(RcvTCB->tcb_slowcount) == 0) {
  1297. RcvTCB->tcb_fastchk &= ~TCP_FLAG_SLOW;
  1298. CheckTCBRcv(RcvTCB);
  1299. }
  1300. }
  1301. //* PushData - Push all data back to the client.
  1302. //
  1303. // Called when we've received a FIN and need to push data to the client.
  1304. //
  1305. // Input: PushTCB - TCB to be pushed.
  1306. //
  1307. // Returns: Nothing.
  1308. //
  1309. void
  1310. PushData(TCB * PushTCB)
  1311. {
  1312. TCPRcvReq *RcvReq;
  1313. CTEStructAssert(PushTCB, tcb);
  1314. RcvReq = PushTCB->tcb_rcvhead;
  1315. while (RcvReq != NULL) {
  1316. CTEStructAssert(RcvReq, trr);
  1317. RcvReq->trr_flags |= TRR_PUSHED;
  1318. RcvReq = RcvReq->trr_next;
  1319. }
  1320. RcvReq = PushTCB->tcb_exprcv;
  1321. while (RcvReq != NULL) {
  1322. CTEStructAssert(RcvReq, trr);
  1323. RcvReq->trr_flags |= TRR_PUSHED;
  1324. RcvReq = RcvReq->trr_next;
  1325. }
  1326. if (PushTCB->tcb_rcvhead != NULL || PushTCB->tcb_exprcv != NULL)
  1327. DelayAction(PushTCB, NEED_RCV_CMPLT);
  1328. }
  1329. //* SplitRcvBuf - Split an IPRcvBuf into three pieces.
  1330. //
  1331. // This function takes an input IPRcvBuf and splits it into three pieces.
  1332. // The first piece is the input buffer, which we just skip over. The second
  1333. // and third pieces are actually copied, even if we already own them, so
  1334. // that the may go to different places.
  1335. //
  1336. // Input: RcvBuf - RcvBuf chain to be split.
  1337. // Size - Total size in bytes of rcvbuf chain.
  1338. // Offset - Offset to skip over.
  1339. // SecondSize - Size in bytes of second piece.
  1340. // SecondBuf - Where to return second buffer pointer.
  1341. // ThirdBuf - Where to return third buffer pointer.
  1342. //
  1343. // Returns: Nothing. *SecondBuf and *ThirdBuf are set to NULL if we can't
  1344. // get memory for them.
  1345. //
  1346. void
  1347. SplitRcvBuf(IPRcvBuf * RcvBuf, uint Size, uint Offset, uint SecondSize,
  1348. IPRcvBuf ** SecondBuf, IPRcvBuf ** ThirdBuf)
  1349. {
  1350. IPRcvBuf *TempBuf;
  1351. uint ThirdSize;
  1352. ASSERT(Offset < Size);
  1353. ASSERT(((Offset + SecondSize) < Size) || (((Offset + SecondSize) == Size)
  1354. && ThirdBuf == NULL));
  1355. ASSERT(RcvBuf != NULL);
  1356. // RcvBuf points at the buffer to copy from, and Offset is the offset into
  1357. // this buffer to copy from.
  1358. if (SecondBuf != NULL) {
  1359. // We need to allocate memory for a second buffer.
  1360. TempBuf = AllocTcpIpr(SecondSize, 'BPCT');
  1361. if (TempBuf != NULL) {
  1362. CopyRcvToBuffer(TempBuf->ipr_buffer, RcvBuf, SecondSize, Offset);
  1363. *SecondBuf = TempBuf;
  1364. } else {
  1365. *SecondBuf = NULL;
  1366. if (ThirdBuf != NULL)
  1367. *ThirdBuf = NULL;
  1368. return;
  1369. }
  1370. }
  1371. if (ThirdBuf != NULL) {
  1372. // We need to allocate memory for a third buffer.
  1373. ThirdSize = Size - (Offset + SecondSize);
  1374. TempBuf = AllocTcpIpr(ThirdSize, 'BPCT');
  1375. if (TempBuf != NULL) {
  1376. CopyRcvToBuffer(TempBuf->ipr_buffer, RcvBuf, ThirdSize,
  1377. Offset + SecondSize);
  1378. *ThirdBuf = TempBuf;
  1379. } else
  1380. *ThirdBuf = NULL;
  1381. }
  1382. }
  1383. //* HandleUrgent - Handle urgent data.
  1384. //
  1385. // Called when an incoming segment has urgent data in it. We make sure there
  1386. // really is urgent data in the segment, and if there is we try to dispose
  1387. // of it either by putting it into a posted buffer or calling an exp. rcv.
  1388. // indication handler.
  1389. //
  1390. // This routine is called at DPC level, and with the TCP locked.
  1391. //
  1392. // Urgent data handling is a little complicated. Each TCB has the starting
  1393. // and ending sequence numbers of the 'current' (last received) bit of urgent
  1394. // data. It is possible that the start of the current urgent data might be
  1395. // greater than tcb_rcvnext, if urgent data came in, we handled it, and then
  1396. // couldn't take the preceding normal data. The urgent valid flag is cleared
  1397. // when the next byte of data the user would read (rcvnext - pendingcnt) is
  1398. // greater than the end of urgent data - we do this so that we can correctly
  1399. // support SIOCATMARK. We always seperate urgent data out of the data stream.
  1400. // If the urgent valid field is set when we get into this routing we have
  1401. // to play a couple of games. If the incoming segment starts in front of the
  1402. // current urgent data, we truncate it before the urgent data, and put any
  1403. // data after the urgent data on the reassemble queue. These gyrations are
  1404. // done to avoid delivering the same urgent data twice. If the urgent valid
  1405. // field in the TCB is set and the segment starts after the current urgent
  1406. // data the new urgent information will replace the current urgent information.
  1407. //
  1408. // Input: RcvTCB - TCB to recv the data on.
  1409. // RcvInfo - RcvInfo structure for the incoming segment.
  1410. // RcvBuf - Pointer to IPRcvBuf train containing the
  1411. // incoming segment.
  1412. // Size - Pointer to size in bytes of data in the segment.
  1413. //
  1414. // Returns: Nothing.
  1415. //
  1416. void
  1417. HandleUrgent(TCB * RcvTCB, TCPRcvInfo * RcvInfo, IPRcvBuf * RcvBuf, uint * Size)
  1418. {
  1419. uint BytesInFront, BytesInBack; // Bytes in front of and in
  1420. // back of the urgent data.
  1421. uint UrgSize; // Size in bytes of urgent data.
  1422. SeqNum UrgStart, UrgEnd;
  1423. IPRcvBuf *EndBuf, *UrgBuf;
  1424. TCPRcvInfo NewRcvInfo;
  1425. CTELockHandle TCBHandle;
  1426. CTEStructAssert(RcvTCB, tcb);
  1427. ASSERT(RcvTCB->tcb_refcnt != 0);
  1428. ASSERT(RcvInfo->tri_flags & TCP_FLAG_URG);
  1429. ASSERT(SEQ_EQ(RcvInfo->tri_seq, RcvTCB->tcb_rcvnext));
  1430. // First, validate the urgent pointer.
  1431. if (RcvTCB->tcb_flags & BSD_URGENT) {
  1432. // We're using BSD style urgent data. We assume that the urgent
  1433. // data is one byte long, and that the urgent pointer points one
  1434. // after the urgent data instead of at the last byte of urgent data.
  1435. // See if the urgent data is in this segment.
  1436. if (RcvInfo->tri_urgent == 0 || RcvInfo->tri_urgent > *Size) {
  1437. // Not in this segment. Clear the urgent flag and return.
  1438. RcvInfo->tri_flags &= ~TCP_FLAG_URG;
  1439. return;
  1440. }
  1441. UrgSize = 1;
  1442. BytesInFront = RcvInfo->tri_urgent - 1;
  1443. } else {
  1444. // This is not BSD style urgent. We assume that the urgent data
  1445. // starts at the front of the segment and the last byte is pointed
  1446. // to by the urgent data pointer.
  1447. BytesInFront = 0;
  1448. UrgSize = MIN(RcvInfo->tri_urgent + 1, *Size);
  1449. }
  1450. BytesInBack = *Size - BytesInFront - UrgSize;
  1451. // UrgStart and UrgEnd are the first and last sequence numbers of the
  1452. // urgent data in this segment.
  1453. UrgStart = RcvInfo->tri_seq + BytesInFront;
  1454. UrgEnd = UrgStart + UrgSize - 1;
  1455. if (!(RcvTCB->tcb_flags & URG_INLINE)) {
  1456. EndBuf = NULL;
  1457. // Now see if this overlaps with any urgent data we've already seen.
  1458. if (RcvTCB->tcb_flags & URG_VALID) {
  1459. // We have some urgent data still around. See if we've advanced
  1460. // rcvnext beyond the urgent data. If we have, this is new urgent
  1461. // data, and we can go ahead and process it (although anyone doing
  1462. // an SIOCATMARK socket command might get confused). If we haven't
  1463. // consumed the data in front of the existing urgent data yet, we'll
  1464. // truncate this seg. to that amount and push the rest onto the
  1465. // reassembly queue. Note that rcvnext should never fall between
  1466. // tcb_urgstart and tcb_urgend.
  1467. ASSERT(SEQ_LT(RcvTCB->tcb_rcvnext, RcvTCB->tcb_urgstart) ||
  1468. SEQ_GT(RcvTCB->tcb_rcvnext, RcvTCB->tcb_urgend));
  1469. if (SEQ_LT(RcvTCB->tcb_rcvnext, RcvTCB->tcb_urgstart)) {
  1470. // There appears to be some overlap in the data stream. Split
  1471. // the buffer up into pieces that come before the current urgent
  1472. // data and after the current urgent data, putting the latter
  1473. // on the reassembly queue.
  1474. UrgSize = RcvTCB->tcb_urgend - RcvTCB->tcb_urgstart + 1;
  1475. BytesInFront = MIN(RcvTCB->tcb_urgstart - RcvTCB->tcb_rcvnext,
  1476. (int)*Size);
  1477. if (SEQ_GT(RcvTCB->tcb_rcvnext + *Size, RcvTCB->tcb_urgend)) {
  1478. // We have data after this piece of urgent data.
  1479. BytesInBack = RcvTCB->tcb_rcvnext + *Size -
  1480. RcvTCB->tcb_urgend;
  1481. } else
  1482. BytesInBack = 0;
  1483. SplitRcvBuf(RcvBuf, *Size, BytesInFront, UrgSize, NULL,
  1484. (BytesInBack ? &EndBuf : NULL));
  1485. if (EndBuf != NULL) {
  1486. NewRcvInfo.tri_seq = RcvTCB->tcb_urgend + 1;
  1487. NewRcvInfo.tri_flags = RcvInfo->tri_flags;
  1488. NewRcvInfo.tri_urgent = UrgEnd - NewRcvInfo.tri_seq;
  1489. if (RcvTCB->tcb_flags & BSD_URGENT)
  1490. NewRcvInfo.tri_urgent++;
  1491. NewRcvInfo.tri_ack = RcvInfo->tri_ack;
  1492. NewRcvInfo.tri_window = RcvInfo->tri_window;
  1493. if (!PutOnRAQ(RcvTCB, &NewRcvInfo, EndBuf, BytesInBack)){
  1494. FreeRBChain(EndBuf);
  1495. }
  1496. }
  1497. *Size = BytesInFront;
  1498. //iishack fix. Do not allow lookahead
  1499. //buffer size to be more than that is allocated!!
  1500. if (RcvBuf->ipr_size >= BytesInFront) {
  1501. RcvBuf->ipr_size = BytesInFront;
  1502. }
  1503. RcvInfo->tri_flags &= ~TCP_FLAG_URG;
  1504. return;
  1505. }
  1506. }
  1507. // We have urgent data we can process now. Split it into its component
  1508. // parts, the first part, the urgent data, and the stuff after the
  1509. // urgent data.
  1510. SplitRcvBuf(RcvBuf, *Size, BytesInFront, UrgSize, &UrgBuf,
  1511. (BytesInBack ? &EndBuf : NULL));
  1512. // If we managed to split out the end stuff, put it on the queue now.
  1513. if (EndBuf != NULL) {
  1514. NewRcvInfo.tri_seq = RcvInfo->tri_seq + BytesInFront + UrgSize;
  1515. NewRcvInfo.tri_flags = RcvInfo->tri_flags & ~TCP_FLAG_URG;
  1516. NewRcvInfo.tri_ack = RcvInfo->tri_ack;
  1517. NewRcvInfo.tri_window = RcvInfo->tri_window;
  1518. PutOnRAQ(RcvTCB, &NewRcvInfo, EndBuf, BytesInBack);
  1519. }
  1520. if (UrgBuf != NULL) {
  1521. // We succesfully split the urgent data out.
  1522. if (!(RcvTCB->tcb_flags & URG_VALID)) {
  1523. RcvTCB->tcb_flags |= URG_VALID;
  1524. RcvTCB->tcb_slowcount++;
  1525. RcvTCB->tcb_fastchk |= TCP_FLAG_SLOW;
  1526. CheckTCBRcv(RcvTCB);
  1527. }
  1528. RcvTCB->tcb_urgstart = UrgStart;
  1529. RcvTCB->tcb_urgend = UrgEnd;
  1530. TCBHandle = DISPATCH_LEVEL;
  1531. DeliverUrgent(RcvTCB, UrgBuf, UrgSize, &TCBHandle);
  1532. }
  1533. *Size = BytesInFront;
  1534. if (RcvBuf->ipr_size >= BytesInFront) {
  1535. RcvBuf->ipr_size = BytesInFront;
  1536. }
  1537. } else {
  1538. // Urgent data is to be processed inline. We just need to remember
  1539. // where it is and treat it as normal data. If there's already urgent
  1540. // data, we remember the latest urgent data.
  1541. RcvInfo->tri_flags &= ~TCP_FLAG_URG;
  1542. if (RcvTCB->tcb_flags & URG_VALID) {
  1543. // There is urgent data. See if this stuff comes after the existing
  1544. // urgent data.
  1545. if (SEQ_LTE(UrgEnd, RcvTCB->tcb_urgend)) {
  1546. // The existing urgent data completely overlaps this stuff,
  1547. // so ignore this.
  1548. return;
  1549. }
  1550. } else {
  1551. RcvTCB->tcb_flags |= URG_VALID;
  1552. RcvTCB->tcb_slowcount++;
  1553. RcvTCB->tcb_fastchk |= TCP_FLAG_SLOW;
  1554. CheckTCBRcv(RcvTCB);
  1555. }
  1556. RcvTCB->tcb_urgstart = UrgStart;
  1557. RcvTCB->tcb_urgend = UrgEnd;
  1558. }
  1559. return;
  1560. }
  1561. //* TdiReceive - Process a receive request.
  1562. //
  1563. // This is the main TDI receive request handler. We validate the connection
  1564. // and make sure that we have a TCB in the proper state, then we try to
  1565. // allocate a receive request structure. If that succeeds, we'll look and
  1566. // see what's happening on the TCB - if there's pending data, we'll put it
  1567. // in the buffer. Otherwise we'll just queue the receive for later.
  1568. //
  1569. // Input: Request - TDI_REQUEST structure for this request.
  1570. // Flags - Pointer to flags word.
  1571. // RcvLength - Pointer to length in bytes of receive buffer.
  1572. // Buffer - Pointer to buffer to take data.
  1573. //
  1574. // Returns: TDI_STATUS of request.
  1575. //
  1576. TDI_STATUS
  1577. TdiReceive(PTDI_REQUEST Request, ushort * Flags, uint * RcvLength,
  1578. PNDIS_BUFFER Buffer)
  1579. {
  1580. TCPConn *Conn;
  1581. TCB *RcvTCB;
  1582. TCPRcvReq *RcvReq;
  1583. CTELockHandle ConnTableHandle, TCBHandle;
  1584. TDI_STATUS Error;
  1585. ushort UFlags;
  1586. Conn = GetConnFromConnID(PtrToUlong(Request->Handle.ConnectionContext), &ConnTableHandle);
  1587. if (Conn != NULL) {
  1588. CTEStructAssert(Conn, tc);
  1589. RcvTCB = Conn->tc_tcb;
  1590. if (RcvTCB != NULL) {
  1591. CTEStructAssert(RcvTCB, tcb);
  1592. CTEGetLock(&RcvTCB->tcb_lock, &TCBHandle);
  1593. CTEFreeLock(&(Conn->tc_ConnBlock->cb_lock), TCBHandle);
  1594. UFlags = *Flags;
  1595. if ((DATA_RCV_STATE(RcvTCB->tcb_state) ||
  1596. (RcvTCB->tcb_pendingcnt != 0 && (UFlags & TDI_RECEIVE_NORMAL)) ||
  1597. (RcvTCB->tcb_urgcnt != 0 && (UFlags & TDI_RECEIVE_EXPEDITED)) ||
  1598. (RcvTCB->tcb_indicated && (RcvTCB->tcb_state == TCB_CLOSE_WAIT)))
  1599. && !CLOSING(RcvTCB)) {
  1600. // We have a TCB, and it's valid. Get a receive request now.
  1601. CheckRBList(RcvTCB->tcb_pendhead, RcvTCB->tcb_pendingcnt);
  1602. RcvReq = GetRcvReq();
  1603. if (RcvReq != NULL) {
  1604. RcvReq->trr_rtn = Request->RequestNotifyObject;
  1605. RcvReq->trr_context = Request->RequestContext;
  1606. RcvReq->trr_buffer = Buffer;
  1607. RcvReq->trr_size = *RcvLength;
  1608. RcvReq->trr_uflags = Flags;
  1609. RcvReq->trr_offset = 0;
  1610. RcvReq->trr_amt = 0;
  1611. RcvReq->trr_flags = (uint) UFlags;
  1612. if ((UFlags & (TDI_RECEIVE_NORMAL | TDI_RECEIVE_EXPEDITED))
  1613. != TDI_RECEIVE_EXPEDITED) {
  1614. // This is not an expedited only receive. Put him
  1615. // on the normal receive queue.
  1616. RcvReq->trr_next = NULL;
  1617. if (RcvTCB->tcb_rcvhead == NULL) {
  1618. // The receive queue is empty. Put him on the front.
  1619. RcvTCB->tcb_rcvhead = RcvReq;
  1620. RcvTCB->tcb_rcvtail = RcvReq;
  1621. } else {
  1622. RcvTCB->tcb_rcvtail->trr_next = RcvReq;
  1623. RcvTCB->tcb_rcvtail = RcvReq;
  1624. }
  1625. //if this rcv is for zero length complete this
  1626. // and indicate pending data again, if any
  1627. if (RcvReq->trr_size == 0) {
  1628. REFERENCE_TCB(RcvTCB);
  1629. RcvReq->trr_flags |= TRR_PUSHED;
  1630. CTEFreeLock(&RcvTCB->tcb_lock,ConnTableHandle);
  1631. CompleteRcvs(RcvTCB);
  1632. CTEGetLock(&RcvTCB->tcb_lock,&ConnTableHandle);
  1633. DerefTCB(RcvTCB, ConnTableHandle);
  1634. return TDI_PENDING;
  1635. }
  1636. // If this recv. can't hold urgent data or there isn't
  1637. // any pending urgent data continue processing.
  1638. if (!(UFlags & TDI_RECEIVE_EXPEDITED) ||
  1639. RcvTCB->tcb_urgcnt == 0) {
  1640. // If tcb_currcv is NULL, there is no currently
  1641. // active receive. In this case, check to see if
  1642. // there is pending data and that we are not
  1643. // currently in a receive indication handler. If
  1644. // both of these are true then deal with the
  1645. // pending data.
  1646. if (RcvTCB->tcb_currcv == NULL) {
  1647. RcvTCB->tcb_currcv = RcvReq;
  1648. // No currently active receive.
  1649. if (!(RcvTCB->tcb_flags & IN_RCV_IND)) {
  1650. // Not in a rcv. indication.
  1651. RcvTCB->tcb_rcvhndlr = BufferData;
  1652. if (RcvTCB->tcb_pendhead == NULL) {
  1653. CTEFreeLock(&RcvTCB->tcb_lock,
  1654. ConnTableHandle);
  1655. return TDI_PENDING;
  1656. } else {
  1657. IPRcvBuf *PendBuffer;
  1658. uint PendSize;
  1659. uint OldRcvWin;
  1660. // We have pending data to deal with.
  1661. PendBuffer = RcvTCB->tcb_pendhead;
  1662. PendSize = RcvTCB->tcb_pendingcnt;
  1663. RcvTCB->tcb_pendhead = NULL;
  1664. RcvTCB->tcb_pendingcnt = 0;
  1665. REFERENCE_TCB(RcvTCB);
  1666. // We assume that BufferData holds
  1667. // the lock (does not yield) during
  1668. // this call. If this changes for some
  1669. // reason, we'll have to fix the code
  1670. // below that does the window update
  1671. // check. See the comments in the
  1672. // BufferData() routine for more info.
  1673. (void)BufferData(RcvTCB, TCP_FLAG_PUSH,
  1674. PendBuffer, PendSize);
  1675. CheckTCBRcv(RcvTCB);
  1676. // Now we need to see if the window
  1677. // has changed. If it has, send an
  1678. // ACK.
  1679. OldRcvWin = RcvTCB->tcb_rcvwin;
  1680. if (OldRcvWin != RcvWin(RcvTCB)) {
  1681. // The window has changed, so send
  1682. // an ACK.
  1683. DelayAction(RcvTCB, NEED_ACK);
  1684. }
  1685. DerefTCB(RcvTCB, ConnTableHandle);
  1686. ProcessTCBDelayQ();
  1687. return TDI_PENDING;
  1688. }
  1689. }
  1690. // In a receive indication. The recv. request
  1691. // is now on the queue, so just fall through
  1692. // to the return.
  1693. }
  1694. // A rcv. is currently active. No need to do
  1695. // anything else.
  1696. CTEFreeLock(&RcvTCB->tcb_lock, ConnTableHandle);
  1697. return TDI_PENDING;
  1698. } else {
  1699. // This buffer can hold urgent data and we have
  1700. // some pending. Deliver it now.
  1701. REFERENCE_TCB(RcvTCB);
  1702. DeliverUrgent(RcvTCB, NULL, 0, &ConnTableHandle);
  1703. DerefTCB(RcvTCB, ConnTableHandle);
  1704. return TDI_PENDING;
  1705. }
  1706. } else {
  1707. TCPRcvReq *Temp;
  1708. // This is an expedited only receive. Just put him
  1709. // on the end of the expedited receive queue.
  1710. Temp = STRUCT_OF(TCPRcvReq, &RcvTCB->tcb_exprcv,
  1711. trr_next);
  1712. while (Temp->trr_next != NULL)
  1713. Temp = Temp->trr_next;
  1714. RcvReq->trr_next = NULL;
  1715. Temp->trr_next = RcvReq;
  1716. if (RcvTCB->tcb_urgpending != NULL) {
  1717. REFERENCE_TCB(RcvTCB);
  1718. DeliverUrgent(RcvTCB, NULL, 0, &ConnTableHandle);
  1719. DerefTCB(RcvTCB, ConnTableHandle);
  1720. return TDI_PENDING;
  1721. } else
  1722. Error = TDI_PENDING;
  1723. }
  1724. } else {
  1725. // Couldn't get a rcv. req.
  1726. Error = TDI_NO_RESOURCES;
  1727. }
  1728. } else {
  1729. // The TCB is in an invalid state.
  1730. Error = TDI_INVALID_STATE;
  1731. }
  1732. CTEFreeLock(&RcvTCB->tcb_lock, ConnTableHandle);
  1733. return Error;
  1734. } else { // No TCB for connection.
  1735. CTEFreeLock(&((Conn->tc_ConnBlock)->cb_lock), ConnTableHandle);
  1736. Error = TDI_INVALID_STATE;
  1737. }
  1738. } else // No connection.
  1739. Error = TDI_INVALID_CONNECTION;
  1740. //CTEFreeLock(&ConnTableLock, ConnTableHandle);
  1741. return Error;
  1742. }