[TCPIP]
[reactos.git] / reactos / lib / drivers / ip / transport / tcp / tcp.c
index 951e807..ce46f95 100644 (file)
 
 LONG TCP_IPIdentification = 0;
 static BOOLEAN TCPInitialized = FALSE;
-static NPAGED_LOOKASIDE_LIST TCPSegmentList;
 PORT_SET TCPPorts;
-CLIENT_DATA ClientInfo;
 
-VOID
-CompleteBucketWorker(PVOID Context)
-{
-    PTDI_BUCKET Bucket = Context;
-    PCONNECTION_ENDPOINT Connection;
-    PTCP_COMPLETION_ROUTINE Complete;
-    
-    ASSERT(Bucket);
-    
-    Connection = Bucket->AssociatedEndpoint;
-    Complete = Bucket->Request.RequestNotifyObject;
-    
-    Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
-    
-    ExFreePoolWithTag(Bucket, TDI_BUCKET_TAG);
-    
-    DereferenceObject(Connection);
-}
-
-VOID
-CompleteBucket(PCONNECTION_ENDPOINT Connection, PTDI_BUCKET Bucket)
-{
-    Bucket->AssociatedEndpoint = Connection;
-    ReferenceObject(Connection);
-    ChewCreate(CompleteBucketWorker, Bucket);
-}
-
-VOID HandleSignalledConnection(PCONNECTION_ENDPOINT Connection)
-{
-        PTDI_BUCKET Bucket;
-        PLIST_ENTRY Entry;
-        NTSTATUS Status;
-        PIRP Irp;
-        PMDL Mdl;
-
-        if (ClientInfo.Unlocked)
-            LockObjectAtDpcLevel(Connection);
-
-        TI_DbgPrint(MID_TRACE,("Handling signalled state on %x\n",
-                               Connection));
-
-        /* Things that can happen when we try the initial connection */
-        if( Connection->SignalState & (SEL_CONNECT | SEL_FIN | SEL_ERROR) ) {
-            while (!IsListEmpty(&Connection->ConnectRequest)) {
-               Entry = RemoveHeadList( &Connection->ConnectRequest );
-
-               Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-
-               if (Connection->SignalState & SEL_ERROR)
-               {
-                   Bucket->Status = TCPTranslateError(OskitTCPGetSocketError(Connection));
-               }
-               else if (Connection->SignalState & SEL_FIN)
-               {
-                   Bucket->Status = STATUS_CANCELLED;
-               }
-               else
-               {
-                   Bucket->Status = STATUS_SUCCESS;
-               }
-               Bucket->Information = 0;
-
-               CompleteBucket(Connection, Bucket);
-           }
-       }
-
-       if( Connection->SignalState & (SEL_ACCEPT | SEL_FIN | SEL_ERROR) ) {
-           /* Handle readable on a listening socket --
-            * TODO: Implement filtering
-            */
-           TI_DbgPrint(DEBUG_TCP,("Accepting new connection on %x (Queue: %s)\n",
-                                  Connection,
-                                  IsListEmpty(&Connection->ListenRequest) ?
-                                  "empty" : "nonempty"));
-
-           while (!IsListEmpty(&Connection->ListenRequest)) {
-               PIO_STACK_LOCATION IrpSp;
-
-               Entry = RemoveHeadList( &Connection->ListenRequest );
-
-               Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-
-               Irp = Bucket->Request.RequestContext;
-               IrpSp = IoGetCurrentIrpStackLocation( Irp );
-
-               TI_DbgPrint(DEBUG_TCP,("Getting the socket\n"));
-
-               if (Connection->SignalState & SEL_ERROR)
-               {
-                   Status = TCPTranslateError(OskitTCPGetSocketError(Connection));
-               }
-               else if (Connection->SignalState & SEL_FIN)
-               {
-                   Status = STATUS_CANCELLED;
-               }
-               else
-               {
-                   Status = TCPServiceListeningSocket(Connection->AddressFile->Listener,
-                                                      Bucket->AssociatedEndpoint,
-                                                      (PTDI_REQUEST_KERNEL)&IrpSp->Parameters);
-               }
-
-               TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n"));
-
-               if( Status == STATUS_PENDING ) {
-                   InsertHeadList( &Connection->ListenRequest, &Bucket->Entry );
-                   break;
-               } else {
-                   Bucket->Status = Status;
-                   Bucket->Information = 0;
-                   DereferenceObject(Bucket->AssociatedEndpoint);
-
-                   CompleteBucket(Connection, Bucket);
-               }
-          }
-      }
-
-      /* Things that happen after we're connected */
-      if( Connection->SignalState & (SEL_READ | SEL_FIN | SEL_ERROR) ) {
-          TI_DbgPrint(DEBUG_TCP,("Readable: irp list %s\n",
-                                 IsListEmpty(&Connection->ReceiveRequest) ?
-                                 "empty" : "nonempty"));
-
-           while (!IsListEmpty(&Connection->ReceiveRequest)) {
-               OSK_UINT RecvLen = 0, Received = 0;
-               PVOID RecvBuffer = 0;
-
-               Entry = RemoveHeadList( &Connection->ReceiveRequest );
-
-               Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-
-               Irp = Bucket->Request.RequestContext;
-               Mdl = Irp->MdlAddress;
-
-               TI_DbgPrint(DEBUG_TCP,
-                           ("Getting the user buffer from %x\n", Mdl));
-
-               NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
-
-               TI_DbgPrint(DEBUG_TCP,
-                           ("Reading %d bytes to %x\n", RecvLen, RecvBuffer));
-
-               TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
-               TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
-
-               if (Connection->SignalState & SEL_ERROR)
-               {
-                   Status = TCPTranslateError(OskitTCPGetSocketError(Connection));
-               }
-               else if (Connection->SignalState & SEL_FIN)
-               {
-                   /* We got here because of a SEL_FIN event */
-                   Status = STATUS_CANCELLED;
-               }
-               else
-               {
-                   Status = TCPTranslateError(OskitTCPRecv(Connection,
-                                                           RecvBuffer,
-                                                           RecvLen,
-                                                           &Received,
-                                                           0));
-               }
-
-               TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Received));
-
-               if( Status == STATUS_PENDING ) {
-                   InsertHeadList( &Connection->ReceiveRequest, &Bucket->Entry );
-                   break;
-               } else {
-                   TI_DbgPrint(DEBUG_TCP,
-                               ("Completing Receive request: %x %x\n",
-                                Bucket->Request, Status));
-
-                   Bucket->Status = Status;
-                   Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? Received : 0;
-
-                   CompleteBucket(Connection, Bucket);
-               }
-           }
-       }
-       if( Connection->SignalState & (SEL_WRITE | SEL_FIN | SEL_ERROR) ) {
-           TI_DbgPrint(DEBUG_TCP,("Writeable: irp list %s\n",
-                                  IsListEmpty(&Connection->SendRequest) ?
-                                  "empty" : "nonempty"));
-
-           while (!IsListEmpty(&Connection->SendRequest)) {
-               OSK_UINT SendLen = 0, Sent = 0;
-               PVOID SendBuffer = 0;
-
-               Entry = RemoveHeadList( &Connection->SendRequest );
-
-               Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-
-               Irp = Bucket->Request.RequestContext;
-               Mdl = Irp->MdlAddress;
-
-               TI_DbgPrint(DEBUG_TCP,
-                           ("Getting the user buffer from %x\n", Mdl));
-
-               NdisQueryBuffer( Mdl, &SendBuffer, &SendLen );
-
-               TI_DbgPrint(DEBUG_TCP,
-                           ("Writing %d bytes to %x\n", SendLen, SendBuffer));
-
-               TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
-
-               if (Connection->SignalState & SEL_ERROR)
-               {
-                   Status = TCPTranslateError(OskitTCPGetSocketError(Connection));
-               }
-               else if (Connection->SignalState & SEL_FIN)
-               {
-                   /* We got here because of a SEL_FIN event */
-                   Status = STATUS_CANCELLED;
-               }
-               else
-               {
-                   Status = TCPTranslateError(OskitTCPSend(Connection,
-                                                           SendBuffer,
-                                                           SendLen,
-                                                           &Sent,
-                                                           0));
-               }
-
-               TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Sent));
-
-               if( Status == STATUS_PENDING ) {
-                   InsertHeadList( &Connection->SendRequest, &Bucket->Entry );
-                   break;
-               } else {
-                   TI_DbgPrint(DEBUG_TCP,
-                               ("Completing Send request: %x %x\n",
-                               Bucket->Request, Status));
-
-                   Bucket->Status = Status;
-                   Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? Sent : 0;
-
-                   CompleteBucket(Connection, Bucket);
-               }
-           }
-       }
-       if( Connection->SignalState & (SEL_WRITE | SEL_FIN | SEL_ERROR) ) {
-          while (!IsListEmpty(&Connection->ShutdownRequest)) {
-            Entry = RemoveHeadList( &Connection->ShutdownRequest );
-            
-            Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-
-            if (Connection->SignalState & SEL_ERROR)
-            {
-                Status = TCPTranslateError(OskitTCPGetSocketError(Connection));
-            }
-            else if (Connection->SignalState & SEL_FIN)
-            {
-                /* We were cancelled by a FIN */
-                Status = STATUS_CANCELLED;
-            }
-            else
-            {
-                /* See if we can satisfy this after the events */
-                if (IsListEmpty(&Connection->SendRequest))
-                {
-                    /* Send queue is empty so we're good to go */
-                    Status = TCPTranslateError(OskitTCPShutdown(Connection, FWRITE));
-                }
-                else
-                {
-                    /* We still have to wait */
-                    Status = STATUS_PENDING;
-                }
-            }
-              
-            if( Status == STATUS_PENDING ) {
-                InsertHeadList( &Connection->ShutdownRequest, &Bucket->Entry );
-                break;
-            } else {
-                TI_DbgPrint(DEBUG_TCP,
-                            ("Completing shutdown request: %x %x\n",
-                             Bucket->Request, Status));
-                
-                if (KeCancelTimer(&Connection->DisconnectTimer))
-                {
-                    DereferenceObject(Connection);
-                }
+#include "lwip/pbuf.h"
+#include "lwip/ip.h"
+#include "lwip/init.h"
+#include "lwip/arch.h"
 
-                Bucket->Status = Status;
-                Bucket->Information = 0;
-                
-                CompleteBucket(Connection, Bucket);
-            }
-          }
-       }
-    
-       if (Connection->SignalState & SEL_FIN)
-       {
-           Connection->SocketContext = NULL;
-           DereferenceObject(Connection);
-       }
-
-       if (ClientInfo.Unlocked)
-           UnlockObjectFromDpcLevel(Connection);
-}
+#include "rosip.h"
 
 VOID NTAPI
 DisconnectTimeoutDpc(PKDPC Dpc,
@@ -326,14 +29,15 @@ DisconnectTimeoutDpc(PKDPC Dpc,
                      PVOID SystemArgument1,
                      PVOID SystemArgument2)
 {
-    PCONNECTION_ENDPOINT Connection = DeferredContext;
+    PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)DeferredContext;
     PLIST_ENTRY Entry;
     PTDI_BUCKET Bucket;
+    NTSTATUS Status;
     
     LockObjectAtDpcLevel(Connection);
     
     /* We timed out waiting for pending sends so force it to shutdown */
-    OskitTCPShutdown(Connection, FWRITE);
+    Status = TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
     
     while (!IsListEmpty(&Connection->SendRequest))
     {
@@ -344,10 +48,11 @@ DisconnectTimeoutDpc(PKDPC Dpc,
         Bucket->Information = 0;
         Bucket->Status = STATUS_FILE_CLOSED;
         
-        CompleteBucket(Connection, Bucket);
+        CompleteBucket(Connection, Bucket, FALSE);
     }
     
-    while (!IsListEmpty(&Connection->ShutdownRequest)) {
+    while (!IsListEmpty(&Connection->ShutdownRequest))
+    {
         Entry = RemoveHeadList( &Connection->ShutdownRequest );
         
         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
@@ -355,7 +60,7 @@ DisconnectTimeoutDpc(PKDPC Dpc,
         Bucket->Status = STATUS_TIMEOUT;
         Bucket->Information = 0;
         
-        CompleteBucket(Connection, Bucket);
+        CompleteBucket(Connection, Bucket, FALSE);
     }
     
     UnlockObjectFromDpcLevel(Connection);
@@ -363,8 +68,9 @@ DisconnectTimeoutDpc(PKDPC Dpc,
     DereferenceObject(Connection);
 }
 
-VOID ConnectionFree(PVOID Object) {
-    PCONNECTION_ENDPOINT Connection = Object;
+VOID ConnectionFree(PVOID Object)
+{
+    PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)Object;
     KIRQL OldIrql;
 
     TI_DbgPrint(DEBUG_TCP, ("Freeing TCP Endpoint\n"));
@@ -376,8 +82,9 @@ VOID ConnectionFree(PVOID Object) {
     ExFreePoolWithTag( Connection, CONN_ENDPT_TAG );
 }
 
-PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
-    PCONNECTION_ENDPOINT Connection =
+PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext )
+{
+    PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)
         ExAllocatePoolWithTag(NonPagedPool, sizeof(CONNECTION_ENDPOINT),
                               CONN_ENDPT_TAG);
     if (!Connection)
@@ -394,14 +101,16 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
     InitializeListHead(&Connection->ReceiveRequest);
     InitializeListHead(&Connection->SendRequest);
     InitializeListHead(&Connection->ShutdownRequest);
-    
+    InitializeListHead(&Connection->PacketQueue);
+
+    /* Initialize disconnect timer */
     KeInitializeTimer(&Connection->DisconnectTimer);
     KeInitializeDpc(&Connection->DisconnectDpc, DisconnectTimeoutDpc, Connection);
 
     /* Save client context pointer */
     Connection->ClientContext = ClientContext;
 
-    Connection->RefCount = 2;
+    Connection->RefCount = 1;
     Connection->Free = ConnectionFree;
 
     /* Add connection endpoint to global list */
@@ -413,142 +122,64 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
 }
 
 NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
-                    UINT Family, UINT Type, UINT Proto ) {
+                    UINT Family, UINT Type, UINT Proto )
+{
     NTSTATUS Status;
     KIRQL OldIrql;
 
     LockObject(Connection, &OldIrql);
 
-    TI_DbgPrint(DEBUG_TCP,("Called: Connection %x, Family %d, Type %d, "
-                           "Proto %d\n",
-                           Connection, Family, Type, Proto));
-
-    Status = TCPTranslateError( OskitTCPSocket( Connection,
-                                                &Connection->SocketContext,
-                                                Family,
-                                                Type,
-                                                Proto ) );
+    TI_DbgPrint(DEBUG_TCP,("[IP, TCPSocket] Called: Connection %x, Family %d, Type %d, "
+                           "Proto %d, sizeof(CONNECTION_ENDPOINT) = %d\n",
+                           Connection, Family, Type, Proto, sizeof(CONNECTION_ENDPOINT)));
 
-    ASSERT_KM_POINTER(Connection->SocketContext);
+    Connection->SocketContext = LibTCPSocket(Connection);
+    if (Connection->SocketContext)
+        Status = STATUS_SUCCESS;
+    else
+        Status = STATUS_INSUFFICIENT_RESOURCES;
 
     UnlockObject(Connection, OldIrql);
 
+    TI_DbgPrint(DEBUG_TCP,("[IP, TCPSocket] Leaving. Status = 0x%x\n", Status));
+
     return Status;
 }
 
-VOID TCPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
-/*
- * FUNCTION: Receives and queues TCP data
- * ARGUMENTS:
- *     IPPacket = Pointer to an IP packet that was received
- * NOTES:
- *     This is the low level interface for receiving TCP data
- */
+NTSTATUS TCPClose( PCONNECTION_ENDPOINT Connection )
 {
     KIRQL OldIrql;
+    PVOID Socket;
 
-    TI_DbgPrint(DEBUG_TCP,("Sending packet %d (%d) to oskit\n",
-                           IPPacket->TotalSize,
-                           IPPacket->HeaderSize));
+    LockObject(Connection, &OldIrql);
 
-    KeAcquireSpinLock(&ClientInfo.Lock, &OldIrql);
-    ClientInfo.Unlocked = TRUE;
-    ClientInfo.OldIrql = OldIrql;
+    Socket = Connection->SocketContext;
 
-    OskitTCPReceiveDatagram( IPPacket->Header,
-                             IPPacket->TotalSize,
-                             IPPacket->HeaderSize );
+    FlushAllQueues(Connection, STATUS_CANCELLED);
 
-    ClientInfo.Unlocked = FALSE;
-    KeReleaseSpinLock(&ClientInfo.Lock, OldIrql);
-}
+    LibTCPClose(Connection, FALSE, TRUE);
 
-/* event.c */
-int TCPSocketState( void *ClientData,
-                    void *WhichSocket,
-                    void *WhichConnection,
-                    OSK_UINT NewState );
-
-int TCPPacketSend( void *ClientData,
-                   OSK_PCHAR Data,
-                   OSK_UINT Len );
-
-POSK_IFADDR TCPFindInterface( void *ClientData,
-                              OSK_UINT AddrType,
-                              OSK_UINT FindType,
-                              OSK_SOCKADDR *ReqAddr );
-
-NTSTATUS TCPMemStartup( void );
-void *TCPMalloc( void *ClientData,
-                 OSK_UINT bytes, OSK_PCHAR file, OSK_UINT line );
-void TCPFree( void *ClientData,
-              void *data, OSK_PCHAR file, OSK_UINT line );
-void TCPMemShutdown( void );
-
-OSKITTCP_EVENT_HANDLERS EventHandlers = {
-    NULL,             /* Client Data */
-    TCPSocketState,   /* SocketState */
-    TCPPacketSend,    /* PacketSend */
-    TCPFindInterface, /* FindInterface */
-    TCPMalloc,        /* Malloc */
-    TCPFree,          /* Free */
-    NULL,             /* Sleep */
-    NULL,             /* Wakeup */
-};
-
-static KEVENT TimerLoopEvent;
-static HANDLE TimerThreadHandle;
-
-/*
- * We are running 2 timers here, one with a 200ms interval (fast) and the other
- * with a 500ms interval (slow). So we need to time out at 200, 400, 500, 600,
- * 800, 1000 and process the "fast" events at 200, 400, 600, 800, 1000 and the
- * "slow" events at 500 and 1000.
- */
-static VOID NTAPI
-TimerThread(PVOID Context)
-{
-    LARGE_INTEGER Timeout;
-    NTSTATUS Status;
-    unsigned Current, NextFast, NextSlow, Next;
-
-    Current = 0;
-    Next = 0;
-    NextFast = 0;
-    NextSlow = 0;
-    while ( 1 ) {
-        if (Next == NextFast) {
-            NextFast += 2;
-       }
-        if (Next == NextSlow) {
-            NextSlow += 5;
-        }
-        Next = min(NextFast, NextSlow);
-        Timeout.QuadPart = (LONGLONG) (Next - Current) * -1000000; /* 100 ms */
-        Status = KeWaitForSingleObject(&TimerLoopEvent, Executive, KernelMode,
-                                       FALSE, &Timeout);
-        if (Status != STATUS_TIMEOUT) {
-            PsTerminateSystemThread(Status);
-        }
+    UnlockObject(Connection, OldIrql);
 
-        TimerOskitTCP( Next == NextFast, Next == NextSlow );
+    DereferenceObject(Connection);
 
-        Current = Next;
-        if (10 <= Current) {
-            Current = 0;
-            Next = 0;
-            NextFast = 0;
-            NextSlow = 0;
-        }
-    }
+    return STATUS_SUCCESS;
 }
 
-static VOID
-StartTimer(VOID)
+VOID TCPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
+/*
+ * FUNCTION: Receives and queues TCP data
+ * ARGUMENTS:
+ *     IPPacket = Pointer to an IP packet that was received
+ * NOTES:
+ *     This is the low level interface for receiving TCP data
+ */
 {
-    KeInitializeEvent(&TimerLoopEvent, NotificationEvent, FALSE);
-    PsCreateSystemThread(&TimerThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0,
-                         TimerThread, NULL);
+    TI_DbgPrint(DEBUG_TCP,("Sending packet %d (%d) to lwIP\n",
+                           IPPacket->TotalSize,
+                           IPPacket->HeaderSize));
+    
+    LibIPInsertPacket(Interface->TCPContext, IPPacket->Header, IPPacket->TotalSize);
 }
 
 NTSTATUS TCPStartup(VOID)
@@ -560,37 +191,18 @@ NTSTATUS TCPStartup(VOID)
 {
     NTSTATUS Status;
 
-    Status = TCPMemStartup();
-    if ( ! NT_SUCCESS(Status) ) {
-        return Status;
-    }
-
     Status = PortsStartup( &TCPPorts, 1, 0xfffe );
-    if( !NT_SUCCESS(Status) ) {
-        TCPMemShutdown();
+    if (!NT_SUCCESS(Status))
+    {
         return Status;
     }
-
-    KeInitializeSpinLock(&ClientInfo.Lock);
-    ClientInfo.Unlocked = FALSE;
-
-    RegisterOskitTCPEventHandlers( &EventHandlers );
-    InitOskitTCP();
-
+    
+    /* Initialize our IP library */
+    LibIPInitialize();
+    
     /* Register this protocol with IP layer */
     IPRegisterProtocol(IPPROTO_TCP, TCPReceive);
-
-    ExInitializeNPagedLookasideList(
-        &TCPSegmentList,                /* Lookaside list */
-        NULL,                           /* Allocate routine */
-        NULL,                           /* Free routine */
-        0,                              /* Flags */
-        sizeof(TCP_SEGMENT),            /* Size of each entry */
-        'SPCT',                         /* Tag */
-        0);                             /* Depth */
-
-    StartTimer();
-
+    
     TCPInitialized = TRUE;
 
     return STATUS_SUCCESS;
@@ -604,99 +216,52 @@ NTSTATUS TCPShutdown(VOID)
  *     Status of operation
  */
 {
-    LARGE_INTEGER WaitForThread;
-
     if (!TCPInitialized)
         return STATUS_SUCCESS;
-
-    WaitForThread.QuadPart = -2500000; /* 250 ms */
-    KeSetEvent(&TimerLoopEvent, IO_NO_INCREMENT, FALSE);
-    ZwWaitForSingleObject(TimerThreadHandle, FALSE, &WaitForThread);
+    
+    LibIPShutdown();
 
     /* Deregister this protocol with IP layer */
     IPRegisterProtocol(IPPROTO_TCP, NULL);
 
-    ExDeleteNPagedLookasideList(&TCPSegmentList);
-
     TCPInitialized = FALSE;
 
-    DeinitOskitTCP();
-
     PortsShutdown( &TCPPorts );
 
-    TCPMemShutdown();
-
     return STATUS_SUCCESS;
 }
 
-NTSTATUS TCPTranslateError( int OskitError ) {
+NTSTATUS TCPTranslateError(const err_t err)
+{
     NTSTATUS Status;
 
-    switch( OskitError ) {
-    case 0: Status = STATUS_SUCCESS; break;
-    case OSK_EADDRNOTAVAIL:
-        Status = STATUS_INVALID_ADDRESS;
-        DbgPrint("OskitTCP: EADDRNOTAVAIL\n");
-        break;
-    case OSK_EADDRINUSE:
-        Status = STATUS_ADDRESS_ALREADY_EXISTS;
-        DbgPrint("OskitTCP: EADDRINUSE\n");
-        break;
-    case OSK_EAFNOSUPPORT:
-        Status = STATUS_INVALID_CONNECTION;
-        DbgPrint("OskitTCP: EAFNOSUPPORT\n");
-        break;
-    case OSK_ECONNREFUSED:
-        Status = STATUS_REMOTE_NOT_LISTENING;
-        DbgPrint("OskitTCP: ECONNREFUSED\n");
-        break;
-    case OSK_ECONNRESET:
-        Status = STATUS_REMOTE_DISCONNECT;
-        DbgPrint("OskitTCP: ECONNRESET\n");
-        break;
-    case OSK_ECONNABORTED:
-        Status = STATUS_LOCAL_DISCONNECT;
-        DbgPrint("OskitTCP: ECONNABORTED\n");
-        break;
-    case OSK_EWOULDBLOCK:
-    case OSK_EINPROGRESS: Status = STATUS_PENDING; break;
-    case OSK_EINVAL:
-        Status = STATUS_INVALID_PARAMETER;
-        DbgPrint("OskitTCP: EINVAL\n");
-        break;
-    case OSK_ENOMEM:
-    case OSK_ENOBUFS:
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        DbgPrint("OskitTCP: ENOMEM/ENOBUFS\n");
-        break;
-    case OSK_EPIPE:
-    case OSK_ESHUTDOWN:
-        Status = STATUS_FILE_CLOSED;
-        DbgPrint("OskitTCP: ESHUTDOWN/EPIPE\n");
-        break;
-    case OSK_EMSGSIZE:
-        Status = STATUS_BUFFER_TOO_SMALL;
-        DbgPrint("OskitTCP: EMSGSIZE\n");
-        break;
-    case OSK_ETIMEDOUT:
-        Status = STATUS_TIMEOUT;
-        DbgPrint("OskitTCP: ETIMEDOUT\n");
-        break;
-    case OSK_ENETUNREACH:
-        Status = STATUS_NETWORK_UNREACHABLE;
-        DbgPrint("OskitTCP: ENETUNREACH\n");
-        break;
-    case OSK_EFAULT:
-        Status = STATUS_ACCESS_VIOLATION;
-        DbgPrint("OskitTCP: EFAULT\n");
-        break;
-    default:
-       DbgPrint("OskitTCP returned unhandled error code: %d\n", OskitError);
-       Status = STATUS_INVALID_CONNECTION;
-       break;
+    switch (err)
+    {
+        case ERR_OK: Status = STATUS_SUCCESS; return Status; //0
+        case ERR_MEM: Status = STATUS_INSUFFICIENT_RESOURCES; break; //-1
+        case ERR_BUF: Status = STATUS_BUFFER_TOO_SMALL; break; //-2
+        case ERR_TIMEOUT: Status = STATUS_TIMEOUT; break; // -3
+        case ERR_RTE: Status = STATUS_NETWORK_UNREACHABLE; break; //-4
+        case ERR_INPROGRESS: Status = STATUS_PENDING; return Status; //-5
+        case ERR_VAL: Status = STATUS_INVALID_PARAMETER; break; //-6
+        case ERR_WOULDBLOCK: Status = STATUS_CANT_WAIT; break; //-7
+        case ERR_USE: Status = STATUS_ADDRESS_ALREADY_EXISTS; break; //-8
+        case ERR_ISCONN: Status = STATUS_UNSUCCESSFUL; break; //-9 (FIXME)
+        case ERR_ABRT: Status = STATUS_LOCAL_DISCONNECT; break; //-10
+        case ERR_RST: Status = STATUS_REMOTE_DISCONNECT; break; //-11
+        case ERR_CLSD: Status = STATUS_FILE_CLOSED; break; //-12
+        case ERR_CONN: Status = STATUS_INVALID_CONNECTION; break; //-13
+        case ERR_ARG: Status = STATUS_INVALID_PARAMETER; break; //-14
+        case ERR_IF: Status = STATUS_UNEXPECTED_NETWORK_ERROR; break; //-15
+        default:
+            DbgPrint("Invalid error value: %d\n", err);
+            ASSERT(FALSE);
+            Status = STATUS_UNSUCCESSFUL;
+            break;
     }
+    
+    DbgPrint("TCP operation failed: 0x%x (%d)\n", Status, err);
 
-    TI_DbgPrint(DEBUG_TCP,("Error %d -> %x\n", OskitError, Status));
     return Status;
 }
 
@@ -705,24 +270,26 @@ NTSTATUS TCPConnect
   PTDI_CONNECTION_INFORMATION ConnInfo,
   PTDI_CONNECTION_INFORMATION ReturnInfo,
   PTCP_COMPLETION_ROUTINE Complete,
-  PVOID Context ) {
+  PVOID Context )
+{
     NTSTATUS Status;
-    SOCKADDR_IN AddressToConnect = { 0 }, AddressToBind = { 0 };
+    struct ip_addr bindaddr, connaddr;
     IP_ADDRESS RemoteAddress;
     USHORT RemotePort;
     TA_IP_ADDRESS LocalAddress;
     PTDI_BUCKET Bucket;
-    PNEIGHBOR_CACHE_ENTRY NCE = NULL;
+    PNEIGHBOR_CACHE_ENTRY NCE;
     KIRQL OldIrql;
 
-    TI_DbgPrint(DEBUG_TCP,("TCPConnect: Called\n"));
+    TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Called\n"));
 
     Status = AddrBuildAddress
         ((PTRANSPORT_ADDRESS)ConnInfo->RemoteAddress,
          &RemoteAddress,
          &RemotePort);
 
-    if (!NT_SUCCESS(Status)) {
+    if (!NT_SUCCESS(Status))
+    {
         TI_DbgPrint(DEBUG_TCP, ("Could not AddrBuildAddress in TCPConnect\n"));
         return Status;
     }
@@ -733,9 +300,6 @@ NTSTATUS TCPConnect
                  RemoteAddress.Address.IPv4Address,
                  RemotePort));
 
-    AddressToConnect.sin_family = AF_INET;
-    AddressToBind = AddressToConnect;
-
     LockObject(Connection, &OldIrql);
 
     if (!Connection->AddressFile)
@@ -751,91 +315,61 @@ NTSTATUS TCPConnect
             UnlockObject(Connection, OldIrql);
             return STATUS_NETWORK_UNREACHABLE;
         }
-    }
 
-    if (Connection->AddressFile->Port)
-    {
-        /* See if we had an unspecified bind address */
-        if (NCE)
-        {
-            /* We did, so use the interface unicast address associated with the route */
-            AddressToBind.sin_addr.s_addr = NCE->Interface->Unicast.Address.IPv4Address;
-        }
-        else
-        {
-            /* Bind address was explicit so use it */
-            AddressToBind.sin_addr.s_addr = Connection->AddressFile->Address.Address.IPv4Address;
-        }
-        
-        AddressToBind.sin_port = Connection->AddressFile->Port;
-        
-        /* Perform an explicit bind */
-        Status = TCPTranslateError(OskitTCPBind(Connection,
-                                                &AddressToBind,
-                                                sizeof(AddressToBind)));
+        bindaddr.addr = NCE->Interface->Unicast.Address.IPv4Address;
     }
     else
     {
-        /* An implicit bind will be performed */
-        Status = STATUS_SUCCESS;
+        bindaddr.addr = Connection->AddressFile->Address.Address.IPv4Address;
     }
 
-    if (NT_SUCCESS(Status)) {        
-        if (NT_SUCCESS(Status))
+    Status = TCPTranslateError(LibTCPBind(Connection,
+                                          &bindaddr,
+                                          Connection->AddressFile->Port));
+    
+    if (NT_SUCCESS(Status))
+    {
+        /* Check if we had an unspecified port */
+        if (!Connection->AddressFile->Port)
         {
-            memcpy( &AddressToConnect.sin_addr,
-                   &RemoteAddress.Address.IPv4Address,
-                   sizeof(AddressToConnect.sin_addr) );
-            AddressToConnect.sin_port = RemotePort;
-            
-            Status = TCPTranslateError
-            ( OskitTCPConnect( Connection,
-                              &AddressToConnect,
-                              sizeof(AddressToConnect) ) );
-
+            /* We did, so we need to copy back the port */
+            Status = TCPGetSockAddress(Connection, (PTRANSPORT_ADDRESS)&LocalAddress, FALSE);
             if (NT_SUCCESS(Status))
             {
-                /* Check if we had an unspecified port */
-                if (!Connection->AddressFile->Port)
-                {
-                    /* We did, so we need to copy back the port */
-                    if (NT_SUCCESS(TCPGetSockAddress(Connection, (PTRANSPORT_ADDRESS)&LocalAddress, FALSE)))
-                    {
-                        /* Allocate the port in the port bitmap */
-                        Connection->AddressFile->Port = TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port);
-
-                        /* This should never fail */
-                        ASSERT(Connection->AddressFile->Port != 0xFFFF);
-                    }
-                }
-                
-                /* Check if the address was unspecified */
-                if (AddrIsUnspecified(&Connection->AddressFile->Address))
-                {
-                    /* It is, so store the address of the outgoing NIC */
-                    Connection->AddressFile->Address = NCE->Interface->Unicast;
-                }
+                /* Allocate the port in the port bitmap */
+                Connection->AddressFile->Port = TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port);
+                    
+                /* This should never fail */
+                ASSERT(Connection->AddressFile->Port != 0xFFFF);
             }
+        }
 
-            if (Status == STATUS_PENDING)
+        if (NT_SUCCESS(Status))
+        {
+            connaddr.addr = RemoteAddress.Address.IPv4Address;
+
+            Bucket = ExAllocatePoolWithTag( NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG );
+            if (!Bucket)
             {
-                Bucket = ExAllocatePoolWithTag( NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG );
-                if( !Bucket )
-                {
-                    UnlockObject(Connection, OldIrql);
-                    return STATUS_NO_MEMORY;
-                }
-                
-                Bucket->Request.RequestNotifyObject = (PVOID)Complete;
-                Bucket->Request.RequestContext = Context;
-                
-                InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
+                UnlockObject(Connection, OldIrql);
+                return STATUS_NO_MEMORY;
             }
+            
+            Bucket->Request.RequestNotifyObject = (PVOID)Complete;
+            Bucket->Request.RequestContext = Context;
+                       
+            InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
+        
+            Status = TCPTranslateError(LibTCPConnect(Connection,
+                                                     &connaddr,
+                                                     RemotePort));
         }
     }
 
     UnlockObject(Connection, OldIrql);
 
+    TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Leaving. Status = 0x%x\n", Status));
+
     return Status;
 }
 
@@ -846,155 +380,86 @@ NTSTATUS TCPDisconnect
   PTDI_CONNECTION_INFORMATION ConnInfo,
   PTDI_CONNECTION_INFORMATION ReturnInfo,
   PTCP_COMPLETION_ROUTINE Complete,
-  PVOID Context ) {
+  PVOID Context )
+{
     NTSTATUS Status = STATUS_INVALID_PARAMETER;
     PTDI_BUCKET Bucket;
     KIRQL OldIrql;
-    PLIST_ENTRY Entry;
     LARGE_INTEGER ActualTimeout;
 
-    TI_DbgPrint(DEBUG_TCP,("started\n"));
+    TI_DbgPrint(DEBUG_TCP,("[IP, TCPDisconnect] Called\n"));
 
     LockObject(Connection, &OldIrql);
 
-    if (Flags & TDI_DISCONNECT_RELEASE)
+    if (Connection->SocketContext)
     {
-        /* See if we can satisfy this right now */
-        if (IsListEmpty(&Connection->SendRequest))
+        if (Flags & TDI_DISCONNECT_RELEASE)
         {
-            /* Send queue is empty so we're good to go */
-            Status = TCPTranslateError(OskitTCPShutdown(Connection, FWRITE));
-            
-            UnlockObject(Connection, OldIrql);
-            
-            return Status;
-        }
-        
-        /* Check if the timeout was 0 */
-        if (Timeout && Timeout->QuadPart == 0)
-        {
-            OskitTCPShutdown(Connection, FWRITE);
-            
-            while (!IsListEmpty(&Connection->SendRequest))
+            if (IsListEmpty(&Connection->SendRequest))
             {
-                Entry = RemoveHeadList(&Connection->SendRequest);
-                
-                Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
-                
-                Bucket->Information = 0;
-                Bucket->Status = STATUS_FILE_CLOSED;
-                
-                CompleteBucket(Connection, Bucket);
+                Status = TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
             }
-            
-            UnlockObject(Connection, OldIrql);
-            
-            return STATUS_TIMEOUT;
-        }
-        
-        /* Otherwise we wait for the send queue to be empty */
-    }
+            else if (Timeout && Timeout->QuadPart == 0)
+            {
+                FlushSendQueue(Connection, STATUS_FILE_CLOSED, FALSE);
+                TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
+                Status = STATUS_TIMEOUT;
+            }
+            else 
+            {
+                /* Use the timeout specified or 1 second if none was specified */
+                if (Timeout)
+                {
+                    ActualTimeout = *Timeout;
+                }
+                else
+                {
+                    ActualTimeout.QuadPart = -1000000;
+                }
 
-    if ((Flags & TDI_DISCONNECT_ABORT) || !Flags)
-    {
-        /* This request overrides any pending graceful disconnects */
-        while (!IsListEmpty(&Connection->ShutdownRequest))
-        {
-            Entry = RemoveHeadList(&Connection->ShutdownRequest);
-            
-            Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
-            
-            Bucket->Information = 0;
-            Bucket->Status = STATUS_FILE_CLOSED;
-            
-            CompleteBucket(Connection, Bucket);
-        }
-        
-        /* Also kill any pending reads and writes */
-        while (!IsListEmpty(&Connection->SendRequest))
-        {
-            Entry = RemoveHeadList(&Connection->SendRequest);
-            
-            Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
-            
-            Bucket->Information = 0;
-            Bucket->Status = STATUS_FILE_CLOSED;
-            
-            CompleteBucket(Connection, Bucket);
+                /* We couldn't complete the request now because we need to wait for outstanding I/O */
+                Bucket = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG);
+                if (!Bucket)
+                {
+                    UnlockObject(Connection, OldIrql);
+                    return STATUS_NO_MEMORY;
+                }
+    
+                Bucket->Request.RequestNotifyObject = (PVOID)Complete;
+                Bucket->Request.RequestContext = Context;
+
+                InsertTailList(&Connection->ShutdownRequest, &Bucket->Entry);
+
+                ReferenceObject(Connection);
+                if (KeCancelTimer(&Connection->DisconnectTimer))
+                {
+                    DereferenceObject(Connection);
+                }
+                KeSetTimer(&Connection->DisconnectTimer, ActualTimeout, &Connection->DisconnectDpc);
+
+                Status = STATUS_PENDING;
+            }
         }
-        
-        while (!IsListEmpty(&Connection->ReceiveRequest))
+
+        if ((Flags & TDI_DISCONNECT_ABORT) || !Flags)
         {
-            Entry = RemoveHeadList(&Connection->ReceiveRequest);
-            
-            Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
-            
-            Bucket->Information = 0;
-            Bucket->Status = STATUS_FILE_CLOSED;
-            
-            CompleteBucket(Connection, Bucket);
+            FlushReceiveQueue(Connection, STATUS_FILE_CLOSED, FALSE);
+            FlushSendQueue(Connection, STATUS_FILE_CLOSED, FALSE);
+            FlushShutdownQueue(Connection, STATUS_FILE_CLOSED, FALSE);
+            Status = TCPTranslateError(LibTCPShutdown(Connection, 1, 1));
         }
-        
-        /* An abort never pends; we just drop everything and complete */
-        Status = TCPTranslateError(OskitTCPShutdown(Connection, FWRITE | FREAD));
-            
-        UnlockObject(Connection, OldIrql);
-            
-        return Status;
-    }
-    
-    /* We couldn't complete the request now because we need to wait for outstanding I/O */
-    Bucket = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG);
-    if (!Bucket)
-    {
-        UnlockObject(Connection, OldIrql);
-        return STATUS_NO_MEMORY;
-    }
-    
-    Bucket->Request.RequestNotifyObject = (PVOID)Complete;
-    Bucket->Request.RequestContext = Context;
-
-    InsertTailList(&Connection->ShutdownRequest, &Bucket->Entry);
-    
-    /* Use the timeout specified or 1 second if none was specified */
-    if (Timeout)
-    {
-        ActualTimeout = *Timeout;
     }
     else
     {
-        ActualTimeout.QuadPart = -1000000;
+        /* We already got closed by the other side so just return success */
+        Status = STATUS_SUCCESS;
     }
-    
-    ReferenceObject(Connection);
-    KeSetTimer(&Connection->DisconnectTimer, ActualTimeout, &Connection->DisconnectDpc);
 
     UnlockObject(Connection, OldIrql);
 
-    TI_DbgPrint(DEBUG_TCP,("finished %x\n", Status));
-
-    return STATUS_PENDING;
-}
+    TI_DbgPrint(DEBUG_TCP,("[IP, TCPDisconnect] Leaving. Status = 0x%x\n", Status));
 
-NTSTATUS TCPClose
-( PCONNECTION_ENDPOINT Connection )
-{
-    KIRQL OldIrql;
-
-    LockObject(Connection, &OldIrql);
-
-    /* We should not be associated to an address file at this point */
-    ASSERT(!Connection->AddressFile);
-
-    OskitTCPClose(Connection);
-
-    Connection->SocketContext = NULL;
-
-    UnlockObject(Connection, OldIrql);
-
-    DereferenceObject(Connection);
-
-    return STATUS_SUCCESS;
+    return Status;
 }
 
 NTSTATUS TCPReceiveData
@@ -1004,53 +469,46 @@ NTSTATUS TCPReceiveData
   PULONG BytesReceived,
   ULONG ReceiveFlags,
   PTCP_COMPLETION_ROUTINE Complete,
-  PVOID Context ) {
-    PVOID DataBuffer;
-    UINT DataLen, Received = 0;
-    NTSTATUS Status;
+  PVOID Context )
+{
     PTDI_BUCKET Bucket;
-    KIRQL OldIrql;
-
-    NdisQueryBuffer( Buffer, &DataBuffer, &DataLen );
-
-    TI_DbgPrint(DEBUG_TCP,("TCP>|< Got an MDL %x (%x:%d)\n", Buffer, DataBuffer, DataLen));
+    PUCHAR DataBuffer;
+    UINT DataLen, Received;
+    NTSTATUS Status;
 
-    LockObject(Connection, &OldIrql);
+    TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Called for %d bytes (on socket %x)\n",
+                           ReceiveLength, Connection->SocketContext));
 
-    Status = TCPTranslateError
-        ( OskitTCPRecv
-          ( Connection,
-            DataBuffer,
-            DataLen,
-            &Received,
-            ReceiveFlags ) );
+    NdisQueryBuffer(Buffer, &DataBuffer, &DataLen);
 
-    TI_DbgPrint(DEBUG_TCP,("OskitTCPReceive: %x, %d\n", Status, Received));
+    Status = LibTCPGetDataFromConnectionQueue(Connection, DataBuffer, DataLen, &Received);
 
-    /* Keep this request around ... there was no data yet */
-    if( Status == STATUS_PENDING ) {
+    if (Status == STATUS_PENDING)
+    {
+    
         /* Freed in TCPSocketState */
-        Bucket = ExAllocatePoolWithTag( NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG );
-        if( !Bucket ) {
-            TI_DbgPrint(DEBUG_TCP,("Failed to allocate bucket\n"));
-            UnlockObject(Connection, OldIrql);
+        Bucket = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG);
+        if (!Bucket)
+        {
+            TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Failed to allocate bucket\n"));
+
             return STATUS_NO_MEMORY;
         }
-
+    
         Bucket->Request.RequestNotifyObject = Complete;
         Bucket->Request.RequestContext = Context;
-        *BytesReceived = 0;
 
-        InsertTailList( &Connection->ReceiveRequest, &Bucket->Entry );
-        TI_DbgPrint(DEBUG_TCP,("Queued read irp\n"));
-    } else {
-        TI_DbgPrint(DEBUG_TCP,("Got status %x, bytes %d\n", Status, Received));
-        *BytesReceived = Received;
-    }
+        ExInterlockedInsertTailList( &Connection->ReceiveRequest, &Bucket->Entry, &Connection->Lock );
+        TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Queued read irp\n"));
 
-    UnlockObject(Connection, OldIrql);
+        TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Leaving. Status = STATUS_PENDING\n"));
 
-    TI_DbgPrint(DEBUG_TCP,("Status %x\n", Status));
+        (*BytesReceived) = 0;
+    }
+    else
+    {
+        (*BytesReceived) = Received;
+    }
 
     return Status;
 }
@@ -1062,30 +520,37 @@ NTSTATUS TCPSendData
   PULONG BytesSent,
   ULONG Flags,
   PTCP_COMPLETION_ROUTINE Complete,
-  PVOID Context ) {
-    UINT Sent = 0;
+  PVOID Context )
+{
     NTSTATUS Status;
     PTDI_BUCKET Bucket;
     KIRQL OldIrql;
 
     LockObject(Connection, &OldIrql);
 
-    TI_DbgPrint(DEBUG_TCP,("Connection = %x\n", Connection));
+    TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Called for %d bytes (on socket %x)\n",
+                           SendLength, Connection->SocketContext));
 
-    Status = TCPTranslateError
-        ( OskitTCPSend( Connection,
-                        (OSK_PCHAR)BufferData, SendLength,
-                        &Sent, 0 ) );
+    TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Connection = %x\n", Connection));
+    TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Connection->SocketContext = %x\n",
+                           Connection->SocketContext));
 
-    TI_DbgPrint(DEBUG_TCP,("OskitTCPSend: %x, %d\n", Status, Sent));
+    Status = TCPTranslateError(LibTCPSend(Connection,
+                                          BufferData,
+                                          SendLength,
+                                          FALSE));
+    
+    TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Send: %x, %d\n", Status, SendLength));
 
     /* Keep this request around ... there was no data yet */
-    if( Status == STATUS_PENDING ) {
+    if (Status == STATUS_PENDING)
+    {
         /* Freed in TCPSocketState */
         Bucket = ExAllocatePoolWithTag( NonPagedPool, sizeof(*Bucket), TDI_BUCKET_TAG );
-        if( !Bucket ) {
+        if (!Bucket)
+        {
             UnlockObject(Connection, OldIrql);
-            TI_DbgPrint(DEBUG_TCP,("Failed to allocate bucket\n"));
+            TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Failed to allocate bucket\n"));
             return STATUS_NO_MEMORY;
         }
         
@@ -1094,65 +559,83 @@ NTSTATUS TCPSendData
         *BytesSent = 0;
         
         InsertTailList( &Connection->SendRequest, &Bucket->Entry );
-        TI_DbgPrint(DEBUG_TCP,("Queued write irp\n"));
-    } else {
-        TI_DbgPrint(DEBUG_TCP,("Got status %x, bytes %d\n", Status, Sent));
-        *BytesSent = Sent;
+        TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Queued write irp\n"));
+    }
+    else if (Status == STATUS_SUCCESS)
+    {
+        *BytesSent = SendLength;
+    }
+    else
+    {
+        *BytesSent = 0;
     }
 
     UnlockObject(Connection, OldIrql);
 
-    TI_DbgPrint(DEBUG_TCP,("Status %x\n", Status));
+    TI_DbgPrint(DEBUG_TCP, ("[IP, TCPSendData] Leaving. Status = %x\n", Status));
 
     return Status;
 }
 
-UINT TCPAllocatePort( UINT HintPort ) {
-    if( HintPort ) {
-        if( AllocatePort( &TCPPorts, HintPort ) ) return HintPort;
-        else {
-            TI_DbgPrint
-                (MID_TRACE,("We got a hint port but couldn't allocate it\n"));
+UINT TCPAllocatePort(const UINT HintPort)
+{
+    if (HintPort)
+    {
+        if (AllocatePort(&TCPPorts, HintPort))
+            return HintPort;
+        else
+        {
+            TI_DbgPrint(MID_TRACE,("We got a hint port but couldn't allocate it\n"));
             return (UINT)-1;
         }
-    } else return AllocatePortFromRange( &TCPPorts, 1024, 5000 );
+    }
+    else
+        return AllocatePortFromRange( &TCPPorts, 1024, 5000 );
 }
 
-VOID TCPFreePort( UINT Port ) {
-    DeallocatePort( &TCPPorts, Port );
+VOID TCPFreePort(const UINT Port)
+{
+    DeallocatePort(&TCPPorts, Port);
 }
 
 NTSTATUS TCPGetSockAddress
 ( PCONNECTION_ENDPOINT Connection,
   PTRANSPORT_ADDRESS Address,
-  BOOLEAN GetRemote ) {
-    OSK_UINT LocalAddress, RemoteAddress;
-    OSK_UI16 LocalPort, RemotePort;
+  BOOLEAN GetRemote )
+{
     PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address;
+    struct ip_addr ipaddr;
     NTSTATUS Status;
     KIRQL OldIrql;
+    
+    AddressIP->TAAddressCount = 1;
+    AddressIP->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
+    AddressIP->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
 
     LockObject(Connection, &OldIrql);
 
-    Status = TCPTranslateError(OskitTCPGetAddress(Connection,
-                                                  &LocalAddress, &LocalPort,
-                                                  &RemoteAddress, &RemotePort));
+    if (GetRemote)
+    {
+        Status = TCPTranslateError(LibTCPGetPeerName(Connection->SocketContext,
+                                    &ipaddr,
+                                    &AddressIP->Address[0].Address[0].sin_port));
+    }
+    else
+    {
+        Status = TCPTranslateError(LibTCPGetHostName(Connection->SocketContext,
+                                    &ipaddr,
+                                    &AddressIP->Address[0].Address[0].sin_port));
+    }
 
     UnlockObject(Connection, OldIrql);
-
-    if (!NT_SUCCESS(Status))
-        return Status;
-
-    AddressIP->TAAddressCount = 1;
-    AddressIP->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
-    AddressIP->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
-    AddressIP->Address[0].Address[0].sin_port = GetRemote ? RemotePort : LocalPort;
-    AddressIP->Address[0].Address[0].in_addr = GetRemote ? RemoteAddress : LocalAddress;
+    
+    AddressIP->Address[0].Address[0].in_addr = ipaddr.addr;
 
     return Status;
 }
 
-BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) {
+BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp )
+{
     PLIST_ENTRY Entry;
     PLIST_ENTRY ListHead[5];
     KIRQL OldIrql;