ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

event.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS TCP/IP protocol driver
00004  * FILE:        transport/tcp/event.c
00005  * PURPOSE:     Transmission Control Protocol
00006  * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
00007  */
00008 
00009 #include "precomp.h"
00010 
00011 #include "lwip/err.h"
00012 #include "lwip/sys.h"
00013 #include "lwip/pbuf.h"
00014 #include "lwip/tcp.h"
00015 #include "lwip/api.h"
00016 
00017 #include "rosip.h"
00018 
00019 static const char * const tcp_state_str[] = {
00020   "CLOSED",      
00021   "LISTEN",      
00022   "SYN_SENT",    
00023   "SYN_RCVD",    
00024   "ESTABLISHED", 
00025   "FIN_WAIT_1",  
00026   "FIN_WAIT_2",  
00027   "CLOSE_WAIT",  
00028   "CLOSING",     
00029   "LAST_ACK",    
00030   "TIME_WAIT"   
00031 };
00032 
00033 extern NPAGED_LOOKASIDE_LIST TdiBucketLookasideList;
00034 
00035 static
00036 VOID
00037 BucketCompletionWorker(PVOID Context)
00038 {
00039     PTDI_BUCKET Bucket = (PTDI_BUCKET)Context;
00040     PTCP_COMPLETION_ROUTINE Complete;
00041     
00042     Complete = (PTCP_COMPLETION_ROUTINE)Bucket->Request.RequestNotifyObject;
00043     
00044     Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
00045     
00046     DereferenceObject(Bucket->AssociatedEndpoint);
00047 
00048     ExFreeToNPagedLookasideList(&TdiBucketLookasideList, Bucket);
00049 }
00050 
00051 VOID
00052 CompleteBucket(PCONNECTION_ENDPOINT Connection, PTDI_BUCKET Bucket, const BOOLEAN Synchronous)
00053 {
00054     ReferenceObject(Connection);
00055     Bucket->AssociatedEndpoint = Connection;
00056     if (Synchronous)
00057     {
00058         BucketCompletionWorker(Bucket);
00059     }
00060     else
00061     {
00062         ChewCreate(BucketCompletionWorker, Bucket);
00063     }
00064 }
00065 
00066 VOID
00067 FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
00068 {
00069     PTDI_BUCKET Bucket;
00070     PLIST_ENTRY Entry;
00071     
00072     ReferenceObject(Connection);
00073     
00074     if (interlocked)
00075     {
00076         while ((Entry = ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, &Connection->Lock)))
00077         {
00078             Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
00079         
00080             TI_DbgPrint(DEBUG_TCP,
00081                         ("Completing Receive request: %x %x\n",
00082                          Bucket->Request, Status));
00083         
00084             Bucket->Status = Status;
00085             Bucket->Information = 0;
00086         
00087             CompleteBucket(Connection, Bucket, FALSE);
00088         }
00089     }
00090     else
00091     {
00092         while (!IsListEmpty(&Connection->ReceiveRequest))
00093         {
00094             Entry = RemoveHeadList(&Connection->ReceiveRequest);
00095             
00096             Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
00097             
00098             Bucket->Information = 0;
00099             Bucket->Status = Status;
00100             
00101             CompleteBucket(Connection, Bucket, FALSE);
00102         }
00103     }
00104 
00105     DereferenceObject(Connection);
00106 }
00107 
00108 VOID
00109 FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
00110 {
00111     PTDI_BUCKET Bucket;
00112     PLIST_ENTRY Entry;
00113     
00114     ReferenceObject(Connection);
00115 
00116     if (interlocked)
00117     {
00118         while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, &Connection->Lock)))
00119         {
00120             Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );    
00121         
00122             TI_DbgPrint(DEBUG_TCP,
00123                         ("Completing Send request: %x %x\n",
00124                          Bucket->Request, Status));
00125         
00126             Bucket->Status = Status;
00127             Bucket->Information = 0;
00128         
00129             CompleteBucket(Connection, Bucket, FALSE);
00130         }
00131     }
00132     else
00133     {
00134         while (!IsListEmpty(&Connection->SendRequest))
00135         {
00136             Entry = RemoveHeadList(&Connection->SendRequest);
00137             
00138             Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
00139             
00140             Bucket->Information = 0;
00141             Bucket->Status = Status;
00142             
00143             CompleteBucket(Connection, Bucket, FALSE);
00144         }
00145     }
00146 
00147     DereferenceObject(Connection);
00148 }
00149 
00150 VOID
00151 FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const BOOLEAN interlocked)
00152 {
00153     PTDI_BUCKET Bucket;
00154     PLIST_ENTRY Entry;
00155     
00156     ReferenceObject(Connection);
00157 
00158     if (interlocked)
00159     {
00160         while ((Entry = ExInterlockedRemoveHeadList(&Connection->ShutdownRequest, &Connection->Lock)))
00161         {   
00162             Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
00163         
00164             Bucket->Status = Status;
00165             Bucket->Information = 0;
00166         
00167             CompleteBucket(Connection, Bucket, FALSE);
00168         }
00169     }
00170     else
00171     {
00172         while (!IsListEmpty(&Connection->ShutdownRequest))
00173         {
00174             Entry = RemoveHeadList(&Connection->ShutdownRequest);
00175             
00176             Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
00177             
00178             Bucket->Information = 0;
00179             Bucket->Status = Status;
00180             
00181             CompleteBucket(Connection, Bucket, FALSE);
00182         }
00183     }
00184 
00185     DereferenceObject(Connection);
00186 }
00187 
00188 VOID
00189 FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
00190 {
00191     PTDI_BUCKET Bucket;
00192     PLIST_ENTRY Entry;
00193     
00194     ReferenceObject(Connection);
00195 
00196     while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock)))
00197     {
00198         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
00199         
00200         Bucket->Status = Status;
00201         Bucket->Information = 0;
00202         
00203         CompleteBucket(Connection, Bucket, FALSE);
00204     }
00205 
00206     DereferenceObject(Connection);
00207 }
00208 
00209 VOID
00210 FlushListenQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
00211 {
00212     PTDI_BUCKET Bucket;
00213     PLIST_ENTRY Entry;
00214     
00215     ReferenceObject(Connection);
00216 
00217     while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock)))
00218     {
00219         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
00220         
00221         Bucket->Status = Status;
00222         Bucket->Information = 0;
00223         
00224         DereferenceObject(Bucket->AssociatedEndpoint);
00225         CompleteBucket(Connection, Bucket, FALSE);
00226     }
00227 
00228     DereferenceObject(Connection);
00229 }
00230 
00231 VOID
00232 FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status)
00233 {    
00234     ReferenceObject(Connection);
00235     
00236     // flush receive queue
00237     FlushReceiveQueue(Connection, Status, TRUE);
00238 
00239     /* We completed the reads successfully but we need to return failure now */
00240     if (Status == STATUS_SUCCESS)
00241     {
00242         Status = STATUS_FILE_CLOSED;
00243     }
00244     
00245     // flush listen queue
00246     FlushListenQueue(Connection, Status);
00247     
00248     // flush send queue
00249     FlushSendQueue(Connection, Status, TRUE);
00250     
00251     // flush connect queue
00252     FlushConnectQueue(Connection, Status);
00253 
00254     // flush shutdown queue
00255     FlushShutdownQueue(Connection, Status, TRUE);
00256     
00257     DereferenceObject(Connection);
00258 }
00259 
00260 VOID
00261 TCPFinEventHandler(void *arg, const err_t err)
00262 {
00263     PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg, LastConnection;
00264     const NTSTATUS Status = TCPTranslateError(err);
00265     KIRQL OldIrql;
00266 
00267     ASSERT(Connection->AddressFile);
00268 
00269     /* Check if this was a partial socket closure */
00270     if (err == ERR_OK && Connection->SocketContext)
00271     {
00272         /* Just flush the receive queue and get out of here */
00273         FlushReceiveQueue(Connection, STATUS_SUCCESS, TRUE);
00274     }
00275     else
00276     {
00277         /* First off all, remove the PCB pointer */
00278         Connection->SocketContext = NULL;
00279 
00280         /* Complete all outstanding requests now */
00281         FlushAllQueues(Connection, Status);
00282 
00283         LockObject(Connection, &OldIrql);
00284 
00285         LockObjectAtDpcLevel(Connection->AddressFile);
00286 
00287         /* Unlink this connection from the address file */
00288         if (Connection->AddressFile->Connection == Connection)
00289         {
00290             Connection->AddressFile->Connection = Connection->Next;
00291             DereferenceObject(Connection);
00292         }
00293         else if (Connection->AddressFile->Listener == Connection)
00294         {
00295             Connection->AddressFile->Listener = NULL;
00296             DereferenceObject(Connection);
00297         }
00298         else
00299         {
00300             LastConnection = Connection->AddressFile->Connection;
00301             while (LastConnection->Next != Connection && LastConnection->Next != NULL)
00302                 LastConnection = LastConnection->Next;
00303             if (LastConnection->Next == Connection)
00304             {
00305                 LastConnection->Next = Connection->Next;
00306                 DereferenceObject(Connection);
00307             }
00308         }
00309 
00310         UnlockObjectFromDpcLevel(Connection->AddressFile);
00311 
00312         /* Remove the address file from this connection */
00313         DereferenceObject(Connection->AddressFile);
00314         Connection->AddressFile = NULL;
00315 
00316         UnlockObject(Connection, OldIrql);
00317     }
00318 }
00319     
00320 VOID
00321 TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
00322 {
00323     PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
00324     PTDI_BUCKET Bucket;
00325     PLIST_ENTRY Entry;
00326     PIRP Irp;
00327     NTSTATUS Status;
00328     KIRQL OldIrql;
00329         
00330     ReferenceObject(Connection);
00331     
00332     while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock)))
00333     {
00334         PIO_STACK_LOCATION IrpSp;
00335         
00336         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
00337         
00338         Irp = Bucket->Request.RequestContext;
00339         IrpSp = IoGetCurrentIrpStackLocation( Irp );
00340         
00341         TI_DbgPrint(DEBUG_TCP,("[IP, TCPAcceptEventHandler] Getting the socket\n"));
00342         
00343         Status = TCPCheckPeerForAccept(newpcb,
00344                                        (PTDI_REQUEST_KERNEL)&IrpSp->Parameters);
00345         
00346         TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n", Status));
00347         
00348         Bucket->Status = Status;
00349         Bucket->Information = 0;
00350                 
00351         if (Status == STATUS_SUCCESS)
00352         {
00353             LockObject(Bucket->AssociatedEndpoint, &OldIrql);
00354 
00355             /* sanity assert...this should never be in anything else but a CLOSED state */
00356             ASSERT( ((PTCP_PCB)Bucket->AssociatedEndpoint->SocketContext)->state == CLOSED );
00357             
00358             /*  free socket context created in FileOpenConnection, as we're using a new one */
00359             LibTCPClose(Bucket->AssociatedEndpoint, TRUE, FALSE);
00360 
00361             /* free previously created socket context (we don't use it, we use newpcb) */
00362             Bucket->AssociatedEndpoint->SocketContext = newpcb;
00363             
00364             LibTCPAccept(newpcb, (PTCP_PCB)Connection->SocketContext, Bucket->AssociatedEndpoint);
00365 
00366             UnlockObject(Bucket->AssociatedEndpoint, OldIrql);
00367         }
00368         
00369         DereferenceObject(Bucket->AssociatedEndpoint);
00370         
00371         CompleteBucket(Connection, Bucket, FALSE);
00372     }
00373     
00374     DereferenceObject(Connection);
00375 }
00376 
00377 VOID
00378 TCPSendEventHandler(void *arg, u16_t space)
00379 {
00380     PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
00381     PTDI_BUCKET Bucket;
00382     PLIST_ENTRY Entry;
00383     PIRP Irp;
00384     NTSTATUS Status;
00385     PMDL Mdl;
00386     
00387     ReferenceObject(Connection);
00388 
00389     while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, &Connection->Lock)))
00390     {
00391         UINT SendLen = 0;
00392         PVOID SendBuffer = 0;
00393         
00394         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
00395         
00396         Irp = Bucket->Request.RequestContext;
00397         Mdl = Irp->MdlAddress;
00398         
00399         TI_DbgPrint(DEBUG_TCP,
00400                     ("Getting the user buffer from %x\n", Mdl));
00401         
00402         NdisQueryBuffer( Mdl, &SendBuffer, &SendLen );
00403         
00404         TI_DbgPrint(DEBUG_TCP,
00405                     ("Writing %d bytes to %x\n", SendLen, SendBuffer));
00406         
00407         TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
00408         TI_DbgPrint
00409         (DEBUG_TCP,
00410          ("Connection->SocketContext: %x\n",
00411           Connection->SocketContext));
00412         
00413         Status = TCPTranslateError(LibTCPSend(Connection,
00414                                               SendBuffer,
00415                                               SendLen, TRUE));
00416         
00417         TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", SendLen));
00418         
00419         if( Status == STATUS_PENDING )
00420         {
00421             ExInterlockedInsertHeadList(&Connection->SendRequest,
00422                                         &Bucket->Entry,
00423                                         &Connection->Lock);
00424             break;
00425         }
00426         else
00427         {
00428             TI_DbgPrint(DEBUG_TCP,
00429                         ("Completing Send request: %x %x\n",
00430                          Bucket->Request, Status));
00431             
00432             Bucket->Status = Status;
00433             Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? SendLen : 0;
00434                         
00435             CompleteBucket(Connection, Bucket, FALSE);
00436         }
00437     }
00438 
00439     //  If we completed all outstanding send requests then finish all pending shutdown requests,
00440     //  cancel the timer and dereference the connection
00441     if (IsListEmpty(&Connection->SendRequest))
00442     {
00443         FlushShutdownQueue(Connection, STATUS_SUCCESS, FALSE);
00444 
00445         if (KeCancelTimer(&Connection->DisconnectTimer))
00446         {
00447             DereferenceObject(Connection);
00448         }
00449     }
00450     
00451     DereferenceObject(Connection);
00452 }
00453 
00454 VOID
00455 TCPRecvEventHandler(void *arg)
00456 {
00457     PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
00458     PTDI_BUCKET Bucket;
00459     PLIST_ENTRY Entry;
00460     PIRP Irp;
00461     PMDL Mdl;
00462     UINT Received;
00463     UINT RecvLen;
00464     PUCHAR RecvBuffer;
00465     NTSTATUS Status;
00466 
00467     ReferenceObject(Connection);
00468 
00469     while ((Entry = ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, &Connection->Lock)))
00470     {
00471         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
00472         
00473         Irp = Bucket->Request.RequestContext;
00474         Mdl = Irp->MdlAddress;
00475 
00476         NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
00477 
00478         Status = LibTCPGetDataFromConnectionQueue(Connection, RecvBuffer, RecvLen, &Received);
00479         if (Status == STATUS_PENDING)
00480         {
00481             ExInterlockedInsertHeadList(&Connection->ReceiveRequest,
00482                                         &Bucket->Entry,
00483                                         &Connection->Lock);
00484             break;
00485         }
00486 
00487         Bucket->Status = Status;
00488         Bucket->Information = Received;
00489 
00490         CompleteBucket(Connection, Bucket, FALSE);
00491     }
00492 
00493     DereferenceObject(Connection);
00494 }
00495 
00496 VOID
00497 TCPConnectEventHandler(void *arg, err_t err)
00498 {
00499     PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
00500     PTDI_BUCKET Bucket;
00501     PLIST_ENTRY Entry;
00502         
00503     ReferenceObject(Connection);
00504     
00505     while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock)))
00506     {
00507         
00508         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
00509         
00510         Bucket->Status = TCPTranslateError(err);
00511         Bucket->Information = 0;
00512                 
00513         CompleteBucket(Connection, Bucket, FALSE);
00514     }
00515     
00516     DereferenceObject(Connection);
00517 }

Generated on Fri May 25 2012 04:22:53 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.