ReactOS 0.4.15-dev-7670-g69b08be
event.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: transport/tcp/event.c
5 * PURPOSE: Transmission Control Protocol
6 * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
7 */
8
9#include "precomp.h"
10
11#include "lwip/err.h"
12#include "lwip/sys.h"
13#include "lwip/pbuf.h"
14#include "lwip/tcp.h"
15#include "lwip/api.h"
16
17#include <lwip_glue/lwip_glue.h>
18
20
21static
22VOID
24{
27
29
30 Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
31
33
34 ExFreeToNPagedLookasideList(&TdiBucketLookasideList, Bucket);
35}
36
37VOID
38CompleteBucket(PCONNECTION_ENDPOINT Connection, PTDI_BUCKET Bucket, const BOOLEAN Synchronous)
39{
40 ReferenceObject(Connection);
41 Bucket->AssociatedEndpoint = Connection;
42 if (Synchronous)
43 {
45 }
46 else
47 {
49 }
50}
51
52VOID
54{
55 PTDI_BUCKET Bucket;
57
59
60 while (!IsListEmpty(&Connection->ReceiveRequest))
61 {
62 Entry = RemoveHeadList(&Connection->ReceiveRequest);
63
65
66 Bucket->Information = 0;
67 Bucket->Status = Status;
68
69 CompleteBucket(Connection, Bucket, FALSE);
70 }
71}
72
73VOID
75{
76 PTDI_BUCKET Bucket;
78
80
81 while (!IsListEmpty(&Connection->SendRequest))
82 {
83 Entry = RemoveHeadList(&Connection->SendRequest);
84
86
87 Bucket->Information = 0;
88 Bucket->Status = Status;
89
90 CompleteBucket(Connection, Bucket, FALSE);
91 }
92}
93
94VOID
96{
97 PTDI_BUCKET Bucket;
99
100 ASSERT_TCPIP_OBJECT_LOCKED(Connection);
101
102 while (!IsListEmpty(&Connection->ShutdownRequest))
103 {
104 Entry = RemoveHeadList(&Connection->ShutdownRequest);
105
107
108 Bucket->Information = 0;
109 Bucket->Status = Status;
110
111 CompleteBucket(Connection, Bucket, FALSE);
112 }
113}
114
115VOID
117{
118 PTDI_BUCKET Bucket;
120
121 ASSERT_TCPIP_OBJECT_LOCKED(Connection);
122
123 while (!IsListEmpty(&Connection->ConnectRequest))
124 {
125 Entry = RemoveHeadList(&Connection->ConnectRequest);
127
128 Bucket->Status = Status;
129 Bucket->Information = 0;
130
131 CompleteBucket(Connection, Bucket, FALSE);
132 }
133}
134
135VOID
137{
138 PTDI_BUCKET Bucket;
140
141 ASSERT_TCPIP_OBJECT_LOCKED(Connection);
142
143 while (!IsListEmpty(&Connection->ListenRequest))
144 {
145 Entry = RemoveHeadList(&Connection->ListenRequest);
147
148 Bucket->Status = Status;
149 Bucket->Information = 0;
150
152 CompleteBucket(Connection, Bucket, FALSE);
153 }
154}
155
156VOID
158{
159 // flush receive queue
160 FlushReceiveQueue(Connection, Status);
161
162 /* We completed the reads successfully but we need to return failure now */
163 if (Status == STATUS_SUCCESS)
164 {
166 }
167
168 // flush listen queue
169 FlushListenQueue(Connection, Status);
170
171 // flush send queue
172 FlushSendQueue(Connection, Status);
173
174 // flush connect queue
175 FlushConnectQueue(Connection, Status);
176
177 // flush shutdown queue
178 FlushShutdownQueue(Connection, Status);
179}
180
181VOID
183{
184 PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg, LastConnection;
186
187 ASSERT(Connection->SocketContext == NULL);
188 ASSERT(Connection->AddressFile);
189 ASSERT(err != ERR_OK);
190
191 LockObject(Connection);
192
193 /* Complete all outstanding requests now */
194 FlushAllQueues(Connection, Status);
195
196 LockObject(Connection->AddressFile);
197
198 /* Unlink this connection from the address file */
199 if (Connection->AddressFile->Connection == Connection)
200 {
201 Connection->AddressFile->Connection = Connection->Next;
202 DereferenceObject(Connection);
203 }
204 else if (Connection->AddressFile->Listener == Connection)
205 {
206 Connection->AddressFile->Listener = NULL;
207 DereferenceObject(Connection);
208 }
209 else
210 {
211 LastConnection = Connection->AddressFile->Connection;
212 while (LastConnection->Next != Connection && LastConnection->Next != NULL)
213 LastConnection = LastConnection->Next;
214 if (LastConnection->Next == Connection)
215 {
216 LastConnection->Next = Connection->Next;
217 DereferenceObject(Connection);
218 }
219 }
220
221 UnlockObject(Connection->AddressFile);
222
223 /* Remove the address file from this connection */
224 DereferenceObject(Connection->AddressFile);
225 Connection->AddressFile = NULL;
226
227 UnlockObject(Connection);
228}
229
230VOID
232{
234 PTDI_BUCKET Bucket;
236 PIRP Irp;
238
239 LockObject(Connection);
240
241 while (!IsListEmpty(&Connection->ListenRequest))
242 {
244
245 Entry = RemoveHeadList(&Connection->ListenRequest);
246
248
249 Irp = Bucket->Request.RequestContext;
251
252 TI_DbgPrint(DEBUG_TCP,("[IP, TCPAcceptEventHandler] Getting the socket\n"));
253
256
257 TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n", Status));
258
259 Bucket->Status = Status;
260 Bucket->Information = 0;
261
262 if (Status == STATUS_SUCCESS)
263 {
265
266 /* sanity assert...this should never be in anything else but a CLOSED state */
267 ASSERT( ((PTCP_PCB)Bucket->AssociatedEndpoint->SocketContext)->state == CLOSED );
268
269 /* free socket context created in FileOpenConnection, as we're using a new one */
271
272 /* free previously created socket context (we don't use it, we use newpcb) */
273 Bucket->AssociatedEndpoint->SocketContext = newpcb;
274
276
277 LibTCPAccept(newpcb, (PTCP_PCB)Connection->SocketContext, Bucket->AssociatedEndpoint);
278 }
279
281
282 CompleteBucket(Connection, Bucket, FALSE);
283
284 if (Status == STATUS_SUCCESS)
285 {
286 break;
287 }
288 }
289
290 UnlockObject(Connection);
291}
292
293VOID
295{
297 PTDI_BUCKET Bucket;
299 PIRP Irp;
301 PMDL Mdl;
302 ULONG BytesSent;
303
304 ReferenceObject(Connection);
305 LockObject(Connection);
306
307 while (!IsListEmpty(&Connection->SendRequest))
308 {
309 UINT SendLen = 0;
310 PVOID SendBuffer = 0;
311
312 Entry = RemoveHeadList(&Connection->SendRequest);
313
314 UnlockObject(Connection);
315
317
318 Irp = Bucket->Request.RequestContext;
319 Mdl = Irp->MdlAddress;
320
322 ("Getting the user buffer from %x\n", Mdl));
323
324 NdisQueryBuffer( Mdl, &SendBuffer, &SendLen );
325
327 ("Writing %d bytes to %x\n", SendLen, SendBuffer));
328
329 TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
331 (DEBUG_TCP,
332 ("Connection->SocketContext: %x\n",
333 Connection->SocketContext));
334
336 SendBuffer,
337 SendLen, &BytesSent, TRUE));
338
339 TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", BytesSent));
340
341 if( Status == STATUS_PENDING )
342 {
343 LockObject(Connection);
344 InsertHeadList(&Connection->SendRequest, &Bucket->Entry);
345 break;
346 }
347 else
348 {
350 ("Completing Send request: %x %x\n",
351 Bucket->Request, Status));
352
353 Bucket->Status = Status;
354 Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? BytesSent : 0;
355
356 CompleteBucket(Connection, Bucket, FALSE);
357 }
358
359 LockObject(Connection);
360 }
361
362 // If we completed all outstanding send requests then finish all pending shutdown requests,
363 // cancel the timer and dereference the connection
364 if (IsListEmpty(&Connection->SendRequest))
365 {
367
368 if (KeCancelTimer(&Connection->DisconnectTimer))
369 {
370 DereferenceObject(Connection);
371 }
372 }
373
374 UnlockObject(Connection);
375
376 DereferenceObject(Connection);
377}
378
379VOID
381{
383 PTDI_BUCKET Bucket;
385 PIRP Irp;
386 PMDL Mdl;
388 UINT RecvLen;
389 PUCHAR RecvBuffer;
391
392 LockObject(Connection);
393
394 while(!IsListEmpty(&Connection->ReceiveRequest))
395 {
396 Entry = RemoveHeadList(&Connection->ReceiveRequest);
398
399 Irp = Bucket->Request.RequestContext;
400 Mdl = Irp->MdlAddress;
401
402 NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
403
404 Status = LibTCPGetDataFromConnectionQueue(Connection, RecvBuffer, RecvLen, &Received);
405 if (Status == STATUS_PENDING)
406 {
407 InsertHeadList(&Connection->ReceiveRequest, &Bucket->Entry);
408 break;
409 }
410
411 Bucket->Status = Status;
412 Bucket->Information = Received;
413
414 CompleteBucket(Connection, Bucket, FALSE);
415 }
416 UnlockObject(Connection);
417}
418
419VOID
421{
423 PTDI_BUCKET Bucket;
425
426 LockObject(Connection);
427
428 while (!IsListEmpty(&Connection->ConnectRequest))
429 {
430 Entry = RemoveHeadList(&Connection->ConnectRequest);
431
433
434 Bucket->Status = TCPTranslateError(err);
435 Bucket->Information = 0;
436
437 CompleteBucket(Connection, Bucket, FALSE);
438 }
439
440 UnlockObject(Connection);
441}
unsigned char BOOLEAN
UINT Received
Definition: arping.c:40
LONG NTSTATUS
Definition: precomp.h:26
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define DEBUG_TCP
Definition: debug.h:28
#define TI_DbgPrint(_t_, _x_)
Definition: debug.h:45
unsigned short u16_t
Definition: cc.h:24
VOID FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
Definition: event.c:116
static VOID BucketCompletionWorker(PVOID Context)
Definition: event.c:23
VOID TCPSendEventHandler(void *arg, const u16_t space)
Definition: event.c:294
VOID FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
Definition: event.c:95
VOID FlushListenQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
Definition: event.c:136
VOID CompleteBucket(PCONNECTION_ENDPOINT Connection, PTDI_BUCKET Bucket, const BOOLEAN Synchronous)
Definition: event.c:38
VOID FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
Definition: event.c:53
VOID TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
Definition: event.c:231
NPAGED_LOOKASIDE_LIST TdiBucketLookasideList
Definition: tcp.c:26
VOID TCPRecvEventHandler(void *arg)
Definition: event.c:380
VOID TCPConnectEventHandler(void *arg, const err_t err)
Definition: event.c:420
VOID TCPFinEventHandler(void *arg, const err_t err)
Definition: event.c:182
VOID FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status)
Definition: event.c:157
VOID FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
Definition: event.c:74
#define ERR_OK
Definition: err.h:52
s8_t err_t
Definition: err.h:47
#define InsertHeadList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
pRequest Complete(RequestStatus)
Status
Definition: gdiplustypes.h:25
NTSTATUS TCPCheckPeerForAccept(PVOID Context, PTDI_REQUEST_KERNEL Request)
Definition: accept.c:17
NTSTATUS TCPTranslateError(const INT8 err)
Definition: tcp.c:267
VOID(* PTCP_COMPLETION_ROUTINE)(PVOID Context, NTSTATUS Status, ULONG Count)
Definition: tcp.h:11
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
struct tcp_pcb * PTCP_PCB
Definition: lwip_glue.h:15
NTSTATUS LibTCPGetDataFromConnectionQueue(PCONNECTION_ENDPOINT Connection, PUCHAR RecvBuffer, UINT RecvLen, UINT *Received)
Definition: tcp.c:100
err_t LibTCPClose(PCONNECTION_ENDPOINT Connection, const int safe, const int callback)
Definition: tcp.c:798
void LibTCPAccept(PTCP_PCB pcb, struct tcp_pcb *listen_pcb, void *arg)
Definition: tcp.c:830
err_t LibTCPSend(PCONNECTION_ENDPOINT Connection, void *const dataptr, const u16_t len, u32_t *sent, const int safe)
Definition: tcp.c:557
#define ASSERT(a)
Definition: mode.c:44
unsigned int UINT
Definition: ndis.h:50
#define NdisQueryBuffer(_Buffer, _VirtualAddress, _Length)
Definition: ndis.h:3029
#define STATUS_FILE_CLOSED
Definition: ntstatus.h:532
#define STATUS_PENDING
Definition: ntstatus.h:82
#define err(...)
#define STATUS_SUCCESS
Definition: shellext.h:65
base of all file and directory entries
Definition: entries.h:83
struct _CONNECTION_ENDPOINT * Connection
Definition: titypes.h:131
struct _CONNECTION_ENDPOINT * Listener
Definition: titypes.h:133
LIST_ENTRY ConnectRequest
Definition: titypes.h:250
LIST_ENTRY SendRequest
Definition: titypes.h:253
LIST_ENTRY ListenRequest
Definition: titypes.h:251
LIST_ENTRY ShutdownRequest
Definition: titypes.h:254
PADDRESS_FILE AddressFile
Definition: titypes.h:247
struct _CONNECTION_ENDPOINT * Next
Definition: titypes.h:269
LIST_ENTRY ReceiveRequest
Definition: titypes.h:252
KTIMER DisconnectTimer
Definition: titypes.h:259
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
Definition: typedefs.h:120
LIST_ENTRY Entry
Definition: titypes.h:230
NTSTATUS Status
Definition: titypes.h:233
ULONG Information
Definition: titypes.h:234
TDI_REQUEST Request
Definition: titypes.h:232
struct _CONNECTION_ENDPOINT * AssociatedEndpoint
Definition: titypes.h:231
PVOID RequestContext
Definition: tdi.h:55
PVOID RequestNotifyObject
Definition: tdi.h:54
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
#define UnlockObject(Object)
Definition: titypes.h:44
#define ReferenceObject(Object)
Definition: titypes.h:14
#define ASSERT_TCPIP_OBJECT_LOCKED(Object)
Definition: titypes.h:51
#define LockObject(Object)
Definition: titypes.h:34
#define DereferenceObject(Object)
Definition: titypes.h:24
struct _CONNECTION_ENDPOINT * PCONNECTION_ENDPOINT
struct _TDI_BUCKET * PTDI_BUCKET
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
BOOLEAN ChewCreate(VOID(*Worker)(PVOID), PVOID WorkerContext)
Definition: workqueue.c:61
struct LOOKASIDE_ALIGN _NPAGED_LOOKASIDE_LIST NPAGED_LOOKASIDE_LIST
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793