526a64b12f7ce449f1cf5f4b48d03381a381d649
[reactos.git] / reactos / sdk / lib / drivers / ip / transport / tcp / tcp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: transport/tcp/tcp.c
5 * PURPOSE: Transmission Control Protocol
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Art Yerkes (arty@users.sf.net)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * arty 12/21/2004 Added accept
11 */
12
13 #include "precomp.h"
14
15 LONG TCP_IPIdentification = 0;
16 static BOOLEAN TCPInitialized = FALSE;
17 PORT_SET TCPPorts;
18
19 #include "lwip/pbuf.h"
20 #include "lwip/ip.h"
21 #include "lwip/init.h"
22 #include "lwip/arch.h"
23
24 #include "rosip.h"
25
26 NPAGED_LOOKASIDE_LIST TdiBucketLookasideList;
27
28 VOID NTAPI
29 DisconnectTimeoutDpc(PKDPC Dpc,
30 PVOID DeferredContext,
31 PVOID SystemArgument1,
32 PVOID SystemArgument2)
33 {
34 PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)DeferredContext;
35 PLIST_ENTRY Entry;
36 PTDI_BUCKET Bucket;
37
38 LockObjectAtDpcLevel(Connection);
39
40 /* We timed out waiting for pending sends so force it to shutdown */
41 TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
42
43 while (!IsListEmpty(&Connection->SendRequest))
44 {
45 Entry = RemoveHeadList(&Connection->SendRequest);
46
47 Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
48
49 Bucket->Information = 0;
50 Bucket->Status = STATUS_FILE_CLOSED;
51
52 CompleteBucket(Connection, Bucket, FALSE);
53 }
54
55 while (!IsListEmpty(&Connection->ShutdownRequest))
56 {
57 Entry = RemoveHeadList( &Connection->ShutdownRequest );
58
59 Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
60
61 Bucket->Status = STATUS_TIMEOUT;
62 Bucket->Information = 0;
63
64 CompleteBucket(Connection, Bucket, FALSE);
65 }
66
67 UnlockObjectFromDpcLevel(Connection);
68
69 DereferenceObject(Connection);
70 }
71
72 VOID ConnectionFree(PVOID Object)
73 {
74 PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)Object;
75 KIRQL OldIrql;
76
77 TI_DbgPrint(DEBUG_TCP, ("Freeing TCP Endpoint\n"));
78
79 TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
80 RemoveEntryList(&Connection->ListEntry);
81 TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
82
83 ExFreePoolWithTag( Connection, CONN_ENDPT_TAG );
84 }
85
86 PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext )
87 {
88 PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)
89 ExAllocatePoolWithTag(NonPagedPool, sizeof(CONNECTION_ENDPOINT), CONN_ENDPT_TAG);
90
91 if (!Connection)
92 return Connection;
93
94 TI_DbgPrint(DEBUG_CPOINT, ("Connection point file object allocated at (0x%X).\n", Connection));
95
96 RtlZeroMemory(Connection, sizeof(CONNECTION_ENDPOINT));
97
98 /* Initialize spin lock that protects the connection endpoint file object */
99 KeInitializeSpinLock(&Connection->Lock);
100 InitializeListHead(&Connection->ConnectRequest);
101 InitializeListHead(&Connection->ListenRequest);
102 InitializeListHead(&Connection->ReceiveRequest);
103 InitializeListHead(&Connection->SendRequest);
104 InitializeListHead(&Connection->ShutdownRequest);
105 InitializeListHead(&Connection->PacketQueue);
106
107 /* Initialize disconnect timer */
108 KeInitializeTimer(&Connection->DisconnectTimer);
109 KeInitializeDpc(&Connection->DisconnectDpc, DisconnectTimeoutDpc, Connection);
110
111 /* Save client context pointer */
112 Connection->ClientContext = ClientContext;
113
114 Connection->RefCount = 1;
115 Connection->Free = ConnectionFree;
116
117 /* Add connection endpoint to global list */
118 ExInterlockedInsertTailList(&ConnectionEndpointListHead,
119 &Connection->ListEntry,
120 &ConnectionEndpointListLock);
121
122 return Connection;
123 }
124
125 NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
126 UINT Family, UINT Type, UINT Proto )
127 {
128 NTSTATUS Status;
129 KIRQL OldIrql;
130
131 LockObject(Connection, &OldIrql);
132
133 TI_DbgPrint(DEBUG_TCP,("[IP, TCPSocket] Called: Connection %x, Family %d, Type %d, "
134 "Proto %d, sizeof(CONNECTION_ENDPOINT) = %d\n",
135 Connection, Family, Type, Proto, sizeof(CONNECTION_ENDPOINT)));
136
137 Connection->SocketContext = LibTCPSocket(Connection);
138 if (Connection->SocketContext)
139 Status = STATUS_SUCCESS;
140 else
141 Status = STATUS_INSUFFICIENT_RESOURCES;
142
143 UnlockObject(Connection, OldIrql);
144
145 TI_DbgPrint(DEBUG_TCP,("[IP, TCPSocket] Leaving. Status = 0x%x\n", Status));
146
147 return Status;
148 }
149
150 NTSTATUS TCPClose( PCONNECTION_ENDPOINT Connection )
151 {
152 KIRQL OldIrql;
153
154 LockObject(Connection, &OldIrql);
155
156 FlushAllQueues(Connection, STATUS_CANCELLED);
157
158 LibTCPClose(Connection, FALSE, TRUE);
159
160 UnlockObject(Connection, OldIrql);
161
162 DereferenceObject(Connection);
163
164 return STATUS_SUCCESS;
165 }
166
167 VOID TCPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
168 /*
169 * FUNCTION: Receives and queues TCP data
170 * ARGUMENTS:
171 * IPPacket = Pointer to an IP packet that was received
172 * NOTES:
173 * This is the low level interface for receiving TCP data
174 */
175 {
176 TI_DbgPrint(DEBUG_TCP,("Sending packet %d (%d) to lwIP\n",
177 IPPacket->TotalSize,
178 IPPacket->HeaderSize));
179
180 LibIPInsertPacket(Interface->TCPContext, IPPacket->Header, IPPacket->TotalSize);
181 }
182
183 NTSTATUS TCPStartup(VOID)
184 /*
185 * FUNCTION: Initializes the TCP subsystem
186 * RETURNS:
187 * Status of operation
188 */
189 {
190 NTSTATUS Status;
191
192 Status = PortsStartup( &TCPPorts, 1, 0xfffe );
193 if (!NT_SUCCESS(Status))
194 {
195 return Status;
196 }
197
198 ExInitializeNPagedLookasideList(&TdiBucketLookasideList,
199 NULL,
200 NULL,
201 0,
202 sizeof(TDI_BUCKET),
203 TDI_BUCKET_TAG,
204 0);
205
206 /* Initialize our IP library */
207 LibIPInitialize();
208
209 /* Register this protocol with IP layer */
210 IPRegisterProtocol(IPPROTO_TCP, TCPReceive);
211
212 TCPInitialized = TRUE;
213
214 return STATUS_SUCCESS;
215 }
216
217
218 NTSTATUS TCPShutdown(VOID)
219 /*
220 * FUNCTION: Shuts down the TCP subsystem
221 * RETURNS:
222 * Status of operation
223 */
224 {
225 if (!TCPInitialized)
226 return STATUS_SUCCESS;
227
228 ExDeleteNPagedLookasideList(&TdiBucketLookasideList);
229
230 LibIPShutdown();
231
232 /* Deregister this protocol with IP layer */
233 IPRegisterProtocol(IPPROTO_TCP, NULL);
234
235 TCPInitialized = FALSE;
236
237 PortsShutdown( &TCPPorts );
238
239 return STATUS_SUCCESS;
240 }
241
242 NTSTATUS TCPTranslateError(const err_t err)
243 {
244 NTSTATUS Status;
245
246 switch (err)
247 {
248 case ERR_OK: Status = STATUS_SUCCESS; return Status; //0
249 case ERR_MEM: Status = STATUS_INSUFFICIENT_RESOURCES; break; //-1
250 case ERR_BUF: Status = STATUS_BUFFER_TOO_SMALL; break; //-2
251 case ERR_TIMEOUT: Status = STATUS_TIMEOUT; break; // -3
252 case ERR_RTE: Status = STATUS_NETWORK_UNREACHABLE; break; //-4
253 case ERR_INPROGRESS: Status = STATUS_PENDING; return Status; //-5
254 case ERR_VAL: Status = STATUS_INVALID_PARAMETER; break; //-6
255 case ERR_WOULDBLOCK: Status = STATUS_CANT_WAIT; break; //-7
256 case ERR_USE: Status = STATUS_ADDRESS_ALREADY_EXISTS; break; //-8
257 case ERR_ISCONN: Status = STATUS_UNSUCCESSFUL; break; //-9 (FIXME)
258 case ERR_ABRT: Status = STATUS_LOCAL_DISCONNECT; break; //-10
259 case ERR_RST: Status = STATUS_REMOTE_DISCONNECT; break; //-11
260 case ERR_CLSD: Status = STATUS_FILE_CLOSED; break; //-12
261 case ERR_CONN: Status = STATUS_INVALID_CONNECTION; break; //-13
262 case ERR_ARG: Status = STATUS_INVALID_PARAMETER; break; //-14
263 case ERR_IF: Status = STATUS_UNEXPECTED_NETWORK_ERROR; break; //-15
264 default:
265 DbgPrint("Invalid error value: %d\n", err);
266 ASSERT(FALSE);
267 Status = STATUS_UNSUCCESSFUL;
268 break;
269 }
270
271 DbgPrint("TCP operation failed: 0x%x (%d)\n", Status, err);
272
273 return Status;
274 }
275
276 NTSTATUS TCPConnect
277 ( PCONNECTION_ENDPOINT Connection,
278 PTDI_CONNECTION_INFORMATION ConnInfo,
279 PTDI_CONNECTION_INFORMATION ReturnInfo,
280 PTCP_COMPLETION_ROUTINE Complete,
281 PVOID Context )
282 {
283 NTSTATUS Status;
284 struct ip_addr bindaddr, connaddr;
285 IP_ADDRESS RemoteAddress;
286 USHORT RemotePort;
287 TA_IP_ADDRESS LocalAddress;
288 PTDI_BUCKET Bucket;
289 PNEIGHBOR_CACHE_ENTRY NCE;
290 KIRQL OldIrql;
291
292 TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Called\n"));
293
294 Status = AddrBuildAddress
295 ((PTRANSPORT_ADDRESS)ConnInfo->RemoteAddress,
296 &RemoteAddress,
297 &RemotePort);
298
299 if (!NT_SUCCESS(Status))
300 {
301 TI_DbgPrint(DEBUG_TCP, ("Could not AddrBuildAddress in TCPConnect\n"));
302 return Status;
303 }
304
305 /* Freed in TCPSocketState */
306 TI_DbgPrint(DEBUG_TCP,
307 ("Connecting to address %x:%x\n",
308 RemoteAddress.Address.IPv4Address,
309 RemotePort));
310
311 LockObject(Connection, &OldIrql);
312
313 if (!Connection->AddressFile)
314 {
315 UnlockObject(Connection, OldIrql);
316 return STATUS_INVALID_PARAMETER;
317 }
318
319 if (AddrIsUnspecified(&Connection->AddressFile->Address))
320 {
321 if (!(NCE = RouteGetRouteToDestination(&RemoteAddress)))
322 {
323 UnlockObject(Connection, OldIrql);
324 return STATUS_NETWORK_UNREACHABLE;
325 }
326
327 bindaddr.addr = NCE->Interface->Unicast.Address.IPv4Address;
328 }
329 else
330 {
331 bindaddr.addr = Connection->AddressFile->Address.Address.IPv4Address;
332 }
333
334 Status = TCPTranslateError(LibTCPBind(Connection,
335 &bindaddr,
336 Connection->AddressFile->Port));
337
338 if (NT_SUCCESS(Status))
339 {
340 /* Check if we had an unspecified address */
341 if (Connection->AddressFile->Address.Address.IPv4Address != bindaddr.addr)
342 {
343 /* We did, so we need to copy back the address */
344 Connection->AddressFile->Address.Address.IPv4Address = bindaddr.addr;
345 }
346 /* Check if we had an unspecified port */
347 if (!Connection->AddressFile->Port)
348 {
349 /* We did, so we need to copy back the port */
350 Status = TCPGetSockAddress(Connection, (PTRANSPORT_ADDRESS)&LocalAddress, FALSE);
351 if (NT_SUCCESS(Status))
352 {
353 /* Allocate the port in the port bitmap */
354 Connection->AddressFile->Port = TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port);
355
356 /* This should never fail */
357 ASSERT(Connection->AddressFile->Port != 0xFFFF);
358 }
359 }
360
361 if (NT_SUCCESS(Status))
362 {
363 connaddr.addr = RemoteAddress.Address.IPv4Address;
364
365 Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
366 if (!Bucket)
367 {
368 UnlockObject(Connection, OldIrql);
369 return STATUS_NO_MEMORY;
370 }
371
372 Bucket->Request.RequestNotifyObject = (PVOID)Complete;
373 Bucket->Request.RequestContext = Context;
374
375 InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
376
377 Status = TCPTranslateError(LibTCPConnect(Connection,
378 &connaddr,
379 RemotePort));
380 }
381 }
382
383 UnlockObject(Connection, OldIrql);
384
385 TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Leaving. Status = 0x%x\n", Status));
386
387 return Status;
388 }
389
390 NTSTATUS TCPDisconnect
391 ( PCONNECTION_ENDPOINT Connection,
392 UINT Flags,
393 PLARGE_INTEGER Timeout,
394 PTDI_CONNECTION_INFORMATION ConnInfo,
395 PTDI_CONNECTION_INFORMATION ReturnInfo,
396 PTCP_COMPLETION_ROUTINE Complete,
397 PVOID Context )
398 {
399 NTSTATUS Status = STATUS_INVALID_PARAMETER;
400 PTDI_BUCKET Bucket;
401 KIRQL OldIrql;
402 LARGE_INTEGER ActualTimeout;
403
404 TI_DbgPrint(DEBUG_TCP,("[IP, TCPDisconnect] Called\n"));
405
406 LockObject(Connection, &OldIrql);
407
408 if (Connection->SocketContext)
409 {
410 if (Flags & TDI_DISCONNECT_RELEASE)
411 {
412 if (IsListEmpty(&Connection->SendRequest))
413 {
414 Status = TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
415 }
416 else if (Timeout && Timeout->QuadPart == 0)
417 {
418 FlushSendQueue(Connection, STATUS_FILE_CLOSED, FALSE);
419 TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
420 Status = STATUS_TIMEOUT;
421 }
422 else
423 {
424 /* Use the timeout specified or 1 second if none was specified */
425 if (Timeout)
426 {
427 ActualTimeout = *Timeout;
428 }
429 else
430 {
431 ActualTimeout.QuadPart = -1000000;
432 }
433
434 /* We couldn't complete the request now because we need to wait for outstanding I/O */
435 Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
436 if (!Bucket)
437 {
438 UnlockObject(Connection, OldIrql);
439 return STATUS_NO_MEMORY;
440 }
441
442 Bucket->Request.RequestNotifyObject = (PVOID)Complete;
443 Bucket->Request.RequestContext = Context;
444
445 InsertTailList(&Connection->ShutdownRequest, &Bucket->Entry);
446
447 ReferenceObject(Connection);
448 if (KeCancelTimer(&Connection->DisconnectTimer))
449 {
450 DereferenceObject(Connection);
451 }
452 KeSetTimer(&Connection->DisconnectTimer, ActualTimeout, &Connection->DisconnectDpc);
453
454 Status = STATUS_PENDING;
455 }
456 }
457
458 if ((Flags & TDI_DISCONNECT_ABORT) || !Flags)
459 {
460 FlushReceiveQueue(Connection, STATUS_FILE_CLOSED, FALSE);
461 FlushSendQueue(Connection, STATUS_FILE_CLOSED, FALSE);
462 FlushShutdownQueue(Connection, STATUS_FILE_CLOSED, FALSE);
463 Status = TCPTranslateError(LibTCPShutdown(Connection, 1, 1));
464 }
465 }
466 else
467 {
468 /* We already got closed by the other side so just return success */
469 Status = STATUS_SUCCESS;
470 }
471
472 UnlockObject(Connection, OldIrql);
473
474 TI_DbgPrint(DEBUG_TCP,("[IP, TCPDisconnect] Leaving. Status = 0x%x\n", Status));
475
476 return Status;
477 }
478
479 NTSTATUS TCPReceiveData
480 ( PCONNECTION_ENDPOINT Connection,
481 PNDIS_BUFFER Buffer,
482 ULONG ReceiveLength,
483 PULONG BytesReceived,
484 ULONG ReceiveFlags,
485 PTCP_COMPLETION_ROUTINE Complete,
486 PVOID Context )
487 {
488 PTDI_BUCKET Bucket;
489 PUCHAR DataBuffer;
490 UINT DataLen, Received;
491 NTSTATUS Status;
492
493 TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Called for %d bytes (on socket %x)\n",
494 ReceiveLength, Connection->SocketContext));
495
496 NdisQueryBuffer(Buffer, &DataBuffer, &DataLen);
497
498 Status = LibTCPGetDataFromConnectionQueue(Connection, DataBuffer, DataLen, &Received);
499
500 if (Status == STATUS_PENDING)
501 {
502 Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
503 if (!Bucket)
504 {
505 TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Failed to allocate bucket\n"));
506
507 return STATUS_NO_MEMORY;
508 }
509
510 Bucket->Request.RequestNotifyObject = Complete;
511 Bucket->Request.RequestContext = Context;
512
513 ExInterlockedInsertTailList( &Connection->ReceiveRequest, &Bucket->Entry, &Connection->Lock );
514 TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Queued read irp\n"));
515
516 TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Leaving. Status = STATUS_PENDING\n"));
517
518 (*BytesReceived) = 0;
519 }
520 else
521 {
522 (*BytesReceived) = Received;
523 }
524
525 return Status;
526 }
527
528 NTSTATUS TCPSendData
529 ( PCONNECTION_ENDPOINT Connection,
530 PCHAR BufferData,
531 ULONG SendLength,
532 PULONG BytesSent,
533 ULONG Flags,
534 PTCP_COMPLETION_ROUTINE Complete,
535 PVOID Context )
536 {
537 NTSTATUS Status;
538 PTDI_BUCKET Bucket;
539 KIRQL OldIrql;
540
541 LockObject(Connection, &OldIrql);
542
543 TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Called for %d bytes (on socket %x)\n",
544 SendLength, Connection->SocketContext));
545
546 TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Connection = %x\n", Connection));
547 TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Connection->SocketContext = %x\n",
548 Connection->SocketContext));
549
550 Status = TCPTranslateError(LibTCPSend(Connection,
551 BufferData,
552 SendLength,
553 BytesSent,
554 FALSE));
555
556 TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Send: %x, %d\n", Status, SendLength));
557
558 /* Keep this request around ... there was no data yet */
559 if (Status == STATUS_PENDING)
560 {
561 /* Freed in TCPSocketState */
562 Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
563 if (!Bucket)
564 {
565 UnlockObject(Connection, OldIrql);
566 TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Failed to allocate bucket\n"));
567 return STATUS_NO_MEMORY;
568 }
569
570 Bucket->Request.RequestNotifyObject = Complete;
571 Bucket->Request.RequestContext = Context;
572
573 InsertTailList( &Connection->SendRequest, &Bucket->Entry );
574 TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Queued write irp\n"));
575 }
576
577 UnlockObject(Connection, OldIrql);
578
579 TI_DbgPrint(DEBUG_TCP, ("[IP, TCPSendData] Leaving. Status = %x\n", Status));
580
581 return Status;
582 }
583
584 UINT TCPAllocatePort(const UINT HintPort)
585 {
586 if (HintPort)
587 {
588 if (AllocatePort(&TCPPorts, HintPort))
589 return HintPort;
590 else
591 {
592 TI_DbgPrint(MID_TRACE,("We got a hint port but couldn't allocate it\n"));
593 return (UINT)-1;
594 }
595 }
596 else
597 return AllocatePortFromRange( &TCPPorts, 1024, 5000 );
598 }
599
600 VOID TCPFreePort(const UINT Port)
601 {
602 DeallocatePort(&TCPPorts, Port);
603 }
604
605 NTSTATUS TCPGetSockAddress
606 ( PCONNECTION_ENDPOINT Connection,
607 PTRANSPORT_ADDRESS Address,
608 BOOLEAN GetRemote )
609 {
610 PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address;
611 struct ip_addr ipaddr;
612 NTSTATUS Status;
613 KIRQL OldIrql;
614
615 AddressIP->TAAddressCount = 1;
616 AddressIP->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
617 AddressIP->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
618
619 LockObject(Connection, &OldIrql);
620
621 if (GetRemote)
622 {
623 Status = TCPTranslateError(LibTCPGetPeerName(Connection->SocketContext,
624 &ipaddr,
625 &AddressIP->Address[0].Address[0].sin_port));
626 }
627 else
628 {
629 Status = TCPTranslateError(LibTCPGetHostName(Connection->SocketContext,
630 &ipaddr,
631 &AddressIP->Address[0].Address[0].sin_port));
632 }
633
634 UnlockObject(Connection, OldIrql);
635
636 AddressIP->Address[0].Address[0].in_addr = ipaddr.addr;
637
638 RtlZeroMemory(&AddressIP->Address[0].Address[0].sin_zero,
639 sizeof(AddressIP->Address[0].Address[0].sin_zero));
640
641 return Status;
642 }
643
644 BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp )
645 {
646 PLIST_ENTRY Entry;
647 PLIST_ENTRY ListHead[5];
648 KIRQL OldIrql;
649 PTDI_BUCKET Bucket;
650 UINT i = 0;
651 BOOLEAN Found = FALSE;
652
653 ListHead[0] = &Endpoint->SendRequest;
654 ListHead[1] = &Endpoint->ReceiveRequest;
655 ListHead[2] = &Endpoint->ConnectRequest;
656 ListHead[3] = &Endpoint->ListenRequest;
657 ListHead[4] = &Endpoint->ShutdownRequest;
658
659 LockObject(Endpoint, &OldIrql);
660
661 for( i = 0; i < 5; i++ )
662 {
663 for( Entry = ListHead[i]->Flink;
664 Entry != ListHead[i];
665 Entry = Entry->Flink )
666 {
667 Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
668 if( Bucket->Request.RequestContext == Irp )
669 {
670 RemoveEntryList( &Bucket->Entry );
671 ExFreeToNPagedLookasideList(&TdiBucketLookasideList, Bucket);
672 Found = TRUE;
673 break;
674 }
675 }
676 }
677
678 UnlockObject(Endpoint, OldIrql);
679
680 return Found;
681 }
682
683 NTSTATUS
684 TCPSetNoDelay(
685 PCONNECTION_ENDPOINT Connection,
686 BOOLEAN Set)
687 {
688 if (!Connection)
689 return STATUS_UNSUCCESSFUL;
690
691 if (Connection->SocketContext == NULL)
692 return STATUS_UNSUCCESSFUL;
693
694 LibTCPSetNoDelay(Connection->SocketContext, Set);
695 return STATUS_SUCCESS;
696 }
697
698
699 /* EOF */