[TCPIP]
authorCameron Gutman <aicommander@gmail.com>
Mon, 20 Aug 2012 07:26:12 +0000 (07:26 +0000)
committerCameron Gutman <aicommander@gmail.com>
Mon, 20 Aug 2012 07:26:12 +0000 (07:26 +0000)
- Implement support for SO_REUSEADDR

svn path=/trunk/; revision=57116

reactos/drivers/network/tcpip/include/fileobjs.h
reactos/drivers/network/tcpip/include/titypes.h
reactos/drivers/network/tcpip/tcpip/fileobjs.c
reactos/drivers/network/tcpip/tcpip/main.c
reactos/lib/drivers/lwip/src/include/lwipopts.h
reactos/lib/drivers/lwip/src/rostcp.c

index d45ec7b..33acb9c 100644 (file)
@@ -16,6 +16,7 @@ NTSTATUS FileOpenAddress(
   PTDI_REQUEST Request,
   PTA_IP_ADDRESS AddrList,
   USHORT Protocol,
+  BOOLEAN Shared,
   PVOID Options);
 
 NTSTATUS FileCloseAddress(
index 7bc8ce3..9f1f1f1 100644 (file)
@@ -135,6 +135,7 @@ typedef struct _ADDRESS_FILE {
     USHORT Family;                        /* Address family */
     USHORT Protocol;                      /* Protocol number */
     USHORT Port;                          /* Network port (network byte order) */
+    LONG Sharers;                         /* Number of file objects with this addr file */
     UCHAR TTL;                            /* Time to live stored in packets sent from this address file */
     UINT DF;                              /* Don't fragment */
     UINT BCast;                           /* Receive broadcast packets */
index 6c475ee..7712688 100644 (file)
@@ -99,6 +99,40 @@ BOOLEAN AddrReceiveMatch(
    return FALSE;
 }
 
+PADDRESS_FILE AddrFindShared(
+    PIP_ADDRESS BindAddress,
+    USHORT Port,
+    USHORT Protocol)
+{
+    PLIST_ENTRY CurrentEntry;
+    KIRQL OldIrql;
+    PADDRESS_FILE Current = NULL;
+
+    TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
+
+    CurrentEntry = AddressFileListHead.Flink;
+    while (CurrentEntry != &AddressFileListHead) {
+        Current = CONTAINING_RECORD(CurrentEntry, ADDRESS_FILE, ListEntry);
+
+        /* See if this address matches the search criteria */
+        if ((Current->Port == Port) &&
+            (Current->Protocol == Protocol))
+        {
+            /* Increase the sharer count */
+            ASSERT(Current->Sharers != 0);
+            InterlockedIncrement(&Current->Sharers);
+            break;
+        }
+
+        CurrentEntry = CurrentEntry->Flink;
+        Current = NULL;
+    }
+
+    TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
+
+    return Current;
+}
+
 /*
  * FUNCTION: Searches through address file entries to find next match
  * ARGUMENTS:
@@ -254,6 +288,7 @@ VOID ControlChannelFree(
  *     Request  = Pointer to TDI request structure for this request
  *     Address  = Pointer to address to be opened
  *     Protocol = Protocol on which to open the address
+ *     Shared   = Specifies if the address is opened for shared access
  *     Options  = Pointer to option buffer
  * RETURNS:
  *     Status of operation
@@ -262,12 +297,24 @@ NTSTATUS FileOpenAddress(
   PTDI_REQUEST Request,
   PTA_IP_ADDRESS Address,
   USHORT Protocol,
+  BOOLEAN Shared,
   PVOID Options)
 {
   PADDRESS_FILE AddrFile;
 
   TI_DbgPrint(MID_TRACE, ("Called (Proto %d).\n", Protocol));
 
+  /* If it's shared and has a port specified, look for a match */
+  if ((Shared != FALSE) && (Address->Address[0].Address[0].sin_port != 0))
+  {
+    AddrFile = AddrFindShared(NULL, Address->Address[0].Address[0].sin_port, Protocol);
+    if (AddrFile != NULL)
+    {
+        Request->Handle.AddressHandle = AddrFile;
+        return STATUS_SUCCESS;
+    }
+  }
+
   AddrFile = ExAllocatePoolWithTag(NonPagedPool, sizeof(ADDRESS_FILE),
                                    ADDR_FILE_TAG);
   if (!AddrFile) {
@@ -279,6 +326,7 @@ NTSTATUS FileOpenAddress(
 
   AddrFile->RefCount = 1;
   AddrFile->Free = AddrFileFree;
+  AddrFile->Sharers = 1;
 
   /* Set our default options */
   AddrFile->TTL = 128;
@@ -431,6 +479,13 @@ NTSTATUS FileCloseAddress(
 
   LockObject(AddrFile, &OldIrql);
 
+  if (InterlockedDecrement(&AddrFile->Sharers) != 0)
+  {
+      /* Still other guys have open handles to this, so keep it around */
+      UnlockObject(AddrFile, OldIrql);
+      return STATUS_SUCCESS;
+  }
+
   /* We have to close this listener because we started it */
   if( AddrFile->Listener )
   {
index 034b9df..a1e847a 100644 (file)
@@ -113,6 +113,7 @@ NTSTATUS TiCreateFileObject(
     PVOID ClientContext;
     NTSTATUS Status;
     ULONG Protocol;
+    BOOLEAN Shared;
 
     TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
 
@@ -196,7 +197,9 @@ NTSTATUS TiCreateFileObject(
             return STATUS_INVALID_PARAMETER;
         }
 
-        Status = FileOpenAddress(&Request, Address, Protocol, NULL);
+        Shared = (IrpSp->Parameters.Create.ShareAccess != 0);
+
+        Status = FileOpenAddress(&Request, Address, Protocol, Shared, NULL);
         if (NT_SUCCESS(Status))
         {
             IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
index 56f9c93..accbd98 100755 (executable)
@@ -52,6 +52,8 @@
 
 #define TCP_QUEUE_OOSEQ                 1
 
+#define SO_REUSE                        1
+
 /* FIXME: These MSS and TCP Window definitions assume an MTU
  * of 1500. We need to add some code to lwIP which would allow us
  * to change these values based upon the interface we are 
index 6ddb7a5..2c223c3 100755 (executable)
@@ -317,6 +317,7 @@ void
 LibTCPBindCallback(void *arg)
 {
     struct lwip_callback_msg *msg = arg;
+    PTCP_PCB pcb = msg->Input.Bind.Connection->SocketContext;
 
     ASSERT(msg);
 
@@ -326,7 +327,14 @@ LibTCPBindCallback(void *arg)
         goto done;
     }
 
-    msg->Output.Bind.Error = tcp_bind((PTCP_PCB)msg->Input.Bind.Connection->SocketContext,
+    /* If this address file is shared, set the SOF_REUSEADDR flag in the PCB */
+    ASSERT(msg->Input.Bind.Connection->AddressFile != NULL);
+    if (msg->Input.Bind.Connection->AddressFile->Sharers != 1)
+    {
+        pcb->so_options |= SOF_REUSEADDR;
+    }
+
+    msg->Output.Bind.Error = tcp_bind(pcb,
                                       msg->Input.Bind.IpAddress,
                                       ntohs(msg->Input.Bind.Port));