Whamcloud - gitweb
LU-459 tests: quiet spurious console/test messages
[fs/lustre-release.git] / libcfs / libcfs / winnt / winnt-tcpip.c
index cffe8a7..2da98fc 100644 (file)
 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
  * vim:expandtab:shiftwidth=4:tabstop=4:
  *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
+ * GPL HEADER START
  *
- *   This file is part of Lustre, http://www.lustre.org.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
- *   Lustre is free software; you can redistribute it and/or
- *   modify it under the terms of version 2 of the GNU General Public
- *   License as published by the Free Software Foundation.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
  *
- *   Lustre is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
  *
- *   You should have received a copy of the GNU General Public License
- *   along with Lustre; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Sun Microsystems, Inc.
  */
 
-#define DEBUG_SUBSYSTEM S_LIBCFS
+#define DEBUG_SUBSYSTEM S_LNET
 
 #include <libcfs/libcfs.h>
 #include <lnet/lnet.h>
 
-#define TDILND_MODULE_NAME L"Tdilnd"
+#define TDILND_MODULE_NAME L"tdilnd"
 
-ks_data_t ks_data;
+ks_tdi_data_t ks_data;
 
-ULONG
-ks_tdi_send_flags(ULONG SockFlags)
+VOID
+KsDumpPrint(PCHAR buffer, ULONG length)
 {
-    ULONG   TdiFlags = 0;
-
-    if (cfs_is_flag_set(SockFlags, MSG_OOB)) {
-        cfs_set_flag(TdiFlags, TDI_SEND_EXPEDITED);
-    }
-
-    if (cfs_is_flag_set(SockFlags, MSG_MORE)) {
-        cfs_set_flag(TdiFlags, TDI_SEND_PARTIAL);
+    ULONG i;
+    for (i=0; i < length; i++) {
+        if (((i+1) % 31) == 0)
+            printk("\n");
+        printk("%2.2x ", (UCHAR)buffer[i]);
     }
-
-    if (cfs_is_flag_set(SockFlags, MSG_DONTWAIT)) {
-        cfs_set_flag(TdiFlags, TDI_SEND_NON_BLOCKING);
-    }
-
-    return TdiFlags;
+    printk("\n");
 }
 
-NTSTATUS
-KsIrpCompletionRoutine(
-    IN PDEVICE_OBJECT    DeviceObject,
-    IN PIRP              Irp,
-    IN PVOID             Context
-    )
-{
-    if (NULL != Context) {
-        KeSetEvent((PKEVENT)Context, IO_NETWORK_INCREMENT, FALSE);
-    }
-
-    return STATUS_MORE_PROCESSING_REQUIRED;
+PVOID
+KsMapMdlBuffer (PMDL    Mdl);
 
-    UNREFERENCED_PARAMETER(DeviceObject);
-    UNREFERENCED_PARAMETER(Irp);
+VOID
+KsDumpMdlChain(PMDL Mdl, ULONG length)
+{
+    PMDL mdl = Mdl;
+    PCHAR buffer = NULL;
+    ULONG len = 0;
+    int i = 0;
+
+    while (mdl) {
+        printk("mdl %d:\n", i);
+        buffer = KsMapMdlBuffer(mdl);
+        KsDumpPrint(buffer, mdl->ByteCount);
+        len += mdl->ByteCount;
+        mdl = mdl->Next;
+    }
+    ASSERT(len == length);
 }
 
-
 /*
- * KsBuildTdiIrp
- *   Allocate a new IRP and initialize it to be issued to tdi
+ * KsLockUserBuffer
+ *   Allocate MDL for the buffer and lock the pages into
+ *   nonpaged pool
  *
  * Arguments:
- *   DeviceObject:  device object created by the underlying
- *                  TDI transport driver
+ *   UserBuffer:  the user buffer to be locked
+ *   Length:      length in bytes of the buffer
+ *   Operation:   read or write access
+ *   pMdl:        the result of the created mdl
  *
  * Return Value:
- *   PRIP:   the allocated Irp in success or NULL in failure.
+ *   NTSTATUS:     kernel status code (STATUS_SUCCESS
+ *                 or other error code)
  *
  * NOTES:
  *   N/A
  */
 
-PIRP
-KsBuildTdiIrp(
-    IN PDEVICE_OBJECT    DeviceObject
+NTSTATUS
+KsLockUserBuffer (
+    IN PVOID            UserBuffer,
+    IN BOOLEAN          bPaged,
+    IN ULONG            Length,
+    IN LOCK_OPERATION   Operation,
+    OUT PMDL *          pMdl
     )
 {
-    PIRP                Irp;
-    PIO_STACK_LOCATION  IrpSp;
+    NTSTATUS    Status;
+    PMDL        Mdl = NULL;
 
-    //
-    // Allocating the IRP ...
-    //
+    LASSERT(UserBuffer != NULL);
 
-    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+    *pMdl = NULL;
 
-    if (NULL != Irp) {
+    Mdl = IoAllocateMdl(
+                UserBuffer,
+                Length,
+                FALSE,
+                FALSE,
+                NULL
+                );
 
-        //
-        // Getting the Next Stack Location ...
-        //
+    if (Mdl == NULL) {
 
-        IrpSp = IoGetNextIrpStackLocation(Irp);
+        Status = STATUS_INSUFFICIENT_RESOURCES;
 
-        //
-        // Initializing Irp ...
-        //
+    } else {
 
-        IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
-        IrpSp->Parameters.DeviceIoControl.IoControlCode = 0;
+        __try {
+
+            if (bPaged) {
+                MmProbeAndLockPages(
+                    Mdl,
+                    KernelMode,
+                    Operation
+                    );
+            } else {
+                MmBuildMdlForNonPagedPool(
+                    Mdl
+                    );
+            }
+
+            Status = STATUS_SUCCESS;
+
+            *pMdl = Mdl;
+
+        } __except (EXCEPTION_EXECUTE_HANDLER) {
+
+            IoFreeMdl(Mdl);
+
+            Mdl = NULL;
+
+            cfs_enter_debugger();
+
+            Status = STATUS_INVALID_USER_BUFFER;
+        }
     }
 
-    return Irp;
+    return Status;
 }
 
 /*
- * KsSubmitTdiIrp
- *   Issue the Irp to the underlying tdi driver
+ * KsMapMdlBuffer
+ *   Map the mdl into a buffer in kernel space
  *
  * Arguments:
- *   DeviceObject:  the device object created by TDI driver
- *   Irp:           the I/O request packet to be processed
- *   bSynchronous:  synchronous or not. If true, we need wait
- *                  until the process is finished.
- *   Information:   returned info
+ *   Mdl:  the mdl to be mapped
  *
  * Return Value:
- *   NTSTATUS:      kernel status code
+ *   PVOID: the buffer mapped or NULL in failure
  *
  * NOTES:
  *   N/A
  */
 
-NTSTATUS
-KsSubmitTdiIrp(
-    IN PDEVICE_OBJECT   DeviceObject,
-    IN PIRP             Irp,
-    IN BOOLEAN          bSynchronous,
-    OUT PULONG          Information
-    )
+PVOID
+KsMapMdlBuffer (PMDL    Mdl)
 {
-    NTSTATUS            Status;
-    KEVENT              Event;
-
-    if (bSynchronous) {
-
-        KeInitializeEvent(
-            &Event,
-            SynchronizationEvent,
-            FALSE
-            );
+    LASSERT(Mdl != NULL);
 
+    return MmGetSystemAddressForMdlSafe(
+                Mdl,
+                NormalPagePriority
+                );
+}
 
-        IoSetCompletionRoutine(
-            Irp,
-            KsIrpCompletionRoutine,
-            &Event,
-            TRUE,
-            TRUE,
-            TRUE
-            );
-    }
 
-    Status = IoCallDriver(DeviceObject, Irp);
+/*
+ * KsReleaseMdl
+ *   Unlock all the pages in the mdl
+ *
+ * Arguments:
+ *   Mdl:  memory description list to be released
+ *
+ * Return Value:
+ *   N/A
+ *
+ * NOTES:
+ *   N/A
+ */
 
-    if (bSynchronous) {
+VOID
+KsReleaseMdl (IN PMDL   Mdl,
+              IN int    Paged )
+{
+    LASSERT(Mdl != NULL);
 
-        if (STATUS_PENDING == Status) {
+    while (Mdl) {
 
-            Status = KeWaitForSingleObject(
-                        &Event,
-                        Executive,
-                        KernelMode,
-                        FALSE,
-                        NULL
-                        );
-        }
+        PMDL    Next;
 
-        Status = Irp->IoStatus.Status;
+        Next = Mdl->Next;
 
-        if (Information) {
-            *Information = (ULONG)(Irp->IoStatus.Information);
+        if (Paged) {
+            MmUnlockPages(Mdl);
         }
 
-        Irp->MdlAddress = NULL;
-        IoFreeIrp(Irp);
-    }
-
-    if (!NT_SUCCESS(Status)) {
+        IoFreeMdl(Mdl);
 
-        KsPrint((2, "KsSubmitTdiIrp: Error when submitting the Irp: Status = %xh (%s) ...\n",
-                    Status, KsNtStatusToString(Status)));
+        Mdl = Next;
     }
-
-    return (Status);
 }
 
-
-
 /*
- * KsOpenControl
- *   Open the Control Channel Object ...
+ * KsQueryMdlsSize
+ *   Query the whole size of a MDL (may be chained)
  *
  * Arguments:
- *   DeviceName:   the device name to be opened
- *   Handle:       opened handle in success case
- *   FileObject:   the fileobject of the device
+ *   Mdl:  the Mdl to be queried
  *
  * Return Value:
- *   NTSTATUS:     kernel status code (STATUS_SUCCESS
- *                 or other error code)
+ *   ULONG: the total size of the mdl
  *
- * Notes:
+ * NOTES:
  *   N/A
  */
 
-NTSTATUS
-KsOpenControl(
-    IN PUNICODE_STRING      DeviceName,
-    OUT HANDLE *            Handle,
-    OUT PFILE_OBJECT *      FileObject
-   )
+ULONG
+KsQueryMdlsSize (PMDL Mdl)
 {
-    NTSTATUS          Status = STATUS_SUCCESS;
-
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    IO_STATUS_BLOCK   IoStatus;
-
+    PMDL    Next = Mdl;
+    ULONG   Length = 0;
 
-    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
 
     //
-    // Initializing ...
+    // Walking the MDL Chain ...
     //
 
-    InitializeObjectAttributes(
-        &ObjectAttributes,
-        DeviceName,
-        OBJ_CASE_INSENSITIVE |
-        OBJ_KERNEL_HANDLE,
-        NULL,
-        NULL
-        );
-
-    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
-
-    //
-    // Creating the Transport Address Object ...
-    //
+    while (Next) {
+        Length += MmGetMdlByteCount(Next);
+        Next = Next->Next;
+    }
 
-    Status = ZwCreateFile(
-                Handle,
-                FILE_READ_DATA | FILE_WRITE_DATA,
-                &ObjectAttributes,
-                &IoStatus,
-                0,
-                FILE_ATTRIBUTE_NORMAL,
-                FILE_SHARE_READ | FILE_SHARE_WRITE,
-                FILE_OPEN,
-                0,
-                NULL,
-                0
-                );
+    return (Length);
+}
 
+/*
+ * KsCopyMdlToBuffer
+ *   Copy payload from  Mdl to buffer
+ *
+ * Arguments:
+ *   SourceMdl: the source mdl
+ *   SourceOffset: start offset of the source
+ *   DestinationBuffer: the dst buffer
+ *   DestinationOffset: the offset where data are to be copied.
+ *   BytesTobecopied: the expteced bytes to be copied
+ *
+ * Return Value:
+ *   Length of data copied from MDL to user buffer
+ *
+ * NOTES:
+ *   N/A
+ */
 
-    if (NT_SUCCESS(Status)) {
+ULONG
+KsCopyMdlToBuffer(
+    IN PMDL     SourceMdl,
+    IN ULONG    SourceOffset,
+    IN PVOID    DestinationBuffer,
+    IN ULONG    DestinationOffset,
+    IN ULONG    BytesTobeCopied
+    )
+{
+    PUCHAR      SourceBuffer = NULL;
+    PUCHAR      TargetBuffer = DestinationBuffer;
+    ULONG       BytesCopied = 0;
 
-        //
-        // Now Obtaining the FileObject of the Transport Address ...
-        //
+    if (MmGetMdlByteCount(SourceMdl) <= SourceOffset) {
+        return 0;
+    }
 
-        Status = ObReferenceObjectByHandle(
-                    *Handle,
-                    FILE_ANY_ACCESS,
-                    NULL,
-                    KernelMode,
-                    FileObject,
-                    NULL
-                    );
+    BytesCopied = MmGetMdlByteCount(SourceMdl) - SourceOffset;
+    if (BytesCopied > BytesTobeCopied) {
+        BytesCopied = BytesTobeCopied;
+    }
 
-        if (!NT_SUCCESS(Status)) {
+    SourceBuffer = (PUCHAR)KsMapMdlBuffer(SourceMdl);
 
-            cfs_enter_debugger();
-            ZwClose(*Handle);
-        }
+    RtlMoveMemory(TargetBuffer + DestinationOffset,
+                  SourceBuffer + SourceOffset, BytesCopied);
 
-    } else {
+   return BytesCopied;
+}
 
-        cfs_enter_debugger();
-    }
+/*
+ * KsInitializeKsTsdu
+ *   Initialize the Tsdu buffer header
+ *
+ * Arguments:
+ *   KsTsdu: the Tsdu to be initialized
+ *   Length: the total length of the Tsdu
+ *
+ * Return Value:
+ *   VOID
+ *
+ * NOTES:
+ *   N/A
+ */
 
-    return (Status);
+VOID
+KsInitializeKsTsdu(
+    PKS_TSDU    KsTsdu,
+    ULONG       Length
+    )
+{
+    KsTsdu->Magic = KS_TSDU_MAGIC;
+    KsTsdu->TotalLength = Length;
+    KsTsdu->StartOffset = KsTsdu->LastOffset =
+    KS_QWORD_ALIGN(sizeof(KS_TSDU));
 }
 
-
 /*
- * KsCloseControl
- *   Release the Control Channel Handle and FileObject
+ * KsAllocateKsTsdu
+ *   Reuse a Tsdu from the freelist or allocate a new Tsdu
+ *   from the LookAsideList table or the NonPagedPool
  *
  * Arguments:
- *   Handle:       the channel handle to be released
- *   FileObject:   the fileobject to be released
+ *   N/A
  *
  * Return Value:
- *   NTSTATUS:     kernel status code (STATUS_SUCCESS
- *                 or other error code)
+ *   PKS_Tsdu: the new Tsdu or NULL if it fails
  *
  * Notes:
  *   N/A
  */
 
-NTSTATUS
-KsCloseControl(
-    IN HANDLE             Handle,
-    IN PFILE_OBJECT       FileObject
-   )
+PKS_TSDU
+KsAllocateKsTsdu()
 {
-    NTSTATUS  Status = STATUS_SUCCESS;
+    PKS_TSDU    KsTsdu = NULL;
 
-    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
+    cfs_spin_lock(&(ks_data.ksnd_tsdu_lock));
 
-    if (FileObject) {
+    if (!cfs_list_empty (&(ks_data.ksnd_freetsdus))) {
 
-        ObDereferenceObject(FileObject);
-    }
+        LASSERT(ks_data.ksnd_nfreetsdus > 0);
 
-    if (Handle) {
+        KsTsdu = cfs_list_entry(ks_data.ksnd_freetsdus.next, KS_TSDU, Link);
+        cfs_list_del(&(KsTsdu->Link));
+        ks_data.ksnd_nfreetsdus--;
 
-        Status = ZwClose(Handle);
+    } else {
+
+        KsTsdu = (PKS_TSDU) cfs_mem_cache_alloc(
+                        ks_data.ksnd_tsdu_slab, 0);
     }
 
-    ASSERT(NT_SUCCESS(Status));
+    cfs_spin_unlock(&(ks_data.ksnd_tsdu_lock));
 
-    return (Status);
+    if (NULL != KsTsdu) {
+        RtlZeroMemory(KsTsdu, ks_data.ksnd_tsdu_size);
+        KsInitializeKsTsdu(KsTsdu, (ULONG)ks_data.ksnd_tsdu_size);
+    }
+
+    return (KsTsdu);
 }
 
+/*
+ * KsFreeKsTsdu
+ *   Release a Tsdu: uninitialize then free it.
+ *
+ * Arguments:
+ *   KsTsdu: Tsdu to be freed.
+ *
+ * Return Value:
+ *   N/A
+ *
+ * Notes:
+ *   N/A
+ */
+
+VOID
+KsFreeKsTsdu(
+    PKS_TSDU  KsTsdu
+    )
+{
+    cfs_mem_cache_free(
+            ks_data.ksnd_tsdu_slab,
+            KsTsdu );
+}
 
 /*
- * KsOpenAddress
- *   Open the tdi address object
+ * KsPutKsTsdu
+ *   Move the Tsdu to the free tsdu list in ks_data.
  *
  * Arguments:
- *   DeviceName:   device name of the address object
- *   pAddress:     tdi address of the address object
- *   AddressLength: length in bytes of the tdi address
- *   Handle:       the newly opened handle
- *   FileObject:   the newly opened fileobject
+ *   KsTsdu: Tsdu to be moved.
  *
  * Return Value:
- *   NTSTATUS:     kernel status code (STATUS_SUCCESS
- *                 or other error code)
+ *   N/A
  *
  * Notes:
  *   N/A
  */
 
-NTSTATUS
-KsOpenAddress(
-    IN PUNICODE_STRING      DeviceName,
-    IN PTRANSPORT_ADDRESS   pAddress,
-    IN ULONG                AddressLength,
-    OUT HANDLE *            Handle,
-    OUT PFILE_OBJECT *      FileObject
-   )
+VOID
+KsPutKsTsdu(
+    PKS_TSDU  KsTsdu
+    )
 {
-    NTSTATUS          Status = STATUS_SUCCESS;
+    cfs_spin_lock(&(ks_data.ksnd_tsdu_lock));
+    if (ks_data.ksnd_nfreetsdus > 128) {
+        KsFreeKsTsdu(KsTsdu);
+    } else {
+        cfs_list_add_tail( &(KsTsdu->Link), &(ks_data.ksnd_freetsdus));
+        ks_data.ksnd_nfreetsdus++;
+    }
+    cfs_spin_unlock(&(ks_data.ksnd_tsdu_lock));
+}
 
-    PFILE_FULL_EA_INFORMATION Ea = NULL;
-    ULONG             EaLength;
-    UCHAR             EaBuffer[EA_MAX_LENGTH];
+/* with tconn lock acquired */
+ks_mdl_t *
+KsLockTsdus(
+    ks_tconn_t *    tconn,
+    PKS_TSDUMGR     TsduMgr,
+    PULONG          Flags,
+    PULONG          Length
+    )
+{
+    ks_mdl_t *      mdl = NULL;
+    ks_mdl_t *      tail = NULL;
 
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    IO_STATUS_BLOCK   IoStatus;
+    PKS_TSDU        KsTsdu;
+    PKS_TSDU_DAT    KsTsduDat;
+    PKS_TSDU_BUF    KsTsduBuf;
+    PKS_TSDU_MDL    KsTsduMdl;
 
-    //
-    // Building EA for the Address Object to be Opened ...
-    //
+    *Length  = 0;
 
-    Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
-    Ea->NextEntryOffset = 0;
-    Ea->Flags = 0;
-    Ea->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
-    Ea->EaValueLength = (USHORT)AddressLength;
-    RtlCopyMemory(
-        &(Ea->EaName),
-        TdiTransportAddress,
-        Ea->EaNameLength + 1
-        );
-    RtlMoveMemory(
-        &(Ea->EaName[Ea->EaNameLength + 1]),
-        pAddress,
-        AddressLength
-        );
-    EaLength =  sizeof(FILE_FULL_EA_INFORMATION) +
-                Ea->EaNameLength + AddressLength;
+    cfs_list_for_each_entry_typed(KsTsdu,
+            &TsduMgr->TsduList,KS_TSDU, Link) {
 
-    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
+        ULONG   start = 0;
 
+        LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
+        start = KsTsdu->StartOffset;
 
-    //
-    // Initializing ...
-    //
+        while (start < KsTsdu->LastOffset) {
 
-    InitializeObjectAttributes(
-        &ObjectAttributes,
-        DeviceName,
-        OBJ_CASE_INSENSITIVE |
-        OBJ_KERNEL_HANDLE,
-        NULL,
-        NULL
-        );
+            ks_mdl_t *  iov = NULL;
 
-    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
+            KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + start);
+            KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + start);
+            KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + start);
+            LASSERT(KsTsduDat->TsduType == TSDU_TYPE_DAT ||
+                    KsTsduBuf->TsduType == TSDU_TYPE_BUF ||
+                    KsTsduMdl->TsduType == TSDU_TYPE_MDL);
 
-    //
-    // Creating the Transport Address Object ...
-    //
+            if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
 
-    Status = ZwCreateFile(
-                Handle,
-                FILE_READ_DATA | FILE_WRITE_DATA,
-                &ObjectAttributes,
-                &IoStatus,
-                0,
-                FILE_ATTRIBUTE_NORMAL,
-                FILE_SHARE_READ | FILE_SHARE_WRITE, /* 0: DON'T REUSE */
-                FILE_OPEN,
-                0,
-                Ea,
-                EaLength
-                );
+                ASSERT(KsTsdu->LastOffset >= start + KsTsduDat->TotalLength);
+                if (KsTsduDat->Mdl) {
+                    iov = KsTsduDat->Mdl;
+                } else {
+                    KsLockUserBuffer(
+                        &KsTsduDat->Data[KsTsduDat->StartOffset],
+                        FALSE,
+                        KsTsduDat->DataLength,
+                        IoReadAccess,
+                        &iov );
+                    KsTsduDat->Mdl = iov;
+                }
+/*
+                printk("KsLockTsdus: %u\n", KsTsduDat->DataLength);
+                KsDumpPrint(
+                        &KsTsduDat->Data[KsTsduDat->StartOffset],
+                        KsTsduDat->DataLength);
+*/                        
+                *Length += KsTsduDat->DataLength;
+                start += KsTsduDat->TotalLength;
 
+            } else if (TSDU_TYPE_BUF == KsTsduBuf->TsduType) {
 
-    if (NT_SUCCESS(Status)) {
+                ASSERT(KsTsdu->LastOffset >= start + sizeof(KS_TSDU_BUF));
+                if (KsTsduBuf->Mdl) {
+                    iov = KsTsduBuf->Mdl;
+                } else {
+                    KsLockUserBuffer(
+                        (PUCHAR)KsTsduBuf->UserBuffer + 
+                                 KsTsduBuf->StartOffset,
+                        FALSE,
+                        KsTsduBuf->DataLength,
+                        IoReadAccess,
+                        &iov );
+                    KsTsduBuf->Mdl = iov;
+                }
 
-        //
-        // Now Obtaining the FileObject of the Transport Address ...
-        //
+                *Length += KsTsduBuf->DataLength;
+                start += sizeof(KS_TSDU_BUF);
 
-        Status = ObReferenceObjectByHandle(
-                    *Handle,
-                    FILE_ANY_ACCESS,
-                    NULL,
-                    KernelMode,
-                    FileObject,
-                    NULL
-                    );
-
-        if (!NT_SUCCESS(Status)) {
+            } else {
 
-            cfs_enter_debugger();
-            ZwClose(*Handle);
-        }
+                LASSERT(TSDU_TYPE_MDL == KsTsduMdl->TsduType);
+                ASSERT(KsTsdu->LastOffset >= start + sizeof(KS_TSDU_MDL));
+                iov = KsTsduMdl->Mdl; 
+                *Length += KsTsduMdl->DataLength;
+                start += sizeof(KS_TSDU_MDL);
+            }
 
-    } else {
+            if (!iov) {
+                cfs_enter_debugger();
+                goto cleanup;
+            }
 
-        cfs_enter_debugger();
+            if (tail) {
+                tail->Next = iov;
+            } else {
+                mdl = iov;
+            }
+            tail = iov;
+            tail->Next = NULL;
+/*
+            printk("KsLockTsdus: mdl %d\n", tail->ByteCount);
+            KsDumpMdlChain(tail, tail->ByteCount);
+*/
+        }
     }
+#if 0
+    if (Flags) {
+        *Flags = TsduFlags;
+    }
+#endif
+    return mdl;
 
-    return (Status);
+cleanup:
+    
+    *Length = 0;
+    return NULL;
 }
 
-/*
- * KsCloseAddress
- *   Release the Hanlde and FileObject of an opened tdi
- *   address object
- *
- * Arguments:
- *   Handle:       the handle to be released
- *   FileObject:   the fileobject to be released
- *
- * Return Value:
- *   NTSTATUS:     kernel status code (STATUS_SUCCESS
- *                 or other error code)
- *
- * Notes:
- *   N/A
- */
-
-NTSTATUS
-KsCloseAddress(
-    IN HANDLE             Handle,
-    IN PFILE_OBJECT       FileObject
-)
+ks_mdl_t *
+KsSplitMdl(
+    IN ks_mdl_t *   master,
+    IN ULONG        offset,
+    IN ULONG        length
+    )
 {
-    NTSTATUS  Status = STATUS_SUCCESS;
-
-    if (FileObject) {
+    ks_mdl_t *  mdl = NULL;
+    char *      ptr = NULL;
 
-        ObDereferenceObject(FileObject);
-    }
+    /* calculate the start virtual address */
+    ptr = (char *)KsMapMdlBuffer(master) + offset;
 
-    if (Handle) {
+    /* allocate new mdl for new memory range */
+    mdl = IoAllocateMdl(ptr, length, FALSE, FALSE, NULL);
 
-        Status = ZwClose(Handle);
+    if (!mdl) {
+        return NULL;
     }
+            
+    /* initialize the mdl */
+    IoBuildPartialMdl(master, mdl, (PVOID)ptr, length);
 
-    ASSERT(NT_SUCCESS(Status));
-
-    return (Status);
+    return mdl;
 }
 
+/* with tconn lock acquired */
+VOID
+KsReleaseTsdus(
+    ks_tconn_t *        tconn,
+    PKS_TSDUMGR         TsduMgr,
+    ULONG               length
+    )
+{
+    PKS_TSDU        KsTsdu;
+    PKS_TSDU_DAT    KsTsduDat;
+    PKS_TSDU_BUF    KsTsduBuf;
+    PKS_TSDU_MDL    KsTsduMdl;
+#if DBG    
+    ULONG           total = TsduMgr->TotalBytes;
+    ULONG           size = length;
+#endif
 
-/*
- * KsOpenConnection
- *   Open a tdi connection object
- *
- * Arguments:
- *   DeviceName:   device name of the connection object
- *   ConnectionContext: the connection context
- *   Handle:       the newly opened handle
- *   FileObject:   the newly opened fileobject
- *
- * Return Value:
- *   NTSTATUS:     kernel status code (STATUS_SUCCESS
- *                 or other error code)
- *
- * Notes:
- *   N/A
- */
+    LASSERT(TsduMgr->TotalBytes >= length);
 
-NTSTATUS
-KsOpenConnection(
-    IN PUNICODE_STRING      DeviceName,
-    IN CONNECTION_CONTEXT   ConnectionContext,
-    OUT HANDLE *            Handle,
-    OUT PFILE_OBJECT *      FileObject
-   )
-{
-    NTSTATUS            Status = STATUS_SUCCESS;
+    while (!cfs_list_empty(&TsduMgr->TsduList)) {
 
-    PFILE_FULL_EA_INFORMATION Ea = NULL;
-    ULONG               EaLength;
-    UCHAR               EaBuffer[EA_MAX_LENGTH];
+        ULONG   start = 0;
 
-    OBJECT_ATTRIBUTES   ObjectAttributes;
-    IO_STATUS_BLOCK     IoStatus;
+        KsTsdu = cfs_list_entry(TsduMgr->TsduList.next, KS_TSDU, Link);
+        LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
+        start = KsTsdu->StartOffset;
 
-    //
-    // Building EA for the Address Object to be Opened ...
-    //
+        while (length > 0 && start < KsTsdu->LastOffset) {
 
-    Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
-    Ea->NextEntryOffset = 0;
-    Ea->Flags = 0;
-    Ea->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
-    Ea->EaValueLength = (USHORT)sizeof(CONNECTION_CONTEXT);
-    RtlCopyMemory(
-        &(Ea->EaName),
-        TdiConnectionContext,
-        Ea->EaNameLength + 1
-        );
-    RtlMoveMemory(
-        &(Ea->EaName[Ea->EaNameLength + 1]),
-        &ConnectionContext,
-        sizeof(CONNECTION_CONTEXT)
-        );
-    EaLength = sizeof(FILE_FULL_EA_INFORMATION) - 1 +
-                               Ea->EaNameLength + 1 + sizeof(CONNECTION_CONTEXT);
+            ULONG           size = 0;
+            ks_mdl_t *      mdl = NULL;
 
-    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
+            KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + start);
+            KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + start);
+            KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + start);
+            LASSERT(KsTsduDat->TsduType == TSDU_TYPE_DAT ||
+                    KsTsduBuf->TsduType == TSDU_TYPE_BUF ||
+                    KsTsduMdl->TsduType == TSDU_TYPE_MDL);
 
+            if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
 
-    //
-    // Initializing ...
-    //
+                ASSERT(KsTsdu->LastOffset >= start + KsTsduDat->DataLength);
+                if (length >= KsTsduDat->DataLength) {
+                    /* whole tsdu is sent out */
+                    size = KsTsduDat->DataLength;
+                    start += KsTsduDat->TotalLength;
+                } else {
+                    size = length;
+                    KsTsduDat->StartOffset += size;
+                }
 
-    InitializeObjectAttributes(
-        &ObjectAttributes,
-        DeviceName,
-        OBJ_CASE_INSENSITIVE |
-        OBJ_KERNEL_HANDLE,
-        NULL,
-        NULL
-        );
+                if (KsTsduDat->Mdl) {
+                    mdl = KsTsduDat->Mdl;
+                    KsTsduDat->Mdl = NULL;
+                }
 
-    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
+                KsTsduDat->DataLength -= size;
 
-    //
-    // Creating the Connection Object ...
-    //
+            } else if (TSDU_TYPE_BUF == KsTsduBuf->TsduType) {
 
-    Status = ZwCreateFile(
-                Handle,
-                FILE_READ_DATA | FILE_WRITE_DATA,
-                &ObjectAttributes,
-                &IoStatus,
-                NULL,
-                FILE_ATTRIBUTE_NORMAL,
-                0,
-                FILE_OPEN,
-                0,
-                Ea,
-                EaLength
-                );
+                ASSERT(KsTsdu->LastOffset >= start + sizeof(KS_TSDU_BUF));
+                if (length >= KsTsduBuf->DataLength) {
+                    /* whole tsdu is sent out */
+                    size = KsTsduBuf->DataLength;
+                    start += sizeof(KS_TSDU_BUF);
+                    LASSERT(KsTsduBuf->UserBuffer);
+                    ExFreePool(KsTsduBuf->UserBuffer);
+                    KsTsduBuf->UserBuffer = NULL;
+                } else {
+                    KsTsduBuf->StartOffset += length;
+                    size = length;
+                }
 
+                if (KsTsduBuf->Mdl) {
+                    mdl = KsTsduBuf->Mdl;
+                    KsTsduBuf->Mdl = NULL;
+                }
 
-    if (NT_SUCCESS(Status)) {
+                KsTsduBuf->DataLength -= size;
+                
+            } else {
 
-        //
-        // Now Obtaining the FileObject of the Transport Address ...
-        //
+                LASSERT(TSDU_TYPE_MDL == KsTsduMdl->TsduType);
+                ASSERT(KsTsdu->LastOffset >= start + sizeof(KS_TSDU_MDL));
+                mdl = KsTsduMdl->Mdl;
+                if (length >= KsTsduMdl->DataLength) {
+                    /* whole mdl is sent out */
+                    size = KsTsduMdl->DataLength;
+                    start += sizeof(KS_TSDU_MDL);
+                    KsTsduMdl->Mdl = NULL;
+                } else {
+                    /* now split the remained data out */
+                    ks_mdl_t * mdl1 = KsSplitMdl(mdl, length,
+                                  KsTsduMdl->DataLength - length);
+                    if (NULL == mdl1) {
+                        mdl->ByteOffset += length;
+                        mdl = NULL;
+                    } else {
+                        KsTsduMdl->Mdl = mdl1;
+                    }
+                    size = length;
+                    KsTsduMdl->StartOffset += size;
+                }
 
-        Status = ObReferenceObjectByHandle(
-                    *Handle,
-                    FILE_ANY_ACCESS,
-                    NULL,
-                    KernelMode,
-                    FileObject,
-                    NULL
-                    );
+                KsTsduMdl->DataLength -= size;
+            }
 
-        if (!NT_SUCCESS(Status)) {
+            length -= size;
+            TsduMgr->TotalBytes -= size;
 
-            cfs_enter_debugger();
-            ZwClose(*Handle);
+            if (mdl) {
+                mdl->Next = NULL;
+                KsReleaseMdl(mdl, FALSE);
+            }
+
+            KsTsdu->StartOffset = start;
         }
 
-    } else {
+        if (KsTsdu->StartOffset >= KsTsdu->LastOffset) {
 
-        cfs_enter_debugger();
+            /* remove KsTsdu from list */
+            cfs_list_del(&KsTsdu->Link);
+            TsduMgr->NumOfTsdu--;
+            KsPutKsTsdu(KsTsdu);
+        }
+
+        if (length == 0) {
+            break;
+        }
     }
 
-    return (Status);
+    LASSERT(length == 0);
+#if DBG
+    LASSERT(total - size == TsduMgr->TotalBytes);
+    KsPrint((4, "KsReleaseTsdus: TsduMgr=%p Remained=%xh (%xh)\n",
+                TsduMgr, TsduMgr->TotalBytes, size ));
+#endif
 }
 
-/*
- * KsCloseConnection
- *   Release the Hanlde and FileObject of an opened tdi
- *   connection object
- *
- * Arguments:
- *   Handle:       the handle to be released
- *   FileObject:   the fileobject to be released
- *
- * Return Value:
- *   NTSTATUS:     kernel status code (STATUS_SUCCESS
- *                 or other error code)
- *
- * Notes:
- *   N/A
- */
-
-NTSTATUS
-KsCloseConnection(
-    IN HANDLE             Handle,
-    IN PFILE_OBJECT       FileObject
+PKS_TSDUMGR
+KsQueryTsduMgr(
+    ks_tconn_t *    tconn,
+    BOOLEAN         expedited,
+    BOOLEAN         sending
     )
 {
-    NTSTATUS  Status = STATUS_SUCCESS;
 
-    if (FileObject) {
-
-        ObDereferenceObject(FileObject);
-    }
+    PKS_CHAIN           KsChain;
+    PKS_TSDUMGR         TsduMgr;
 
-    if (Handle) {
+    /* get the latest Tsdu buffer form TsduMgr list.
+       just set NULL if the list is empty. */
 
-        Status = ZwClose(Handle);
+    if (sending) {
+        if (tconn->kstc_type == kstt_sender) {
+            KsChain = &(tconn->sender.kstc_send);
+        } else {
+            LASSERT(tconn->kstc_type == kstt_child);
+            KsChain = &(tconn->child.kstc_send);
+        }
+    } else {
+        if (tconn->kstc_type == kstt_sender) {
+            KsChain = &(tconn->sender.kstc_recv);
+        } else {
+            LASSERT(tconn->kstc_type == kstt_child);
+            KsChain = &(tconn->child.kstc_recv);
+        }
     }
 
-    ASSERT(NT_SUCCESS(Status));
+    if (expedited) {
+        TsduMgr = &(KsChain->Expedited);
+    } else {
+        TsduMgr = &(KsChain->Normal);
+    }
 
-    return (Status);
+    return TsduMgr;
 }
 
-
-/*
- * KsAssociateAddress
- *   Associate an address object with a connection object
- *
- * Arguments:
- *   AddressHandle:  the handle of the address object
- *   ConnectionObject:  the FileObject of the connection
- *
- * Return Value:
- *   NTSTATUS:     kernel status code (STATUS_SUCCESS
- *                 or other error code)
- *
- * Notes:
- *   N/A
- */
-
-NTSTATUS
-KsAssociateAddress(
-    IN HANDLE           AddressHandle,
-    IN PFILE_OBJECT     ConnectionObject
-    )
+PKS_TSDU
+KsGetTsdu(PKS_TSDUMGR TsduMgr, ULONG Length)
 {
-    NTSTATUS            Status;
-    PDEVICE_OBJECT      DeviceObject;
-    PIRP                Irp;
+    PKS_TSDU KsTsdu = NULL;
 
-    //
-    // Getting the DeviceObject from Connection FileObject
-    //
+    /* retrieve the latest Tsdu buffer form TsduMgr
+       list if the list is not empty. */
 
-    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
+    if (cfs_list_empty(&(TsduMgr->TsduList))) {
 
-    //
-    // Building Tdi Internal Irp ...
-    //
-
-    Irp = KsBuildTdiIrp(DeviceObject);
-
-    if (NULL == Irp) {
-
-        Status = STATUS_INSUFFICIENT_RESOURCES;
+        LASSERT(TsduMgr->NumOfTsdu == 0);
+        KsTsdu = NULL;
 
     } else {
 
-        //
-        // Assocating the Address Object with the Connection Object
-        //
+        LASSERT(TsduMgr->NumOfTsdu > 0);
+        KsTsdu = cfs_list_entry(TsduMgr->TsduList.prev, KS_TSDU, Link);
 
-        TdiBuildAssociateAddress(
-            Irp,
-            DeviceObject,
-            ConnectionObject,
-            NULL,
-            NULL,
-            AddressHandle
-            );
+        /* if this Tsdu does not contain enough space, we need
+           allocate a new Tsdu queue. */
 
-        //
-        // Calling the Transprot Driver with the Prepared Irp
-        //
+        if (KsTsdu->LastOffset + Length > KsTsdu->TotalLength) {
+            KsTsdu = NULL;
+        }
+    }
 
-        Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
+    /* allocate a new Tsdu in case we are not statisfied. */
+    if (NULL == KsTsdu) {
+        KsTsdu = KsAllocateKsTsdu();
+        if (NULL != KsTsdu) {
+            cfs_list_add_tail(&(KsTsdu->Link), &(TsduMgr->TsduList));
+            TsduMgr->NumOfTsdu++;
+        }
     }
 
-    return (Status);
+    return KsTsdu;
 }
 
+ULONG
+KsWriteTsduDat(
+    PKS_TSDUMGR TsduMgr,
+    PCHAR       buffer,
+    ULONG       length,
+    ULONG       flags
+    )
+{
+    PKS_TSDU            KsTsdu;
+    PKS_TSDU_DAT        KsTsduDat;
+    PKS_TSDU_BUF        KsTsduBuf;
+
+    BOOLEAN             bNewBuff = FALSE;
+    PCHAR               Buffer = NULL;
 
 /*
- * KsDisassociateAddress
- *   Disassociate the connection object (the relationship will
- *   the corresponding address object will be dismissed. )
- *
- * Arguments:
- *   ConnectionObject:  the FileObject of the connection
- *
- * Return Value:
- *   NTSTATUS:     kernel status code (STATUS_SUCCESS
- *                 or other error code)
- *
- * Notes:
- *   N/A
- */
+    printk("KsWriteTsduDat: %u\n", length);
+    KsDumpPrint(buffer, length);
+*/
+    /* if the Tsdu is even larger than the biggest Tsdu, we have
+       to allocate new buffer and use TSDU_TYPE_BUF to store it */
 
-NTSTATUS
-KsDisassociateAddress(
-    IN PFILE_OBJECT     ConnectionObject
-    )
-{
-    NTSTATUS            Status;
-    PDEVICE_OBJECT      DeviceObject;
-    PIRP                   Irp;
+    if ( KS_TSDU_STRU_SIZE(length) > ks_data.ksnd_tsdu_size -
+         KS_QWORD_ALIGN(sizeof(KS_TSDU))) {
+        bNewBuff = TRUE;
+    }
 
-    //
-    // Getting the DeviceObject from Connection FileObject
-    //
+    /* allocating the buffer for TSDU_TYPE_BUF */
+    if (bNewBuff) {
+        Buffer = ExAllocatePool(NonPagedPool, length);
+        if (NULL == Buffer) {
+            /* there's no enough memory for us. We just try to
+               receive maximum bytes with a new Tsdu */
+            bNewBuff = FALSE;
+            length = ks_data.ksnd_tsdu_size - KS_TSDU_STRU_SIZE(0) - 
+                     KS_QWORD_ALIGN(sizeof(KS_TSDU));
+        }
+    }
 
-    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
+    /* get empty Tsdu from TsduMgr */
+    KsTsdu = KsGetTsdu(TsduMgr, bNewBuff ? sizeof(KS_TSDU_BUF) :
+                                KS_TSDU_STRU_SIZE(length) );
 
-    //
-    // Building Tdi Internal Irp ...
-    //
+    /* allocate a new Tsdu in case we are not statisfied. */
+    if (NULL == KsTsdu) {
+        goto errorout;
+    }
 
-    Irp = KsBuildTdiIrp(DeviceObject);
+    KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
+    KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
 
-    if (NULL == Irp) {
+    if (bNewBuff) {
 
-        Status = STATUS_INSUFFICIENT_RESOURCES;
+        /* setup up the KS_TSDU_BUF record */
+        KsTsduBuf->TsduType     = TSDU_TYPE_BUF;
+        KsTsduBuf->TsduFlags    = 0;
+        KsTsduBuf->StartOffset  = 0;
+        KsTsduBuf->UserBuffer   = Buffer;
+        KsTsduBuf->DataLength   = length;
+        KsTsduBuf->Mdl          = NULL;
+        if (cfs_is_flag_set(flags, TDI_SEND_PARTIAL)) {
+            KsTsduBuf->TsduFlags |= KS_TSDU_COMM_PARTIAL;
+        }
+
+        KsTsdu->LastOffset += sizeof(KS_TSDU_BUF);
 
     } else {
 
-        //
-        // Disassocating the Address Object with the Connection Object
-        //
+        /* setup the KS_TSDU_DATA to contain all the messages */
 
-        TdiBuildDisassociateAddress(
-            Irp,
-            DeviceObject,
-            ConnectionObject,
-            NULL,
-            NULL
-            );
+        KsTsduDat->TsduType     =  TSDU_TYPE_DAT;
+        KsTsduDat->TsduFlags    = 0;
 
-        //
-        // Calling the Transprot Driver with the Prepared Irp
-        //
+        if ( KsTsdu->TotalLength - KsTsdu->LastOffset < 
+            KS_TSDU_STRU_SIZE(length) ) {
+            length = KsTsdu->TotalLength - KsTsdu->LastOffset -
+                     FIELD_OFFSET(KS_TSDU_DAT, Data);
+        }
+        KsTsduDat->DataLength   =  length;
+        KsTsduDat->TotalLength  =  KS_TSDU_STRU_SIZE(length);
+        KsTsduDat->StartOffset  = 0;
+        KsTsduDat->Mdl = NULL;
+        if (cfs_is_flag_set(flags, TDI_SEND_PARTIAL)) {
+            KsTsduDat->TsduFlags |= KS_TSDU_COMM_PARTIAL;
+        }
 
-        Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
+        Buffer = &KsTsduDat->Data[0];
+        KsTsdu->LastOffset += KsTsduDat->TotalLength;
     }
 
-    return (Status);
-}
-
+    RtlMoveMemory(Buffer, buffer, length);
+    TsduMgr->TotalBytes += length;
 
-/*
+    KsPrint((4, "KsWriteTsduDat: TsduMgr=%p bytes in queue:%xh (%xh)\n",
+                TsduMgr, TsduMgr->TotalBytes, length));
+    return length;
 
-//
-// Connection Control Event Callbacks
-//
+errorout:
 
-TDI_EVENT_CONNECT
-TDI_EVENT_DISCONNECT
-TDI_EVENT_ERROR
+    return 0;
+}
 
-//
-// Tcp Event Callbacks
-//
+ULONG
+KsWriteTsduBuf(
+    PKS_TSDUMGR TsduMgr,
+    PCHAR       buffer,
+    ULONG       length,
+    ULONG       flags
+    )
+{
+    PKS_TSDU            KsTsdu;
+    PKS_TSDU_BUF        KsTsduBuf;
 
-TDI_EVENT_RECEIVE
-TDI_EVENT_RECEIVE_EXPEDITED
-TDI_EVENT_CHAINED_RECEIVE
-TDI_EVENT_CHAINED_RECEIVE_EXPEDITED
+    /* get empty Tsdu from TsduMgr */
+    KsTsdu = KsGetTsdu(TsduMgr, sizeof(KS_TSDU_BUF));
 
-//
-// Udp Event Callbacks
-//
+    /* allocate a new Tsdu in case we are not statisfied. */
+    if (NULL == KsTsdu) {
+        goto errorout;
+    }
 
-TDI_EVENT_RECEIVE_DATAGRAM
-TDI_EVENT_CHAINED_RECEIVE_DATAGRAM
+    /* setup up the KS_TSDU_BUF record */
+    KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
+    KsTsduBuf->TsduType     = TSDU_TYPE_BUF;
+    KsTsduBuf->TsduFlags    = 0;
+    KsTsduBuf->StartOffset  = 0;
+    KsTsduBuf->UserBuffer   = buffer;
+    KsTsduBuf->DataLength   = length;
+    KsTsduBuf->Mdl          = NULL;
+    KsTsdu->LastOffset += sizeof(KS_TSDU_BUF);
+    if (cfs_is_flag_set(flags, TDI_SEND_PARTIAL)) {
+        KsTsduBuf->TsduFlags |= KS_TSDU_COMM_PARTIAL;
+    }
 
-*/
+    TsduMgr->TotalBytes  +=  length;
+    KsPrint((4, "KsWriteTsduBuf: TsduMgr=%p bytes in queue:%xh (%xh)\n",
+                TsduMgr, TsduMgr->TotalBytes, length));
 
+    return length;
 
-/*
- * KsSetEventHandlers
- *   Set the tdi event callbacks with an address object
- *
- * Arguments:
- *   AddressObject: the FileObject of the address object
- *   EventContext:  the parameter for the callbacks
- *   Handlers:      the handlers indictor array
- *
- * Return Value:
- *   NTSTATUS:     kernel status code (STATUS_SUCCESS
- *                 or other error code)
- *
- * NOTES:
- *   N/A
- */
+errorout:
+    return 0;
+}
 
-NTSTATUS
-KsSetEventHandlers(
-    IN PFILE_OBJECT                         AddressObject,  // Address File Object
-    IN PVOID                                EventContext,   // Context for Handlers
-    IN PKS_EVENT_HANDLERS                   Handlers        // Handlers Indictor
-   )
+ULONG
+KsWriteTsduMdl(
+    PKS_TSDUMGR     TsduMgr,
+    ks_mdl_t *      mdl, 
+    PVOID           desc,
+    ULONG           offset,
+    ULONG           length,
+    ULONG           flags
+    )
 {
-    NTSTATUS             Status = STATUS_SUCCESS;
-    PDEVICE_OBJECT       DeviceObject;
-    USHORT               i = 0;
+    PKS_TSDU            KsTsdu;
+    PKS_TSDU_MDL        KsTsduMdl;
 
-    DeviceObject = IoGetRelatedDeviceObject(AddressObject);
+    /* get empty Tsdu from TsduMgr */
+    KsTsdu = KsGetTsdu(TsduMgr, sizeof(KS_TSDU_MDL));
 
-    for (i=0; i < TDI_EVENT_MAXIMUM_HANDLER; i++) {
+    /* allocate a new Tsdu in case we are not statisfied. */
+    if (NULL == KsTsdu) {
+        goto errorout;
+    }
 
-        //
-        // Setup the tdi event callback handler if requested.
-        //
+    /* setup up the KS_TSDU_MDL record */
+    KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
+    KsTsduMdl->TsduType     = TSDU_TYPE_MDL;
+    KsTsduMdl->TsduFlags    = 0;
+    KsTsduMdl->StartOffset  = 0;
+    KsTsduMdl->BaseOffset   = offset;
+    KsTsduMdl->DataLength   = length;
+    KsTsduMdl->Mdl          = mdl;
+    KsTsduMdl->Descriptor   = desc;
+    KsTsdu->LastOffset += sizeof(KS_TSDU_MDL);
+    if (cfs_is_flag_set(flags, TDI_SEND_PARTIAL)) {
+        KsTsduMdl->TsduFlags |= KS_TSDU_COMM_PARTIAL;
+    }
 
-        if (Handlers->IsActive[i]) {
+    TsduMgr->TotalBytes  +=  length;
+    KsPrint((4, "KsWriteTsduMdl: TsduMgr=%p bytes in queue:%xh (%xh)\n",
+                TsduMgr, TsduMgr->TotalBytes, length));
 
-            PIRP            Irp;
+    return length;
 
-            //
-            // Building Tdi Internal Irp ...
-            //
+errorout:
+    return 0;
+}
 
-            Irp = KsBuildTdiIrp(DeviceObject);
+ULONG
+KsReadTsdu (
+    PKS_TSDUMGR     TsduMgr,
+    PCHAR           buffer,
+    ULONG           length,
+    ULONG           flags
+    )
+{
+    PKS_TSDU        KsTsdu;
+    PKS_TSDU_DAT    KsTsduDat;
+    PKS_TSDU_BUF    KsTsduBuf;
+    PKS_TSDU_MDL    KsTsduMdl;
 
-            if (NULL == Irp) {
+    PUCHAR          Buffer;
+    ULONG           BytesRecved = 0;
+#if DBG
+    ULONG           TotalBytes = TsduMgr->TotalBytes;
+#endif    
 
-                Status = STATUS_INSUFFICIENT_RESOURCES;
+    KsPrint((4, "KsReadTsdu: TsduMgr=%p request=%xh total=%xh\n",
+                TsduMgr, length, TsduMgr->TotalBytes ));
+NextTsdu:
 
-            } else {
+    if (TsduMgr->TotalBytes == 0) {
 
-                //
-                // Building the Irp to set the Event Handler ...
-                //
+        /* It's a notification event. We need reset it to
+           un-signaled state in case there no any tsdus. */
 
-                TdiBuildSetEventHandler(
-                    Irp,
-                    DeviceObject,
-                    AddressObject,
-                    NULL,
-                    NULL,
-                    i,                      /* tdi event type */
-                    Handlers->Handler[i],   /* tdi event handler */
-                    EventContext            /* context for the handler */
-                    );
+        KeResetEvent(&(TsduMgr->Event));
 
-                //
-                // Calling the Transprot Driver with the Prepared Irp
-                //
+    } else {
 
-                Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
+        KsTsdu = cfs_list_entry(TsduMgr->TsduList.next, KS_TSDU, Link);
+        LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
 
-                //
-                // tcp/ip tdi does not support these two event callbacks
-                //
+        /* remove the KsTsdu from TsduMgr list to release the lock */
+        cfs_list_del(&(KsTsdu->Link));
+        TsduMgr->NumOfTsdu--;
 
-                if ((!NT_SUCCESS(Status)) && ( i == TDI_EVENT_SEND_POSSIBLE ||
-                     i == TDI_EVENT_CHAINED_RECEIVE_EXPEDITED )) {
-                    cfs_enter_debugger();
-                    Status = STATUS_SUCCESS;
-                }
-            }
+        while (length > BytesRecved) {
 
-            if (!NT_SUCCESS(Status)) {
-                cfs_enter_debugger();
-                goto errorout;
+            ULONG BytesToCopy = 0;
+            ULONG StartOffset = 0;
+            ULONG BytesCopied = 0;
+
+            if (KsTsdu->StartOffset >= KsTsdu->LastOffset) {
+                /* KsTsdu is empty now, we need free it ... */
+                KsPutKsTsdu(KsTsdu);
+                KsTsdu = NULL;
+                break;
             }
-        }
-    }
 
+            KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
+            KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
+            KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
 
-errorout:
+            if ( TSDU_TYPE_DAT == KsTsduDat->TsduType ||
+                 TSDU_TYPE_BUF == KsTsduBuf->TsduType ) {
 
-    if (!NT_SUCCESS(Status)) {
+                if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
 
-        KsPrint((2, "KsSetEventHandlers: Error Status = %xh (%s)\n",
-                    Status, KsNtStatusToString(Status) ));
-    }
+                    /* Data Tsdu Unit ... */
+                    Buffer = &KsTsduDat->Data[0];
+                    StartOffset = KsTsduDat->StartOffset;
+                    if (KsTsduDat->DataLength - KsTsduDat->StartOffset > length - BytesRecved) {
+                        /* Recvmsg requst could be statisfied ... */
+                        BytesToCopy = length - BytesRecved;
+                    } else {
+                        BytesToCopy = KsTsduDat->DataLength - KsTsduDat->StartOffset;
+                    }
 
-    return (Status);
-}
+                } else {
 
+                    /* Buffer Tsdu Unit */
+                    ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
+                    Buffer = KsTsduBuf->UserBuffer;
+                    StartOffset = KsTsduBuf->StartOffset;
 
+                    if (KsTsduBuf->DataLength - KsTsduBuf->StartOffset > length - BytesRecved) {
+                        /* Recvmsg requst could be statisfied ... */
+                        BytesToCopy = length - BytesRecved;
+                    } else {
+                        BytesToCopy = KsTsduBuf->DataLength - KsTsduBuf->StartOffset;
+                    }
+                }
 
-/*
- * KsQueryAddressInfo
- *   Query the address of the FileObject specified
- *
- * Arguments:
- *   FileObject:  the FileObject to be queried
- *   AddressInfo: buffer to contain the address info
- *   AddressSize: length of the AddressInfo buffer
- *
- * Return Value:
- *   NTSTATUS:     kernel status code (STATUS_SUCCESS
- *                 or other error code)
- *
- * Notes:
- *   N/A
- */
+                if (BytesToCopy > 0) {
+                    RtlMoveMemory(buffer + BytesRecved, Buffer + StartOffset, BytesToCopy);
+                }
+                BytesCopied = BytesToCopy;
+                BytesRecved += BytesCopied;
+                LASSERT(TsduMgr->TotalBytes >= BytesCopied);
+                TsduMgr->TotalBytes -= BytesCopied;
+                KsPrint((4, "KsReadTsdu: TsduMgr=%p copied=%xh recved=%xh\n",
+                            TsduMgr, BytesCopied, BytesRecved ));
 
-NTSTATUS
-KsQueryAddressInfo(
-    PFILE_OBJECT            FileObject,
-    PTDI_ADDRESS_INFO       AddressInfo,
-    PULONG                  AddressSize
-   )
-{
-    NTSTATUS          Status = STATUS_UNSUCCESSFUL;
-    PIRP              Irp = NULL;
-    PMDL              Mdl;
-    PDEVICE_OBJECT    DeviceObject;
+                if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
 
-    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
+                    KsTsduDat->StartOffset += BytesCopied;
+                    if (KsTsduDat->StartOffset == KsTsduDat->DataLength) {
+                        if (KsTsduDat->Mdl) {
+                            KsTsduDat->Mdl->Next = NULL;
+                            KsReleaseMdl(KsTsduDat->Mdl, FALSE);
+                        }
+                        KsTsdu->StartOffset += KsTsduDat->TotalLength;
+                    }
 
-    DeviceObject = IoGetRelatedDeviceObject(FileObject);
+                } else {
 
-    RtlZeroMemory(AddressInfo, *(AddressSize));
+                    ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
+                    KsTsduBuf->StartOffset += BytesCopied;
+                    if (KsTsduBuf->StartOffset == KsTsduBuf->DataLength) {
+                        KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
+                        /* now we need release the buf to system pool */
+                        if (KsTsduBuf->Mdl) {
+                            KsTsduBuf->Mdl->Next = NULL;
+                            KsReleaseMdl(KsTsduBuf->Mdl, FALSE);
+                        }
+                        ExFreePool(KsTsduBuf->UserBuffer);
+                    }
+                }
 
-    //
-    // Allocating the Tdi Setting Irp ...
-    //
+            } else if (TSDU_TYPE_MDL == KsTsduMdl->TsduType) {
 
-    Irp = KsBuildTdiIrp(DeviceObject);
+                /* MDL Tsdu Unit ... */
+                if (KsTsduMdl->DataLength > length - BytesRecved) {
+                    /* Recvmsg requst could be statisfied ... */
+                    BytesToCopy = length - BytesRecved;
+                } else {
+                    BytesToCopy = KsTsduMdl->DataLength;
+                }
 
-    if (NULL == Irp) {
+                BytesCopied = 
+                    KsCopyMdlToBuffer(
+                            KsTsduMdl->Mdl,
+                            KsTsduMdl->StartOffset + 
+                            KsTsduMdl->BaseOffset,
+                            buffer,
+                            BytesRecved,
+                            BytesToCopy
+                            );
+                KsPrint((4, "KsReadTsdu: TsduMgr=%p mdl=%p dec=%p copied=%xh "
+                            "recved=%xh\n",
+                            TsduMgr, KsTsduMdl->Mdl, KsTsduMdl->Descriptor,
+                            BytesCopied, BytesRecved + BytesCopied));
+                if (BytesCopied == 0) {
+                    cfs_enter_debugger();
+                    break;
+                }
 
-        Status = STATUS_INSUFFICIENT_RESOURCES;
+                KsTsduMdl->StartOffset += BytesCopied;
+                KsTsduMdl->DataLength  -= BytesCopied;
+                BytesRecved += BytesCopied;
+                LASSERT(TsduMgr->TotalBytes >= BytesCopied);
+                TsduMgr->TotalBytes -= BytesCopied;
 
-    } else {
+                if (0 == KsTsduMdl->DataLength) {
 
-        //
-        // Locking the User Buffer / Allocating a MDL for it
-        //
+                    /* Call TdiReturnChainedReceives to release the Tsdu memory */
+                    LASSERT(KsTsduMdl->Descriptor != NULL);
+                    if (KsTsduMdl->Descriptor) {
+                        TdiReturnChainedReceives(
+                            &(KsTsduMdl->Descriptor),
+                            1 );
+                    }
 
-        Status = KsLockUserBuffer(
-                    AddressInfo,
-                    FALSE,
-                    *(AddressSize),
-                    IoModifyAccess,
-                    &Mdl
-                    );
+                    KsTsdu->StartOffset += sizeof(KS_TSDU_MDL);
+                }
 
-        if (!NT_SUCCESS(Status)) {
+            } else {
+                KsPrint((1, "KsReadTsdu: unknown tsdu slot: slot = %x type = %x Start= %x Length=%x\n",
+                        KsTsduDat, KsTsduDat->TsduType, KsTsduDat->StartOffset, KsTsduDat->DataLength));
+                KsPrint((1, "            Tsdu = %x Magic=%x: Start = %x Last = %x Length = %x\n",
+                        KsTsdu, KsTsdu->Magic, KsTsdu->StartOffset, KsTsdu->LastOffset, KsTsdu->TotalLength));
+                cfs_enter_debugger();
+            }
+        }
 
-            IoFreeIrp(Irp);
-            Irp = NULL;
+        /* we need attach the KsTsdu to the list header */
+        if (KsTsdu) {
+            if (KsTsdu->StartOffset >= KsTsdu->LastOffset) {
+                KsPutKsTsdu(KsTsdu);
+                KsTsdu = NULL;
+            } else {
+                TsduMgr->NumOfTsdu++;
+                cfs_list_add(&(KsTsdu->Link), &(TsduMgr->TsduList));
+            }
+        }
+        
+        if (length > BytesRecved) {
+            goto NextTsdu;
         }
     }
 
-    if (Irp) {
+#if DBG
+    LASSERT(TotalBytes == TsduMgr->TotalBytes + BytesRecved);
+#endif
+    KsPrint((4, "KsReadTsdu: TsduMgr=%p recved=%xh (%xh) remained=%xh\n",
+                TsduMgr, BytesRecved, length, TsduMgr->TotalBytes ));
 
-        LASSERT(NT_SUCCESS(Status));
+    return BytesRecved;
+}
 
-        TdiBuildQueryInformation(
-                    Irp,
-                    DeviceObject,
-                    FileObject,
-                    NULL,
-                    NULL,
-                    TDI_QUERY_ADDRESS_INFO,
-                    Mdl
-                    );
 
-        Status = KsSubmitTdiIrp(
-                    DeviceObject,
-                    Irp,
-                    TRUE,
-                    AddressSize
-                    );
+ULONG
+KsTdiSendFlags(int SockFlags)
+{
+    ULONG   TdiFlags = 0;
 
-        KsReleaseMdl(Mdl, FALSE);
+    if (cfs_is_flag_set(SockFlags, MSG_OOB)) {
+        cfs_set_flag(TdiFlags, TDI_SEND_EXPEDITED);
     }
 
-    if (!NT_SUCCESS(Status)) {
+    if (cfs_is_flag_set(SockFlags, MSG_MORE)) {
+        cfs_set_flag(TdiFlags, TDI_SEND_PARTIAL);
+    }
 
-        cfs_enter_debugger();
-        //TDI_BUFFER_OVERFLOW
+    if (cfs_is_flag_set(SockFlags, MSG_DONTWAIT)) {
+        cfs_set_flag(TdiFlags, TDI_SEND_NON_BLOCKING);
     }
 
-    return (Status);
+    return TdiFlags;
 }
 
-/*
- * KsQueryProviderInfo
- *   Query the underlying transport device's information
- *
- * Arguments:
- *   TdiDeviceName:  the transport device's name string
- *   ProviderInfo:   TDI_PROVIDER_INFO struncture
- *
- * Return Value:
- *   NTSTATUS:       Nt system status code
-  *
- * NOTES:
- *   N/A
- */
-
-NTSTATUS
-KsQueryProviderInfo(
-    PWSTR               TdiDeviceName,
-    PTDI_PROVIDER_INFO  ProviderInfo
-   )
+ULONG
+KsTdiRecvFlags(int SockFlags)
 {
-    NTSTATUS            Status = STATUS_SUCCESS;
-
-    PIRP                Irp = NULL;
-    PMDL                Mdl = NULL;
-
-    UNICODE_STRING      ControlName;
+    ULONG   TdiFlags = 0;
 
-    HANDLE              Handle;
-    PFILE_OBJECT        FileObject;
-    PDEVICE_OBJECT      DeviceObject;
+    if (cfs_is_flag_set(SockFlags, MSG_OOB)) {
+        cfs_set_flag(TdiFlags, TDI_RECEIVE_EXPEDITED);
+    }
 
-    ULONG               ProviderSize = 0;
+    if (cfs_is_flag_set(SockFlags, MSG_MORE)) {
+        cfs_set_flag(TdiFlags, TDI_RECEIVE_PARTIAL);
+    }
 
-    RtlInitUnicodeString(&ControlName, TdiDeviceName);
+    if (cfs_is_flag_set(SockFlags, MSG_DONTWAIT)) {
+        cfs_set_flag(TdiFlags, TDI_SEND_NON_BLOCKING);
+    }
 
-    //
-    // Open the Tdi Control Channel
-    //
+    return TdiFlags;
+}
 
-    Status = KsOpenControl(
-                &ControlName,
-                &Handle,
-                &FileObject
-                );
+int
+KsWriteTsdus(PKS_TSDUMGR TsduMgr, char * buffer, int length, int flags)
+{
+    int rc = 0;
 
-    if (!NT_SUCCESS(Status)) {
+    if (TsduMgr->TotalBytes <= TDINAL_MAX_TSDU_QUEUE_SIZE) {
+        rc = KsWriteTsduDat(TsduMgr, buffer, length, flags);
+    }
 
-        KsPrint((2, "KsQueryProviderInfo: Fail to open the tdi control channel.\n"));
-        return (Status);
+    if (rc > 0) {
+        return rc;
     }
 
-    //
-    // Obtain The Related Device Object
-    //
+   return -EAGAIN;
+}
 
-    DeviceObject = IoGetRelatedDeviceObject(FileObject);
+int
+KsReadTsdus(PKS_TSDUMGR TsduMgr, char * buffer, int length, int flags)
+{
+    int rc = KsReadTsdu(TsduMgr, buffer, length, flags);
 
-    ProviderSize = sizeof(TDI_PROVIDER_INFO);
-    RtlZeroMemory(ProviderInfo, ProviderSize);
+    if (rc > 0) {
+        return rc;
+    }
 
-    //
-    // Allocating the Tdi Setting Irp ...
-    //
+    return -EAGAIN;
+}
 
-    Irp = KsBuildTdiIrp(DeviceObject);
+/*
+ * KsInitializeKsTsduMgr
+ *   Initialize the management structure of
+ *   Tsdu buffers
+ *
+ * Arguments:
+ *   TsduMgr: the TsduMgr to be initialized
+ *
+ * Return Value:
+ *   VOID
+ *
+ * NOTES:
+ *   N/A
+ */
 
-    if (NULL == Irp) {
-
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-
-    } else {
-
-        //
-        // Locking the User Buffer / Allocating a MDL for it
-        //
-
-        Status = KsLockUserBuffer(
-                    ProviderInfo,
-                    FALSE,
-                    ProviderSize,
-                    IoModifyAccess,
-                    &Mdl
-                    );
-
-        if (!NT_SUCCESS(Status)) {
-
-            IoFreeIrp(Irp);
-            Irp = NULL;
-        }
-    }
-
-    if (Irp) {
-
-        LASSERT(NT_SUCCESS(Status));
-
-        TdiBuildQueryInformation(
-                    Irp,
-                    DeviceObject,
-                    FileObject,
-                    NULL,
-                    NULL,
-                    TDI_QUERY_PROVIDER_INFO,
-                    Mdl
-                    );
+VOID
+KsInitializeKsTsduMgr(
+    PKS_TSDUMGR     TsduMgr
+    )
+{
+    KeInitializeEvent(
+            &(TsduMgr->Event),
+            NotificationEvent,
+            FALSE
+            );
 
-        Status = KsSubmitTdiIrp(
-                    DeviceObject,
-                    Irp,
-                    TRUE,
-                    &ProviderSize
-                    );
+    CFS_INIT_LIST_HEAD(
+            &(TsduMgr->TsduList)
+            );
 
-        KsReleaseMdl(Mdl, FALSE);
-    }
+    TsduMgr->NumOfTsdu  = 0;
+    TsduMgr->TotalBytes = 0;
 
-    if (!NT_SUCCESS(Status)) {
+    cfs_spin_lock_init(&TsduMgr->Lock);
+}
 
-        cfs_enter_debugger();
-        //TDI_BUFFER_OVERFLOW
-    }
 
-    KsCloseControl(Handle, FileObject);
+/*
+ * KsInitializeKsChain
+ *   Initialize the China structure for receiving
+ *   or transmitting
+ *
+ * Arguments:
+ *   KsChain: the KsChain to be initialized
+ *
+ * Return Value:
+ *   VOID
+ *
+ * NOTES:
+ *   N/A
+ */
 
-    return (Status);
+VOID
+KsInitializeKsChain(
+    PKS_CHAIN       KsChain
+    )
+{
+    KsInitializeKsTsduMgr(&(KsChain->Normal));
+    KsInitializeKsTsduMgr(&(KsChain->Expedited));
+    KsChain->Expedited.OOB = TRUE;
 }
 
+
 /*
- * KsQueryConnectionInfo
- *   Query the connection info of the FileObject specified
- *   (some statics data of the traffic)
+ * KsCleanupTsduMgr
+ *   Clean up all the Tsdus in the TsduMgr list
  *
  * Arguments:
- *   FileObject:     the FileObject to be queried
- *   ConnectionInfo: buffer to contain the connection info
- *   ConnectionSize: length of the ConnectionInfo buffer
+ *   TsduMgr: the Tsdu list manager
  *
  * Return Value:
- *   NTSTATUS:     kernel status code (STATUS_SUCCESS
- *                 or other error code)
+ *   NTSTATUS:  nt status code
  *
  * NOTES:
  *   N/A
  */
 
 NTSTATUS
-KsQueryConnectionInfo(
-    PFILE_OBJECT            ConnectionObject,
-    PTDI_CONNECTION_INFO    ConnectionInfo,
-    PULONG                  ConnectionSize
-   )
+KsCleanupTsduMgr(
+    PKS_TSDUMGR     TsduMgr
+    )
 {
-    NTSTATUS          Status = STATUS_UNSUCCESSFUL;
-    PIRP              Irp = NULL;
-    PMDL              Mdl;
-    PDEVICE_OBJECT    DeviceObject;
+    PKS_TSDU        KsTsdu;
+    PKS_TSDU_DAT    KsTsduDat;
+    PKS_TSDU_BUF    KsTsduBuf;
+    PKS_TSDU_MDL    KsTsduMdl;
 
-    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
+    LASSERT(NULL != TsduMgr);
 
-    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
+    KsRemoveTdiEngine(TsduMgr);
+    KeSetEvent(&(TsduMgr->Event), 0, FALSE);
 
-    RtlZeroMemory(ConnectionInfo, *(ConnectionSize));
+    while (!cfs_list_empty(&TsduMgr->TsduList)) {
 
-    //
-    // Allocating the Tdi Query Irp ...
-    //
+        KsTsdu = cfs_list_entry(TsduMgr->TsduList.next, KS_TSDU, Link);
+        LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
 
-    Irp = KsBuildTdiIrp(DeviceObject);
+        if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
 
-    if (NULL == Irp) {
+            //
+            // KsTsdu is empty now, we need free it ...
+            //
 
-        Status = STATUS_INSUFFICIENT_RESOURCES;
+            cfs_list_del(&(KsTsdu->Link));
+            TsduMgr->NumOfTsdu--;
 
-    } else {
+            KsFreeKsTsdu(KsTsdu);
 
-        //
-        // Locking the User Buffer / Allocating a MDL for it
-        //
+        } else {
 
-        Status = KsLockUserBuffer(
-                    ConnectionInfo,
-                    FALSE,
-                    *(ConnectionSize),
-                    IoModifyAccess,
-                    &Mdl
-                    );
+            KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
+            KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
+            KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
 
-        if (NT_SUCCESS(Status)) {
+            if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
 
-            IoFreeIrp(Irp);
-            Irp = NULL;
-        }
-    }
+                KsTsdu->StartOffset += KsTsduDat->TotalLength;
 
-    if (Irp) {
+            } else if (TSDU_TYPE_BUF == KsTsduBuf->TsduType) {
 
-        LASSERT(NT_SUCCESS(Status));
+                ASSERT(KsTsduBuf->UserBuffer != NULL);
 
-        TdiBuildQueryInformation(
-                    Irp,
-                    DeviceObject,
-                    ConnectionObject,
-                    NULL,
-                    NULL,
-                    TDI_QUERY_CONNECTION_INFO,
-                    Mdl
-                    );
+                if (KsTsduBuf->DataLength > KsTsduBuf->StartOffset) {
+                    if (KsTsduBuf->Mdl) {
+                        KsTsduBuf->Mdl->Next = NULL;
+                        KsReleaseMdl(KsTsduBuf->Mdl, FALSE);
+                    }
+                    ExFreePool(KsTsduBuf->UserBuffer);
+                } else {
+                    cfs_enter_debugger();
+                }
 
-        Status = KsSubmitTdiIrp(
-                    DeviceObject,
-                    Irp,
-                    TRUE,
-                    ConnectionSize
-                    );
+                KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
 
-        KsReleaseMdl(Mdl, FALSE);
+            } else if (TSDU_TYPE_MDL == KsTsduMdl->TsduType) {
+
+                //
+                // MDL Tsdu Unit ...
+                //
+                if (KsTsduMdl->Descriptor) {
+                    TdiReturnChainedReceives(
+                        &(KsTsduMdl->Descriptor),
+                        1 );
+                } else if (KsTsduMdl->Mdl) {
+                    KsTsduMdl->Mdl->Next = NULL;
+                    KsReleaseMdl(KsTsduMdl->Mdl, FALSE);
+                }
+
+                KsTsdu->StartOffset += sizeof(KS_TSDU_MDL);
+            }
+        }
     }
 
-    return (Status);
+    return STATUS_SUCCESS;
 }
 
 
 /*
- * KsInitializeTdiAddress
- *   Initialize the tdi addresss
+ * KsCleanupKsChain
+ *   Clean up the TsduMgrs of the KsChain
  *
  * Arguments:
- *   pTransportAddress: tdi address to be initialized
- *   IpAddress:         the ip address of object
- *   IpPort:            the ip port of the object
+ *   KsChain: the chain managing TsduMgr
  *
  * Return Value:
- *   ULONG: the total size of the tdi address
+ *   NTSTATUS:  nt status code
  *
  * NOTES:
  *   N/A
  */
 
-ULONG
-KsInitializeTdiAddress(
-    IN OUT PTA_IP_ADDRESS   pTransportAddress,
-    IN ULONG                IpAddress,
-    IN USHORT               IpPort
+NTSTATUS
+KsCleanupKsChain(
+    PKS_CHAIN   KsChain
     )
 {
-    pTransportAddress->TAAddressCount = 1;
-    pTransportAddress->Address[ 0 ].AddressLength = TDI_ADDRESS_LENGTH_IP;
-    pTransportAddress->Address[ 0 ].AddressType   = TDI_ADDRESS_TYPE_IP;
-    pTransportAddress->Address[ 0 ].Address[ 0 ].sin_port = IpPort;
-    pTransportAddress->Address[ 0 ].Address[ 0 ].in_addr  = IpAddress;
+    NTSTATUS    Status;
 
-    return (FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address) + TDI_ADDRESS_LENGTH_IP);
+    LASSERT(NULL != KsChain);
+
+    Status = KsCleanupTsduMgr(
+                &(KsChain->Normal)
+                );
+
+    if (!NT_SUCCESS(Status)) {
+        cfs_enter_debugger();
+        goto errorout;
+    }
+
+    Status = KsCleanupTsduMgr(
+                &(KsChain->Expedited)
+                );
+
+    if (!NT_SUCCESS(Status)) {
+        cfs_enter_debugger();
+        goto errorout;
+    }
+
+errorout:
+
+    return Status;
 }
 
+
 /*
- * KsQueryTdiAddressLength
- *   Query the total size of the tdi address
+ * KsCleanupTsdu
+ *   Clean up all the Tsdus of a tdi connected object
  *
  * Arguments:
- *   pTransportAddress: tdi address to be queried
+ *   tconn: the tdi connection which is connected already.
  *
  * Return Value:
- *   ULONG: the total size of the tdi address
- *
- * NOTES:
- *   N/A
- */
-
-ULONG
-KsQueryTdiAddressLength(
-    PTRANSPORT_ADDRESS      pTransportAddress
-    )
-{
-    ULONG                   TotalLength = 0;
-    LONG                    i;
-
-    PTA_ADDRESS UNALIGNED   pTaAddress = NULL;
-
-    ASSERT (NULL != pTransportAddress);
-
-    TotalLength  = FIELD_OFFSET(TRANSPORT_ADDRESS, Address) +
-                   FIELD_OFFSET(TA_ADDRESS, Address) * pTransportAddress->TAAddressCount;
-
-    pTaAddress = (TA_ADDRESS UNALIGNED *)pTransportAddress->Address;
-
-    for (i = 0; i < pTransportAddress->TAAddressCount; i++)
-    {
-        TotalLength += pTaAddress->AddressLength;
-        pTaAddress = (TA_ADDRESS UNALIGNED *)((PCHAR)pTaAddress +
-                                           FIELD_OFFSET(TA_ADDRESS,Address) +
-                                           pTaAddress->AddressLength );
-    }
-
-    return (TotalLength);
-}
-
-
-/*
- * KsQueryIpAddress
- *   Query the ip address of the tdi object
- *
- * Arguments:
- *   FileObject: tdi object to be queried
- *   TdiAddress: TdiAddress buffer, to store the queried
- *               tdi ip address
- *   AddressLength: buffer length of the TdiAddress
- *
- * Return Value:
- *   ULONG: the total size of the tdi ip address
+ *   Nt status code
  *
  * NOTES:
  *   N/A
  */
 
 NTSTATUS
-KsQueryIpAddress(
-    PFILE_OBJECT    FileObject,
-    PVOID           TdiAddress,
-    ULONG*          AddressLength
+KsCleanupTsdu(
+    ks_tconn_t * tconn
     )
 {
-    NTSTATUS        Status;
-
-    PTDI_ADDRESS_INFO   TdiAddressInfo;
-    ULONG               Length;
-
-
-    //
-    // Maximum length of TDI_ADDRESSS_INFO with one TRANSPORT_ADDRESS
-    //
-
-    Length = MAX_ADDRESS_LENGTH;
+    NTSTATUS        Status = STATUS_SUCCESS;
 
-    TdiAddressInfo = (PTDI_ADDRESS_INFO)
-                        ExAllocatePoolWithTag(
-                            NonPagedPool,
-                            Length,
-                            'KSAI' );
 
-    if (NULL == TdiAddressInfo) {
+    if (tconn->kstc_type != kstt_sender &&
+        tconn->kstc_type != kstt_child ) {
 
-        Status = STATUS_INSUFFICIENT_RESOURCES;
         goto errorout;
     }
 
+    if (tconn->kstc_type == kstt_sender) {
 
-    Status = KsQueryAddressInfo(
-        FileObject,
-        TdiAddressInfo,
-        &Length
-        );
-
-errorout:
-
-    if (NT_SUCCESS(Status))
-    {
-        if (*AddressLength < Length) {
-
-            Status = STATUS_BUFFER_TOO_SMALL;
+        Status = KsCleanupKsChain(
+                    &(tconn->sender.kstc_recv)
+                    );
 
-        } else {
+        if (!NT_SUCCESS(Status)) {
+            cfs_enter_debugger();
+            goto errorout;
+        }
 
-            *AddressLength = Length;
-            RtlCopyMemory(
-                TdiAddress,
-                &(TdiAddressInfo->Address),
-                Length
-                );
+        Status = KsCleanupKsChain(
+                    &(tconn->sender.kstc_send)
+                    );
 
-            Status = STATUS_SUCCESS;
+        if (!NT_SUCCESS(Status)) {
+            cfs_enter_debugger();
+            goto errorout;
         }
 
     } else {
 
-    }
+        Status = KsCleanupKsChain(
+                    &(tconn->child.kstc_recv)
+                    );
 
+        if (!NT_SUCCESS(Status)) {
+            cfs_enter_debugger();
+            goto errorout;
+        }
 
-    if (NULL != TdiAddressInfo) {
+        Status = KsCleanupKsChain(
+                    &(tconn->child.kstc_send)
+                    );
 
-        ExFreePool(TdiAddressInfo);
-    }
+        if (!NT_SUCCESS(Status)) {
+            cfs_enter_debugger();
+            goto errorout;
+        }
 
-    return Status;
-}
+    }
 
+errorout:
 
-/*
- * KsErrorEventHandler
- *   the common error event handler callback
- *
- * Arguments:
- *   TdiEventContext: should be the socket
- *   Status: the error code
- *
- * Return Value:
- *   Status: STATS_SUCCESS
- *
- * NOTES:
- *   We need not do anything in such a severe
- *   error case. System will process it for us.
- */
+    return (Status);
+}
 
 NTSTATUS
-KsErrorEventHandler(
-    IN PVOID        TdiEventContext,
-    IN NTSTATUS     Status
-   )
+KsIrpCompletionRoutine(
+    IN PDEVICE_OBJECT    DeviceObject,
+    IN PIRP              Irp,
+    IN PVOID             Context
+    )
 {
-    KsPrint((2, "KsErrorEventHandler called at Irql = %xh ...\n",
-                KeGetCurrentIrql()));
+    if (NULL != Context) {
+        KeSetEvent((PKEVENT)Context, IO_NETWORK_INCREMENT, FALSE);
+    }
 
-    cfs_enter_debugger();
+    return STATUS_MORE_PROCESSING_REQUIRED;
 
-    return (STATUS_SUCCESS);
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(Irp);
 }
 
 
 /*
- * ks_set_handlers
- *   setup all the event handler callbacks
+ * KsBuildTdiIrp
+ *   Allocate a new IRP and initialize it to be issued to tdi
  *
  * Arguments:
- *   tconn: the tdi connecton object
+ *   DeviceObject:  device object created by the underlying
+ *                  TDI transport driver
  *
  * Return Value:
- *   int: ks error code
+ *   PRIP:   the allocated Irp in success or NULL in failure.
  *
  * NOTES:
  *   N/A
  */
 
-int
-ks_set_handlers(
-    ksock_tconn_t *     tconn
+PIRP
+KsBuildTdiIrp(
+    IN PDEVICE_OBJECT    DeviceObject
     )
 {
-    NTSTATUS            status = STATUS_SUCCESS;
-    KS_EVENT_HANDLERS   handlers;
-
-    /* to make sure the address object is opened already */
-    if (tconn->kstc_addr.FileObject == NULL) {
-        goto errorout;
-    }
+    PIRP                Irp;
+    PIO_STACK_LOCATION  IrpSp;
 
-    /* initialize the handlers indictor array. for sender and listenr,
-       there are different set of callbacks. for child, we just return. */
+    //
+    // Allocating the IRP ...
+    //
 
-    memset(&handlers, 0, sizeof(KS_EVENT_HANDLERS));
+    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
 
-    SetEventHandler(handlers, TDI_EVENT_ERROR, KsErrorEventHandler);
-    SetEventHandler(handlers, TDI_EVENT_DISCONNECT, KsDisconnectEventHandler);
-    SetEventHandler(handlers, TDI_EVENT_RECEIVE, KsTcpReceiveEventHandler);
-    SetEventHandler(handlers, TDI_EVENT_RECEIVE_EXPEDITED, KsTcpReceiveExpeditedEventHandler);
-    SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE, KsTcpChainedReceiveEventHandler);
+    if (NULL != Irp) {
 
-    // SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE_EXPEDITED, KsTcpChainedReceiveExpeditedEventHandler);
+        //
+        // Getting the Next Stack Location ...
+        //
 
-    if (tconn->kstc_type == kstt_listener) {
-        SetEventHandler(handlers, TDI_EVENT_CONNECT, KsConnectEventHandler);
-    } else if (tconn->kstc_type == kstt_child) {
-        goto errorout;
-    }
+        IrpSp = IoGetNextIrpStackLocation(Irp);
 
-    /* set all the event callbacks */
-    status = KsSetEventHandlers(
-                tconn->kstc_addr.FileObject, /* Address File Object  */
-                tconn,                       /* Event Context */
-                &handlers                    /* Event callback handlers */
-                );
+        //
+        // Initializing Irp ...
+        //
 
-errorout:
+        IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
+        IrpSp->Parameters.DeviceIoControl.IoControlCode = 0;
+    }
 
-    return cfs_error_code(status);
+    return Irp;
 }
 
-
 /*
- * ks_reset_handlers
- *   disable all the event handler callbacks (set to NULL)
+ * KsSubmitTdiIrp
+ *   Issue the Irp to the underlying tdi driver
  *
  * Arguments:
- *   tconn: the tdi connecton object
+ *   DeviceObject:  the device object created by TDI driver
+ *   Irp:           the I/O request packet to be processed
+ *   bSynchronous:  synchronous or not. If true, we need wait
+ *                  until the process is finished.
+ *   Information:   returned info
  *
  * Return Value:
- *   int: ks error code
+ *   NTSTATUS:      kernel status code
  *
  * NOTES:
  *   N/A
  */
 
-int
-ks_reset_handlers(
-    ksock_tconn_t *     tconn
+NTSTATUS
+KsSubmitTdiIrp(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp,
+    IN BOOLEAN          bSynchronous,
+    OUT PULONG          Information
     )
 {
-    NTSTATUS            status = STATUS_SUCCESS;
-    KS_EVENT_HANDLERS   handlers;
-
-    /* to make sure the address object is opened already */
-    if (tconn->kstc_addr.FileObject == NULL) {
-        goto errorout;
-    }
+    NTSTATUS            Status;
+    KEVENT              Event;
 
-    /* initialize the handlers indictor array. for sender and listenr,
-       there are different set of callbacks. for child, we just return. */
+    if (bSynchronous) {
 
-    memset(&handlers, 0, sizeof(KS_EVENT_HANDLERS));
+        KeInitializeEvent(
+            &Event,
+            SynchronizationEvent,
+            FALSE
+            );
 
-    SetEventHandler(handlers, TDI_EVENT_ERROR, NULL);
-    SetEventHandler(handlers, TDI_EVENT_DISCONNECT, NULL);
-    SetEventHandler(handlers, TDI_EVENT_RECEIVE, NULL);
-    SetEventHandler(handlers, TDI_EVENT_RECEIVE_EXPEDITED, NULL);
-    SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE, NULL);
-    // SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE_EXPEDITED, NULL);
 
-    if (tconn->kstc_type == kstt_listener) {
-        SetEventHandler(handlers, TDI_EVENT_CONNECT, NULL);
-    } else if (tconn->kstc_type == kstt_child) {
-        goto errorout;
+        IoSetCompletionRoutine(
+            Irp,
+            KsIrpCompletionRoutine,
+            &Event,
+            TRUE,
+            TRUE,
+            TRUE
+            );
     }
 
-    /* set all the event callbacks */
-    status = KsSetEventHandlers(
-                tconn->kstc_addr.FileObject, /* Address File Object  */
-                tconn,                       /* Event Context */
-                &handlers                    /* Event callback handlers */
-                );
+    Status = IoCallDriver(DeviceObject, Irp);
 
-errorout:
+    if (bSynchronous) {
 
-    return cfs_error_code(status);
+        if (STATUS_PENDING == Status) {
+
+            Status = KeWaitForSingleObject(
+                        &Event,
+                        Executive,
+                        KernelMode,
+                        FALSE,
+                        NULL
+                        );
+        }
+
+        Status = Irp->IoStatus.Status;
+
+        if (Information) {
+            *Information = (ULONG)(Irp->IoStatus.Information);
+        }
+
+        IoFreeIrp(Irp);
+    }
+
+    if (!NT_SUCCESS(Status)) {
+
+        KsPrint((1, "KsSubmitTdiIrp: Error when submitting the Irp: "
+                    "Status = %xh (%s)\n", Status, KsNtStatusToString(Status)));
+    }
+
+    return (Status);
 }
 
 
+
 /*
- * KsAcceptCompletionRoutine
- *   Irp completion routine for TdiBuildAccept (KsConnectEventHandler)
- *
- *   Here system gives us a chance to check the conneciton is built
- *   ready or not.
+ * KsOpenControl
+ *   Open the Control Channel Object ...
  *
  * Arguments:
- *   DeviceObject:  the device object of the transport driver
- *   Irp:           the Irp is being completed.
- *   Context:       the context we specified when issuing the Irp
+ *   DeviceName:   the device name to be opened
+ *   Handle:       opened handle in success case
+ *   FileObject:   the fileobject of the device
  *
  * Return Value:
- *   Nt status code
+ *   NTSTATUS:     kernel status code (STATUS_SUCCESS
+ *                 or other error code)
  *
  * Notes:
  *   N/A
  */
 
 NTSTATUS
-KsAcceptCompletionRoutine(
-    IN PDEVICE_OBJECT   DeviceObject,
-    IN PIRP             Irp,
-    IN PVOID            Context
-    )
+KsOpenControl(
+    IN PUNICODE_STRING      DeviceName,
+    OUT HANDLE *            Handle,
+    OUT PFILE_OBJECT *      FileObject
+   )
 {
-    ksock_tconn_t * child = (ksock_tconn_t *) Context;
-    ksock_tconn_t * parent = child->child.kstc_parent;
+    NTSTATUS          Status = STATUS_SUCCESS;
 
-    KsPrint((2, "KsAcceptCompletionRoutine: called at Irql: %xh\n",
-                KeGetCurrentIrql() ));
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK   IoStatus;
 
-    KsPrint((2, "KsAcceptCompletionRoutine: Context = %xh Status = %xh\n",
-                 Context, Irp->IoStatus.Status));
 
-    LASSERT(child->kstc_type == kstt_child);
+    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
 
-    spin_lock(&(child->kstc_lock));
+    //
+    // Initializing ...
+    //
 
-    LASSERT(parent->kstc_state == ksts_listening);
-    LASSERT(child->kstc_state == ksts_connecting);
+    InitializeObjectAttributes(
+        &ObjectAttributes,
+        DeviceName,
+        OBJ_CASE_INSENSITIVE |
+        OBJ_KERNEL_HANDLE,
+        NULL,
+        NULL
+        );
 
-    if (NT_SUCCESS(Irp->IoStatus.Status)) {
+    LASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL );
 
-        child->child.kstc_accepted = TRUE;
+    //
+    // Creating the Transport Address Object ...
+    //
 
-        child->kstc_state = ksts_connected;
+    Status = ZwCreateFile(
+                Handle,
+                FILE_READ_DATA | FILE_WRITE_DATA,
+                &ObjectAttributes,
+                &IoStatus,
+                0,
+                FILE_ATTRIBUTE_NORMAL,
+                FILE_SHARE_READ | FILE_SHARE_WRITE,
+                FILE_OPEN,
+                0,
+                NULL,
+                0
+                );
 
-        /* wake up the daemon thread which waits on this event */
-        KeSetEvent(
-            &(parent->listener.kstc_accept_event),
-            0,
-            FALSE
-            );
 
-        spin_unlock(&(child->kstc_lock));
+    if (NT_SUCCESS(Status)) {
 
-        KsPrint((2, "KsAcceptCompletionRoutine: Get %xh now signal the event ...\n", parent));
+        //
+        // Now Obtaining the FileObject of the Transport Address ...
+        //
 
-    } else {
+        Status = ObReferenceObjectByHandle(
+                    *Handle,
+                    FILE_ANY_ACCESS,
+                    NULL,
+                    KernelMode,
+                    FileObject,
+                    NULL
+                    );
 
-        /* re-use this child connecton  */
-        child->child.kstc_accepted = FALSE;
-        child->child.kstc_busy = FALSE;
-        child->kstc_state = ksts_associated;
+        if (!NT_SUCCESS(Status)) {
 
-        spin_unlock(&(child->kstc_lock));
-    }
+            cfs_enter_debugger();
+            ZwClose(*Handle);
+        }
 
-    /* now free the Irp */
-    IoFreeIrp(Irp);
+    } else {
 
-    /* drop the refer count of the child */
-    ks_put_tconn(child);
+        cfs_enter_debugger();
+    }
 
-    return (STATUS_MORE_PROCESSING_REQUIRED);
+    return (Status);
 }
 
 
 /*
- * ks_get_vacancy_backlog
- *   Get a vacancy listeing child from the backlog list
+ * KsCloseControl
+ *   Release the Control Channel Handle and FileObject
  *
  * Arguments:
- *   parent: the listener daemon connection
+ *   Handle:       the channel handle to be released
+ *   FileObject:   the fileobject to be released
  *
  * Return Value:
- *   the child listening connection or NULL in failure
+ *   NTSTATUS:     kernel status code (STATUS_SUCCESS
+ *                 or other error code)
  *
- * Notes
- *   Parent's lock should be acquired before calling.
+ * Notes:
+ *   N/A
  */
 
-ksock_tconn_t *
-ks_get_vacancy_backlog(
-    ksock_tconn_t *  parent
-    )
+NTSTATUS
+KsCloseControl(
+    IN HANDLE             Handle,
+    IN PFILE_OBJECT       FileObject
+   )
 {
-    ksock_tconn_t * child;
-
-    LASSERT(parent->kstc_type == kstt_listener);
-    LASSERT(parent->kstc_state == ksts_listening);
-
-    if (list_empty(&(parent->listener.kstc_listening.list))) {
-
-        child = NULL;
-
-    } else {
-
-        struct list_head * tmp;
+    NTSTATUS  Status = STATUS_SUCCESS;
 
-        /* check the listening queue and try to get a free connecton */
+    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
 
-        list_for_each(tmp, &(parent->listener.kstc_listening.list)) {
-            child = list_entry (tmp, ksock_tconn_t, child.kstc_link);
-            spin_lock(&(child->kstc_lock));
+    if (FileObject) {
 
-            if (!child->child.kstc_busy) {
-                LASSERT(child->kstc_state == ksts_associated);
-                child->child.kstc_busy = TRUE;
-                spin_unlock(&(child->kstc_lock));
-                break;
-            } else {
-                spin_unlock(&(child->kstc_lock));
-                child = NULL;
-            }
-        }
+        ObDereferenceObject(FileObject);
     }
 
-    return child;
-}
-
-ks_addr_slot_t *
-KsSearchIpAddress(PUNICODE_STRING  DeviceName)
-{
-    ks_addr_slot_t * slot = NULL;
-    PLIST_ENTRY      list = NULL;
-
-    spin_lock(&ks_data.ksnd_addrs_lock);
+    if (Handle) {
 
-    list = ks_data.ksnd_addrs_list.Flink;
-    while (list != &ks_data.ksnd_addrs_list) {
-        slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
-        if (RtlCompareUnicodeString(
-                    DeviceName,
-                    &slot->devname,
-                    TRUE) == 0) {
-            break;
-        }
-        list = list->Flink;
-        slot = NULL;
+        Status = ZwClose(Handle);
     }
 
-    spin_unlock(&ks_data.ksnd_addrs_lock);
+    ASSERT(NT_SUCCESS(Status));
 
-    return slot;
+    return (Status);
 }
 
-void
-KsCleanupIpAddresses()
+
+/*
+ * KsOpenAddress
+ *   Open the tdi address object
+ *
+ * Arguments:
+ *   DeviceName:   device name of the address object
+ *   pAddress:     tdi address of the address object
+ *   AddressLength: length in bytes of the tdi address
+ *   Handle:       the newly opened handle
+ *   FileObject:   the newly opened fileobject
+ *
+ * Return Value:
+ *   NTSTATUS:     kernel status code (STATUS_SUCCESS
+ *                 or other error code)
+ *
+ * Notes:
+ *   N/A
+ */
+
+NTSTATUS
+KsOpenAddress(
+    IN PUNICODE_STRING      DeviceName,
+    IN PTRANSPORT_ADDRESS   pAddress,
+    IN ULONG                AddressLength,
+    OUT HANDLE *            Handle,
+    OUT PFILE_OBJECT *      FileObject
+   )
 {
-    spin_lock(&ks_data.ksnd_addrs_lock);
+    NTSTATUS          Status = STATUS_SUCCESS;
 
-    while (!IsListEmpty(&ks_data.ksnd_addrs_list)) {
+    PFILE_FULL_EA_INFORMATION Ea = NULL;
+    ULONG             EaLength;
+    UCHAR             EaBuffer[EA_MAX_LENGTH];
 
-        ks_addr_slot_t * slot = NULL;
-        PLIST_ENTRY      list = NULL;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK   IoStatus;
 
-        list = RemoveHeadList(&ks_data.ksnd_addrs_list);
-        slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
-        cfs_free(slot);
-        ks_data.ksnd_naddrs--;
-    }
+    //
+    // Building EA for the Address Object to be Opened ...
+    //
 
-    cfs_assert(ks_data.ksnd_naddrs == 0);
-    spin_unlock(&ks_data.ksnd_addrs_lock);
-}
+    Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
+    Ea->NextEntryOffset = 0;
+    Ea->Flags = 0;
+    Ea->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
+    Ea->EaValueLength = (USHORT)AddressLength;
+    RtlCopyMemory(
+        &(Ea->EaName),
+        TdiTransportAddress,
+        Ea->EaNameLength + 1
+        );
+    RtlMoveMemory(
+        &(Ea->EaName[Ea->EaNameLength + 1]),
+        pAddress,
+        AddressLength
+        );
+    EaLength =  sizeof(FILE_FULL_EA_INFORMATION) +
+                Ea->EaNameLength + AddressLength;
 
-VOID
-KsAddAddressHandler(
-    IN  PTA_ADDRESS      Address,
-    IN  PUNICODE_STRING  DeviceName,
-    IN  PTDI_PNP_CONTEXT Context
-    )
-{
-    PTDI_ADDRESS_IP IpAddress = NULL;
+    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
 
-    if ( Address->AddressType == TDI_ADDRESS_TYPE_IP &&
-         Address->AddressLength == TDI_ADDRESS_LENGTH_IP ) {
 
-        ks_addr_slot_t * slot = NULL;
+    //
+    // Initializing ...
+    //
 
-        IpAddress = (PTDI_ADDRESS_IP) &Address->Address[0];
-        KsPrint((1, "KsAddAddressHandle: Device=%wZ Context=%xh IpAddress=%xh(%d.%d.%d.%d)\n",
-                  DeviceName, Context, IpAddress->in_addr,
-                   (IpAddress->in_addr & 0xFF000000) >> 24,
-                   (IpAddress->in_addr & 0x00FF0000) >> 16,
-                   (IpAddress->in_addr & 0x0000FF00) >> 8,
-                   (IpAddress->in_addr & 0x000000FF) >> 0 ));
+    InitializeObjectAttributes(
+        &ObjectAttributes,
+        DeviceName,
+        OBJ_CASE_INSENSITIVE |
+        OBJ_KERNEL_HANDLE,
+        NULL,
+        NULL
+        );
 
-        slot = KsSearchIpAddress(DeviceName);
+    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
 
-        if (slot != NULL) {
-            slot->up = TRUE;
-            slot->ip_addr = ntohl(IpAddress->in_addr);
-        } else {
-            slot = cfs_alloc(sizeof(ks_addr_slot_t) + DeviceName->Length, CFS_ALLOC_ZERO);
-            if (slot != NULL) {
-                spin_lock(&ks_data.ksnd_addrs_lock);
-                InsertTailList(&ks_data.ksnd_addrs_list, &slot->link);
-                sprintf(slot->iface, "eth%d", ks_data.ksnd_naddrs++);
-                slot->ip_addr = ntohl(IpAddress->in_addr);
-                slot->up = TRUE;
-                RtlMoveMemory(&slot->buffer[0], DeviceName->Buffer, DeviceName->Length);
-                slot->devname.Length = DeviceName->Length;
-                slot->devname.MaximumLength = DeviceName->Length + sizeof(WCHAR);
-                slot->devname.Buffer = slot->buffer;
-                spin_unlock(&ks_data.ksnd_addrs_lock);
-            }
-        }
-    }
-}
+    //
+    // Creating the Transport Address Object ...
+    //
 
-VOID
-KsDelAddressHandler(
-    IN  PTA_ADDRESS      Address,
-    IN  PUNICODE_STRING  DeviceName,
-    IN  PTDI_PNP_CONTEXT Context
-    )
-{
-    PTDI_ADDRESS_IP IpAddress = NULL;
+    Status = ZwCreateFile(
+                Handle,
+                FILE_READ_DATA | FILE_WRITE_DATA,
+                &ObjectAttributes,
+                &IoStatus,
+                0,
+                FILE_ATTRIBUTE_NORMAL,
+                FILE_SHARE_READ | FILE_SHARE_WRITE, /* 0: DON'T REUSE */
+                FILE_OPEN,
+                0,
+                Ea,
+                EaLength
+                );
 
-    if ( Address->AddressType == TDI_ADDRESS_TYPE_IP &&
-         Address->AddressLength == TDI_ADDRESS_LENGTH_IP ) {
 
-        ks_addr_slot_t * slot = NULL;
+    if (NT_SUCCESS(Status)) {
 
-        slot = KsSearchIpAddress(DeviceName);
+        //
+        // Now Obtaining the FileObject of the Transport Address ...
+        //
 
-        if (slot != NULL) {
-            slot->up = FALSE;
+        Status = ObReferenceObjectByHandle(
+                    *Handle,
+                    FILE_ANY_ACCESS,
+                    NULL,
+                    KernelMode,
+                    FileObject,
+                    NULL
+                    );
+
+        if (!NT_SUCCESS(Status)) {
+
+            cfs_enter_debugger();
+            ZwClose(*Handle);
         }
 
-        IpAddress = (PTDI_ADDRESS_IP) &Address->Address[0];
-        KsPrint((1, "KsDelAddressHandle: Device=%wZ Context=%xh IpAddress=%xh(%d.%d.%d.%d)\n",
-                  DeviceName, Context, IpAddress->in_addr,
-                   (IpAddress->in_addr & 0xFF000000) >> 24,
-                   (IpAddress->in_addr & 0x00FF0000) >> 16,
-                   (IpAddress->in_addr & 0x0000FF00) >> 8,
-                   (IpAddress->in_addr & 0x000000FF) >> 0 ));
+    } else {
+
+        cfs_enter_debugger();
     }
+
+    return (Status);
 }
 
+/*
+ * KsCloseAddress
+ *   Release the Hanlde and FileObject of an opened tdi
+ *   address object
+ *
+ * Arguments:
+ *   Handle:       the handle to be released
+ *   FileObject:   the fileobject to be released
+ *
+ * Return Value:
+ *   NTSTATUS:     kernel status code (STATUS_SUCCESS
+ *                 or other error code)
+ *
+ * Notes:
+ *   N/A
+ */
+
 NTSTATUS
-KsRegisterPnpHandlers()
+KsCloseAddress(
+    IN HANDLE             Handle,
+    IN PFILE_OBJECT       FileObject
+)
 {
-    TDI20_CLIENT_INTERFACE_INFO ClientInfo;
-
-    /* initialize the global ks_data members */
-    RtlInitUnicodeString(&ks_data.ksnd_client_name, TDILND_MODULE_NAME);
-    spin_lock_init(&ks_data.ksnd_addrs_lock);
-    InitializeListHead(&ks_data.ksnd_addrs_list);
-
-    /* register the pnp handlers */
-    RtlZeroMemory(&ClientInfo, sizeof(ClientInfo));
-    ClientInfo.TdiVersion = TDI_CURRENT_VERSION;
+    NTSTATUS  Status = STATUS_SUCCESS;
 
-    ClientInfo.ClientName = &ks_data.ksnd_client_name;
-    ClientInfo.AddAddressHandlerV2 =  KsAddAddressHandler;
-    ClientInfo.DelAddressHandlerV2 =  KsDelAddressHandler;
+    if (FileObject) {
 
-    return TdiRegisterPnPHandlers(&ClientInfo, sizeof(ClientInfo),
-                                  &ks_data.ksnd_pnp_handle);
-}
+        ObDereferenceObject(FileObject);
+    }
 
-VOID
-KsDeregisterPnpHandlers()
-{
-    if (ks_data.ksnd_pnp_handle) {
+    if (Handle) {
 
-        /* De-register the pnp handlers */
+        Status = ZwClose(Handle);
+    }
 
-        TdiDeregisterPnPHandlers(ks_data.ksnd_pnp_handle);
-        ks_data.ksnd_pnp_handle = NULL;
+    ASSERT(NT_SUCCESS(Status));
 
-        /* cleanup all the ip address slots */
-        KsCleanupIpAddresses();
-    }
+    return (Status);
 }
 
+
 /*
- * KsConnectEventHandler
- *   Connect event handler event handler, called by the underlying TDI
- *   transport in response to an incoming request to the listening daemon.
- *
- *   it will grab a vacancy backlog from the children tconn list, and
- *   build an acception Irp with it, then transfer the Irp to TDI driver.
+ * KsOpenConnection
+ *   Open a tdi connection object
  *
  * Arguments:
- *   TdiEventContext:  the tdi connnection object of the listening daemon
- *   ......
+ *   DeviceName:   device name of the connection object
+ *   ConnectionContext: the connection context
+ *   Handle:       the newly opened handle
+ *   FileObject:   the newly opened fileobject
  *
  * Return Value:
- *   Nt kernel status code
+ *   NTSTATUS:     kernel status code (STATUS_SUCCESS
+ *                 or other error code)
  *
  * Notes:
  *   N/A
  */
 
 NTSTATUS
-KsConnectEventHandler(
-    IN PVOID                    TdiEventContext,
-    IN LONG                     RemoteAddressLength,
-    IN PVOID                    RemoteAddress,
-    IN LONG                     UserDataLength,
-    IN PVOID                    UserData,
-    IN LONG                     OptionsLength,
-    IN PVOID                    Options,
-    OUT CONNECTION_CONTEXT *    ConnectionContext,
-    OUT PIRP *                  AcceptIrp
-    )
+KsOpenConnection(
+    IN PUNICODE_STRING      DeviceName,
+    IN CONNECTION_CONTEXT   ConnectionContext,
+    OUT HANDLE *            Handle,
+    OUT PFILE_OBJECT *      FileObject
+   )
 {
-    ksock_tconn_t *             parent;
-    ksock_tconn_t *             child;
+    NTSTATUS            Status = STATUS_SUCCESS;
 
-    PFILE_OBJECT                FileObject;
-    PDEVICE_OBJECT              DeviceObject;
-    NTSTATUS                    Status;
+    PFILE_FULL_EA_INFORMATION Ea = NULL;
+    ULONG               EaLength;
+    UCHAR               EaBuffer[EA_MAX_LENGTH];
 
-    PIRP                        Irp = NULL;
-    PTDI_CONNECTION_INFORMATION ConnectionInfo = NULL;
+    OBJECT_ATTRIBUTES   ObjectAttributes;
+    IO_STATUS_BLOCK     IoStatus;
 
-    KsPrint((2,"KsConnectEventHandler: call at Irql: %u\n", KeGetCurrentIrql()));
-    parent = (ksock_tconn_t *) TdiEventContext;
+    //
+    // Building EA for the Address Object to be Opened ...
+    //
 
-    LASSERT(parent->kstc_type == kstt_listener);
+    Ea = (PFILE_FULL_EA_INFORMATION)EaBuffer;
+    Ea->NextEntryOffset = 0;
+    Ea->Flags = 0;
+    Ea->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
+    Ea->EaValueLength = (USHORT)sizeof(CONNECTION_CONTEXT);
+    RtlCopyMemory(
+        &(Ea->EaName),
+        TdiConnectionContext,
+        Ea->EaNameLength + 1
+        );
+    RtlMoveMemory(
+        &(Ea->EaName[Ea->EaNameLength + 1]),
+        &ConnectionContext,
+        sizeof(CONNECTION_CONTEXT)
+        );
+    EaLength = sizeof(FILE_FULL_EA_INFORMATION) - 1 +
+                               Ea->EaNameLength + 1 + sizeof(CONNECTION_CONTEXT);
 
-    spin_lock(&(parent->kstc_lock));
-
-    if (parent->kstc_state == ksts_listening) {
-
-        /* allocate a new ConnectionInfo to backup the peer's info */
-
-        ConnectionInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(
-                NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) +
-                RemoteAddressLength, 'iCsK' );
-
-        if (NULL == ConnectionInfo) {
-
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-            cfs_enter_debugger();
-            goto errorout;
-        }
-
-        /* initializing ConnectionInfo structure ... */
-
-        ConnectionInfo->UserDataLength = UserDataLength;
-        ConnectionInfo->UserData = UserData;
-        ConnectionInfo->OptionsLength = OptionsLength;
-        ConnectionInfo->Options = Options;
-        ConnectionInfo->RemoteAddressLength = RemoteAddressLength;
-        ConnectionInfo->RemoteAddress = ConnectionInfo + 1;
-
-        RtlCopyMemory(
-                ConnectionInfo->RemoteAddress,
-                RemoteAddress,
-                RemoteAddressLength
-                );
-
-        /* get the vacancy listening child tdi connections */
-
-        child = ks_get_vacancy_backlog(parent);
-
-        if (child) {
-
-            spin_lock(&(child->kstc_lock));
-            child->child.kstc_info.ConnectionInfo = ConnectionInfo;
-            child->child.kstc_info.Remote = ConnectionInfo->RemoteAddress;
-            child->kstc_state = ksts_connecting;
-            spin_unlock(&(child->kstc_lock));
-
-        } else {
+    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
 
-            KsPrint((2, "KsConnectEventHandler: No enough backlogs: Refsued the connectio: %xh\n", parent));
 
-            Status = STATUS_INSUFFICIENT_RESOURCES;
+    //
+    // Initializing ...
+    //
 
-            goto errorout;
-        }
+    InitializeObjectAttributes(
+        &ObjectAttributes,
+        DeviceName,
+        OBJ_CASE_INSENSITIVE |
+        OBJ_KERNEL_HANDLE,
+        NULL,
+        NULL
+        );
 
-        FileObject = child->child.kstc_info.FileObject;
-        DeviceObject = IoGetRelatedDeviceObject (FileObject);
+    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
 
-        Irp = KsBuildTdiIrp(DeviceObject);
+    //
+    // Creating the Connection Object ...
+    //
 
-        TdiBuildAccept(
-                Irp,
-                DeviceObject,
-                FileObject,
-                KsAcceptCompletionRoutine,
-                child,
+    Status = ZwCreateFile(
+                Handle,
+                FILE_READ_DATA | FILE_WRITE_DATA,
+                &ObjectAttributes,
+                &IoStatus,
                 NULL,
-                NULL
+                FILE_ATTRIBUTE_NORMAL,
+                FILE_SHARE_READ | FILE_SHARE_WRITE,
+                FILE_OPEN,
+                0,
+                Ea,
+                EaLength
                 );
 
-        IoSetNextIrpStackLocation(Irp);
-
-        /* grap the refer of the child tdi connection */
-        ks_get_tconn(child);
-
-        Status = STATUS_MORE_PROCESSING_REQUIRED;
-
-        *AcceptIrp = Irp;
-        *ConnectionContext = child;
-
-    } else {
-
-        Status = STATUS_CONNECTION_REFUSED;
-        goto errorout;
-    }
-
-    spin_unlock(&(parent->kstc_lock));
-
-    return Status;
 
-errorout:
+    if (NT_SUCCESS(Status)) {
 
-    spin_unlock(&(parent->kstc_lock));
+        //
+        // Now Obtaining the FileObject of the Transport Address ...
+        //
 
-    {
-        *AcceptIrp = NULL;
-        *ConnectionContext = NULL;
+        Status = ObReferenceObjectByHandle(
+                    *Handle,
+                    FILE_ANY_ACCESS,
+                    NULL,
+                    KernelMode,
+                    FileObject,
+                    NULL
+                    );
 
-        if (ConnectionInfo) {
+        if (!NT_SUCCESS(Status)) {
 
-            ExFreePool(ConnectionInfo);
+            cfs_enter_debugger();
+            ZwClose(*Handle);
         }
 
-        if (Irp) {
+    } else {
 
-            IoFreeIrp (Irp);
-        }
+        cfs_enter_debugger();
     }
 
-    return Status;
+    return (Status);
 }
 
 /*
- * KsDisconnectCompletionRoutine
- *   the Irp completion routine for TdiBuildDisconect
- *
- *   We just signal the event and return MORE_PRO... to
- *   let the caller take the responsibility of the Irp.
+ * KsCloseConnection
+ *   Release the Hanlde and FileObject of an opened tdi
+ *   connection object
  *
  * Arguments:
- *   DeviceObject:  the device object of the transport
- *   Irp:           the Irp is being completed.
- *   Context:       the event specified by the caller
+ *   Handle:       the handle to be released
+ *   FileObject:   the fileobject to be released
  *
  * Return Value:
- *   Nt status code
+ *   NTSTATUS:     kernel status code (STATUS_SUCCESS
+ *                 or other error code)
  *
  * Notes:
  *   N/A
  */
 
 NTSTATUS
-KsDisconectCompletionRoutine (
-    IN PDEVICE_OBJECT   DeviceObject,
-    IN PIRP             Irp,
-    IN PVOID            Context
+KsCloseConnection(
+    IN HANDLE             Handle,
+    IN PFILE_OBJECT       FileObject
     )
 {
+    NTSTATUS  Status = STATUS_SUCCESS;
 
-    KeSetEvent((PKEVENT) Context, 0, FALSE);
+    if (FileObject) {
 
-    return STATUS_MORE_PROCESSING_REQUIRED;
+        ObDereferenceObject(FileObject);
+    }
 
-    UNREFERENCED_PARAMETER(DeviceObject);
+    if (Handle) {
+
+        Status = ZwClose(Handle);
+    }
+
+    ASSERT(NT_SUCCESS(Status));
+
+    return (Status);
 }
 
 
 /*
- * KsDisconnectHelper
- *   the routine to be executed in the WorkItem procedure
- *   this routine is to disconnect a tdi connection
+ * KsAssociateAddress
+ *   Associate an address object with a connection object
  *
  * Arguments:
- *   Workitem:  the context transferred to the workitem
+ *   AddressHandle:  the handle of the address object
+ *   ConnectionObject:  the FileObject of the connection
  *
  * Return Value:
- *   N/A
+ *   NTSTATUS:     kernel status code (STATUS_SUCCESS
+ *                 or other error code)
  *
  * Notes:
- *   tconn is already referred in abort_connecton ...
+ *   N/A
  */
 
-VOID
-KsDisconnectHelper(PKS_DISCONNECT_WORKITEM WorkItem)
+NTSTATUS
+KsAssociateAddress(
+    IN HANDLE           AddressHandle,
+    IN PFILE_OBJECT     ConnectionObject
+    )
 {
-    ksock_tconn_t * tconn = WorkItem->tconn;
+    NTSTATUS            Status;
+    PDEVICE_OBJECT      DeviceObject;
+    PIRP                Irp;
 
-    DbgPrint("KsDisconnectHelper: disconnecting tconn=%p\n", tconn);
-    ks_disconnect_tconn(tconn, WorkItem->Flags);
+    //
+    // Getting the DeviceObject from Connection FileObject
+    //
 
-    KeSetEvent(&(WorkItem->Event), 0, FALSE);
+    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
 
-    spin_lock(&(tconn->kstc_lock));
-    cfs_clear_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
-    spin_unlock(&(tconn->kstc_lock));
-    ks_put_tconn(tconn);
+    //
+    // Building Tdi Internal Irp ...
+    //
+
+    Irp = KsBuildTdiIrp(DeviceObject);
+
+    if (NULL == Irp) {
+
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+
+    } else {
+
+        //
+        // Assocating the Address Object with the Connection Object
+        //
+
+        TdiBuildAssociateAddress(
+            Irp,
+            DeviceObject,
+            ConnectionObject,
+            NULL,
+            NULL,
+            AddressHandle
+            );
+
+        //
+        // Calling the Transprot Driver with the Prepared Irp
+        //
+
+        Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
+    }
+
+    return (Status);
 }
 
 
 /*
- * KsDisconnectEventHandler
- *   Disconnect event handler event handler, called by the underlying TDI transport
- *   in response to an incoming disconnection notification from a remote node.
+ * KsDisassociateAddress
+ *   Disassociate the connection object (the relationship will
+ *   the corresponding address object will be dismissed. )
  *
  * Arguments:
- *   ConnectionContext:  tdi connnection object
- *   DisconnectFlags:    specifies the nature of the disconnection
- *   ......
+ *   ConnectionObject:  the FileObject of the connection
  *
  * Return Value:
- *   Nt kernel status code
+ *   NTSTATUS:     kernel status code (STATUS_SUCCESS
+ *                 or other error code)
  *
  * Notes:
  *   N/A
  */
 
-
 NTSTATUS
-KsDisconnectEventHandler(
-    IN PVOID                TdiEventContext,
-    IN CONNECTION_CONTEXT   ConnectionContext,
-    IN LONG                 DisconnectDataLength,
-    IN PVOID                DisconnectData,
-    IN LONG                 DisconnectInformationLength,
-    IN PVOID                DisconnectInformation,
-    IN ULONG                DisconnectFlags
+KsDisassociateAddress(
+    IN PFILE_OBJECT     ConnectionObject
     )
 {
-    ksock_tconn_t *         tconn;
-    NTSTATUS                Status;
-    PKS_DISCONNECT_WORKITEM WorkItem;
-
-    tconn = (ksock_tconn_t *)ConnectionContext;
+    NTSTATUS            Status;
+    PDEVICE_OBJECT      DeviceObject;
+    PIRP                   Irp;
 
-    KsPrint((2, "KsTcpDisconnectEventHandler: called at Irql: %xh\n",
-                KeGetCurrentIrql() ));
+    //
+    // Getting the DeviceObject from Connection FileObject
+    //
 
-    KsPrint((2, "tconn = %x DisconnectFlags= %xh\n",
-                 tconn, DisconnectFlags));
+    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
 
-    ks_get_tconn(tconn);
-    spin_lock(&(tconn->kstc_lock));
+    //
+    // Building Tdi Internal Irp ...
+    //
 
-    WorkItem = &(tconn->kstc_disconnect);
+    Irp = KsBuildTdiIrp(DeviceObject);
 
-    if (tconn->kstc_state != ksts_connected) {
+    if (NULL == Irp) {
 
-        Status = STATUS_SUCCESS;
+        Status = STATUS_INSUFFICIENT_RESOURCES;
 
     } else {
 
-        if (cfs_is_flag_set(DisconnectFlags, TDI_DISCONNECT_ABORT)) {
-
-            Status = STATUS_REMOTE_DISCONNECT;
-
-        } else if (cfs_is_flag_set(DisconnectFlags, TDI_DISCONNECT_RELEASE)) {
-
-            Status = STATUS_GRACEFUL_DISCONNECT;
-        }
-
-        if (!cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY)) {
-
-            ks_get_tconn(tconn);
+        //
+        // Disassocating the Address Object with the Connection Object
+        //
 
-            WorkItem->Flags = DisconnectFlags;
-            WorkItem->tconn = tconn;
+        TdiBuildDisassociateAddress(
+            Irp,
+            DeviceObject,
+            ConnectionObject,
+            NULL,
+            NULL
+            );
 
-            cfs_set_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
+        //
+        // Calling the Transprot Driver with the Prepared Irp
+        //
 
-            /* queue the workitem to call */
-            ExQueueWorkItem(&(WorkItem->WorkItem), DelayedWorkQueue);
-        }
+        Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
     }
 
-    spin_unlock(&(tconn->kstc_lock));
-    ks_put_tconn(tconn);
-
-    return  (Status);
+    return (Status);
 }
 
-NTSTATUS
-KsTcpReceiveCompletionRoutine(
-    IN PIRP                         Irp,
-    IN PKS_TCP_COMPLETION_CONTEXT   Context
-    )
-{
-    NTSTATUS Status = Irp->IoStatus.Status;
-
-    if (NT_SUCCESS(Status)) {
-
-        ksock_tconn_t *tconn = Context->tconn;
-
-        PKS_TSDU_DAT  KsTsduDat = Context->CompletionContext;
-        PKS_TSDU_BUF  KsTsduBuf = Context->CompletionContext;
 
-        KsPrint((1, "KsTcpReceiveCompletionRoutine: Total %xh bytes.\n",
-                   Context->KsTsduMgr->TotalBytes ));
-
-        spin_lock(&(tconn->kstc_lock));
-
-        if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
-            if (cfs_is_flag_set(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING)) {
-                cfs_clear_flag(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING);
-            } else {
-                cfs_enter_debugger();
-            }
-        } else {
-            ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
-            if (cfs_is_flag_set(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING)) {
-                cfs_clear_flag(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING);
-            } else {
-                cfs_enter_debugger();
-            }
-        }
-
-        spin_unlock(&(tconn->kstc_lock));
-
-        /* wake up the thread waiting for the completion of this Irp */
-        KeSetEvent(Context->Event, 0, FALSE);
-
-        /* re-active the ks connection and wake up the scheduler */
-        if (tconn->kstc_conn && tconn->kstc_sched_cb) {
-            tconn->kstc_sched_cb( tconn, FALSE, NULL,
-                                  Context->KsTsduMgr->TotalBytes );
-        }
+/*
 
-    } else {
+//
+// Connection Control Event Callbacks
+//
 
-        /* un-expected errors occur, we must abort the connection */
-        ks_abort_tconn(Context->tconn);
-    }
+TDI_EVENT_CONNECT
+TDI_EVENT_DISCONNECT
+TDI_EVENT_ERROR
 
-    if (Context) {
+//
+// Tcp Event Callbacks
+//
 
-        /* Freeing the Context structure... */
-        ExFreePool(Context);
-        Context = NULL;
-    }
+TDI_EVENT_RECEIVE
+TDI_EVENT_RECEIVE_EXPEDITED
+TDI_EVENT_CHAINED_RECEIVE
+TDI_EVENT_CHAINED_RECEIVE_EXPEDITED
 
+//
+// Udp Event Callbacks
+//
 
-    /* free the Irp */
-    if (Irp) {
-        IoFreeIrp(Irp);
-    }
+TDI_EVENT_RECEIVE_DATAGRAM
+TDI_EVENT_CHAINED_RECEIVE_DATAGRAM
 
-    return (Status);
-}
+*/
 
 
 /*
- * KsTcpCompletionRoutine
- *   the Irp completion routine for TdiBuildSend and TdiBuildReceive ...
- *   We need call the use's own CompletionRoutine if specified. Or
- *   it's a synchronous case, we need signal the event.
+ * KsSetEventHandlers
+ *   Set the tdi event callbacks with an address object
  *
  * Arguments:
- *   DeviceObject:  the device object of the transport
- *   Irp:           the Irp is being completed.
- *   Context:       the context we specified when issuing the Irp
+ *   AddressObject: the FileObject of the address object
+ *   EventContext:  the parameter for the callbacks
+ *   Handlers:      the handlers indictor array
  *
  * Return Value:
- *   Nt status code
+ *   NTSTATUS:     kernel status code (STATUS_SUCCESS
+ *                 or other error code)
  *
- * Notes:
+ * NOTES:
  *   N/A
  */
 
 NTSTATUS
-KsTcpCompletionRoutine(
-    IN PDEVICE_OBJECT   DeviceObject,
-    IN PIRP             Irp,
-    IN PVOID            Context
-    )
+KsSetEventHandlers(
+    IN PFILE_OBJECT                         AddressObject,  // Address File Object
+    IN PVOID                                EventContext,   // Context for Handlers
+    IN PKS_EVENT_HANDLERS                   Handlers        // Handlers Indictor
+   )
 {
-    if (Context) {
+    NTSTATUS             Status = STATUS_SUCCESS;
+    PDEVICE_OBJECT       DeviceObject;
+    USHORT               i = 0;
 
-        PKS_TCP_COMPLETION_CONTEXT  CompletionContext = NULL;
-        ksock_tconn_t * tconn = NULL;
+    DeviceObject = IoGetRelatedDeviceObject(AddressObject);
 
-        CompletionContext = (PKS_TCP_COMPLETION_CONTEXT) Context;
-        tconn = CompletionContext->tconn;
+    for (i=0; i < TDI_EVENT_MAXIMUM_HANDLER; i++) {
 
-        /* release the chained mdl */
-        KsReleaseMdl(Irp->MdlAddress, FALSE);
-        Irp->MdlAddress = NULL;
+        //
+        // Setup the tdi event callback handler if requested.
+        //
 
-        if (CompletionContext->CompletionRoutine) {
+        if (Handlers->IsActive[i]) {
 
-            if ( CompletionContext->bCounted &&
-                 InterlockedDecrement(&CompletionContext->ReferCount) != 0 ) {
-                    goto errorout;
-            }
+            PIRP            Irp;
 
             //
-            // Giving control to user specified CompletionRoutine ...
+            // Building Tdi Internal Irp ...
             //
 
-            CompletionContext->CompletionRoutine(
+            Irp = KsBuildTdiIrp(DeviceObject);
+
+            if (NULL == Irp) {
+
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+
+            } else {
+
+                //
+                // Building the Irp to set the Event Handler ...
+                //
+
+                TdiBuildSetEventHandler(
                     Irp,
-                    CompletionContext
+                    DeviceObject,
+                    AddressObject,
+                    NULL,
+                    NULL,
+                    i,                      /* tdi event type */
+                    Handlers->Handler[i],   /* tdi event handler */
+                    EventContext            /* context for the handler */
                     );
 
-        } else {
-
-            //
-            // Signaling  the Event ...
-            //
+                //
+                // Calling the Transprot Driver with the Prepared Irp
+                //
 
-            KeSetEvent(CompletionContext->Event, 0, FALSE);
-        }
+                Status = KsSubmitTdiIrp(DeviceObject, Irp, TRUE, NULL);
 
-        /* drop the reference count of the tconn object */
-        ks_put_tconn(tconn);
+                //
+                // tcp/ip tdi does not support these two event callbacks
+                //
 
-    } else {
+                if ((!NT_SUCCESS(Status)) && ( i == TDI_EVENT_SEND_POSSIBLE ||
+                     i == TDI_EVENT_CHAINED_RECEIVE_EXPEDITED )) {
+                    cfs_enter_debugger();
+                    Status = STATUS_SUCCESS;
+                }
+            }
 
-        cfs_enter_debugger();
+            if (!NT_SUCCESS(Status)) {
+                cfs_enter_debugger();
+                goto errorout;
+            }
+        }
     }
 
+
 errorout:
 
-    return STATUS_MORE_PROCESSING_REQUIRED;
+    if (!NT_SUCCESS(Status)) {
+
+        KsPrint((1, "KsSetEventHandlers: Error Status = %xh (%s)\n",
+                    Status, KsNtStatusToString(Status) ));
+    }
+
+    return (Status);
 }
 
+
+
 /*
- * KsTcpSendCompletionRoutine
- *   the user specified Irp completion routine for asynchronous
- *   data transmission requests.
- *
- *   It will do th cleanup job of the ksock_tx_t and wake up the
- *   ks scheduler thread
+ * KsQueryAddressInfo
+ *   Query the address of the FileObject specified
  *
  * Arguments:
- *   Irp:           the Irp is being completed.
- *   Context:       the context we specified when issuing the Irp
+ *   FileObject:  the FileObject to be queried
+ *   AddressInfo: buffer to contain the address info
+ *   AddressSize: length of the AddressInfo buffer
  *
  * Return Value:
- *   Nt status code
+ *   NTSTATUS:     kernel status code (STATUS_SUCCESS
+ *                 or other error code)
  *
  * Notes:
  *   N/A
  */
 
 NTSTATUS
-KsTcpSendCompletionRoutine(
-    IN PIRP                         Irp,
-    IN PKS_TCP_COMPLETION_CONTEXT   Context
-    )
+KsQueryAddressInfo(
+    PFILE_OBJECT            FileObject,
+    PTDI_ADDRESS_INFO       AddressInfo,
+    PULONG                  AddressSize
+   )
 {
-    NTSTATUS        Status = Irp->IoStatus.Status;
-    ULONG           rc = Irp->IoStatus.Information;
-    ksock_tconn_t * tconn = Context->tconn;
-    PKS_TSDUMGR     KsTsduMgr = Context->KsTsduMgr;
+    NTSTATUS          Status = STATUS_UNSUCCESSFUL;
+    PIRP              Irp = NULL;
+    PMDL              Mdl;
+    PDEVICE_OBJECT    DeviceObject;
 
-    ENTRY;
+    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
 
-    LASSERT(tconn) ;
+    DeviceObject = IoGetRelatedDeviceObject(FileObject);
 
-    if (NT_SUCCESS(Status)) {
+    RtlZeroMemory(AddressInfo, *(AddressSize));
 
-        if (Context->bCounted) {
-            PVOID   tx = Context->CompletionContext;
+    //
+    // Allocating the Tdi Setting Irp ...
+    //
 
-            ASSERT(tconn->kstc_update_tx != NULL);
+    Irp = KsBuildTdiIrp(DeviceObject);
 
-            /* update the tx, rebasing the kiov or iov pointers */
-            tx = tconn->kstc_update_tx(tconn, tx, rc);
+    if (NULL == Irp) {
 
-            /* update the KsTsudMgr total bytes */
-            spin_lock(&tconn->kstc_lock);
-            KsTsduMgr->TotalBytes -= rc;
-            spin_unlock(&tconn->kstc_lock);
+        Status = STATUS_INSUFFICIENT_RESOURCES;
 
-            /*
-             * now it's time to re-queue the conns into the
-             * scheduler queue and wake the scheduler thread.
-             */
+    } else {
 
-            if (tconn->kstc_conn && tconn->kstc_sched_cb) {
-                tconn->kstc_sched_cb( tconn, TRUE, tx, 0);
-            }
+        //
+        // Locking the User Buffer / Allocating a MDL for it
+        //
 
-        } else {
-
-            PKS_TSDU            KsTsdu = Context->CompletionContext;
-            PKS_TSDU_BUF        KsTsduBuf = Context->CompletionContext2;
-            PKS_TSDU_DAT        KsTsduDat = Context->CompletionContext2;
-
-            spin_lock(&tconn->kstc_lock);
-            /* This is bufferred sending ... */
-            ASSERT(KsTsduBuf->StartOffset == 0);
-
-            if (KsTsduBuf->DataLength > Irp->IoStatus.Information) {
-                /* not fully sent .... we have to abort the connection */
-                spin_unlock(&tconn->kstc_lock);
-                ks_abort_tconn(tconn);
-                goto errorout;
-            }
-
-            if (KsTsduBuf->TsduType  == TSDU_TYPE_BUF) {
-                /* free the buffer */
-                ExFreePool(KsTsduBuf->UserBuffer);
-                KsTsduMgr->TotalBytes -= KsTsduBuf->DataLength;
-                KsTsdu->StartOffset   += sizeof(KS_TSDU_BUF);
-            } else if (KsTsduDat->TsduType  == TSDU_TYPE_DAT) {
-                KsTsduMgr->TotalBytes -= KsTsduDat->DataLength;
-                KsTsdu->StartOffset   += KsTsduDat->TotalLength;
-            } else {
-                cfs_enter_debugger(); /* shoult not get here */
-            }
-
-            if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
+        Status = KsLockUserBuffer(
+                    AddressInfo,
+                    FALSE,
+                    *(AddressSize),
+                    IoModifyAccess,
+                    &Mdl
+                    );
 
-                list_del(&KsTsdu->Link);
-                KsTsduMgr->NumOfTsdu--;
-                KsPutKsTsdu(KsTsdu);
-            }
+        if (!NT_SUCCESS(Status)) {
 
-            spin_unlock(&tconn->kstc_lock);
+            IoFreeIrp(Irp);
+            Irp = NULL;
         }
+    }
 
-    } else {
-
-        /* cfs_enter_debugger(); */
-
-        /*
-         *  for the case that the transmission is ussuccessful,
-         *  we need abort the tdi connection, but not destroy it.
-         *  the socknal conn will drop the refer count, then the
-         *  tdi connection will be freed.
-         */
+    if (Irp) {
 
-        ks_abort_tconn(tconn);
-    }
+        LASSERT(NT_SUCCESS(Status));
 
-errorout:
+        TdiBuildQueryInformation(
+                    Irp,
+                    DeviceObject,
+                    FileObject,
+                    NULL,
+                    NULL,
+                    TDI_QUERY_ADDRESS_INFO,
+                    Mdl
+                    );
 
-    /* freeing the Context structure... */
+        Status = KsSubmitTdiIrp(
+                    DeviceObject,
+                    Irp,
+                    TRUE,
+                    AddressSize
+                    );
 
-    if (Context) {
-        ExFreePool(Context);
-        Context = NULL;
+        KsReleaseMdl(Mdl, FALSE);
     }
 
-    /* it's our duty to free the Irp. */
+    if (!NT_SUCCESS(Status)) {
 
-    if (Irp) {
-        IoFreeIrp(Irp);
-        Irp = NULL;
+        cfs_enter_debugger();
+        //TDI_BUFFER_OVERFLOW
     }
 
-    EXIT;
-
-    return Status;
+    return (Status);
 }
 
 /*
- *  Normal receive event handler
+ * KsQueryProviderInfo
+ *   Query the underlying transport device's information
  *
- *  It will move data from system Tsdu to our TsduList
+ * Arguments:
+ *   TdiDeviceName:  the transport device's name string
+ *   ProviderInfo:   TDI_PROVIDER_INFO struncture
+ *
+ * Return Value:
+ *   NTSTATUS:       Nt system status code
+  *
+ * NOTES:
+ *   N/A
  */
 
 NTSTATUS
-KsTcpReceiveEventHandler(
-    IN PVOID                TdiEventContext,
-    IN CONNECTION_CONTEXT   ConnectionContext,
-    IN ULONG                ReceiveFlags,
-    IN ULONG                BytesIndicated,
-    IN ULONG                BytesAvailable,
-    OUT ULONG *             BytesTaken,
-    IN PVOID                Tsdu,
-    OUT PIRP *              IoRequestPacket
+KsQueryProviderInfo(
+    PWSTR               TdiDeviceName,
+    PTDI_PROVIDER_INFO  ProviderInfo
    )
 {
-    NTSTATUS            Status;
-
-    ksock_tconn_t *     tconn;
-
-    PKS_CHAIN           KsChain;
-    PKS_TSDUMGR         KsTsduMgr;
-    PKS_TSDU            KsTsdu;
-    PKS_TSDU_DAT        KsTsduDat;
-    PKS_TSDU_BUF        KsTsduBuf;
-
-    BOOLEAN             bIsExpedited;
-    BOOLEAN             bIsCompleteTsdu;
-
-    BOOLEAN             bNewTsdu = FALSE;
-    BOOLEAN             bNewBuff = FALSE;
-
-    PCHAR               Buffer = NULL;
+    NTSTATUS            Status = STATUS_SUCCESS;
 
     PIRP                Irp = NULL;
     PMDL                Mdl = NULL;
+
+    UNICODE_STRING      ControlName;
+
+    HANDLE              Handle;
     PFILE_OBJECT        FileObject;
     PDEVICE_OBJECT      DeviceObject;
 
-    ULONG               BytesReceived = 0;
+    ULONG               ProviderSize = 0;
 
-    PKS_TCP_COMPLETION_CONTEXT context = NULL;
+    RtlInitUnicodeString(&ControlName, TdiDeviceName);
 
+    //
+    // Open the Tdi Control Channel
+    //
 
-    tconn = (ksock_tconn_t *) ConnectionContext;
+    Status = KsOpenControl(
+                &ControlName,
+                &Handle,
+                &FileObject
+                );
 
-    ks_get_tconn(tconn);
+    if (!NT_SUCCESS(Status)) {
 
-    /* check whether the whole body of payload is received or not */
-    if ( (cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_ENTIRE_MESSAGE)) &&
-         (BytesIndicated == BytesAvailable) ) {
-        bIsCompleteTsdu = TRUE;
-    } else {
-        bIsCompleteTsdu = FALSE;
+        KsPrint((1, "KsQueryProviderInfo: Fail to open the tdi control channel.\n"));
+        return (Status);
     }
 
-    bIsExpedited = cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_EXPEDITED);
+    //
+    // Obtain The Related Device Object
+    //
 
-    KsPrint((2, "KsTcpReceiveEventHandler BytesIndicated = %d BytesAvailable = %d ...\n", BytesIndicated, BytesAvailable));
-    KsPrint((2, "bIsCompleteTsdu = %d bIsExpedited = %d\n", bIsCompleteTsdu, bIsExpedited ));
+    DeviceObject = IoGetRelatedDeviceObject(FileObject);
 
-    spin_lock(&(tconn->kstc_lock));
+    ProviderSize = sizeof(TDI_PROVIDER_INFO);
+    RtlZeroMemory(ProviderInfo, ProviderSize);
 
-    /*  check whether we are conntected or not listener Â¡Â­*/
-    if ( !((tconn->kstc_state == ksts_connected) &&
-           (tconn->kstc_type == kstt_sender ||
-            tconn->kstc_type == kstt_child))) {
+    //
+    // Allocating the Tdi Setting Irp ...
+    //
 
-        *BytesTaken = BytesIndicated;
+    Irp = KsBuildTdiIrp(DeviceObject);
 
-        spin_unlock(&(tconn->kstc_lock));
-        ks_put_tconn(tconn);
+    if (NULL == Irp) {
 
-        return (STATUS_SUCCESS);
-    }
+        Status = STATUS_INSUFFICIENT_RESOURCES;
 
-    if (tconn->kstc_type == kstt_sender) {
-        KsChain = &(tconn->sender.kstc_recv);
     } else {
-        LASSERT(tconn->kstc_type == kstt_child);
-        KsChain = &(tconn->child.kstc_recv);
-    }
 
-    if (bIsExpedited) {
-        KsTsduMgr = &(KsChain->Expedited);
-    } else {
-        KsTsduMgr = &(KsChain->Normal);
-    }
+        //
+        // Locking the User Buffer / Allocating a MDL for it
+        //
 
-    /* if the Tsdu is even larger than the biggest Tsdu, we have
-       to allocate new buffer and use TSDU_TYOE_BUF to store it */
+        Status = KsLockUserBuffer(
+                    ProviderInfo,
+                    FALSE,
+                    ProviderSize,
+                    IoModifyAccess,
+                    &Mdl
+                    );
 
-    if ( KS_TSDU_STRU_SIZE(BytesAvailable) > ks_data.ksnd_tsdu_size -
-         KS_DWORD_ALIGN(sizeof(KS_TSDU))) {
-        bNewBuff = TRUE;
+        if (!NT_SUCCESS(Status)) {
+
+            IoFreeIrp(Irp);
+            Irp = NULL;
+        }
     }
 
-    /* retrieve the latest Tsdu buffer form TsduMgr
-       list if the list is not empty. */
+    if (Irp) {
 
-    if (list_empty(&(KsTsduMgr->TsduList))) {
+        LASSERT(NT_SUCCESS(Status));
 
-        LASSERT(KsTsduMgr->NumOfTsdu == 0);
-        KsTsdu = NULL;
+        TdiBuildQueryInformation(
+                    Irp,
+                    DeviceObject,
+                    FileObject,
+                    NULL,
+                    NULL,
+                    TDI_QUERY_PROVIDER_INFO,
+                    Mdl
+                    );
 
-    } else {
+        Status = KsSubmitTdiIrp(
+                    DeviceObject,
+                    Irp,
+                    TRUE,
+                    &ProviderSize
+                    );
 
-        LASSERT(KsTsduMgr->NumOfTsdu > 0);
-        KsTsdu = list_entry(KsTsduMgr->TsduList.prev, KS_TSDU, Link);
+        KsReleaseMdl(Mdl, FALSE);
+    }
 
-        /* if this Tsdu does not contain enough space, we need
-           allocate a new Tsdu queue. */
+    if (!NT_SUCCESS(Status)) {
 
-        if (bNewBuff) {
-            if ( KsTsdu->LastOffset + sizeof(KS_TSDU_BUF) >
-                 KsTsdu->TotalLength )  {
-                KsTsdu = NULL;
-            }
-        } else {
-            if ( KS_TSDU_STRU_SIZE(BytesAvailable) >
-                 KsTsdu->TotalLength - KsTsdu->LastOffset ) {
-                KsTsdu = NULL;
-            }
-        }
+        cfs_enter_debugger();
+        //TDI_BUFFER_OVERFLOW
     }
 
-    /* allocating the buffer for TSDU_TYPE_BUF */
-    if (bNewBuff) {
-        Buffer = ExAllocatePool(NonPagedPool, BytesAvailable);
-        if (NULL == Buffer) {
-            /* there's no enough memory for us. We just try to
-               receive maximum bytes with a new Tsdu */
-            bNewBuff = FALSE;
-            KsTsdu = NULL;
-        }
-    }
+    KsCloseControl(Handle, FileObject);
 
-    /* allocate a new Tsdu in case we are not statisfied. */
+    return (Status);
+}
 
-    if (NULL == KsTsdu) {
+/*
+ * KsQueryConnectionInfo
+ *   Query the connection info of the FileObject specified
+ *   (some statics data of the traffic)
+ *
+ * Arguments:
+ *   FileObject:     the FileObject to be queried
+ *   ConnectionInfo: buffer to contain the connection info
+ *   ConnectionSize: length of the ConnectionInfo buffer
+ *
+ * Return Value:
+ *   NTSTATUS:     kernel status code (STATUS_SUCCESS
+ *                 or other error code)
+ *
+ * NOTES:
+ *   N/A
+ */
 
-        KsTsdu = KsAllocateKsTsdu();
+NTSTATUS
+KsQueryConnectionInfo(
+    PFILE_OBJECT            ConnectionObject,
+    PTDI_CONNECTION_INFO    ConnectionInfo,
+    PULONG                  ConnectionSize
+   )
+{
+    NTSTATUS          Status = STATUS_UNSUCCESSFUL;
+    PIRP              Irp = NULL;
+    PMDL              Mdl;
+    PDEVICE_OBJECT    DeviceObject;
 
-        if (NULL == KsTsdu) {
-            goto errorout;
-        } else {
-            bNewTsdu = TRUE;
-        }
-    }
+    LASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
 
-    KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
-    KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
+    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
 
-    if (bNewBuff) {
+    RtlZeroMemory(ConnectionInfo, *(ConnectionSize));
 
-        /* setup up the KS_TSDU_BUF record */
+    //
+    // Allocating the Tdi Query Irp ...
+    //
 
-        KsTsduBuf->TsduType     = TSDU_TYPE_BUF;
-        KsTsduBuf->TsduFlags    = 0;
-        KsTsduBuf->StartOffset  = 0;
-        KsTsduBuf->UserBuffer   = Buffer;
-        KsTsduBuf->DataLength   = BytesReceived = BytesAvailable;
+    Irp = KsBuildTdiIrp(DeviceObject);
 
-        KsTsdu->LastOffset += sizeof(KS_TSDU_BUF);
+    if (NULL == Irp) {
 
-    } else {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
 
-        /* setup the KS_TSDU_DATA to contain all the messages */
+    } else {
 
-        KsTsduDat->TsduType     =  TSDU_TYPE_DAT;
-        KsTsduDat->TsduFlags    = 0;
+        //
+        // Locking the User Buffer / Allocating a MDL for it
+        //
 
-        if ( KsTsdu->TotalLength - KsTsdu->LastOffset >=
-            KS_TSDU_STRU_SIZE(BytesAvailable) ) {
-            BytesReceived = BytesAvailable;
-        } else {
-            BytesReceived = KsTsdu->TotalLength - KsTsdu->LastOffset -
-                            FIELD_OFFSET(KS_TSDU_DAT, Data);
-            BytesReceived &= (~((ULONG)3));
-        }
-        KsTsduDat->DataLength   =  BytesReceived;
-        KsTsduDat->TotalLength  =  KS_TSDU_STRU_SIZE(BytesReceived);
-        KsTsduDat->StartOffset  = 0;
+        Status = KsLockUserBuffer(
+                    ConnectionInfo,
+                    FALSE,
+                    *(ConnectionSize),
+                    IoModifyAccess,
+                    &Mdl
+                    );
 
-        Buffer = &KsTsduDat->Data[0];
+        if (NT_SUCCESS(Status)) {
 
-        KsTsdu->LastOffset += KsTsduDat->TotalLength;
+            IoFreeIrp(Irp);
+            Irp = NULL;
+        }
     }
 
-    KsTsduMgr->TotalBytes  +=  BytesReceived;
+    if (Irp) {
 
-    if (bIsCompleteTsdu) {
+        LASSERT(NT_SUCCESS(Status));
 
-        /* It's a complete receive, we just move all
-           the data from system to our Tsdu */
+        TdiBuildQueryInformation(
+                    Irp,
+                    DeviceObject,
+                    ConnectionObject,
+                    NULL,
+                    NULL,
+                    TDI_QUERY_CONNECTION_INFO,
+                    Mdl
+                    );
 
-        RtlMoveMemory(
-            Buffer,
-            Tsdu,
-            BytesReceived
-            );
+        Status = KsSubmitTdiIrp(
+                    DeviceObject,
+                    Irp,
+                    TRUE,
+                    ConnectionSize
+                    );
 
-        *BytesTaken = BytesReceived;
-        Status = STATUS_SUCCESS;
+        KsReleaseMdl(Mdl, FALSE);
+    }
 
-        if (bNewTsdu) {
-            list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
-            KsTsduMgr->NumOfTsdu++;
-        }
+    return (Status);
+}
 
-        KeSetEvent(&(KsTsduMgr->Event), 0, FALSE);
 
-        /* re-active the ks connection and wake up the scheduler */
-        if (tconn->kstc_conn && tconn->kstc_sched_cb) {
-            tconn->kstc_sched_cb( tconn, FALSE, NULL,
-                                  KsTsduMgr->TotalBytes );
-        }
+/*
+ * KsInitializeTdiAddress
+ *   Initialize the tdi addresss
+ *
+ * Arguments:
+ *   pTransportAddress: tdi address to be initialized
+ *   IpAddress:         the ip address of object
+ *   IpPort:            the ip port of the object
+ *
+ * Return Value:
+ *   ULONG: the total size of the tdi address
+ *
+ * NOTES:
+ *   N/A
+ */
 
-    } else {
+ULONG
+KsInitializeTdiAddress(
+    IN OUT PTA_IP_ADDRESS   pTransportAddress,
+    IN ULONG                IpAddress,
+    IN USHORT               IpPort
+    )
+{
+    pTransportAddress->TAAddressCount = 1;
+    pTransportAddress->Address[ 0 ].AddressLength = TDI_ADDRESS_LENGTH_IP;
+    pTransportAddress->Address[ 0 ].AddressType   = TDI_ADDRESS_TYPE_IP;
+    pTransportAddress->Address[ 0 ].Address[ 0 ].sin_port = IpPort;
+    pTransportAddress->Address[ 0 ].Address[ 0 ].in_addr  = IpAddress;
 
-        /* there's still data in tdi internal queue, we need issue a new
-           Irp to receive all of them. first allocate the tcp context */
+    return (FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address) + TDI_ADDRESS_LENGTH_IP);
+}
 
-        context = ExAllocatePoolWithTag(
-                        NonPagedPool,
-                        sizeof(KS_TCP_COMPLETION_CONTEXT),
-                        'cTsK');
+/*
+ * KsQueryTdiAddressLength
+ *   Query the total size of the tdi address
+ *
+ * Arguments:
+ *   pTransportAddress: tdi address to be queried
+ *
+ * Return Value:
+ *   ULONG: the total size of the tdi address
+ *
+ * NOTES:
+ *   N/A
+ */
 
-        if (!context) {
+ULONG
+KsQueryTdiAddressLength(
+    PTRANSPORT_ADDRESS      pTransportAddress
+    )
+{
+    ULONG                   TotalLength = 0;
+    LONG                    i;
 
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-            goto errorout;
-        }
+    PTA_ADDRESS             pTaAddress = NULL;
 
-        /* setup the context */
-        RtlZeroMemory(context, sizeof(KS_TCP_COMPLETION_CONTEXT));
+    ASSERT (NULL != pTransportAddress);
 
-        context->tconn             = tconn;
-        context->CompletionRoutine = KsTcpReceiveCompletionRoutine;
-        context->CompletionContext = KsTsdu;
-        context->CompletionContext = bNewBuff ? (PVOID)KsTsduBuf : (PVOID)KsTsduDat;
-        context->KsTsduMgr         = KsTsduMgr;
-        context->Event             = &(KsTsduMgr->Event);
+    TotalLength  = FIELD_OFFSET(TRANSPORT_ADDRESS, Address) +
+                   FIELD_OFFSET(TA_ADDRESS, Address) * pTransportAddress->TAAddressCount;
 
-        if (tconn->kstc_type == kstt_sender) {
-            FileObject = tconn->sender.kstc_info.FileObject;
-        } else {
-            FileObject = tconn->child.kstc_info.FileObject;
-        }
+    pTaAddress = (PTA_ADDRESS)pTransportAddress->Address;
 
-        DeviceObject = IoGetRelatedDeviceObject(FileObject);
+    for (i = 0; i < pTransportAddress->TAAddressCount; i++)
+    {
+        TotalLength += pTaAddress->AddressLength;
+        pTaAddress = (PTA_ADDRESS)((PCHAR)pTaAddress +
+                                           FIELD_OFFSET(TA_ADDRESS,Address) +
+                                           pTaAddress->AddressLength );
+    }
 
-        /* build new tdi Irp and setup it. */
-        Irp = KsBuildTdiIrp(DeviceObject);
+    return (TotalLength);
+}
 
-        if (NULL == Irp) {
-            goto errorout;
-        }
 
-        Status = KsLockUserBuffer(
-                    Buffer,
-                    FALSE,
-                    BytesReceived,
-                    IoModifyAccess,
-                    &Mdl
-                    );
+/*
+ * KsQueryIpAddress
+ *   Query the ip address of the tdi object
+ *
+ * Arguments:
+ *   FileObject: tdi object to be queried
+ *   TdiAddress: TdiAddress buffer, to store the queried
+ *               tdi ip address
+ *   AddressLength: buffer length of the TdiAddress
+ *
+ * Return Value:
+ *   ULONG: the total size of the tdi ip address
+ *
+ * NOTES:
+ *   N/A
+ */
 
-        if (!NT_SUCCESS(Status)) {
-            goto errorout;
-        }
+NTSTATUS
+KsQueryIpAddress(
+    PFILE_OBJECT    FileObject,
+    PVOID           TdiAddress,
+    ULONG*          AddressLength
+    )
+{
+    NTSTATUS        Status;
 
-        TdiBuildReceive(
-            Irp,
-            DeviceObject,
-            FileObject,
-            KsTcpCompletionRoutine,
-            context,
-            Mdl,
-            ReceiveFlags & (TDI_RECEIVE_NORMAL | TDI_RECEIVE_EXPEDITED),
-            BytesReceived
-          );
+    PTDI_ADDRESS_INFO   TdiAddressInfo;
+    ULONG               Length;
 
-        IoSetNextIrpStackLocation(Irp);
 
-        /* return the newly built Irp to transport driver,
-           it will process it to receive all the data */
+    //
+    // Maximum length of TDI_ADDRESSS_INFO with one TRANSPORT_ADDRESS
+    //
 
-        *IoRequestPacket = Irp;
-        *BytesTaken = 0;
+    Length = MAX_ADDRESS_LENGTH;
 
-        if (bNewTsdu) {
+    TdiAddressInfo = (PTDI_ADDRESS_INFO)
+                        ExAllocatePoolWithTag(
+                            NonPagedPool,
+                            Length,
+                            'KSAI' );
 
-            list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
-            KsTsduMgr->NumOfTsdu++;
-        }
+    if (NULL == TdiAddressInfo) {
 
-        if (bNewBuff) {
-            cfs_set_flag(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING);
-        } else {
-            cfs_set_flag(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING);
-        }
-        ks_get_tconn(tconn);
-        Status = STATUS_MORE_PROCESSING_REQUIRED;
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto errorout;
     }
 
-    spin_unlock(&(tconn->kstc_lock));
-    ks_put_tconn(tconn);
 
-    return (Status);
+    Status = KsQueryAddressInfo(
+                FileObject,
+                TdiAddressInfo,
+                &Length
+                );
 
 errorout:
 
-    spin_unlock(&(tconn->kstc_lock));
-
-    if (bNewTsdu && (KsTsdu != NULL)) {
-        KsFreeKsTsdu(KsTsdu);
-    }
-
-    if (Mdl) {
-        KsReleaseMdl(Mdl, FALSE);
-    }
+    if (NT_SUCCESS(Status)) {
 
-    if (Irp) {
-        IoFreeIrp(Irp);
+        if (*AddressLength < Length) {
+            Status = STATUS_BUFFER_TOO_SMALL;
+        } else {
+            *AddressLength = Length;
+            RtlCopyMemory(
+                TdiAddress,
+                &(TdiAddressInfo->Address),
+                Length
+                );
+            Status = STATUS_SUCCESS;
+        }
     }
 
-    if (context) {
-        ExFreePool(context);
+    if (NULL != TdiAddressInfo) {
+        ExFreePool(TdiAddressInfo);
     }
 
-    ks_abort_tconn(tconn);
-    ks_put_tconn(tconn);
-
-    *BytesTaken = BytesAvailable;
-    Status = STATUS_SUCCESS;
-
-    return (Status);
+    return Status;
 }
 
-/*
- *  Expedited receive event handler
- */
 
-NTSTATUS
-KsTcpReceiveExpeditedEventHandler(
-    IN PVOID                TdiEventContext,
-    IN CONNECTION_CONTEXT   ConnectionContext,
-    IN ULONG                ReceiveFlags,
-    IN ULONG                BytesIndicated,
-    IN ULONG                BytesAvailable,
-    OUT ULONG *             BytesTaken,
-    IN PVOID                Tsdu,
-    OUT PIRP *              IoRequestPacket
-    )
+/*
+ * KsErrorEventHandler
+ *   the common error event handler callback
+ *
+ * Arguments:
+ *   TdiEventContext: should be the socket
+ *   Status: the error code
+ *
+ * Return Value:
+ *   Status: STATS_SUCCESS
+ *
+ * NOTES:
+ *   We need not do anything in such a severe
+ *   error case. System will process it for us.
+ */
+
+NTSTATUS
+KsErrorEventHandler(
+    IN PVOID        TdiEventContext,
+    IN NTSTATUS     Status
+   )
 {
-    return KsTcpReceiveEventHandler(
-                TdiEventContext,
-                ConnectionContext,
-                ReceiveFlags | TDI_RECEIVE_EXPEDITED,
-                BytesIndicated,
-                BytesAvailable,
-                BytesTaken,
-                Tsdu,
-                IoRequestPacket
-                );
-}
+    KsPrint((1, "KsErrorEventHandler called at Irql = %xh ...\n",
+                KeGetCurrentIrql()));
+
+    cfs_enter_debugger();
 
+    return (STATUS_SUCCESS);
+}
 
 /*
- *  Bulk receive event handler
+ * KsAcceptCompletionRoutine
+ *   Irp completion routine for TdiBuildAccept (KsConnectEventHandler)
  *
- *  It will queue all the system Tsdus to our TsduList.
- *  Then later ks_recv_mdl will release them.
+ *   Here system gives us a chance to check the conneciton is built
+ *   ready or not.
+ *
+ * Arguments:
+ *   DeviceObject:  the device object of the transport driver
+ *   Irp:           the Irp is being completed.
+ *   Context:       the context we specified when issuing the Irp
+ *
+ * Return Value:
+ *   Nt status code
+ *
+ * Notes:
+ *   N/A
  */
 
 NTSTATUS
-KsTcpChainedReceiveEventHandler (
-    IN PVOID TdiEventContext,       // the event context
-    IN CONNECTION_CONTEXT ConnectionContext,
-    IN ULONG ReceiveFlags,
-    IN ULONG ReceiveLength,
-    IN ULONG StartingOffset,        // offset of start of client data in TSDU
-    IN PMDL  Tsdu,                  // TSDU data chain
-    IN PVOID TsduDescriptor         // for call to TdiReturnChainedReceives
+KsAcceptCompletionRoutine(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp,
+    IN PVOID            Context
     )
 {
+    ks_tconn_t * child = (ks_tconn_t *) Context;
+    ks_tconn_t * parent = child->child.kstc_parent;
 
-    NTSTATUS            Status;
+    KsPrint((2, "KsAcceptCompletionRoutine at Irql: %xh child: %p status: %p\n",
+                 KeGetCurrentIrql(), child, Irp->IoStatus.Status));
 
-    ksock_tconn_t *     tconn;
+    LASSERT(child->kstc_type == kstt_child);
 
-    PKS_CHAIN           KsChain;
-    PKS_TSDUMGR         KsTsduMgr;
-    PKS_TSDU            KsTsdu;
-    PKS_TSDU_MDL        KsTsduMdl;
+    cfs_spin_lock(&(child->kstc_lock));
 
-    BOOLEAN             bIsExpedited;
-    BOOLEAN             bNewTsdu = FALSE;
+    LASSERT(parent->kstc_state == ksts_listening);
+    LASSERT(child->kstc_state == ksts_connecting);
 
-    tconn = (ksock_tconn_t *) ConnectionContext;
+    if (NT_SUCCESS(Irp->IoStatus.Status)) {
 
-    bIsExpedited = cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_EXPEDITED);
+        child->child.kstc_accepted = TRUE;
 
-    KsPrint((2, "KsTcpChainedReceive: ReceiveLength = %xh bIsExpedited = %d\n", ReceiveLength, bIsExpedited));
+        child->kstc_state = ksts_connected;
 
-    ks_get_tconn(tconn);
-    spin_lock(&(tconn->kstc_lock));
+        /* wake up the daemon thread which waits on this event */
+        KeSetEvent(
+            &(parent->listener.kstc_accept_event),
+            0,
+            FALSE
+            );
 
-    /* check whether we are conntected or not listener Â¡Â­*/
-    if ( !((tconn->kstc_state == ksts_connected) &&
-         (tconn->kstc_type == kstt_sender ||
-          tconn->kstc_type == kstt_child))) {
+        cfs_spin_unlock(&(child->kstc_lock));
 
-        spin_unlock(&(tconn->kstc_lock));
-        ks_put_tconn(tconn);
+        KsPrint((2, "KsAcceptCompletionRoutine: singal parent: %p (child: %p)\n",
+                    parent, child));
 
-        return (STATUS_SUCCESS);
-    }
+    } else {
 
-    /* get the latest Tsdu buffer form TsduMgr list.
-       just set NULL if the list is empty. */
+        /* re-use this child connecton  */
+        child->child.kstc_accepted = FALSE;
+        child->child.kstc_busy = FALSE;
+        child->kstc_state = ksts_associated;
 
-    if (tconn->kstc_type == kstt_sender) {
-        KsChain = &(tconn->sender.kstc_recv);
-    } else {
-        LASSERT(tconn->kstc_type == kstt_child);
-        KsChain = &(tconn->child.kstc_recv);
+        cfs_spin_unlock(&(child->kstc_lock));
     }
 
-    if (bIsExpedited) {
-        KsTsduMgr = &(KsChain->Expedited);
-    } else {
-        KsTsduMgr = &(KsChain->Normal);
-    }
+    /* now free the Irp */
+    IoFreeIrp(Irp);
 
-    if (list_empty(&(KsTsduMgr->TsduList))) {
+    /* drop the refer count of the child */
+    ks_put_tconn(child);
 
-        LASSERT(KsTsduMgr->NumOfTsdu == 0);
-        KsTsdu = NULL;
+    return (STATUS_MORE_PROCESSING_REQUIRED);
+}
 
-    } else {
+ks_addr_slot_t *
+KsSearchIpAddress(PUNICODE_STRING  DeviceName)
+{
+    ks_addr_slot_t * slot = NULL;
+    PLIST_ENTRY      list = NULL;
 
-        LASSERT(KsTsduMgr->NumOfTsdu > 0);
-        KsTsdu = list_entry(KsTsduMgr->TsduList.prev, KS_TSDU, Link);
-        LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
+    cfs_spin_lock(&ks_data.ksnd_addrs_lock);
 
-        if (sizeof(KS_TSDU_MDL) > KsTsdu->TotalLength - KsTsdu->LastOffset) {
-            KsTsdu = NULL;
+    list = ks_data.ksnd_addrs_list.Flink;
+    while (list != &ks_data.ksnd_addrs_list) {
+        slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
+        if (RtlCompareUnicodeString(
+                    DeviceName,
+                    &slot->devname,
+                    TRUE) == 0) {
+            break;
         }
+        list = list->Flink;
+        slot = NULL;
     }
 
-    /* if there's no Tsdu or the free size is not enough for this
-       KS_TSDU_MDL structure. We need re-allocate a new Tsdu.  */
+    cfs_spin_unlock(&ks_data.ksnd_addrs_lock);
 
-    if (NULL == KsTsdu) {
+    return slot;
+}
 
-        KsTsdu = KsAllocateKsTsdu();
+void
+KsCleanupIpAddresses()
+{
+    cfs_spin_lock(&ks_data.ksnd_addrs_lock);
 
-        if (NULL == KsTsdu) {
-            goto errorout;
-        } else {
-            bNewTsdu = TRUE;
-        }
-    }
+    while (!IsListEmpty(&ks_data.ksnd_addrs_list)) {
 
-    /* just queue the KS_TSDU_MDL to the Tsdu buffer */
+        ks_addr_slot_t * slot = NULL;
+        PLIST_ENTRY      list = NULL;
 
-    KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
+        list = RemoveHeadList(&ks_data.ksnd_addrs_list);
+        slot = CONTAINING_RECORD(list, ks_addr_slot_t, link);
+        cfs_free(slot);
+        ks_data.ksnd_naddrs--;
+    }
 
-    KsTsduMdl->TsduType     =  TSDU_TYPE_MDL;
-    KsTsduMdl->DataLength   =  ReceiveLength;
-    KsTsduMdl->StartOffset  =  StartingOffset;
-    KsTsduMdl->Mdl          =  Tsdu;
-    KsTsduMdl->Descriptor   =  TsduDescriptor;
+    cfs_assert(ks_data.ksnd_naddrs == 0);
+    cfs_spin_unlock(&ks_data.ksnd_addrs_lock);
+}
 
-    KsTsdu->LastOffset     += sizeof(KS_TSDU_MDL);
-    KsTsduMgr->TotalBytes  += ReceiveLength;
+VOID
+KsAddAddressHandler(
+    IN  PTA_ADDRESS      Address,
+    IN  PUNICODE_STRING  DeviceName,
+    IN  PTDI_PNP_CONTEXT Context
+    )
+{
+    PTDI_ADDRESS_IP IpAddress = NULL;
 
-    KsPrint((2, "KsTcpChainedReceiveEventHandler: Total %xh bytes.\n",
-                KsTsduMgr->TotalBytes ));
+    if ( Address->AddressType == TDI_ADDRESS_TYPE_IP &&
+         Address->AddressLength == TDI_ADDRESS_LENGTH_IP ) {
 
-    Status = STATUS_PENDING;
+        ks_addr_slot_t * slot = NULL;
 
-    /* attach it to the TsduMgr list if the Tsdu is newly created. */
-    if (bNewTsdu) {
+        IpAddress = (PTDI_ADDRESS_IP) &Address->Address[0];
+        KsPrint((2, "KsAddAddressHandle: Device=%wZ Context=%xh "
+                     "IpAddress=%xh(%d.%d.%d.%d)\n",
+                     DeviceName, Context, IpAddress->in_addr,
+                     (IpAddress->in_addr & 0x000000FF) >> 0,
+                     (IpAddress->in_addr & 0x0000FF00) >> 8,
+                     (IpAddress->in_addr & 0x00FF0000) >> 16,
+                     (IpAddress->in_addr & 0xFF000000) >> 24
+               ));
 
-        list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
-        KsTsduMgr->NumOfTsdu++;
-    }
+        slot = KsSearchIpAddress(DeviceName);
 
-    spin_unlock(&(tconn->kstc_lock));
+        if (slot != NULL) {
+            slot->up = TRUE;
+            slot->ip_addr = ntohl(IpAddress->in_addr);
+        } else {
 
-    /* wake up the threads waiing in ks_recv_mdl */
-    KeSetEvent(&(KsTsduMgr->Event), 0, FALSE);
+            /* Matt: only add 192.168.10/5/92.xxx for temporary test */
+            if ((IpAddress->in_addr & 0x00FFFFFF) != 0x000aa8c0 &&
+                (IpAddress->in_addr & 0x00FFFFFF) != 0x0092a8c0 &&
+                (IpAddress->in_addr & 0x00FFFFFF) != 0x0005a8c0 ) {
+                return;
+            }
 
-    if (tconn->kstc_conn && tconn->kstc_sched_cb) {
-        tconn->kstc_sched_cb( tconn, FALSE, NULL,
-                              KsTsduMgr->TotalBytes );
+            slot = cfs_alloc(sizeof(ks_addr_slot_t) + DeviceName->Length, CFS_ALLOC_ZERO);
+            if (slot != NULL) {
+                cfs_spin_lock(&ks_data.ksnd_addrs_lock);
+                InsertTailList(&ks_data.ksnd_addrs_list, &slot->link);
+                sprintf(slot->iface, "eth%d", ks_data.ksnd_naddrs++);
+                slot->ip_addr = ntohl(IpAddress->in_addr);
+                slot->netmask = 0x00FFFFFF; /* Matt: hardcode*/
+                slot->up = TRUE;
+                RtlMoveMemory(&slot->buffer[0], DeviceName->Buffer, DeviceName->Length);
+                slot->devname.Length = DeviceName->Length;
+                slot->devname.MaximumLength = DeviceName->Length + sizeof(WCHAR);
+                slot->devname.Buffer = slot->buffer;
+                cfs_spin_unlock(&ks_data.ksnd_addrs_lock);
+
+                KsPrint((0, "KsAddAddressHandle: %s added: ip=%xh(%d.%d.%d.%d)\n",
+                            slot->iface, IpAddress->in_addr,
+                            (IpAddress->in_addr & 0x000000FF) >> 0,
+                            (IpAddress->in_addr & 0x0000FF00) >> 8,
+                            (IpAddress->in_addr & 0x00FF0000) >> 16,
+                            (IpAddress->in_addr & 0xFF000000) >> 24
+                       ));
+            }
+        }
     }
+}
 
-    ks_put_tconn(tconn);
+VOID
+KsDelAddressHandler(
+    IN  PTA_ADDRESS      Address,
+    IN  PUNICODE_STRING  DeviceName,
+    IN  PTDI_PNP_CONTEXT Context
+    )
+{
+    PTDI_ADDRESS_IP IpAddress = NULL;
 
-    /* Return STATUS_PENDING to system because we are still
-       owning the MDL resources. ks_recv_mdl is expected
-       to free the MDL resources. */
+    if ( Address->AddressType == TDI_ADDRESS_TYPE_IP &&
+         Address->AddressLength == TDI_ADDRESS_LENGTH_IP ) {
 
-    return (Status);
+        ks_addr_slot_t * slot = NULL;
 
-errorout:
+        slot = KsSearchIpAddress(DeviceName);
 
-    spin_unlock(&(tconn->kstc_lock));
+        if (slot != NULL) {
+            slot->up = FALSE;
+        }
 
-    if (bNewTsdu && (KsTsdu != NULL)) {
-        KsFreeKsTsdu(KsTsdu);
+        IpAddress = (PTDI_ADDRESS_IP) &Address->Address[0];
+        KsPrint((2, "KsDelAddressHandle: Device=%wZ Context=%xh IpAddress=%xh(%d.%d.%d.%d)\n",
+                  DeviceName, Context, IpAddress->in_addr,
+                   (IpAddress->in_addr & 0xFF000000) >> 24,
+                   (IpAddress->in_addr & 0x00FF0000) >> 16,
+                   (IpAddress->in_addr & 0x0000FF00) >> 8,
+                   (IpAddress->in_addr & 0x000000FF) >> 0 ));
     }
+}
 
-    /* abort the tdi connection */
-    ks_abort_tconn(tconn);
-    ks_put_tconn(tconn);
+NTSTATUS
+KsRegisterPnpHandlers()
+{
+    TDI20_CLIENT_INTERFACE_INFO ClientInfo;
 
+    /* initialize the global ks_data members */
+    RtlInitUnicodeString(&ks_data.ksnd_client_name, TDILND_MODULE_NAME);
+    cfs_spin_lock_init(&ks_data.ksnd_addrs_lock);
+    InitializeListHead(&ks_data.ksnd_addrs_list);
 
-    Status = STATUS_SUCCESS;
+    /* register the pnp handlers */
+    RtlZeroMemory(&ClientInfo, sizeof(ClientInfo));
+    ClientInfo.TdiVersion = TDI_CURRENT_VERSION;
 
-    return (Status);
+    ClientInfo.ClientName = &ks_data.ksnd_client_name;
+    ClientInfo.AddAddressHandlerV2 =  KsAddAddressHandler;
+    ClientInfo.DelAddressHandlerV2 =  KsDelAddressHandler;
+
+    return TdiRegisterPnPHandlers(&ClientInfo, sizeof(ClientInfo),
+                                  &ks_data.ksnd_pnp_handle);
 }
 
+VOID
+KsDeregisterPnpHandlers()
+{
+    if (ks_data.ksnd_pnp_handle) {
 
-/*
- *  Expedited & Bulk receive event handler
- */
+        /* De-register the pnp handlers */
 
-NTSTATUS
-KsTcpChainedReceiveExpeditedEventHandler (
-    IN PVOID                TdiEventContext,       // the event context
-    IN CONNECTION_CONTEXT   ConnectionContext,
-    IN ULONG                ReceiveFlags,
-    IN ULONG                ReceiveLength,
-    IN ULONG                StartingOffset,        // offset of start of client data in TSDU
-    IN PMDL                 Tsdu,                  // TSDU data chain
-    IN PVOID                TsduDescriptor         // for call to TdiReturnChainedReceives
-    )
-{
-    return KsTcpChainedReceiveEventHandler(
-                TdiEventContext,
-                ConnectionContext,
-                ReceiveFlags | TDI_RECEIVE_EXPEDITED,
-                ReceiveLength,
-                StartingOffset,
-                Tsdu,
-                TsduDescriptor );
-}
-
-
-VOID
-KsPrintProviderInfo(
-   PWSTR DeviceName,
-   PTDI_PROVIDER_INFO ProviderInfo
-   )
-{
-    KsPrint((2, "%ws ProviderInfo:\n", DeviceName));
-
-    KsPrint((2, "  Version              : 0x%4.4X\n", ProviderInfo->Version ));
-    KsPrint((2, "  MaxSendSize          : %d\n", ProviderInfo->MaxSendSize ));
-    KsPrint((2, "  MaxConnectionUserData: %d\n", ProviderInfo->MaxConnectionUserData ));
-    KsPrint((2, "  MaxDatagramSize      : %d\n", ProviderInfo->MaxDatagramSize ));
-    KsPrint((2, "  ServiceFlags         : 0x%8.8X\n", ProviderInfo->ServiceFlags ));
-
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_CONNECTION_MODE) {
-        KsPrint((2, "  CONNECTION_MODE\n"));
-    }
-
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_ORDERLY_RELEASE) {
-        KsPrint((2, "  ORDERLY_RELEASE\n"));
-    }
-
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_CONNECTIONLESS_MODE) {
-        KsPrint((2, "  CONNECTIONLESS_MODE\n"));
-    }
+        TdiDeregisterPnPHandlers(ks_data.ksnd_pnp_handle);
+        ks_data.ksnd_pnp_handle = NULL;
 
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_ERROR_FREE_DELIVERY) {
-        KsPrint((2, "  ERROR_FREE_DELIVERY\n"));
+        /* cleanup all the ip address slots */
+        KsCleanupIpAddresses();
     }
+}
 
-    if( ProviderInfo->ServiceFlags & TDI_SERVICE_SECURITY_LEVEL ) {
-        KsPrint((2, "  SECURITY_LEVEL\n"));
-    }
 
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_BROADCAST_SUPPORTED) {
-        KsPrint((2, "  BROADCAST_SUPPORTED\n"));
-    }
+/*
+ * KsGetVacancyBacklog
+ *   Get a vacancy listeing child from the backlog list
+ *
+ * Arguments:
+ *   parent: the listener daemon connection
+ *
+ * Return Value:
+ *   the child listening connection or NULL in failure
+ *
+ * Notes
+ *   Parent's lock should be acquired before calling.
+ */
 
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_MULTICAST_SUPPORTED) {
-        KsPrint((2, "  MULTICAST_SUPPORTED\n"));
-    }
+ks_tconn_t *
+KsGetVacancyBacklog(
+    ks_tconn_t *  parent
+    )
+{
+    ks_tconn_t * child;
 
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_DELAYED_ACCEPTANCE) {
-        KsPrint((2, "  DELAYED_ACCEPTANCE\n"));
-    }
+    LASSERT(parent->kstc_type == kstt_listener);
+    LASSERT(parent->kstc_state == ksts_listening);
 
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_EXPEDITED_DATA) {
-        KsPrint((2, "  EXPEDITED_DATA\n"));
-    }
+    if (cfs_list_empty(&(parent->listener.kstc_listening.list))) {
 
-    if( ProviderInfo->ServiceFlags & TDI_SERVICE_INTERNAL_BUFFERING) {
-        KsPrint((2, "  INTERNAL_BUFFERING\n"));
-    }
+        child = NULL;
 
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_ROUTE_DIRECTED) {
-        KsPrint((2, "  ROUTE_DIRECTED\n"));
-    }
+    } else {
 
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_NO_ZERO_LENGTH) {
-        KsPrint((2, "  NO_ZERO_LENGTH\n"));
-    }
+        cfs_list_t * tmp;
 
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_POINT_TO_POINT) {
-        KsPrint((2, "  POINT_TO_POINT\n"));
-    }
+        /* check the listening queue and try to get a free connecton */
 
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_MESSAGE_MODE) {
-        KsPrint((2, "  MESSAGE_MODE\n"));
-    }
+        cfs_list_for_each(tmp, &(parent->listener.kstc_listening.list)) {
+            child = cfs_list_entry (tmp, ks_tconn_t, child.kstc_link);
+            cfs_spin_lock(&(child->kstc_lock));
 
-    if (ProviderInfo->ServiceFlags & TDI_SERVICE_HALF_DUPLEX) {
-        KsPrint((2, "  HALF_DUPLEX\n"));
+            if (!child->child.kstc_busy) {
+                LASSERT(child->kstc_state == ksts_associated);
+                child->child.kstc_busy = TRUE;
+                cfs_spin_unlock(&(child->kstc_lock));
+                break;
+            } else {
+                cfs_spin_unlock(&(child->kstc_lock));
+                child = NULL;
+            }
+        }
     }
 
-    KsPrint((2, "  MinimumLookaheadData : %d\n", ProviderInfo->MinimumLookaheadData ));
-    KsPrint((2, "  MaximumLookaheadData : %d\n", ProviderInfo->MaximumLookaheadData ));
-    KsPrint((2, "  NumberOfResources    : %d\n", ProviderInfo->NumberOfResources ));
+    return child;
 }
 
-
 /*
- * KsAllocateKsTsdu
- *   Reuse a Tsdu from the freelist or allocate a new Tsdu
- *   from the LookAsideList table or the NonPagedPool
+ * KsConnectEventHandler
+ *   Connect event handler event handler, called by the underlying TDI
+ *   transport in response to an incoming request to the listening daemon.
+ *
+ *   it will grab a vacancy backlog from the children tconn list, and
+ *   build an acception Irp with it, then transfer the Irp to TDI driver.
  *
  * Arguments:
- *   N/A
+ *   TdiEventContext:  the tdi connnection object of the listening daemon
+ *   ......
  *
  * Return Value:
- *   PKS_Tsdu: the new Tsdu or NULL if it fails
+ *   Nt kernel status code
  *
  * Notes:
  *   N/A
  */
 
-PKS_TSDU
-KsAllocateKsTsdu()
+NTSTATUS
+KsConnectEventHandler(
+    IN PVOID                    TdiEventContext,
+    IN LONG                     RemoteAddressLength,
+    IN PVOID                    RemoteAddress,
+    IN LONG                     UserDataLength,
+    IN PVOID                    UserData,
+    IN LONG                     OptionsLength,
+    IN PVOID                    Options,
+    OUT CONNECTION_CONTEXT *    ConnectionContext,
+    OUT PIRP *                  AcceptIrp
+    )
 {
-    PKS_TSDU    KsTsdu = NULL;
+    ks_tconn_t *                parent;
+    ks_tconn_t *                child;
 
-    spin_lock(&(ks_data.ksnd_tsdu_lock));
+    PFILE_OBJECT                FileObject;
+    PDEVICE_OBJECT              DeviceObject;
+    NTSTATUS                    Status;
 
-    if (!list_empty (&(ks_data.ksnd_freetsdus))) {
+    PIRP                        Irp = NULL;
+    PTDI_CONNECTION_INFORMATION ConnectionInfo = NULL;
 
-        LASSERT(ks_data.ksnd_nfreetsdus > 0);
+    KsPrint((2,"KsConnectEventHandler: call at Irql: %u\n", KeGetCurrentIrql()));
+    parent = (ks_tconn_t *) TdiEventContext;
 
-        KsTsdu = list_entry(ks_data.ksnd_freetsdus.next, KS_TSDU, Link);
-        list_del(&(KsTsdu->Link));
-        ks_data.ksnd_nfreetsdus--;
+    LASSERT(parent->kstc_type == kstt_listener);
+
+    cfs_spin_lock(&(parent->kstc_lock));
+
+    if (parent->kstc_state == ksts_listening) {
+
+        /* allocate a new ConnectionInfo to backup the peer's info */
+
+        ConnectionInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(
+                NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) +
+                RemoteAddressLength, 'iCsK' );
+
+        if (NULL == ConnectionInfo) {
+
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            cfs_enter_debugger();
+            goto errorout;
+        }
+
+        /* initializing ConnectionInfo structure ... */
+
+        ConnectionInfo->UserDataLength = UserDataLength;
+        ConnectionInfo->UserData = UserData;
+        ConnectionInfo->OptionsLength = OptionsLength;
+        ConnectionInfo->Options = Options;
+        ConnectionInfo->RemoteAddressLength = RemoteAddressLength;
+        ConnectionInfo->RemoteAddress = ConnectionInfo + 1;
+
+        RtlCopyMemory(
+                ConnectionInfo->RemoteAddress,
+                RemoteAddress,
+                RemoteAddressLength
+                );
+
+        /* get the vacancy listening child tdi connections */
+
+        child = KsGetVacancyBacklog(parent);
+
+        if (child) {
+
+            cfs_spin_lock(&(child->kstc_lock));
+            child->child.kstc_info.ConnectionInfo = ConnectionInfo;
+            child->child.kstc_info.Remote = ConnectionInfo->RemoteAddress;
+            child->kstc_state = ksts_connecting;
+            cfs_spin_unlock(&(child->kstc_lock));
+
+        } else {
+
+            KsPrint((1, "KsConnectEventHandler: No enough backlogs: Refsued the connectio: %xh\n", parent));
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto errorout;
+        }
+
+        FileObject = child->child.kstc_info.FileObject;
+        DeviceObject = IoGetRelatedDeviceObject (FileObject);
+
+        Irp = KsBuildTdiIrp(DeviceObject);
+
+        TdiBuildAccept(
+                Irp,
+                DeviceObject,
+                FileObject,
+                KsAcceptCompletionRoutine,
+                child,
+                NULL,
+                NULL
+                );
+
+        IoSetNextIrpStackLocation(Irp);
+
+        /* grap the refer of the child tdi connection */
+        ks_get_tconn(child);
+
+        Status = STATUS_MORE_PROCESSING_REQUIRED;
+        *AcceptIrp = Irp;
+        *ConnectionContext = child;
 
     } else {
 
-        KsTsdu = (PKS_TSDU) cfs_mem_cache_alloc(
-                        ks_data.ksnd_tsdu_slab, 0);
+        Status = STATUS_CONNECTION_REFUSED;
+        goto errorout;
     }
 
-    spin_unlock(&(ks_data.ksnd_tsdu_lock));
+    cfs_spin_unlock(&(parent->kstc_lock));
 
-    if (NULL != KsTsdu) {
-        KsInitializeKsTsdu(KsTsdu, ks_data.ksnd_tsdu_size);
+    return Status;
+
+errorout:
+
+    cfs_spin_unlock(&(parent->kstc_lock));
+
+    *AcceptIrp = NULL;
+    *ConnectionContext = NULL;
+
+    if (ConnectionInfo) {
+        ExFreePool(ConnectionInfo);
     }
 
-    return (KsTsdu);
-}
+    if (Irp) {
+        IoFreeIrp (Irp);
+    }
 
+    return Status;
+}
 
 /*
- * KsPutKsTsdu
- *   Move the Tsdu to the free tsdu list in ks_data.
+ * KsDisconnectCompletionRoutine
+ *   the Irp completion routine for TdiBuildDisconect
+ *
+ *   We just signal the event and return MORE_PRO... to
+ *   let the caller take the responsibility of the Irp.
  *
  * Arguments:
- *   KsTsdu: Tsdu to be moved.
+ *   DeviceObject:  the device object of the transport
+ *   Irp:           the Irp is being completed.
+ *   Context:       the event specified by the caller
  *
  * Return Value:
- *   N/A
+ *   Nt status code
  *
  * Notes:
  *   N/A
  */
 
-VOID
-KsPutKsTsdu(
-    PKS_TSDU  KsTsdu
+NTSTATUS
+KsDisconectCompletionRoutine (
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp,
+    IN PVOID            Context
     )
 {
-    spin_lock(&(ks_data.ksnd_tsdu_lock));
 
-    list_add_tail( &(KsTsdu->Link), &(ks_data.ksnd_freetsdus));
-    ks_data.ksnd_nfreetsdus++;
+    KeSetEvent((PKEVENT) Context, 0, FALSE);
 
-    spin_unlock(&(ks_data.ksnd_tsdu_lock));
-}
+    return STATUS_MORE_PROCESSING_REQUIRED;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+}
 
 
 /*
- * KsFreeKsTsdu
- *   Release a Tsdu: uninitialize then free it.
+ * KsDisconnectHelper
+ *   the routine to be executed in the WorkItem procedure
+ *   this routine is to disconnect a tdi connection
  *
  * Arguments:
- *   KsTsdu: Tsdu to be freed.
+ *   Workitem:  the context transferred to the workitem
  *
  * Return Value:
  *   N/A
  *
  * Notes:
- *   N/A
+ *   tconn is already referred in abort_connecton ...
  */
 
 VOID
-KsFreeKsTsdu(
-    PKS_TSDU  KsTsdu
-    )
+KsDisconnectHelper(PKS_DISCONNECT_WORKITEM WorkItem)
 {
-    cfs_mem_cache_free(
-            ks_data.ksnd_tsdu_slab,
-            KsTsdu );
-}
+    ks_tconn_t * tconn = WorkItem->tconn;
 
+    KsPrint((1, "KsDisconnectHelper: disconnecting tconn=%p\n", tconn));
+    ks_disconnect_tconn(tconn, WorkItem->Flags);
 
-/*
- * KsInitializeKsTsdu
- *   Initialize the Tsdu buffer header
- *
- * Arguments:
- *   KsTsdu: the Tsdu to be initialized
- *   Length: the total length of the Tsdu
- *
- * Return Value:
- *   VOID
- *
- * NOTES:
- *   N/A
- */
+    KeSetEvent(&(WorkItem->Event), 0, FALSE);
 
-VOID
-KsInitializeKsTsdu(
-    PKS_TSDU    KsTsdu,
-    ULONG       Length
-    )
-{
-    RtlZeroMemory(KsTsdu, Length);
-    KsTsdu->Magic = KS_TSDU_MAGIC;
-    KsTsdu->TotalLength = Length;
-    KsTsdu->StartOffset = KsTsdu->LastOffset =
-    KS_DWORD_ALIGN(sizeof(KS_TSDU));
+    cfs_spin_lock(&(tconn->kstc_lock));
+    cfs_clear_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
+    cfs_spin_unlock(&(tconn->kstc_lock));
+    ks_put_tconn(tconn);
 }
 
 
 /*
- * KsInitializeKsTsduMgr
- *   Initialize the management structure of
- *   Tsdu buffers
+ * KsDisconnectEventHandler
+ *   Disconnect event handler event handler, called by the underlying TDI transport
+ *   in response to an incoming disconnection notification from a remote node.
  *
  * Arguments:
- *   TsduMgr: the TsduMgr to be initialized
+ *   ConnectionContext:  tdi connnection object
+ *   DisconnectFlags:    specifies the nature of the disconnection
+ *   ......
  *
  * Return Value:
- *   VOID
+ *   Nt kernel status code
  *
- * NOTES:
+ * Notes:
  *   N/A
  */
 
-VOID
-KsInitializeKsTsduMgr(
-    PKS_TSDUMGR     TsduMgr
+
+NTSTATUS
+KsDisconnectEventHandler(
+    IN PVOID                TdiEventContext,
+    IN CONNECTION_CONTEXT   ConnectionContext,
+    IN LONG                 DisconnectDataLength,
+    IN PVOID                DisconnectData,
+    IN LONG                 DisconnectInformationLength,
+    IN PVOID                DisconnectInformation,
+    IN ULONG                DisconnectFlags
     )
 {
-    KeInitializeEvent(
-            &(TsduMgr->Event),
-            NotificationEvent,
-            FALSE
-            );
-
-    CFS_INIT_LIST_HEAD(
-            &(TsduMgr->TsduList)
-            );
-
-    TsduMgr->NumOfTsdu  = 0;
-    TsduMgr->TotalBytes = 0;
-}
+    ks_tconn_t *            tconn;
+    NTSTATUS                Status;
+    PKS_DISCONNECT_WORKITEM WorkItem;
 
+    tconn = (ks_tconn_t *)ConnectionContext;
 
-/*
- * KsInitializeKsChain
- *   Initialize the China structure for receiving
- *   or transmitting
- *
- * Arguments:
- *   KsChain: the KsChain to be initialized
- *
- * Return Value:
- *   VOID
- *
- * NOTES:
- *   N/A
- */
+    KsPrint((2, "KsTcpDisconnectEventHandler: called at Irql: %xh\n",
+                KeGetCurrentIrql() ));
 
-VOID
-KsInitializeKsChain(
-    PKS_CHAIN       KsChain
-    )
-{
-    KsInitializeKsTsduMgr(&(KsChain->Normal));
-    KsInitializeKsTsduMgr(&(KsChain->Expedited));
-}
+    KsPrint((2, "tconn = %x DisconnectFlags= %xh\n",
+                 tconn, DisconnectFlags));
 
+    ks_get_tconn(tconn);
+    cfs_spin_lock(&(tconn->kstc_lock));
 
-/*
- * KsCleanupTsduMgr
- *   Clean up all the Tsdus in the TsduMgr list
- *
- * Arguments:
- *   KsTsduMgr: the Tsdu list manager
- *
- * Return Value:
- *   NTSTATUS:  nt status code
- *
- * NOTES:
- *   N/A
- */
+    WorkItem = &(tconn->kstc_disconnect);
 
-NTSTATUS
-KsCleanupTsduMgr(
-    PKS_TSDUMGR     KsTsduMgr
-    )
-{
-    PKS_TSDU        KsTsdu;
-    PKS_TSDU_DAT    KsTsduDat;
-    PKS_TSDU_BUF    KsTsduBuf;
-    PKS_TSDU_MDL    KsTsduMdl;
+    if (tconn->kstc_state != ksts_connected) {
 
-    LASSERT(NULL != KsTsduMgr);
+        Status = STATUS_SUCCESS;
 
-    KeSetEvent(&(KsTsduMgr->Event), 0, FALSE);
+    } else {
 
-    while (!list_empty(&KsTsduMgr->TsduList)) {
+        if (cfs_is_flag_set(DisconnectFlags, TDI_DISCONNECT_ABORT)) {
 
-        KsTsdu = list_entry(KsTsduMgr->TsduList.next, KS_TSDU, Link);
-        LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
+            Status = STATUS_REMOTE_DISCONNECT;
 
-        if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
+        } else if (cfs_is_flag_set(DisconnectFlags, TDI_DISCONNECT_RELEASE)) {
 
-            //
-            // KsTsdu is empty now, we need free it ...
-            //
+            Status = STATUS_GRACEFUL_DISCONNECT;
+        }
 
-            list_del(&(KsTsdu->Link));
-            KsTsduMgr->NumOfTsdu--;
+        if (!cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY)) {
 
-            KsFreeKsTsdu(KsTsdu);
+            ks_get_tconn(tconn);
 
-        } else {
+            WorkItem->Flags = DisconnectFlags;
+            WorkItem->tconn = tconn;
 
-            KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
-            KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
-            KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
+            cfs_set_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
 
-            if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
+            /* queue the workitem to call */
+            ExQueueWorkItem(&(WorkItem->WorkItem), DelayedWorkQueue);
+        }
+    }
 
-                KsTsdu->StartOffset += KsTsduDat->TotalLength;
+    cfs_spin_unlock(&(tconn->kstc_lock));
+    ks_put_tconn(tconn);
 
-            } else if (TSDU_TYPE_BUF == KsTsduBuf->TsduType) {
+    return  (Status);
+}
 
-                ASSERT(KsTsduBuf->UserBuffer != NULL);
+NTSTATUS
+KsTcpReceiveCompletionRoutine(
+    IN PIRP                         Irp,
+    IN PKS_TCP_COMPLETION_CONTEXT   Context
+    )
+{
+    ks_tconn_t *tconn = Context->tconn;
+    NTSTATUS    status = Irp->IoStatus.Status;
+    ULONG       length = (ULONG)Irp->IoStatus.Information;
 
-                if (KsTsduBuf->DataLength > KsTsduBuf->StartOffset) {
-                    ExFreePool(KsTsduBuf->UserBuffer);
-                } else {
-                    cfs_enter_debugger();
-                }
+    LASSERT(Context != NULL);
 
-                KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
+    if (NT_SUCCESS(status)) {
 
-            } else if (TSDU_TYPE_MDL == KsTsduMdl->TsduType) {
+        PKS_TSDUMGR  TsduMgr = Context->TsduMgr;
+        PCHAR        Buffer = Context->Buffer;
 
-                //
-                // MDL Tsdu Unit ...
-                //
+        KsPrint((4, "KsTcpReceiveCompletionRoutine: Total %xh bytes.\n",
+                    TsduMgr->TotalBytes ));
 
-                TdiReturnChainedReceives(
-                    &(KsTsduMdl->Descriptor),
-                    1 );
+        ks_lock_tsdumgr(TsduMgr);
+        KsWriteTsduBuf(TsduMgr, Context->Buffer, length, 0);
+        /* signal TsduMgr event */
+        KeSetEvent(&(Context->TsduMgr->Event), 0, FALSE);
+        ks_unlock_tsdumgr(TsduMgr);
 
-                KsTsdu->StartOffset += sizeof(KS_TSDU_MDL);
+        /* re-active the ks connection and wake up the scheduler */
+        if (KS_CAN_SCHED(TsduMgr)) {
+            if (tconn->kstc_conn && tconn->kstc_sched_cb) {
+                tconn->kstc_sched_cb(tconn, FALSE);
             }
         }
-    }
-
-    return STATUS_SUCCESS;
-}
 
+        ks_put_tconn(tconn);
 
-/*
- * KsCleanupKsChain
- *   Clean up the TsduMgrs of the KsChain
- *
- * Arguments:
- *   KsChain: the chain managing TsduMgr
- *
- * Return Value:
- *   NTSTATUS:  nt status code
- *
- * NOTES:
- *   N/A
- */
+    } else {
 
-NTSTATUS
-KsCleanupKsChain(
-    PKS_CHAIN   KsChain
-    )
-{
-    NTSTATUS    Status;
+        /* un-expected errors occur, we must abort the connection */
+        ks_put_tconn(tconn);
+        ks_abort_tconn(tconn);
+    }
 
-    LASSERT(NULL != KsChain);
 
-    Status = KsCleanupTsduMgr(
-                &(KsChain->Normal)
-                );
+    if (Context) {
 
-    if (!NT_SUCCESS(Status)) {
-        cfs_enter_debugger();
-        goto errorout;
+        /* free the Context structure... */
+        ASSERT(Context->Magic == KS_TCP_CONTEXT_MAGIC);
+        Context->Magic = 'CDAB';
+        cfs_free(Context);
     }
 
-    Status = KsCleanupTsduMgr(
-                &(KsChain->Expedited)
-                );
+    /* free the Irp */
+    if (Irp) {
 
-    if (!NT_SUCCESS(Status)) {
-        cfs_enter_debugger();
-        goto errorout;
-    }
+        /* release mdl chain */
+        if (Irp->MdlAddress) {
+            KsReleaseMdl(Irp->MdlAddress, FALSE);
+        }
 
-errorout:
+        /* free irp packet */
+        IoFreeIrp(Irp);
+    }
 
-    return Status;
+    return (status);
 }
 
 
 /*
- * KsCleanupTsdu
- *   Clean up all the Tsdus of a tdi connected object
+ * KsTcpCompletionRoutine
+ *   the Irp completion routine for TdiBuildSend and TdiBuildReceive ...
+ *   We need call the use's own CompletionRoutine if specified. Or
+ *   it's a synchronous case, we need signal the event.
  *
  * Arguments:
- *   tconn: the tdi connection which is connected already.
+ *   DeviceObject:  the device object of the transport
+ *   Irp:           the Irp is being completed.
+ *   Context:       the context we specified when issuing the Irp
  *
  * Return Value:
  *   Nt status code
  *
- * NOTES:
+ * Notes:
  *   N/A
  */
 
 NTSTATUS
-KsCleanupTsdu(
-    ksock_tconn_t * tconn
-    )
+KsTcpCompletionRoutine(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp,
+    IN PVOID            Context
+    )
 {
-    NTSTATUS        Status = STATUS_SUCCESS;
+    if (Context) {
 
+        PKS_TCP_COMPLETION_CONTEXT  context = NULL;
+        ks_tconn_t * tconn = NULL;
 
-    if (tconn->kstc_type != kstt_sender &&
-        tconn->kstc_type != kstt_child ) {
+        context = (PKS_TCP_COMPLETION_CONTEXT) Context;
+        ASSERT(context->Magic == KS_TCP_CONTEXT_MAGIC);
+        tconn = context->tconn;
 
-        goto errorout;
-    }
+        if (context->CompletionRoutine) {
 
-    if (tconn->kstc_type == kstt_sender) {
+            //
+            // Giving control to user specified CompletionRoutine ...
+            //
 
-        Status = KsCleanupKsChain(
-                    &(tconn->sender.kstc_recv)
-                    );
+            context->CompletionRoutine(Irp, context);
 
-        if (!NT_SUCCESS(Status)) {
-            cfs_enter_debugger();
-            goto errorout;
-        }
+        } else {
 
-        Status = KsCleanupKsChain(
-                    &(tconn->sender.kstc_send)
-                    );
+            //
+            // Signaling  the Event ...
+            //
+            LASSERT(NULL != context->Event);
+            KeSetEvent(context->Event, 0, FALSE);
 
-        if (!NT_SUCCESS(Status)) {
-            cfs_enter_debugger();
-            goto errorout;
+            /* drop the reference count of the tconn object */
+            ks_put_tconn(tconn);
         }
 
     } else {
 
-        Status = KsCleanupKsChain(
-                    &(tconn->child.kstc_recv)
-                    );
-
-        if (!NT_SUCCESS(Status)) {
-            cfs_enter_debugger();
-            goto errorout;
-        }
-
-        Status = KsCleanupKsChain(
-                    &(tconn->child.kstc_send)
-                    );
-
-        if (!NT_SUCCESS(Status)) {
-            cfs_enter_debugger();
-            goto errorout;
-        }
-
+        /* cfs_enter_debugger(); */
     }
 
-errorout:
-
-    return (Status);
+    return STATUS_MORE_PROCESSING_REQUIRED;
 }
 
-
 /*
- * KsCopyMdlChainToMdlChain
- *   Copy data from  a [chained] Mdl to anther [chained] Mdl.
- *   Tdi library does not provide this function. We have to
- *   realize it ourselives.
+ * KsTcpSendCompletionRoutine
+ *   the user specified Irp completion routine for asynchronous
+ *   data transmission requests.
+ *
+ *   It will do th cleanup job of the ks_tx_t and wake up the
+ *   ks scheduler thread
  *
  * Arguments:
- *   SourceMdlChain: the source mdl
- *   SourceOffset:   start offset of the source
- *   DestinationMdlChain: the dst mdl
- *   DestinationOffset: the offset where data are to be copied.
- *   BytesTobecopied:   the expteced bytes to be copied
- *   BytesCopied:    to store the really copied data length
+ *   Irp:           the Irp is being completed.
+ *   Context:       the context we specified when issuing the Irp
  *
  * Return Value:
- *   NTSTATUS: STATUS_SUCCESS or other error code
+ *   Nt status code
  *
- * NOTES:
- *   The length of source mdl must be >= SourceOffset + BytesTobecopied
+ * Notes:
+ *   N/A
  */
 
 NTSTATUS
-KsCopyMdlChainToMdlChain(
-    IN PMDL     SourceMdlChain,
-    IN ULONG    SourceOffset,
-    IN PMDL     DestinationMdlChain,
-    IN ULONG    DestinationOffset,
-    IN ULONG    BytesTobecopied,
-    OUT PULONG  BytesCopied
+KsTcpSendCompletionRoutine(
+    IN PIRP                         Irp,
+    IN PKS_TCP_COMPLETION_CONTEXT   context
     )
 {
-    PMDL        SrcMdl = SourceMdlChain;
-    PMDL        DstMdl = DestinationMdlChain;
-
-    PUCHAR      SrcBuf = NULL;
-    PUCHAR      DstBuf = NULL;
-
-    ULONG       dwBytes = 0;
-
-    NTSTATUS    Status = STATUS_SUCCESS;
-
-
-    while (dwBytes < BytesTobecopied) {
-
-        ULONG   Length = 0;
-
-        while (MmGetMdlByteCount(SrcMdl) <= SourceOffset) {
-
-            SourceOffset -= MmGetMdlByteCount(SrcMdl);
+    NTSTATUS          status = Irp->IoStatus.Status;
+    ULONG             rc = (ULONG)(ULONG_PTR)Irp->IoStatus.Information;
+    ks_tconn_t *      tconn = context->tconn;
 
-            SrcMdl = SrcMdl->Next;
+    PKS_TSDUMGR       TsduMgr = context->TsduMgr;
+    PKEVENT           Event = context->Event;
 
-            if (NULL == SrcMdl) {
+    LASSERT(tconn != NULL && tconn->kstc_magic == KS_TCONN_MAGIC);
+    LASSERT(context && context->Magic == KS_TCP_CONTEXT_MAGIC);
 
-                Status = STATUS_INVALID_PARAMETER;
-                goto errorout;
-            }
-        }
-
-        while (MmGetMdlByteCount(DstMdl) <= DestinationOffset) {
+    KsPrint((4, "KsTcpSendCompltionRoutine: tconn = %p TsduMgr = %p "
+                "status = %xh bytes = %xh/%x\n", tconn, TsduMgr, status,
+                Irp->IoStatus.Information, TsduMgr->TotalBytes));
 
-            DestinationOffset -= MmGetMdlByteCount(DstMdl);
+    ks_lock_tsdumgr(TsduMgr);
 
-            DstMdl = DstMdl->Next;
+    if (NT_SUCCESS(status)) {
 
-            if (NULL == DstMdl) {
+        /* cleanup processed TsduMgr queue */
+        KsReleaseTsdus(tconn, TsduMgr, rc);
 
-                Status = STATUS_INVALID_PARAMETER;
-                goto errorout;
-            }
+        /* queue to delivery engine if there's still remained data */
+        TsduMgr->Busy = FALSE;
+        if (TsduMgr->TotalBytes > 0) {
+            KsQueueTdiEngine(tconn, TsduMgr);
         }
+        /* signal TsduMgr event */
+        KeSetEvent(&(TsduMgr->Event), 0, FALSE);
+        ks_unlock_tsdumgr(TsduMgr);
 
-        DstBuf = (PUCHAR)KsMapMdlBuffer(DstMdl);
+        /*
+         * now it's time to re-queue the conns into the
+         * scheduler queue and wake the scheduler thread.
+         */
 
-        if ((NULL == DstBuf)) {
-            Status = STATUS_INSUFFICIENT_RESOURCES;
-            goto errorout;
+        if (tconn->kstc_conn && tconn->kstc_sched_cb) {
+            tconn->kstc_sched_cb(tconn, TRUE);
         }
 
-        //
-        // Here we need skip the OVERFLOW case via RtlCopyMemory :-(
-        //
-
-        if ( KsQueryMdlsSize(SrcMdl) - SourceOffset >
-             MmGetMdlByteCount(DstMdl) - DestinationOffset ) {
-
-            Length = BytesTobecopied - dwBytes;
-
-            if (Length > KsQueryMdlsSize(SrcMdl) - SourceOffset) {
-                Length = KsQueryMdlsSize(SrcMdl) - SourceOffset;
-            }
-
-            if (Length > MmGetMdlByteCount(DstMdl) - DestinationOffset) {
-                Length = MmGetMdlByteCount(DstMdl) - DestinationOffset;
-            }
+    } else {
 
-            SrcBuf = (PUCHAR)KsMapMdlBuffer(SrcMdl);
+        ks_unlock_tsdumgr(TsduMgr);
 
-            if ((NULL == DstBuf)) {
-                Status = STATUS_INSUFFICIENT_RESOURCES;
-                goto errorout;
-            }
+        KsPrint((1, "KsTcpSendCompltionRoutine: failed tconn: %p "
+                    "TsduMgr: %p status: %xh\n", tconn, TsduMgr, status));
 
-            RtlCopyMemory(
-                DstBuf + DestinationOffset,
-                SrcBuf + SourceOffset,
-                Length
-                );
+        /* cfs_enter_debugger(); */
 
-        } else {
+        /*
+         *  for the case that the transmission is unsuccessful,
+         *  we need abort the tdi connection, but not destroy it.
+         *  the socknal conn will drop the refer count, then the
+         *  tdi connection will be freed.
+         */
 
-            Status = TdiCopyMdlToBuffer(
-                        SrcMdl,
-                        SourceOffset,
-                        DstBuf,
-                        DestinationOffset,
-                        MmGetMdlByteCount(DstMdl),
-                        &Length
-                        );
+        ks_abort_tconn(tconn);
+    }
 
-            if (STATUS_BUFFER_OVERFLOW == Status) {
-                cfs_enter_debugger();
-            } else if (!NT_SUCCESS(Status)) {
-                cfs_enter_debugger();
-                goto errorout;
-            }
-        }
+    /* drop tconn reference */
+    ks_put_tconn(tconn);
 
-        SourceOffset += Length;
-        DestinationOffset += Length;
-        dwBytes += Length;
+    /* freeing the context structure */
+    if (context) {
+        ASSERT(context->Magic == KS_TCP_CONTEXT_MAGIC);
+        context->Magic = 'CDAB';
+        cfs_free(context);
     }
 
-errorout:
-
-    if (NT_SUCCESS(Status)) {
-        *BytesCopied = dwBytes;
-    } else {
-        *BytesCopied = 0;
+    /* free the Irp structure */
+    if (Irp) {
+        /* mdl chain was released by KsReleaseTsdus*/
+        Irp->MdlAddress = NULL;
+        IoFreeIrp(Irp);
+        Irp = NULL;
     }
 
-    return Status;
+    return status;
 }
 
-
-
 /*
- * KsQueryMdlSize
- *   Query the whole size of a MDL (may be chained)
- *
- * Arguments:
- *   Mdl:  the Mdl to be queried
- *
- * Return Value:
- *   ULONG: the total size of the mdl
+ *  Normal receive event handler
  *
- * NOTES:
- *   N/A
+ *  It will move data from system Tsdu to our TsduList
  */
 
-ULONG
-KsQueryMdlsSize (PMDL Mdl)
+NTSTATUS
+KsTcpReceiveEventHandler(
+    IN PVOID                TdiEventContext,
+    IN CONNECTION_CONTEXT   ConnectionContext,
+    IN ULONG                ReceiveFlags,
+    IN ULONG                BytesIndicated,
+    IN ULONG                BytesAvailable,
+    OUT ULONG *             BytesTaken,
+    IN PVOID                Tsdu,
+    OUT PIRP *              IoRequestPacket
+   )
 {
-    PMDL    Next = Mdl;
-    ULONG   Length = 0;
+    NTSTATUS            status;
 
+    ks_tconn_t *        tconn;
 
-    //
-    // Walking the MDL Chain ...
-    //
+    BOOLEAN             bIsExpedited;
+    BOOLEAN             bIsCompleteTsdu;
 
-    while (Next) {
-        Length += MmGetMdlByteCount(Next);
-        Next = Next->Next;
-    }
+    PCHAR               Buffer = NULL;
+    PIRP                Irp = NULL;
+    PMDL                Mdl = NULL;
+    PFILE_OBJECT        FileObject;
+    PDEVICE_OBJECT      DeviceObject;
+    PKS_TSDUMGR         TsduMgr;
 
-    return (Length);
-}
+    PKS_TCP_COMPLETION_CONTEXT context = NULL;
 
+    tconn = (ks_tconn_t *) ConnectionContext;
+    ks_get_tconn(tconn);
 
-/*
- * KsLockUserBuffer
- *   Allocate MDL for the buffer and lock the pages into
- *   nonpaged pool
- *
- * Arguments:
- *   UserBuffer:  the user buffer to be locked
- *   Length:      length in bytes of the buffer
- *   Operation:   read or write access
- *   pMdl:        the result of the created mdl
- *
- * Return Value:
- *   NTSTATUS:     kernel status code (STATUS_SUCCESS
- *                 or other error code)
- *
- * NOTES:
- *   N/A
- */
+    /* check expedited flag */
+    bIsExpedited = cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_EXPEDITED);
 
-NTSTATUS
-KsLockUserBuffer (
-    IN PVOID            UserBuffer,
-    IN BOOLEAN          bPaged,
-    IN ULONG            Length,
-    IN LOCK_OPERATION   Operation,
-    OUT PMDL *          pMdl
-    )
-{
-    NTSTATUS    Status;
-    PMDL        Mdl = NULL;
+    /* check whether the whole body of payload is received or not */
+    if ( (cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_ENTIRE_MESSAGE)) &&
+         (BytesIndicated == BytesAvailable) ) {
+        bIsCompleteTsdu = TRUE;
+    } else {
+        bIsCompleteTsdu = FALSE;
+    }
 
-    LASSERT(UserBuffer != NULL);
+    KsPrint((4, "KsTcpReceiveEventHandler BytesIndicated = %d BytesAvailable = %d ...\n",
+                BytesIndicated, BytesAvailable));
+    KsPrint((4, "bIsCompleteTsdu = %d bIsExpedited = %d\n", bIsCompleteTsdu, bIsExpedited ));
 
-    *pMdl = NULL;
+    /* check whether we are conntected or not listener */
+    if ( !((tconn->kstc_state == ksts_connected) &&
+           (tconn->kstc_type == kstt_sender ||
+            tconn->kstc_type == kstt_child))) {
 
-    Mdl = IoAllocateMdl(
-                UserBuffer,
-                Length,
-                FALSE,
-                FALSE,
-                NULL
-                );
+        *BytesTaken = BytesIndicated;
+        ks_put_tconn(tconn);
+        return (STATUS_SUCCESS);
+    }
 
-    if (Mdl == NULL) {
+    /* query tsdu mgr */
+    TsduMgr = KsQueryTsduMgr(tconn, bIsExpedited, FALSE);
 
-        Status = STATUS_INSUFFICIENT_RESOURCES;
+    ks_lock_tsdumgr(TsduMgr);
+    if (bIsCompleteTsdu) {
 
-    } else {
+        *BytesTaken = KsWriteTsduDat(TsduMgr, Tsdu, BytesAvailable, 0);
+        status = STATUS_SUCCESS;
 
-        __try {
+        /* signal TsduMgr event */
+        KeSetEvent(&(TsduMgr->Event), 0, FALSE);
+        ks_unlock_tsdumgr(TsduMgr);
 
-            if (bPaged) {
-                MmProbeAndLockPages(
-                    Mdl,
-                    KernelMode,
-                    Operation
-                    );
-            } else {
-                MmBuildMdlForNonPagedPool(
-                    Mdl
-                    );
+        /* re-active the ks connection and wake up the scheduler */
+        if (KS_CAN_SCHED(TsduMgr)) {
+            if (tconn->kstc_conn && tconn->kstc_sched_cb) {
+                tconn->kstc_sched_cb(tconn, FALSE);
             }
+        }
 
-            Status = STATUS_SUCCESS;
+    } else {
 
-            *pMdl = Mdl;
+        ks_unlock_tsdumgr(TsduMgr);
 
-        } __except (EXCEPTION_EXECUTE_HANDLER) {
-
-            IoFreeMdl(Mdl);
-
-            Mdl = NULL;
-
-            cfs_enter_debugger();
-
-            Status = STATUS_INVALID_USER_BUFFER;
+        /* allocate buffer for further data in tsdu queue */
+        Buffer = ExAllocatePool(NonPagedPool, BytesAvailable);
+        if (NULL == Buffer) {
+            status = STATUS_INSUFFICIENT_RESOURCES;
+            goto errorout;
         }
-    }
-
-    return Status;
-}
-
-/*
- * KsMapMdlBuffer
- *   Map the mdl into a buffer in kernel space
- *
- * Arguments:
- *   Mdl:  the mdl to be mapped
- *
- * Return Value:
- *   PVOID: the buffer mapped or NULL in failure
- *
- * NOTES:
- *   N/A
- */
-
-PVOID
-KsMapMdlBuffer (PMDL    Mdl)
-{
-    LASSERT(Mdl != NULL);
-
-    return MmGetSystemAddressForMdlSafe(
-                Mdl,
-                NormalPagePriority
-                );
-}
-
-
-/*
- * KsReleaseMdl
- *   Unlock all the pages in the mdl
- *
- * Arguments:
- *   Mdl:  memory description list to be released
- *
- * Return Value:
- *   N/A
- *
- * NOTES:
- *   N/A
- */
-
-VOID
-KsReleaseMdl (IN PMDL   Mdl,
-              IN int    Paged )
-{
-    LASSERT(Mdl != NULL);
-
-    while (Mdl) {
 
-        PMDL    Next;
-
-        Next = Mdl->Next;
-
-        if (Paged) {
-            MmUnlockPages(Mdl);
+        /* there's still data in tdi internal queue, we need issue a new
+           Irp to receive all of them. first allocate the tcp context */
+        context = cfs_alloc(sizeof(KS_TCP_COMPLETION_CONTEXT), 0);
+        if (!context) {
+            status = STATUS_INSUFFICIENT_RESOURCES;
+            goto errorout;
         }
 
-        IoFreeMdl(Mdl);
-
-        Mdl = Next;
-    }
-}
-
+        /* setup the context */
+        RtlZeroMemory(context, sizeof(KS_TCP_COMPLETION_CONTEXT));
+        context->Magic             = KS_TCP_CONTEXT_MAGIC;
+        context->tconn             = tconn;
+        context->CompletionRoutine = KsTcpReceiveCompletionRoutine;
+        context->CompletionContext = Buffer;
+        context->TsduMgr           = TsduMgr;
+        context->Buffer            = Buffer;
+        context->Event             = &(TsduMgr->Event);
 
-/*
- * ks_lock_buffer
- *   allocate MDL for the user spepcified buffer and lock (paging-in)
- *   all the pages of the buffer into system memory
- *
- * Arguments:
- *   buffer:  the user buffer to be locked
- *   length:  length in bytes of the buffer
- *   access:  read or write access
- *   mdl:     the result of the created mdl
- *
- * Return Value:
- *   int:     the ks error code: 0: success / -x: failture
- *
- * Notes:
- *   N/A
- */
+        if (tconn->kstc_type == kstt_sender) {
+            FileObject = tconn->sender.kstc_info.FileObject;
+        } else {
+            FileObject = tconn->child.kstc_info.FileObject;
+        }
+        DeviceObject = IoGetRelatedDeviceObject(FileObject);
 
-int
-ks_lock_buffer (
-    void *            buffer,
-    int               paged,
-    int               length,
-    LOCK_OPERATION    access,
-    ksock_mdl_t **    kmdl
-    )
-{
-    NTSTATUS        status;
+        /* build new tdi Irp and setup it. */
+        Irp = KsBuildTdiIrp(DeviceObject);
+        if (NULL == Irp) {
+            goto errorout;
+        }
 
-    status = KsLockUserBuffer(
-                    buffer,
-                    paged !=0,
-                    length,
-                    access,
-                    kmdl
+        status = KsLockUserBuffer(
+                    Buffer,
+                    FALSE,
+                    BytesAvailable,
+                    IoModifyAccess,
+                    &Mdl
                     );
 
-    return cfs_error_code(status);
-}
-
-
-/*
- * ks_map_mdl
- *   Map the mdl pages into kernel space
- *
- * Arguments:
- *   mdl:  the mdl to be mapped
- *
- * Return Value:
- *   void *: the buffer mapped or NULL in failure
- *
- * Notes:
- *   N/A
- */
-
-void *
-ks_map_mdl (ksock_mdl_t * mdl)
-{
-    LASSERT(mdl != NULL);
-
-    return KsMapMdlBuffer(mdl);
-}
-
-/*
- *  ks_release_mdl
- *   Unlock all the pages in the mdl and release the mdl
- *
- * Arguments:
- *   mdl:  memory description list to be released
- *
- * Return Value:
- *   N/A
- *
- * Notes:
- *   N/A
- */
-
-void
-ks_release_mdl (ksock_mdl_t *mdl, int paged)
-{
-    LASSERT(mdl != NULL);
-
-    KsReleaseMdl(mdl, paged);
-}
-
-
-/*
- * ks_create_tconn
- *   allocate a new tconn structure from the SLAB cache or
- *   NonPaged sysetm pool
- *
- * Arguments:
- *   N/A
- *
- * Return Value:
- *   ksock_tconn_t *: the address of tconn or NULL if it fails
- *
- * NOTES:
- *   N/A
- */
-
-ksock_tconn_t *
-ks_create_tconn()
-{
-    ksock_tconn_t * tconn = NULL;
-
-    /* allocate ksoc_tconn_t from the slab cache memory */
-
-    tconn = (ksock_tconn_t *)cfs_mem_cache_alloc(
-                ks_data.ksnd_tconn_slab, CFS_ALLOC_ZERO);
-
-    if (tconn) {
-
-        /* zero tconn elements */
-        memset(tconn, 0, sizeof(ksock_tconn_t));
-
-        /* initialize the tconn ... */
-        tconn->kstc_magic = KS_TCONN_MAGIC;
+        if (!NT_SUCCESS(status)) {
+            goto errorout;
+        }
 
-        ExInitializeWorkItem(
-            &(tconn->kstc_disconnect.WorkItem),
-            KsDisconnectHelper,
-            &(tconn->kstc_disconnect)
-            );
+        TdiBuildReceive(
+            Irp,
+            DeviceObject,
+            FileObject,
+            KsTcpCompletionRoutine,
+            context,
+            Mdl,
+            ReceiveFlags & (TDI_RECEIVE_NORMAL | TDI_RECEIVE_EXPEDITED),
+            BytesAvailable
+          );
 
-        KeInitializeEvent(
-                &(tconn->kstc_disconnect.Event),
-                SynchronizationEvent,
-                FALSE );
+        IoSetNextIrpStackLocation(Irp);
 
-        ExInitializeWorkItem(
-            &(tconn->kstc_destroy),
-            ks_destroy_tconn,
-            tconn
-            );
+        /* return the newly built Irp to transport driver,
+           it will process it to receive all the data */
 
-        spin_lock_init(&(tconn->kstc_lock));
+        *IoRequestPacket = Irp;
+        *BytesTaken = 0;
 
         ks_get_tconn(tconn);
-
-        spin_lock(&(ks_data.ksnd_tconn_lock));
-
-        /* attach it into global list in ks_data */
-
-        list_add(&(tconn->kstc_list), &(ks_data.ksnd_tconns));
-        ks_data.ksnd_ntconns++;
-        spin_unlock(&(ks_data.ksnd_tconn_lock));
-
-        tconn->kstc_rcv_wnd = tconn->kstc_snd_wnd = 0x10000;
+        status = STATUS_MORE_PROCESSING_REQUIRED;
     }
 
-    return (tconn);
-}
-
-
-/*
- * ks_free_tconn
- *   free the tconn structure to the SLAB cache or NonPaged
- *   sysetm pool
- *
- * Arguments:
- *   tconn:  the tcon is to be freed
- *
- * Return Value:
- *   N/A
- *
- * Notes:
- *   N/A
- */
-
-void
-ks_free_tconn(ksock_tconn_t * tconn)
-{
-    LASSERT(atomic_read(&(tconn->kstc_refcount)) == 0);
+    ks_put_tconn(tconn);
 
-    spin_lock(&(ks_data.ksnd_tconn_lock));
+    return (status);
 
-    /* remove it from the global list */
-    list_del(&tconn->kstc_list);
-    ks_data.ksnd_ntconns--;
+errorout:
 
-    /* if this is the last tconn, it would be safe for
-       ks_tdi_fini_data to quit ... */
-    if (ks_data.ksnd_ntconns == 0) {
-        cfs_wake_event(&ks_data.ksnd_tconn_exit);
+    if (Mdl) {
+        KsReleaseMdl(Mdl, FALSE);
     }
-    spin_unlock(&(ks_data.ksnd_tconn_lock));
 
-    /* free the structure memory */
-    cfs_mem_cache_free(ks_data.ksnd_tconn_slab, tconn);
-}
-
-
-/*
- * ks_init_listener
- *   Initialize the tconn as a listener (daemon)
- *
- * Arguments:
- *   tconn: the listener tconn
- *
- * Return Value:
- *   N/A
- *
- * Notes:
- *   N/A
- */
-
-void
-ks_init_listener(
-    ksock_tconn_t * tconn
-    )
-{
-    /* preparation: intialize the tconn members */
-
-    tconn->kstc_type = kstt_listener;
-
-    RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
-
-    CFS_INIT_LIST_HEAD(&(tconn->listener.kstc_listening.list));
-    CFS_INIT_LIST_HEAD(&(tconn->listener.kstc_accepted.list));
-
-    cfs_init_event( &(tconn->listener.kstc_accept_event),
-                    TRUE,
-                    FALSE );
-
-    cfs_init_event( &(tconn->listener.kstc_destroy_event),
-                    TRUE,
-                    FALSE );
-
-    tconn->kstc_state = ksts_inited;
-}
-
-
-/*
- * ks_init_sender
- *   Initialize the tconn as a sender
- *
- * Arguments:
- *   tconn: the sender tconn
- *
- * Return Value:
- *   N/A
- *
- * Notes:
- *   N/A
- */
-
-void
-ks_init_sender(
-    ksock_tconn_t * tconn
-    )
-{
-    tconn->kstc_type = kstt_sender;
-    RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
-
-    KsInitializeKsChain(&(tconn->sender.kstc_recv));
-    KsInitializeKsChain(&(tconn->sender.kstc_send));
-
-    tconn->kstc_snd_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
-    tconn->kstc_rcv_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
-
-    tconn->kstc_state = ksts_inited;
-}
-
-/*
- * ks_init_child
- *   Initialize the tconn as a child
- *
- * Arguments:
- *   tconn: the child tconn
- *
- * Return Value:
- *   N/A
- *
- * NOTES:
- *   N/A
- */
-
-void
-ks_init_child(
-    ksock_tconn_t * tconn
-    )
-{
-    tconn->kstc_type = kstt_child;
-    RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
+    if (Buffer) {
+        ExFreePool(Buffer);
+    }
 
-    KsInitializeKsChain(&(tconn->child.kstc_recv));
-    KsInitializeKsChain(&(tconn->child.kstc_send));
+    if (Irp) {
+        IoFreeIrp(Irp);
+    }
 
-    tconn->kstc_snd_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
-    tconn->kstc_rcv_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
+    if (context) {
+        ASSERT(context->Magic == KS_TCP_CONTEXT_MAGIC);
+        context->Magic = 'CDAB';
+        cfs_free(context);
+    }
 
-    tconn->kstc_state = ksts_inited;
-}
+    ks_abort_tconn(tconn);
+    ks_put_tconn(tconn);
 
-/*
- * ks_get_tconn
- *   increase the reference count of the tconn with 1
- *
- * Arguments:
- *   tconn: the tdi connection to be referred
- *
- * Return Value:
- *   N/A
- *
- * NOTES:
- *   N/A
- */
+    *BytesTaken = BytesAvailable;
 
-void
-ks_get_tconn(
-    ksock_tconn_t * tconn
-    )
-{
-    atomic_inc(&(tconn->kstc_refcount));
+    return STATUS_SUCCESS;
 }
 
 /*
- * ks_put_tconn
- *   decrease the reference count of the tconn and destroy
- *   it if the refercount becomes 0.
- *
- * Arguments:
- *   tconn: the tdi connection to be dereferred
- *
- * Return Value:
- *   N/A
- *
- * NOTES:
- *   N/A
+ *  Expedited receive event handler
  */
 
-void
-ks_put_tconn(
-    ksock_tconn_t *tconn
+NTSTATUS
+KsTcpReceiveExpeditedEventHandler(
+    IN PVOID                TdiEventContext,
+    IN CONNECTION_CONTEXT   ConnectionContext,
+    IN ULONG                ReceiveFlags,
+    IN ULONG                BytesIndicated,
+    IN ULONG                BytesAvailable,
+    OUT ULONG *             BytesTaken,
+    IN PVOID                Tsdu,
+    OUT PIRP *              IoRequestPacket
     )
 {
-    if (atomic_dec_and_test(&(tconn->kstc_refcount))) {
-
-        spin_lock(&(tconn->kstc_lock));
-
-        if ( ( tconn->kstc_type == kstt_child ||
-               tconn->kstc_type == kstt_sender ) &&
-             ( tconn->kstc_state == ksts_connected ) ) {
-
-            spin_unlock(&(tconn->kstc_lock));
-
-            ks_abort_tconn(tconn);
-
-        } else {
-
-            if (cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DESTROY_BUSY)) {
-                cfs_enter_debugger();
-            } else {
-                ExQueueWorkItem(
-                        &(tconn->kstc_destroy),
-                        DelayedWorkQueue
-                        );
-
-                cfs_set_flag(tconn->kstc_flags, KS_TCONN_DESTROY_BUSY);
-            }
-
-            spin_unlock(&(tconn->kstc_lock));
-        }
-    }
+    return KsTcpReceiveEventHandler(
+                TdiEventContext,
+                ConnectionContext,
+                ReceiveFlags | TDI_RECEIVE_EXPEDITED,
+                BytesIndicated,
+                BytesAvailable,
+                BytesTaken,
+                Tsdu,
+                IoRequestPacket
+                );
 }
 
 /*
- * ks_destroy_tconn
- *   cleanup the tdi connection and free it
- *
- * Arguments:
- *   tconn: the tdi connection to be cleaned.
- *
- * Return Value:
- *   N/A
+ *  Bulk receive event handler
  *
- * NOTES:
- *   N/A
+ *  It will queue all the system Tsdus to our TsduList.
+ *  Then later ks_recv_mdl will release them.
  */
 
-void
-ks_destroy_tconn(
-    ksock_tconn_t *     tconn
+NTSTATUS
+KsTcpChainedReceiveEventHandler (
+    IN PVOID TdiEventContext,       // the event context
+    IN CONNECTION_CONTEXT ConnectionContext,
+    IN ULONG ReceiveFlags,
+    IN ULONG ReceiveLength,
+    IN ULONG StartingOffset,        // offset of start of client data in TSDU
+    IN PMDL  Tsdu,                  // TSDU data chain
+    IN PVOID TsduDescriptor         // for call to TdiReturnChainedReceives
     )
 {
-    LASSERT(tconn->kstc_refcount.counter == 0);
-
-    if (tconn->kstc_type == kstt_listener) {
-
-        ks_reset_handlers(tconn);
-
-        /* for listener, we just need to close the address object */
-        KsCloseAddress(
-                tconn->kstc_addr.Handle,
-                tconn->kstc_addr.FileObject
-                );
-
-        tconn->kstc_state = ksts_inited;
-
-    } else if (tconn->kstc_type == kstt_child) {
-
-        /* for child tdi conections */
-
-        /* disassociate the relation between it's connection object
-           and the address object */
-
-        if (tconn->kstc_state == ksts_associated) {
-            KsDisassociateAddress(
-                tconn->child.kstc_info.FileObject
-                );
-        }
-
-        /* release the connection object */
 
-        KsCloseConnection(
-                tconn->child.kstc_info.Handle,
-                tconn->child.kstc_info.FileObject
-                );
-
-        /* release it's refer of it's parent's address object */
-        KsCloseAddress(
-                NULL,
-                tconn->kstc_addr.FileObject
-                );
-
-        spin_lock(&tconn->child.kstc_parent->kstc_lock);
-        spin_lock(&tconn->kstc_lock);
-
-        tconn->kstc_state = ksts_inited;
-
-        /* remove it frome it's parent's queues */
-
-        if (tconn->child.kstc_queued) {
-
-            list_del(&(tconn->child.kstc_link));
-
-            if (tconn->child.kstc_queueno) {
-
-                LASSERT(tconn->child.kstc_parent->listener.kstc_accepted.num > 0);
-                tconn->child.kstc_parent->listener.kstc_accepted.num -= 1;
-
-            } else {
+    NTSTATUS            status;
+    ks_tconn_t *        tconn;
 
-                LASSERT(tconn->child.kstc_parent->listener.kstc_listening.num > 0);
-                tconn->child.kstc_parent->listener.kstc_listening.num -= 1;
-            }
+    PKS_TSDUMGR         TsduMgr;
 
-            tconn->child.kstc_queued = FALSE;
-        }
+    BOOLEAN             expedited;
 
-        spin_unlock(&tconn->kstc_lock);
-        spin_unlock(&tconn->child.kstc_parent->kstc_lock);
+    tconn = (ks_tconn_t *) ConnectionContext;
+    expedited = cfs_is_flag_set(ReceiveFlags, TDI_RECEIVE_EXPEDITED);
 
-        /* drop the reference of the parent tconn */
-        ks_put_tconn(tconn->child.kstc_parent);
+    KsPrint((4, "KsTcpChainedReceive: sock: %p conn: %p ReceiveLength: %xh "
+                "bIsExpedited: %d Tsdu=%p TsduDesc=%p data=%xh\n",
+                 tconn, tconn->kstc_conn, ReceiveLength, expedited,
+                 Tsdu, TsduDescriptor, *((PULONG)KsMapMdlBuffer(Tsdu))));
 
-    } else if (tconn->kstc_type == kstt_sender) {
+    ks_get_tconn(tconn);
 
-        ks_reset_handlers(tconn);
+    /* check whether we are conntected or not listener */
+    if ( !((tconn->kstc_state == ksts_connected) &&
+         (tconn->kstc_type == kstt_sender ||
+          tconn->kstc_type == kstt_child))) {
 
-        /* release the connection object */
+        ks_put_tconn(tconn);
+        return (STATUS_SUCCESS);
+    }
 
-        KsCloseConnection(
-                tconn->sender.kstc_info.Handle,
-                tconn->sender.kstc_info.FileObject
-                );
+    if (Tsdu) {
 
-        /* release it's refer of it's parent's address object */
-        KsCloseAddress(
-                tconn->kstc_addr.Handle,
-                tconn->kstc_addr.FileObject
-                );
+        TsduMgr = KsQueryTsduMgr(tconn, expedited, FALSE);
+        ks_lock_tsdumgr(TsduMgr);
+#if FALSE
+        KsWriteTsduMdl(TsduMgr, Tsdu,  TsduDescriptor,
+                       StartingOffset, ReceiveLength, 0);
+        status = STATUS_PENDING;
+#else
+        KsWriteTsduDat(TsduMgr, (PCHAR)KsMapMdlBuffer(Tsdu) + 
+                       StartingOffset, ReceiveLength, 0);
+        status = STATUS_SUCCESS;
+#endif
+        KeSetEvent(&(TsduMgr->Event), 0, FALSE);
+        ks_unlock_tsdumgr(TsduMgr);
 
-        tconn->kstc_state = ksts_inited;
+        /* re-active the ks connection and wake up the scheduler */
+        if (KS_CAN_SCHED(TsduMgr)) {
+            if (tconn->kstc_conn && tconn->kstc_sched_cb) {
+                tconn->kstc_sched_cb(tconn, FALSE);
+            }
+        }
 
     } else {
-        cfs_enter_debugger();
+
+        ks_abort_tconn(tconn);
+        status = STATUS_CONNECTION_ABORTED;
     }
 
-    /* free the tconn structure ... */
+    ks_put_tconn(tconn);
 
-    ks_free_tconn(tconn);
+    /* Return STATUS_PENDING to system because we are still
+       owning the MDL resources. ks_recv_mdl is expected
+       to free the MDL resources. */
+
+    return (status);
 }
 
-int
-ks_query_data(
-    ksock_tconn_t * tconn,
-    size_t *        size,
-    int             bIsExpedited )
+
+/*
+ *  Expedited & Bulk receive event handler
+ */
+
+NTSTATUS
+KsTcpChainedReceiveExpeditedEventHandler (
+    IN PVOID                TdiEventContext,       // the event context
+    IN CONNECTION_CONTEXT   ConnectionContext,
+    IN ULONG                ReceiveFlags,
+    IN ULONG                ReceiveLength,
+    IN ULONG                StartingOffset,        // offset of start of client data in TSDU
+    IN PMDL                 Tsdu,                  // TSDU data chain
+    IN PVOID                TsduDescriptor         // for call to TdiReturnChainedReceives
+    )
 {
-    int             rc = 0;
+    return KsTcpChainedReceiveEventHandler(
+                TdiEventContext,
+                ConnectionContext,
+                ReceiveFlags | TDI_RECEIVE_EXPEDITED,
+                ReceiveLength,
+                StartingOffset,
+                Tsdu,
+                TsduDescriptor );
+}
 
-    PKS_CHAIN       KsChain;
-    PKS_TSDUMGR     KsTsduMgr;
 
-    *size = 0;
+/*
+ * KsSetHandlers
+ *   setup all the event handler callbacks
+ *
+ * Arguments:
+ *   tconn: the tdi connecton object
+ *
+ * Return Value:
+ *   int: ks error code
+ *
+ * NOTES:
+ *   N/A
+ */
 
-    ks_get_tconn(tconn);
-    spin_lock(&(tconn->kstc_lock));
+int
+KsSetHandlers(
+    ks_tconn_t *     tconn
+    )
+{
+    NTSTATUS            status = STATUS_SUCCESS;
+    KS_EVENT_HANDLERS   handlers;
 
-    if ( tconn->kstc_type != kstt_sender &&
-         tconn->kstc_type != kstt_child) {
-        rc = -EINVAL;
-        spin_unlock(&(tconn->kstc_lock));
+    /* to make sure the address object is opened already */
+    if (tconn->kstc_addr.FileObject == NULL) {
         goto errorout;
     }
 
-    if (tconn->kstc_state != ksts_connected) {
-        rc = -ENOTCONN;
-        spin_unlock(&(tconn->kstc_lock));
-        goto errorout;
-    }
+    /* initialize the handlers indictor array. for sender and listenr,
+       there are different set of callbacks. for child, we just return. */
 
-    if (tconn->kstc_type == kstt_sender) {
-        KsChain = &(tconn->sender.kstc_recv);
-    } else {
-        LASSERT(tconn->kstc_type == kstt_child);
-        KsChain = &(tconn->child.kstc_recv);
-    }
+    memset(&handlers, 0, sizeof(KS_EVENT_HANDLERS));
 
-    if (bIsExpedited) {
-        KsTsduMgr = &(KsChain->Expedited);
-    } else {
-        KsTsduMgr = &(KsChain->Normal);
+    SetEventHandler(handlers, TDI_EVENT_ERROR, KsErrorEventHandler);
+    SetEventHandler(handlers, TDI_EVENT_DISCONNECT, KsDisconnectEventHandler);
+    SetEventHandler(handlers, TDI_EVENT_RECEIVE, KsTcpReceiveEventHandler);
+    SetEventHandler(handlers, TDI_EVENT_RECEIVE_EXPEDITED, KsTcpReceiveExpeditedEventHandler);
+    SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE, KsTcpChainedReceiveEventHandler);
+
+    // SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE_EXPEDITED, KsTcpChainedReceiveExpeditedEventHandler);
+
+    if (tconn->kstc_type == kstt_listener) {
+        SetEventHandler(handlers, TDI_EVENT_CONNECT, KsConnectEventHandler);
+    } else if (tconn->kstc_type == kstt_child) {
+        goto errorout;
     }
 
-    *size = KsTsduMgr->TotalBytes;
-    spin_unlock(&(tconn->kstc_lock));
+    /* set all the event callbacks */
+    status = KsSetEventHandlers(
+                tconn->kstc_addr.FileObject, /* Address File Object  */
+                tconn,                       /* Event Context */
+                &handlers                    /* Event callback handlers */
+                );
 
 errorout:
 
-    ks_put_tconn(tconn);
-
-    return (rc);
+    return cfs_error_code(status);
 }
 
+
 /*
- * ks_get_tcp_option
- *   Query the the options of the tcp stream connnection
+ * KsResetHandlers
+ *   disable all the event handler callbacks (set to NULL)
  *
  * Arguments:
- *   tconn:         the tdi connection
- *   ID:            option id
- *   OptionValue:   buffer to store the option value
- *   Length:        the length of the value, to be returned
+ *   tconn: the tdi connecton object
  *
  * Return Value:
- *   int:           ks return code
+ *   int: ks error code
  *
  * NOTES:
  *   N/A
  */
 
 int
-ks_get_tcp_option (
-    ksock_tconn_t *     tconn,
-    ULONG               ID,
-    PVOID               OptionValue,
-    PULONG              Length
+KsResetHandlers(
+    ks_tconn_t *     tconn
     )
 {
-    NTSTATUS            Status = STATUS_SUCCESS;
-
-    IO_STATUS_BLOCK     IoStatus;
-
-    TCP_REQUEST_QUERY_INFORMATION_EX QueryInfoEx;
-
-    PFILE_OBJECT        ConnectionObject;
-    PDEVICE_OBJECT      DeviceObject = NULL;
+    NTSTATUS            status = STATUS_SUCCESS;
+    KS_EVENT_HANDLERS   handlers;
 
-    PIRP                Irp = NULL;
-    PIO_STACK_LOCATION  IrpSp = NULL;
+    /* to make sure the address object is opened already */
+    if (tconn->kstc_addr.FileObject == NULL) {
+        goto errorout;
+    }
 
-    KEVENT              Event;
+    /* initialize the handlers indictor array. for sender and listenr,
+       there are different set of callbacks. for child, we just return. */
 
-    /* make sure the tdi connection is connected ? */
+    memset(&handlers, 0, sizeof(KS_EVENT_HANDLERS));
 
-    ks_get_tconn(tconn);
+    SetEventHandler(handlers, TDI_EVENT_ERROR, NULL);
+    SetEventHandler(handlers, TDI_EVENT_DISCONNECT, NULL);
+    SetEventHandler(handlers, TDI_EVENT_RECEIVE, NULL);
+    SetEventHandler(handlers, TDI_EVENT_RECEIVE_EXPEDITED, NULL);
+    SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE, NULL);
+    // SetEventHandler(handlers, TDI_EVENT_CHAINED_RECEIVE_EXPEDITED, NULL);
 
-    if (tconn->kstc_state != ksts_connected) {
-        Status = STATUS_INVALID_PARAMETER;
+    if (tconn->kstc_type == kstt_listener) {
+        SetEventHandler(handlers, TDI_EVENT_CONNECT, NULL);
+    } else if (tconn->kstc_type == kstt_child) {
         goto errorout;
     }
 
-    LASSERT(tconn->kstc_type == kstt_sender ||
-           tconn->kstc_type == kstt_child);
+    /* set all the event callbacks */
+    status = KsSetEventHandlers(
+                tconn->kstc_addr.FileObject, /* Address File Object  */
+                tconn,                       /* Event Context */
+                &handlers                    /* Event callback handlers */
+                );
 
-    if (tconn->kstc_type == kstt_sender) {
-        ConnectionObject = tconn->sender.kstc_info.FileObject;
-    } else {
-        ConnectionObject = tconn->child.kstc_info.FileObject;
-    }
+errorout:
 
-    QueryInfoEx.ID.toi_id = ID;
-    QueryInfoEx.ID.toi_type   = INFO_TYPE_CONNECTION;
-    QueryInfoEx.ID.toi_class  = INFO_CLASS_PROTOCOL;
-    QueryInfoEx.ID.toi_entity.tei_entity   = CO_TL_ENTITY;
-    QueryInfoEx.ID.toi_entity.tei_instance = 0;
+    return cfs_error_code(status);
+}
 
-    RtlZeroMemory(&(QueryInfoEx.Context), CONTEXT_SIZE);
+VOID
+KsPrintProviderInfo(
+   PWSTR DeviceName,
+   PTDI_PROVIDER_INFO ProviderInfo
+   )
+{
+    KsPrint((2, "%ws ProviderInfo:\n", DeviceName));
 
-    KeInitializeEvent(&Event, NotificationEvent, FALSE);
-    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
+    KsPrint((2, "  Version              : 0x%4.4X\n", ProviderInfo->Version ));
+    KsPrint((2, "  MaxSendSize          : %d\n", ProviderInfo->MaxSendSize ));
+    KsPrint((2, "  MaxConnectionUserData: %d\n", ProviderInfo->MaxConnectionUserData ));
+    KsPrint((2, "  MaxDatagramSize      : %d\n", ProviderInfo->MaxDatagramSize ));
+    KsPrint((2, "  ServiceFlags         : 0x%8.8X\n", ProviderInfo->ServiceFlags ));
 
-    Irp = IoBuildDeviceIoControlRequest(
-                IOCTL_TCP_QUERY_INFORMATION_EX,
-                DeviceObject,
-                &QueryInfoEx,
-                sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
-                OptionValue,
-                *Length,
-                FALSE,
-                &Event,
-                &IoStatus
-                );
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_CONNECTION_MODE) {
+        KsPrint((2, "  CONNECTION_MODE\n"));
+    }
 
-    if (Irp == NULL) {
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto errorout;
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_ORDERLY_RELEASE) {
+        KsPrint((2, "  ORDERLY_RELEASE\n"));
     }
 
-    IrpSp = IoGetNextIrpStackLocation(Irp);
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_CONNECTIONLESS_MODE) {
+        KsPrint((2, "  CONNECTIONLESS_MODE\n"));
+    }
 
-    if (IrpSp == NULL) {
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_ERROR_FREE_DELIVERY) {
+        KsPrint((2, "  ERROR_FREE_DELIVERY\n"));
+    }
 
-        IoFreeIrp(Irp);
-        Irp = NULL;
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto errorout;
+    if( ProviderInfo->ServiceFlags & TDI_SERVICE_SECURITY_LEVEL ) {
+        KsPrint((2, "  SECURITY_LEVEL\n"));
     }
 
-    IrpSp->FileObject = ConnectionObject;
-    IrpSp->DeviceObject = DeviceObject;
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_BROADCAST_SUPPORTED) {
+        KsPrint((2, "  BROADCAST_SUPPORTED\n"));
+    }
 
-    Status = IoCallDriver(DeviceObject, Irp);
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_MULTICAST_SUPPORTED) {
+        KsPrint((2, "  MULTICAST_SUPPORTED\n"));
+    }
 
-    if (Status == STATUS_PENDING) {
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_DELAYED_ACCEPTANCE) {
+        KsPrint((2, "  DELAYED_ACCEPTANCE\n"));
+    }
 
-        KeWaitForSingleObject(
-                &Event,
-                Executive,
-                KernelMode,
-                FALSE,
-                NULL
-                );
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_EXPEDITED_DATA) {
+        KsPrint((2, "  EXPEDITED_DATA\n"));
+    }
 
-        Status = IoStatus.Status;
+    if( ProviderInfo->ServiceFlags & TDI_SERVICE_INTERNAL_BUFFERING) {
+        KsPrint((2, "  INTERNAL_BUFFERING\n"));
     }
 
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_ROUTE_DIRECTED) {
+        KsPrint((2, "  ROUTE_DIRECTED\n"));
+    }
 
-    if (NT_SUCCESS(Status)) {
-        *Length = IoStatus.Information;
-    } else {
-        cfs_enter_debugger();
-        memset(OptionValue, 0, *Length);
-        Status = STATUS_SUCCESS;
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_NO_ZERO_LENGTH) {
+        KsPrint((2, "  NO_ZERO_LENGTH\n"));
     }
 
-errorout:
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_POINT_TO_POINT) {
+        KsPrint((2, "  POINT_TO_POINT\n"));
+    }
 
-    ks_put_tconn(tconn);
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_MESSAGE_MODE) {
+        KsPrint((2, "  MESSAGE_MODE\n"));
+    }
 
-    return cfs_error_code(Status);
+    if (ProviderInfo->ServiceFlags & TDI_SERVICE_HALF_DUPLEX) {
+        KsPrint((2, "  HALF_DUPLEX\n"));
+    }
+
+    KsPrint((2, "  MinimumLookaheadData : %d\n", ProviderInfo->MinimumLookaheadData ));
+    KsPrint((2, "  MaximumLookaheadData : %d\n", ProviderInfo->MaximumLookaheadData ));
+    KsPrint((2, "  NumberOfResources    : %d\n", ProviderInfo->NumberOfResources ));
 }
 
+
 /*
- * ks_set_tcp_option
- *   Set the the options for the tcp stream connnection
+ * ks_create_tconn
+ *   allocate a new tconn structure from the SLAB cache or
+ *   NonPaged sysetm pool
  *
  * Arguments:
- *   tconn:     the tdi connection
- *   ID:        option id
- *   OptionValue: buffer containing the new option value
- *   Length:    the length of the value
+ *   N/A
  *
  * Return Value:
- *   int:       ks return code
+ *   ks_tconn_t *: the address of tconn or NULL if it fails
  *
  * NOTES:
  *   N/A
  */
 
-NTSTATUS
-ks_set_tcp_option (
-    ksock_tconn_t * tconn,
-    ULONG           ID,
-    PVOID           OptionValue,
-    ULONG           Length
-    )
+ks_tconn_t *
+ks_create_tconn()
 {
-    NTSTATUS            Status = STATUS_SUCCESS;
+    ks_tconn_t * tconn = NULL;
 
-    IO_STATUS_BLOCK     IoStatus;
+    /* allocate ksoc_tconn_t from the slab cache memory */
+    tconn = (ks_tconn_t *)cfs_mem_cache_alloc(
+                ks_data.ksnd_tconn_slab, CFS_ALLOC_ZERO);
 
-    ULONG               SetInfoExLength;
-    PTCP_REQUEST_SET_INFORMATION_EX SetInfoEx = NULL;
+    if (tconn) {
 
-    PFILE_OBJECT        ConnectionObject;
-    PDEVICE_OBJECT      DeviceObject = NULL;
+        /* zero tconn elements */
+        memset(tconn, 0, sizeof(ks_tconn_t));
 
-    PIRP                Irp = NULL;
-    PIO_STACK_LOCATION  IrpSp = NULL;
+        /* initialize the tconn ... */
+        tconn->kstc_magic = KS_TCONN_MAGIC;
 
-    PKEVENT             Event;
+        ExInitializeWorkItem(
+                &(tconn->kstc_disconnect.WorkItem),
+                KsDisconnectHelper,
+                &(tconn->kstc_disconnect)
+                );
 
-    /* make sure the tdi connection is connected ? */
+        KeInitializeEvent(
+                &(tconn->kstc_disconnect.Event),
+                SynchronizationEvent,
+                FALSE );
 
-    ks_get_tconn(tconn);
+        ExInitializeWorkItem(
+                &(tconn->kstc_destroy),
+                ks_destroy_tconn,
+                tconn
+            );
 
-    if (tconn->kstc_state != ksts_connected) {
-        Status = STATUS_INVALID_PARAMETER;
-        goto errorout;
-    }
+        cfs_spin_lock_init(&(tconn->kstc_lock));
 
-    LASSERT(tconn->kstc_type == kstt_sender ||
-           tconn->kstc_type == kstt_child);
+        ks_get_tconn(tconn);
+        cfs_spin_lock(&(ks_data.ksnd_tconn_lock));
 
-    if (tconn->kstc_type == kstt_sender) {
-        ConnectionObject = tconn->sender.kstc_info.FileObject;
-    } else {
-        ConnectionObject = tconn->child.kstc_info.FileObject;
+        /* attach it into global list in ks_data */
+
+        cfs_list_add(&(tconn->kstc_list), &(ks_data.ksnd_tconns));
+        ks_data.ksnd_ntconns++;
+        cfs_spin_unlock(&(ks_data.ksnd_tconn_lock));
+
+        tconn->kstc_rcv_wnd = tconn->kstc_snd_wnd = 0x10000;
     }
+    KsPrint((3, "ks_create_tconn: new connection: %p\n", tconn));
+    return (tconn);
+}
 
-    SetInfoExLength =  sizeof(TCP_REQUEST_SET_INFORMATION_EX) - 1 + Length + sizeof(KEVENT);
+/*
+ * ks_free_tconn
+ *   free the tconn structure to the SLAB cache or NonPaged
+ *   sysetm pool
+ *
+ * Arguments:
+ *   tconn:  the tcon is to be freed
+ *
+ * Return Value:
+ *   N/A
+ *
+ * Notes:
+ *   N/A
+ */
 
-    SetInfoEx = ExAllocatePoolWithTag(
-                    NonPagedPool,
-                    SetInfoExLength,
-                    'TSSK'
-                    );
+void
+ks_free_tconn(ks_tconn_t * tconn)
+{
+    LASSERT(cfs_atomic_read(&(tconn->kstc_refcount)) == 0);
 
-    if (SetInfoEx == NULL) {
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto errorout;
+    cfs_spin_lock(&(ks_data.ksnd_tconn_lock));
+
+    /* remove it from the global list */
+    cfs_list_del(&tconn->kstc_list);
+    ks_data.ksnd_ntconns--;
+
+    /* if this is the last tconn, it would be safe for
+       ks_tdi_fini_data to quit ... */
+    if (ks_data.ksnd_ntconns == 0) {
+        cfs_wake_event(&ks_data.ksnd_tconn_exit);
     }
+    cfs_spin_unlock(&(ks_data.ksnd_tconn_lock));
 
-    SetInfoEx->ID.toi_id = ID;
+    /* free the structure memory */
+    cfs_mem_cache_free(ks_data.ksnd_tconn_slab, tconn);
 
-    SetInfoEx->ID.toi_type  = INFO_TYPE_CONNECTION;
-    SetInfoEx->ID.toi_class = INFO_CLASS_PROTOCOL;
-    SetInfoEx->ID.toi_entity.tei_entity   = CO_TL_ENTITY;
-    SetInfoEx->ID.toi_entity.tei_instance = TL_INSTANCE;
+    KsPrint((3, "ks_free_tconn: tconn %p is freed.\n", tconn));
+}
 
-    SetInfoEx->BufferSize = Length;
-    RtlCopyMemory(&(SetInfoEx->Buffer[0]), OptionValue, Length);
 
-    Event = (PKEVENT)(&(SetInfoEx->Buffer[Length]));
-    KeInitializeEvent(Event, NotificationEvent, FALSE);
+/*
+ * ks_init_listener
+ *   Initialize the tconn as a listener (daemon)
+ *
+ * Arguments:
+ *   tconn: the listener tconn
+ *
+ * Return Value:
+ *   N/A
+ *
+ * Notes:
+ *   N/A
+ */
 
-    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
+void
+ks_init_listener(
+    ks_tconn_t * tconn
+    )
+{
+    /* preparation: intialize the tconn members */
 
-    Irp = IoBuildDeviceIoControlRequest(
-                IOCTL_TCP_SET_INFORMATION_EX,
-                DeviceObject,
-                SetInfoEx,
-                SetInfoExLength,
-                NULL,
-                0,
-                FALSE,
-                Event,
-                &IoStatus
-                );
+    tconn->kstc_type = kstt_listener;
 
-    if (Irp == NULL) {
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto errorout;
-    }
+    RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
 
-    IrpSp = IoGetNextIrpStackLocation(Irp);
+    CFS_INIT_LIST_HEAD(&(tconn->listener.kstc_listening.list));
+    CFS_INIT_LIST_HEAD(&(tconn->listener.kstc_accepted.list));
 
-    if (IrpSp == NULL) {
-        IoFreeIrp(Irp);
-        Irp = NULL;
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto errorout;
-    }
+    cfs_init_event( &(tconn->listener.kstc_accept_event),
+                    TRUE,
+                    FALSE );
 
-    IrpSp->FileObject = ConnectionObject;
-    IrpSp->DeviceObject = DeviceObject;
+    cfs_init_event( &(tconn->listener.kstc_destroy_event),
+                    TRUE,
+                    FALSE );
 
-    Status = IoCallDriver(DeviceObject, Irp);
+    tconn->kstc_state = ksts_inited;
+}
 
-    if (Status == STATUS_PENDING) {
 
-        KeWaitForSingleObject(
-                Event,
-                Executive,
-                KernelMode,
-                FALSE,
-                NULL
-                );
+/*
+ * ks_init_sender
+ *   Initialize the tconn as a sender
+ *
+ * Arguments:
+ *   tconn: the sender tconn
+ *
+ * Return Value:
+ *   N/A
+ *
+ * Notes:
+ *   N/A
+ */
 
-        Status = IoStatus.Status;
-    }
+void
+ks_init_sender(
+    ks_tconn_t * tconn
+    )
+{
+    tconn->kstc_type = kstt_sender;
+    RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
 
-errorout:
+    KsInitializeKsChain(&(tconn->sender.kstc_recv));
+    KsInitializeKsChain(&(tconn->sender.kstc_send));
 
-    if (SetInfoEx) {
-        ExFreePool(SetInfoEx);
-    }
+    tconn->kstc_snd_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
+    tconn->kstc_rcv_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
 
-    if (!NT_SUCCESS(Status)) {
-        printk("ks_set_tcp_option: error setup tcp option: ID (%d), Status = %xh\n",
-               ID, Status);
-        Status = STATUS_SUCCESS;
-    }
+    tconn->kstc_state = ksts_inited;
+}
+
+/*
+ * ks_init_child
+ *   Initialize the tconn as a child
+ *
+ * Arguments:
+ *   tconn: the child tconn
+ *
+ * Return Value:
+ *   N/A
+ *
+ * NOTES:
+ *   N/A
+ */
+
+void
+ks_init_child(
+    ks_tconn_t * tconn
+    )
+{
+    tconn->kstc_type = kstt_child;
+    RtlInitUnicodeString(&(tconn->kstc_dev), TCP_DEVICE_NAME);
 
-    ks_put_tconn(tconn);
+    KsInitializeKsChain(&(tconn->child.kstc_recv));
+    KsInitializeKsChain(&(tconn->child.kstc_send));
 
-    return cfs_error_code(Status);
+    tconn->kstc_snd_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
+    tconn->kstc_rcv_wnd = TDINAL_WINDOW_DEFAULT_SIZE;
+
+    tconn->kstc_state = ksts_inited;
 }
 
 /*
- * ks_bind_tconn
- *   bind the tdi connection object with an address
+ * ks_get_tconn
+ *   increase the reference count of the tconn with 1
  *
  * Arguments:
- *   tconn:    tconn to be bound
- *   parent:   the parent tconn object
- *   ipaddr:   the ip address
- *   port:     the port number
+ *   tconn: the tdi connection to be referred
  *
  * Return Value:
- *   int:   0 for success or ks error codes.
+ *   N/A
  *
  * NOTES:
  *   N/A
  */
 
-int
-ks_bind_tconn (
-    ksock_tconn_t * tconn,
-    ksock_tconn_t * parent,
-    ulong_ptr   addr,
-    unsigned short  port
+void
+ks_get_tconn(
+    ks_tconn_t * tconn
     )
 {
-    NTSTATUS            status;
-    int                 rc = 0;
-
-    ksock_tdi_addr_t    taddr;
-
-    memset(&taddr, 0, sizeof(ksock_tdi_addr_t));
-
-    if (tconn->kstc_state != ksts_inited) {
-
-        status = STATUS_INVALID_PARAMETER;
-        rc = cfs_error_code(status);
-
-        goto errorout;
-
-    } else if (tconn->kstc_type == kstt_child) {
-
-        if (NULL == parent) {
-            status = STATUS_INVALID_PARAMETER;
-            rc = cfs_error_code(status);
-
-            goto errorout;
-        }
-
-        /* refer it's parent's address object */
-
-        taddr = parent->kstc_addr;
-        ObReferenceObject(taddr.FileObject);
-
-        ks_get_tconn(parent);
-
-    } else {
-
-        PTRANSPORT_ADDRESS TdiAddress = &(taddr.Tdi);
-        ULONG              AddrLen = 0;
+    cfs_atomic_inc(&(tconn->kstc_refcount));
+}
 
-        /* intialize the tdi address*/
+/*
+ * ks_put_tconn
+ *   decrease the reference count of the tconn and destroy
+ *   it if the refercount becomes 0.
+ *
+ * Arguments:
+ *   tconn: the tdi connection to be dereferred
+ *
+ * Return Value:
+ *   N/A
+ *
+ * NOTES:
+ *   N/A
+ */
 
-        TdiAddress->TAAddressCount = 1;
-        TdiAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
-        TdiAddress->Address[0].AddressType   = TDI_ADDRESS_TYPE_IP;
+void
+ks_put_tconn(
+    ks_tconn_t *tconn
+    )
+{
+    if (cfs_atomic_dec_and_test(&(tconn->kstc_refcount))) {
 
-        ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_port = htons(port);
-        ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->in_addr = htonl(addr);
+        cfs_spin_lock(&(tconn->kstc_lock));
 
-        memset(&(((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_zero[0]),0,8);
+        if ( ( tconn->kstc_type == kstt_child ||
+               tconn->kstc_type == kstt_sender ) &&
+             ( tconn->kstc_state == ksts_connected ) ) {
 
+            cfs_spin_unlock(&(tconn->kstc_lock));
 
-        /* open the transport address object */
+            ks_abort_tconn(tconn);
 
-        AddrLen = FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address) +
-                  TDI_ADDRESS_LENGTH_IP;
+        } else {
 
-        status = KsOpenAddress(
-                    &(tconn->kstc_dev),
-                    &(taddr.Tdi),
-                    AddrLen,
-                    &(taddr.Handle),
-                    &(taddr.FileObject)
-                    );
+            if (cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DESTROY_BUSY)) {
+                cfs_enter_debugger();
+            } else {
+                ExQueueWorkItem(
+                        &(tconn->kstc_destroy),
+                        DelayedWorkQueue
+                        );
 
-        if (!NT_SUCCESS(status)) {
+                cfs_set_flag(tconn->kstc_flags, KS_TCONN_DESTROY_BUSY);
+            }
 
-            KsPrint((0, "ks_bind_tconn: failed to open ip addr object (%x:%d), status = %xh\n",
-                        addr, port,  status ));
-            rc = cfs_error_code(status);
-            goto errorout;
+            cfs_spin_unlock(&(tconn->kstc_lock));
         }
     }
-
-    if (tconn->kstc_type == kstt_child) {
-        tconn->child.kstc_parent = parent;
-    }
-
-    tconn->kstc_state = ksts_bind;
-    tconn->kstc_addr  = taddr;
-
-errorout:
-
-    return (rc);
 }
 
 /*
- * ks_build_tconn
- *  build tcp/streaming connection to remote peer
+ * ks_destroy_tconn
+ *   cleanup the tdi connection and free it
  *
  * Arguments:
- *   tconn:    tconn to be connected to the peer
- *   addr:     the peer's ip address
- *   port:     the peer's port number
+ *   tconn: the tdi connection to be cleaned.
  *
  * Return Value:
- *   int:   0 for success or ks error codes.
+ *   N/A
  *
- * Notes:
+ * NOTES:
  *   N/A
  */
 
-int
-ks_build_tconn(
-    ksock_tconn_t *                 tconn,
-    ulong_ptr                       addr,
-    unsigned short                  port
+void
+ks_destroy_tconn(
+    ks_tconn_t *     tconn
     )
 {
-    int                             rc = 0;
-    NTSTATUS                        status = STATUS_SUCCESS;
-
+    LASSERT(tconn->kstc_refcount.counter == 0);
 
-    PFILE_OBJECT                    ConnectionObject = NULL;
-    PDEVICE_OBJECT                  DeviceObject = NULL;
+    if (tconn->kstc_type == kstt_listener) {
 
-    PTDI_CONNECTION_INFORMATION     ConnectionInfo = NULL;
-    ULONG                           AddrLength;
+        KsResetHandlers(tconn);
 
-    PIRP                            Irp = NULL;
+        /* for listener, we just need to close the address object */
+        KsCloseAddress(
+                tconn->kstc_addr.Handle,
+                tconn->kstc_addr.FileObject
+                );
 
-    LASSERT(tconn->kstc_type == kstt_sender);
-    LASSERT(tconn->kstc_state == ksts_bind);
+        tconn->kstc_state = ksts_inited;
 
-    ks_get_tconn(tconn);
+    } else if (tconn->kstc_type == kstt_child) {
 
-    {
-        /* set the event callbacks */
-        rc = ks_set_handlers(tconn);
+        /* for child tdi conections */
 
-        if (rc < 0) {
-            cfs_enter_debugger();
-            goto errorout;
-        }
-    }
+        /* disassociate the relation between it's connection object
+           and the address object */
 
-    /* create the connection file handle / object  */
-    status = KsOpenConnection(
-                &(tconn->kstc_dev),
-                (CONNECTION_CONTEXT)tconn,
-                &(tconn->sender.kstc_info.Handle),
-                &(tconn->sender.kstc_info.FileObject)
+        if (tconn->kstc_state == ksts_associated) {
+            KsDisassociateAddress(
+                tconn->child.kstc_info.FileObject
                 );
+        }
 
-    if (!NT_SUCCESS(status)) {
-        rc = cfs_error_code(status);
-        cfs_enter_debugger();
-        goto errorout;
-    }
-
-    /* associdate the the connection with the adress object of the tconn */
+        /* release the connection object */
 
-    status = KsAssociateAddress(
-                tconn->kstc_addr.Handle,
-                tconn->sender.kstc_info.FileObject
+        KsCloseConnection(
+                tconn->child.kstc_info.Handle,
+                tconn->child.kstc_info.FileObject
                 );
 
-    if (!NT_SUCCESS(status)) {
-        rc = cfs_error_code(status);
-        cfs_enter_debugger();
-        goto errorout;
-    }
-
-    tconn->kstc_state = ksts_associated;
+        /* release it's refer of it's parent's address object */
+        KsCloseAddress(
+                NULL,
+                tconn->kstc_addr.FileObject
+                );
 
-    /* Allocating Connection Info Together with the Address */
-    AddrLength = FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address)
-                 + TDI_ADDRESS_LENGTH_IP;
+        cfs_spin_lock(&tconn->child.kstc_parent->kstc_lock);
+        cfs_spin_lock(&tconn->kstc_lock);
 
-    ConnectionInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(
-    NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) + AddrLength, 'iCsK');
+        tconn->kstc_state = ksts_inited;
 
-    if (NULL == ConnectionInfo) {
+        /* remove it frome it's parent's queues */
 
-        status = STATUS_INSUFFICIENT_RESOURCES;
-        rc = cfs_error_code(status);
-        cfs_enter_debugger();
-        goto errorout;
-    }
+        if (tconn->child.kstc_queued) {
 
-    /* Initializing ConnectionInfo ... */
-    {
-        PTRANSPORT_ADDRESS TdiAddress;
+            cfs_list_del(&(tconn->child.kstc_link));
 
-        /* ConnectionInfo settings */
+            if (tconn->child.kstc_queueno) {
 
-        ConnectionInfo->UserDataLength = 0;
-        ConnectionInfo->UserData = NULL;
-        ConnectionInfo->OptionsLength = 0;
-        ConnectionInfo->Options = NULL;
-        ConnectionInfo->RemoteAddressLength = AddrLength;
-        ConnectionInfo->RemoteAddress = ConnectionInfo + 1;
+                LASSERT(tconn->child.kstc_parent->listener.kstc_accepted.num > 0);
+                tconn->child.kstc_parent->listener.kstc_accepted.num -= 1;
 
+            } else {
 
-        /* intialize the tdi address*/
+                LASSERT(tconn->child.kstc_parent->listener.kstc_listening.num > 0);
+                tconn->child.kstc_parent->listener.kstc_listening.num -= 1;
+            }
 
-        TdiAddress = ConnectionInfo->RemoteAddress;
+            tconn->child.kstc_queued = FALSE;
+        }
 
-        TdiAddress->TAAddressCount = 1;
-        TdiAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
-        TdiAddress->Address[0].AddressType   = TDI_ADDRESS_TYPE_IP;
+        cfs_spin_unlock(&tconn->kstc_lock);
+        cfs_spin_unlock(&tconn->child.kstc_parent->kstc_lock);
 
-        ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_port = htons(port);
-        ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->in_addr = htonl(addr);
+        /* drop the reference of the parent tconn */
+        ks_put_tconn(tconn->child.kstc_parent);
 
-        memset(&(((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_zero[0]),0,8);
-    }
+    } else if (tconn->kstc_type == kstt_sender) {
 
-    /* Now prepare to connect the remote peer ... */
+        KsResetHandlers(tconn);
 
-    ConnectionObject = tconn->sender.kstc_info.FileObject;
-    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
+        /* release the connection object */
 
-    /* allocate a new Irp */
+        KsCloseConnection(
+                tconn->sender.kstc_info.Handle,
+                tconn->sender.kstc_info.FileObject
+                );
 
-    Irp = KsBuildTdiIrp(DeviceObject);
+        /* release it's refer of it's parent's address object */
+        KsCloseAddress(
+                tconn->kstc_addr.Handle,
+                tconn->kstc_addr.FileObject
+                );
 
-    if (NULL == Irp) {
+        tconn->kstc_state = ksts_inited;
 
-        status = STATUS_INSUFFICIENT_RESOURCES;
-        rc = cfs_error_code(status);
+    } else {
         cfs_enter_debugger();
-        goto errorout;
     }
 
-    /* setup the Irp */
+    /* free the tconn structure ... */
 
-    TdiBuildConnect(
-            Irp,
-            DeviceObject,
-            ConnectionObject,
-            NULL,
-            NULL,
-            NULL,
-            ConnectionInfo,
-            NULL
-            );
+    ks_free_tconn(tconn);
+}
 
+/*
+ * ks_get_tcp_option
+ *   Query the the options of the tcp stream connnection
+ *
+ * Arguments:
+ *   tconn:         the tdi connection
+ *   ID:            option id
+ *   OptionValue:   buffer to store the option value
+ *   Length:        the length of the value, to be returned
+ *
+ * Return Value:
+ *   int:           ks return code
+ *
+ * NOTES:
+ *   N/A
+ */
 
-    /* sumbit the Irp to the underlying transport driver */
-    status = KsSubmitTdiIrp(
-                    DeviceObject,
-                    Irp,
-                    TRUE,
-                    NULL
-                    );
+int
+ks_get_tcp_option (
+    ks_tconn_t *        tconn,
+    ULONG               ID,
+    PVOID               OptionValue,
+    PULONG              Length
+    )
+{
+    NTSTATUS            Status = STATUS_SUCCESS;
 
-    spin_lock(&(tconn->kstc_lock));
+    IO_STATUS_BLOCK     IoStatus;
 
-    if (NT_SUCCESS(status)) {
+    TCP_REQUEST_QUERY_INFORMATION_EX QueryInfoEx;
 
-        /* Connected! the conneciton is built successfully. */
+    PFILE_OBJECT        ConnectionObject;
+    PDEVICE_OBJECT      DeviceObject = NULL;
 
-        tconn->kstc_state = ksts_connected;
+    PIRP                Irp = NULL;
+    PIO_STACK_LOCATION  IrpSp = NULL;
 
-        tconn->sender.kstc_info.ConnectionInfo = ConnectionInfo;
-        tconn->sender.kstc_info.Remote         = ConnectionInfo->RemoteAddress;
+    KEVENT              Event;
+
+    /* make sure the tdi connection is connected ? */
 
-        spin_unlock(&(tconn->kstc_lock));
+    ks_get_tconn(tconn);
+
+    if (tconn->kstc_state != ksts_connected) {
+        Status = STATUS_INVALID_PARAMETER;
+        goto errorout;
+    }
+
+    LASSERT(tconn->kstc_type == kstt_sender ||
+           tconn->kstc_type == kstt_child);
 
+    if (tconn->kstc_type == kstt_sender) {
+        ConnectionObject = tconn->sender.kstc_info.FileObject;
     } else {
+        ConnectionObject = tconn->child.kstc_info.FileObject;
+    }
 
-        /* Not connected! Abort it ... */
+    QueryInfoEx.ID.toi_id = ID;
+    QueryInfoEx.ID.toi_type   = INFO_TYPE_CONNECTION;
+    QueryInfoEx.ID.toi_class  = INFO_CLASS_PROTOCOL;
+    QueryInfoEx.ID.toi_entity.tei_entity   = CO_TL_ENTITY;
+    QueryInfoEx.ID.toi_entity.tei_instance = 0;
 
-        if (rc != 0) {
-            cfs_enter_debugger();
-        }
+    RtlZeroMemory(&(QueryInfoEx.Context), CONTEXT_SIZE);
 
-        Irp = NULL;
-        rc = cfs_error_code(status);
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
 
-        tconn->kstc_state = ksts_associated;
-        spin_unlock(&(tconn->kstc_lock));
+    Irp = IoBuildDeviceIoControlRequest(
+                IOCTL_TCP_QUERY_INFORMATION_EX,
+                DeviceObject,
+                &QueryInfoEx,
+                sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
+                OptionValue,
+                *Length,
+                FALSE,
+                &Event,
+                &IoStatus
+                );
 
-        /* disassocidate the connection and the address object,
-           after cleanup,  it's safe to set the state to abort ... */
+    if (Irp == NULL) {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto errorout;
+    }
 
-        if ( NT_SUCCESS(KsDisassociateAddress(
-                        tconn->sender.kstc_info.FileObject))) {
-            tconn->kstc_state = ksts_aborted;
-        }
+    IrpSp = IoGetNextIrpStackLocation(Irp);
 
-        /* reset the event callbacks */
-        rc = ks_reset_handlers(tconn);
+    if (IrpSp == NULL) {
 
+        IoFreeIrp(Irp);
+        Irp = NULL;
+        Status = STATUS_INSUFFICIENT_RESOURCES;
         goto errorout;
     }
 
-errorout:
+    IrpSp->FileObject = ConnectionObject;
+    IrpSp->DeviceObject = DeviceObject;
 
-    if (NT_SUCCESS(status)) {
+    Status = IoCallDriver(DeviceObject, Irp);
 
-        ks_query_local_ipaddr(tconn);
+    if (Status == STATUS_PENDING) {
 
-    } else {
+        KeWaitForSingleObject(
+                &Event,
+                Executive,
+                KernelMode,
+                FALSE,
+                NULL
+                );
 
-        if (ConnectionInfo) {
-            ExFreePool(ConnectionInfo);
-        }
-        if (Irp) {
-            IoFreeIrp(Irp);
-        }
+        Status = IoStatus.Status;
+    }
+
+
+    if (NT_SUCCESS(Status)) {
+        *Length = (ULONG)(ULONG_PTR)IoStatus.Information;
+    } else {
+        cfs_enter_debugger();
+        memset(OptionValue, 0, *Length);
+        Status = STATUS_SUCCESS;
     }
 
+errorout:
+
     ks_put_tconn(tconn);
 
-    return (rc);
+    return cfs_error_code(Status);
 }
 
-
 /*
- * ks_disconnect_tconn
- *   disconnect the tconn from a connection
+ * ks_set_tcp_option
+ *   Set the the options for the tcp stream connnection
  *
  * Arguments:
- *   tconn: the tdi connecton object connected already
- *   flags: flags & options for disconnecting
+ *   tconn:     the tdi connection
+ *   ID:        option id
+ *   OptionValue: buffer containing the new option value
+ *   Length:    the length of the value
  *
  * Return Value:
- *   int: ks error code
+ *   int:       ks return code
  *
- * Notes:
+ * NOTES:
  *   N/A
  */
 
-int
-ks_disconnect_tconn(
-    ksock_tconn_t *     tconn,
-    ulong_ptr       flags
+NTSTATUS
+ks_set_tcp_option (
+    ks_tconn_t *    tconn,
+    ULONG           ID,
+    PVOID           OptionValue,
+    ULONG           Length
     )
 {
-    NTSTATUS            status = STATUS_SUCCESS;
+    NTSTATUS            Status = STATUS_SUCCESS;
+
+    IO_STATUS_BLOCK     IoStatus;
 
-    ksock_tconn_info_t * info;
+    ULONG               SetInfoExLength;
+    PTCP_REQUEST_SET_INFORMATION_EX SetInfoEx = NULL;
 
     PFILE_OBJECT        ConnectionObject;
     PDEVICE_OBJECT      DeviceObject = NULL;
 
     PIRP                Irp = NULL;
+    PIO_STACK_LOCATION  IrpSp = NULL;
 
-    KEVENT              Event;
-
-    ks_get_tconn(tconn);
-
-    /* make sure tt's connected already and it
-       must be a sender or a child ...       */
+    PKEVENT             Event;
 
-    LASSERT(tconn->kstc_state == ksts_connected);
-    LASSERT( tconn->kstc_type == kstt_sender ||
-            tconn->kstc_type == kstt_child);
+    /* make sure the tdi connection is connected ? */
 
-    /* reset all the event handlers to NULL */
+    ks_get_tconn(tconn);
 
-    if (tconn->kstc_type != kstt_child) {
-        ks_reset_handlers (tconn);
+    if (tconn->kstc_state != ksts_connected) {
+        Status = STATUS_INVALID_PARAMETER;
+        goto errorout;
     }
 
-    /* Disconnecting to the remote peer ... */
+    LASSERT(tconn->kstc_type == kstt_sender ||
+           tconn->kstc_type == kstt_child);
 
     if (tconn->kstc_type == kstt_sender) {
-        info = &(tconn->sender.kstc_info);
+        ConnectionObject = tconn->sender.kstc_info.FileObject;
     } else {
-        info = &(tconn->child.kstc_info);
+        ConnectionObject = tconn->child.kstc_info.FileObject;
     }
 
-    ConnectionObject = info->FileObject;
-    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
-
-    /* allocate an Irp and setup it */
-
-    Irp = KsBuildTdiIrp(DeviceObject);
+    SetInfoExLength =  sizeof(TCP_REQUEST_SET_INFORMATION_EX) - 1 + Length + sizeof(KEVENT);
 
-    if (NULL == Irp) {
+    SetInfoEx = ExAllocatePoolWithTag(
+                    NonPagedPool,
+                    SetInfoExLength,
+                    'TSSK'
+                    );
 
-        status = STATUS_INSUFFICIENT_RESOURCES;
-        cfs_enter_debugger();
+    if (SetInfoEx == NULL) {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
         goto errorout;
     }
 
-    KeInitializeEvent(
-            &Event,
-            SynchronizationEvent,
-            FALSE
-            );
-
-    TdiBuildDisconnect(
-            Irp,
-            DeviceObject,
-            ConnectionObject,
-            KsDisconectCompletionRoutine,
-            &Event,
-            NULL,
-            flags,
-            NULL,
-            NULL
-            );
-
-    /* issue the Irp to the underlying transport
-       driver to disconnect the connection    */
+    SetInfoEx->ID.toi_id = ID;
 
-    status = IoCallDriver(DeviceObject, Irp);
+    SetInfoEx->ID.toi_type  = INFO_TYPE_CONNECTION;
+    SetInfoEx->ID.toi_class = INFO_CLASS_PROTOCOL;
+    SetInfoEx->ID.toi_entity.tei_entity   = CO_TL_ENTITY;
+    SetInfoEx->ID.toi_entity.tei_instance = TL_INSTANCE;
 
-    if (STATUS_PENDING == status) {
+    SetInfoEx->BufferSize = Length;
+    RtlCopyMemory(&(SetInfoEx->Buffer[0]), OptionValue, Length);
 
-        status = KeWaitForSingleObject(
-                     &Event,
-                     Executive,
-                     KernelMode,
-                     FALSE,
-                     NULL
-                     );
+    Event = (PKEVENT)(&(SetInfoEx->Buffer[Length]));
+    KeInitializeEvent(Event, NotificationEvent, FALSE);
 
-        status = Irp->IoStatus.Status;
-    }
+    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
 
-    KsPrint((2, "KsDisconnect: Disconnection is done with Status = %xh (%s) ...\n",
-                status, KsNtStatusToString(status)));
+    Irp = IoBuildDeviceIoControlRequest(
+                IOCTL_TCP_SET_INFORMATION_EX,
+                DeviceObject,
+                SetInfoEx,
+                SetInfoExLength,
+                NULL,
+                0,
+                FALSE,
+                Event,
+                &IoStatus
+                );
 
-    IoFreeIrp(Irp);
+    if (Irp == NULL) {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto errorout;
+    }
 
-    if (info->ConnectionInfo) {
+    IrpSp = IoGetNextIrpStackLocation(Irp);
 
-        /* disassociate the association between connection/address objects */
+    if (IrpSp == NULL) {
+        IoFreeIrp(Irp);
+        Irp = NULL;
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto errorout;
+    }
 
-        status = KsDisassociateAddress(ConnectionObject);
+    IrpSp->FileObject = ConnectionObject;
+    IrpSp->DeviceObject = DeviceObject;
 
-        if (!NT_SUCCESS(status)) {
-            cfs_enter_debugger();
-        }
+    Status = IoCallDriver(DeviceObject, Irp);
 
-        spin_lock(&(tconn->kstc_lock));
+    if (Status == STATUS_PENDING) {
 
-        /* cleanup the tsdumgr Lists */
-        KsCleanupTsdu (tconn);
+        KeWaitForSingleObject(
+                Event,
+                Executive,
+                KernelMode,
+                FALSE,
+                NULL
+                );
 
-        /* set the state of the tconn */
-        if (NT_SUCCESS(status)) {
-            tconn->kstc_state = ksts_disconnected;
-        } else {
-            tconn->kstc_state = ksts_associated;
-        }
+        Status = IoStatus.Status;
+    }
 
-        /* free  the connection info to system pool*/
-        ExFreePool(info->ConnectionInfo);
-        info->ConnectionInfo = NULL;
-        info->Remote = NULL;
+errorout:
 
-        spin_unlock(&(tconn->kstc_lock));
+    if (SetInfoEx) {
+        ExFreePool(SetInfoEx);
     }
 
-    status = STATUS_SUCCESS;
-
-errorout:
+    if (!NT_SUCCESS(Status)) {
+        KsPrint((0, "ks_set_tcp_option: error setup tcp option: "
+                    "ID (%d) Status = %xh\n", ID, Status));
+        Status = STATUS_SUCCESS;
+    }
 
     ks_put_tconn(tconn);
 
-    return cfs_error_code(status);
+    return cfs_error_code(Status);
 }
 
-
 /*
- * ks_abort_tconn
- *   The connection is broken un-expectedly. We need do
- *   some cleanup.
+ * ks_bind_tconn
+ *   bind the tdi connection object with an address
  *
  * Arguments:
- *   tconn: the tdi connection
+ *   tconn:    tconn to be bound
+ *   parent:   the parent tconn object
+ *   ipaddr:   the ip address
+ *   port:     the port number
  *
  * Return Value:
- *   N/A
+ *   int:   0 for success or ks error codes.
  *
- * Notes:
+ * NOTES:
  *   N/A
  */
 
-void
-ks_abort_tconn(
-    ksock_tconn_t *     tconn
+int
+ks_bind_tconn (
+    ks_tconn_t *    tconn,
+    ks_tconn_t *    parent,
+    ulong           addr,
+    unsigned short  port
     )
 {
-    PKS_DISCONNECT_WORKITEM WorkItem = NULL;
+    NTSTATUS            status;
+    int                 rc = 0;
 
-    WorkItem = &(tconn->kstc_disconnect);
+    ks_tdi_addr_t    taddr;
 
-    ks_get_tconn(tconn);
-    spin_lock(&(tconn->kstc_lock));
+    memset(&taddr, 0, sizeof(ks_tdi_addr_t));
 
-    if (tconn->kstc_state != ksts_connected) {
-        ks_put_tconn(tconn);
-    } else {
+    if (tconn->kstc_state != ksts_inited) {
 
-        if (!cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY)) {
+        status = STATUS_INVALID_PARAMETER;
+        rc = cfs_error_code(status);
+        goto errorout;
 
-            WorkItem->Flags = TDI_DISCONNECT_ABORT;
-            WorkItem->tconn = tconn;
+    } else if (tconn->kstc_type == kstt_child) {
 
-            cfs_set_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
+        if (NULL == parent) {
+            status = STATUS_INVALID_PARAMETER;
+            rc = cfs_error_code(status);
 
-            ExQueueWorkItem(
-                    &(WorkItem->WorkItem),
-                    DelayedWorkQueue
-                    );
+            goto errorout;
         }
-    }
 
-    spin_unlock(&(tconn->kstc_lock));
-}
+        /* refer it's parent's address object */
 
+        taddr = parent->kstc_addr;
+        ObReferenceObject(taddr.FileObject);
 
-/*
- * ks_query_local_ipaddr
- *   query the local connection ip address
- *
- * Arguments:
- *   tconn:  the tconn which is connected
- *
- * Return Value:
- *   int: ks error code
- *
- * Notes:
- *   N/A
- */
+        ks_get_tconn(parent);
 
-int
-ks_query_local_ipaddr(
-    ksock_tconn_t *     tconn
-    )
-{
-    PFILE_OBJECT    FileObject = NULL;
-    NTSTATUS        status;
+    } else {
 
-    PTRANSPORT_ADDRESS TdiAddress;
-    ULONG              AddressLength;
+        PTRANSPORT_ADDRESS TdiAddress = &(taddr.Tdi);
+        ULONG              AddrLen = 0;
 
-    if (tconn->kstc_type == kstt_sender) {
-        FileObject = tconn->sender.kstc_info.FileObject;
-    } else if (tconn->kstc_type == kstt_child) {
-        FileObject = tconn->child.kstc_info.FileObject;
-    } else {
-        status = STATUS_INVALID_PARAMETER;
-        goto errorout;
-    }
+        /* intialize the tdi address*/
 
-    TdiAddress = &(tconn->kstc_addr.Tdi);
-    AddressLength = MAX_ADDRESS_LENGTH;
+        TdiAddress->TAAddressCount = 1;
+        TdiAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
+        TdiAddress->Address[0].AddressType   = TDI_ADDRESS_TYPE_IP;
 
-    status =  KsQueryIpAddress(FileObject, TdiAddress, &AddressLength);
+        ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_port = htons(port);
+        ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->in_addr = (ULONG)htonl(addr);
 
-    if (NT_SUCCESS(status)) {
+        memset(&(((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_zero[0]),0,8);
 
-        KsPrint((0, "ks_query_local_ipaddr: Local ip address = %xh port = %xh\n",
-                ((PTDI_ADDRESS_IP)(&(TdiAddress->Address[0].Address)))->in_addr,
-                ((PTDI_ADDRESS_IP)(&(TdiAddress->Address[0].Address)))->sin_port ));
-    } else {
-        KsPrint((0, "KsQueryonnectionIpAddress: Failed to query the connection local ip address.\n"));
+
+        /* open the transport address object */
+
+        AddrLen = FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address) +
+                  TDI_ADDRESS_LENGTH_IP;
+
+        status = KsOpenAddress(
+                    &(tconn->kstc_dev),
+                    &(taddr.Tdi),
+                    AddrLen,
+                    &(taddr.Handle),
+                    &(taddr.FileObject)
+                    );
+
+        if (!NT_SUCCESS(status)) {
+
+            KsPrint((1, "ks_bind_tconn: failed to open ip addr object (%x:%d), status = %xh\n",
+                        addr, port,  status ));
+            rc = cfs_error_code(status);
+            goto errorout;
+        }
+    }
+
+    if (tconn->kstc_type == kstt_child) {
+        tconn->child.kstc_parent = parent;
     }
 
+    tconn->kstc_state = ksts_bind;
+    tconn->kstc_addr  = taddr;
+
 errorout:
 
-    return cfs_error_code(status);
+    return (rc);
 }
 
 /*
- * ks_send_mdl
- *   send MDL chain to the peer for a stream connection
+ * ks_build_tconn
+ *  build tcp/streaming connection to remote peer
  *
  * Arguments:
- *   tconn: tdi connection object
- *   tx:    the transmit context
- *   mdl:   the mdl chain containing the data
- *   len:   length of the data
- *   flags: flags of the transmission
+ *   tconn:    tconn to be connected to the peer
+ *   addr:     the peer's ip address
+ *   port:     the peer's port number
  *
  * Return Value:
- *   ks return code
+ *   int:   0 for success or ks error codes.
  *
  * Notes:
  *   N/A
  */
 
 int
-ks_send_mdl(
-    ksock_tconn_t * tconn,
-    void *          tx,
-    ksock_mdl_t *   mdl,
-    int             len,
-    int             flags
+ks_build_tconn(
+    ks_tconn_t *                    tconn,
+    ulong                           addr,
+    unsigned short                  port
     )
 {
-    NTSTATUS            Status;
-    int                 rc = 0;
-    ulong_ptr       length;
-    ulong_ptr       tflags;
-    ksock_tdi_tx_t *    context;
+    int                             rc = 0;
+    NTSTATUS                        status = STATUS_SUCCESS;
 
-    PKS_CHAIN           KsChain;
-    PKS_TSDUMGR         KsTsduMgr;
-    PKS_TSDU            KsTsdu;
-    PKS_TSDU_BUF        KsTsduBuf;
-    PKS_TSDU_DAT        KsTsduDat;
 
-    BOOLEAN             bNewTsdu = FALSE;   /* newly allocated */
-    BOOLEAN             bNewBuff = FALSE;   /* newly allocated */
+    PFILE_OBJECT                    ConnectionObject = NULL;
+    PDEVICE_OBJECT                  DeviceObject = NULL;
+
+    PTDI_CONNECTION_INFORMATION     ConnectionInfo = NULL;
+    ULONG                           AddrLength;
+
+    PIRP                            Irp = NULL;
+
+    LASSERT(tconn->kstc_type == kstt_sender);
+    LASSERT(tconn->kstc_state == ksts_bind);
+
+    ks_get_tconn(tconn);
+
+    {
+        /* set the event callbacks */
+        rc = KsSetHandlers(tconn);
+
+        if (rc < 0) {
+            cfs_enter_debugger();
+            goto errorout;
+        }
+    }
+
+    /* create the connection file handle / object  */
+    status = KsOpenConnection(
+                &(tconn->kstc_dev),
+                (CONNECTION_CONTEXT)tconn,
+                &(tconn->sender.kstc_info.Handle),
+                &(tconn->sender.kstc_info.FileObject)
+                );
 
-    BOOLEAN             bBuffed;            /* bufferred sending */
+    if (!NT_SUCCESS(status)) {
+        rc = cfs_error_code(status);
+        cfs_enter_debugger();
+        goto errorout;
+    }
 
-    PUCHAR              Buffer = NULL;
-    ksock_mdl_t *       NewMdl = NULL;
+    /* associdate the the connection with the adress object of the tconn */
 
-    PIRP                Irp = NULL;
-    PFILE_OBJECT        ConnObject;
-    PDEVICE_OBJECT      DeviceObject;
+    status = KsAssociateAddress(
+                tconn->kstc_addr.Handle,
+                tconn->sender.kstc_info.FileObject
+                );
 
-    BOOLEAN             bIsNonBlock;
+    if (!NT_SUCCESS(status)) {
+        rc = cfs_error_code(status);
+        cfs_enter_debugger();
+        goto errorout;
+    }
 
-    ks_get_tconn(tconn);
+    tconn->kstc_state = ksts_associated;
 
-    tflags = ks_tdi_send_flags(flags);
-    bIsNonBlock  = cfs_is_flag_set(flags, MSG_DONTWAIT);
+    /* Allocating Connection Info Together with the Address */
+    AddrLength = FIELD_OFFSET(TRANSPORT_ADDRESS, Address->Address)
+                 + TDI_ADDRESS_LENGTH_IP;
 
-    spin_lock(&tconn->kstc_lock);
+    ConnectionInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(
+    NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) + AddrLength, 'iCsK');
 
-    LASSERT( tconn->kstc_type == kstt_sender ||
-             tconn->kstc_type == kstt_child );
+    if (NULL == ConnectionInfo) {
 
-    if (tconn->kstc_state != ksts_connected) {
-        spin_unlock(&tconn->kstc_lock);
-        ks_put_tconn(tconn);
-        return -ENOTCONN;
+        status = STATUS_INSUFFICIENT_RESOURCES;
+        rc = cfs_error_code(status);
+        cfs_enter_debugger();
+        goto errorout;
     }
 
-    /* get the latest Tsdu buffer form TsduMgr list.
-       just set NULL if the list is empty. */
-
-    if (tconn->kstc_type == kstt_sender) {
-        KsChain = &(tconn->sender.kstc_send);
-    } else {
-        LASSERT(tconn->kstc_type == kstt_child);
-        KsChain = &(tconn->child.kstc_send);
-    }
+    /* Initializing ConnectionInfo ... */
+    {
+        PTRANSPORT_ADDRESS TdiAddress;
 
-    if (cfs_is_flag_set(tflags, TDI_SEND_EXPEDITED)) {
-        KsTsduMgr = &(KsChain->Expedited);
-    } else {
-        KsTsduMgr = &(KsChain->Normal);
-    }
+        /* ConnectionInfo settings */
 
-    if (KsTsduMgr->TotalBytes + len <= tconn->kstc_snd_wnd) {
-        bBuffed = TRUE;
-    } else {
-        bBuffed = FALSE;
-    }
+        ConnectionInfo->UserDataLength = 0;
+        ConnectionInfo->UserData = NULL;
+        ConnectionInfo->OptionsLength = 0;
+        ConnectionInfo->Options = NULL;
+        ConnectionInfo->RemoteAddressLength = AddrLength;
+        ConnectionInfo->RemoteAddress = ConnectionInfo + 1;
 
-    /* do the preparation work for bufferred sending */
 
-    if (bBuffed) {
+        /* intialize the tdi address*/
 
-        /* if the data is even larger than the biggest Tsdu, we have
-           to allocate new buffer and use TSDU_TYOE_BUF to store it */
+        TdiAddress = ConnectionInfo->RemoteAddress;
 
-        if ( KS_TSDU_STRU_SIZE((ULONG)len) > ks_data.ksnd_tsdu_size
-             - KS_DWORD_ALIGN(sizeof(KS_TSDU))) {
-            bNewBuff = TRUE;
-        }
+        TdiAddress->TAAddressCount = 1;
+        TdiAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
+        TdiAddress->Address[0].AddressType   = TDI_ADDRESS_TYPE_IP;
 
-        if (list_empty(&(KsTsduMgr->TsduList))) {
+        ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_port = htons(port);
+        ((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->in_addr = (ULONG)htonl(addr);
 
-            LASSERT(KsTsduMgr->NumOfTsdu == 0);
-            KsTsdu = NULL;
+        memset(&(((PTDI_ADDRESS_IP)&(TdiAddress->Address[0].Address))->sin_zero[0]),0,8);
+    }
 
-        } else {
+    /* Now prepare to connect the remote peer ... */
 
-            LASSERT(KsTsduMgr->NumOfTsdu > 0);
-            KsTsdu = list_entry(KsTsduMgr->TsduList.prev, KS_TSDU, Link);
-            LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
+    ConnectionObject = tconn->sender.kstc_info.FileObject;
+    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
 
+    /* allocate a new Irp */
 
-            /* check whether KsTsdu free space is enough, or we need alloc new Tsdu */
-            if (bNewBuff) {
-                if (sizeof(KS_TSDU_BUF) + KsTsdu->LastOffset > KsTsdu->TotalLength) {
-                    KsTsdu = NULL;
-                }
-            } else {
-                if ( KS_TSDU_STRU_SIZE((ULONG)len) >
-                     KsTsdu->TotalLength - KsTsdu->LastOffset ) {
-                    KsTsdu = NULL;
-                }
-            }
-        }
+    Irp = KsBuildTdiIrp(DeviceObject);
 
-        /* if there's no Tsdu or the free size is not enough for the
-           KS_TSDU_BUF or KS_TSDU_DAT. We need re-allocate a new Tsdu.  */
+    if (NULL == Irp) {
 
-        if (NULL == KsTsdu) {
+        status = STATUS_INSUFFICIENT_RESOURCES;
+        rc = cfs_error_code(status);
+        cfs_enter_debugger();
+        goto errorout;
+    }
 
-            KsTsdu = KsAllocateKsTsdu();
+    /* setup the Irp */
 
-            if (NULL == KsTsdu) {
-                bBuffed = FALSE;
-                bNewBuff = FALSE;
-            } else {
-                bNewTsdu = TRUE;
-            }
-        }
+    TdiBuildConnect(
+            Irp,
+            DeviceObject,
+            ConnectionObject,
+            NULL,
+            NULL,
+            NULL,
+            ConnectionInfo,
+            NULL
+            );
 
-        /* process the case that a new buffer is to be allocated from system memory */
-        if (bNewBuff) {
 
-            /* now allocating internal buffer to contain the payload */
-            Buffer = ExAllocatePool(NonPagedPool, len);
+    /* sumbit the Irp to the underlying transport driver */
+    status = KsSubmitTdiIrp(
+                    DeviceObject,
+                    Irp,
+                    TRUE,
+                    NULL
+                    );
 
-            if (NULL == Buffer) {
-                bBuffed = FALSE;
-            }
-        }
-    }
+    cfs_spin_lock(&(tconn->kstc_lock));
 
-    if (bBuffed) {
+    if (NT_SUCCESS(status)) {
 
-        if (bNewBuff) {
+        /* Connected! the conneciton is built successfully. */
 
-            /* queue a new KS_TSDU_BUF to the Tsdu buffer */
-            KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
+        tconn->kstc_state = ksts_connected;
 
-            KsTsduBuf->TsduFlags    =  0;
-            KsTsduBuf->DataLength   =  (ULONG)len;
-            KsTsduBuf->StartOffset  =  0;
-            KsTsduBuf->UserBuffer   =  Buffer;
-        } else {
-            /* queue a new KS_TSDU_BUF to the Tsdu buffer */
-            KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->LastOffset);
+        tconn->sender.kstc_info.ConnectionInfo = ConnectionInfo;
+        tconn->sender.kstc_info.Remote         = ConnectionInfo->RemoteAddress;
 
-            KsTsduDat->TsduFlags    =  0;
-            KsTsduDat->DataLength   =  (ULONG)len;
-            KsTsduDat->StartOffset  =  0;
-            KsTsduDat->TotalLength  = KS_TSDU_STRU_SIZE((ULONG)len);
+        cfs_spin_unlock(&(tconn->kstc_lock));
 
-            Buffer = &KsTsduDat->Data[0];
-        }
+    } else {
 
-        /* now locking the Buffer and copy user payload into the buffer */
-        ASSERT(Buffer != NULL);
+        /* Not connected! Abort it ... */
 
-        rc = ks_lock_buffer(Buffer, FALSE, len, IoReadAccess, &NewMdl);
         if (rc != 0) {
-            printk("ks_send_mdl: bufferred: error allocating mdl.\n");
-            bBuffed = FALSE;
-        } else {
-            ULONG BytesCopied = 0;
-            TdiCopyMdlToBuffer(mdl, 0, Buffer, 0, (ULONG)len, &BytesCopied);
-            if (BytesCopied != (ULONG) len) {
-                bBuffed = FALSE;
-            }
+            cfs_enter_debugger();
         }
 
-        /* Do the finializing job if we succeed to to lock the buffer and move
-           user data. Or we need do cleaning up ... */
-        if (bBuffed) {
+        Irp = NULL;
+        rc = cfs_error_code(status);
 
-            if (bNewBuff) {
-                KsTsduBuf->TsduType     =  TSDU_TYPE_BUF;
-                KsTsdu->LastOffset += sizeof(KS_TSDU_BUF);
+        tconn->kstc_state = ksts_associated;
+        cfs_spin_unlock(&(tconn->kstc_lock));
 
-            } else {
-                KsTsduDat->TsduType     =  TSDU_TYPE_DAT;
-                KsTsdu->LastOffset += KsTsduDat->TotalLength;
-            }
+        /* disassocidate the connection and the address object,
+           after cleanup,  it's safe to set the state to abort ... */
 
-            /* attach it to the TsduMgr list if the Tsdu is newly created. */
-            if (bNewTsdu) {
+        if ( NT_SUCCESS(KsDisassociateAddress(
+                        tconn->sender.kstc_info.FileObject))) {
+            tconn->kstc_state = ksts_aborted;
+        }
 
-                list_add_tail(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
-                KsTsduMgr->NumOfTsdu++;
-            }
+        /* reset the event callbacks */
+        rc = KsResetHandlers(tconn);
 
-        } else {
+        goto errorout;
+    }
 
-            if (NewMdl) {
-                ks_release_mdl(NewMdl, FALSE);
-                NewMdl = NULL;
-            }
+errorout:
 
-            if (bNewBuff) {
-                ExFreePool(Buffer);
-                Buffer = NULL;
-                bNewBuff = FALSE;
-            }
-        }
-    }
+    if (NT_SUCCESS(status)) {
 
-    /* update the TotalBytes being in sending */
-    KsTsduMgr->TotalBytes += (ULONG)len;
+        ks_query_local_ipaddr(tconn);
 
-    spin_unlock(&tconn->kstc_lock);
+    } else {
 
-    /* cleanup the Tsdu if not successful */
-    if (!bBuffed && bNewTsdu) {
-        KsPutKsTsdu(KsTsdu);
-        bNewTsdu = FALSE;
-        KsTsdu = NULL;
+        if (ConnectionInfo) {
+            ExFreePool(ConnectionInfo);
+        }
+        if (Irp) {
+            IoFreeIrp(Irp);
+        }
     }
 
-    /* we need allocate the ksock_tx_t structure from memory pool. */
+    ks_put_tconn(tconn);
 
-    context = cfs_alloc(sizeof(ksock_tdi_tx_t) + sizeof(KEVENT),0);
-    if (!context) {
-        /* release the chained mdl */
-        ks_release_mdl(mdl, FALSE);
+    return (rc);
+}
 
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto errorout;
-    }
 
-    /* intialize the TcpContext */
+/*
+ * ks_disconnect_tconn
+ *   disconnect the tconn from a connection
+ *
+ * Arguments:
+ *   tconn: the tdi connecton object connected already
+ *   flags: flags & options for disconnecting
+ *
+ * Return Value:
+ *   int: ks error code
+ *
+ * Notes:
+ *   N/A
+ */
 
-    memset(context,0, sizeof(ksock_tdi_tx_t) + sizeof(KEVENT));
+int
+ks_disconnect_tconn(
+    ks_tconn_t *    tconn,
+    ulong           flags
+    )
+{
+    NTSTATUS            status = STATUS_SUCCESS;
 
-    context->tconn = tconn;
-    context->Event = (PKEVENT) ((PUCHAR)context + sizeof(ksock_tdi_tx_t));
+    ks_tconn_info_t *   info;
+
+    PFILE_OBJECT        ConnectionObject;
+    PDEVICE_OBJECT      DeviceObject = NULL;
 
-    KeInitializeEvent(context->Event, SynchronizationEvent, FALSE);
+    PIRP                Irp = NULL;
 
-    if (bBuffed) {
+    KEVENT              Event;
 
-         /* for bufferred transmission, we need set
-            the internal completion routine.  */
+    ks_get_tconn(tconn);
 
-        context->CompletionRoutine  = KsTcpSendCompletionRoutine;
-        context->KsTsduMgr          = KsTsduMgr;
-        context->CompletionContext  = KsTsdu;
-        context->CompletionContext2 = (bNewBuff ? (PVOID)KsTsduBuf : (PVOID)KsTsduDat);
-        context->bCounted = FALSE;
+    /* make sure tt's connected already and it
+       must be a sender or a child ...       */
 
-    } else if (bIsNonBlock) {
+    LASSERT(tconn->kstc_state == ksts_connected);
+    LASSERT( tconn->kstc_type == kstt_sender ||
+            tconn->kstc_type == kstt_child);
 
-         /* for non-blocking transmission, we need set
-            the internal completion routine too.  */
+    /* reset all the event handlers to NULL */
 
-        context->CompletionRoutine = KsTcpSendCompletionRoutine;
-        context->CompletionContext = tx;
-        context->KsTsduMgr         = KsTsduMgr;
-        context->bCounted = TRUE;
-        context->ReferCount = 2;
+    if (tconn->kstc_type != kstt_child) {
+        KsResetHandlers (tconn);
     }
 
+    /* Disconnecting to the remote peer ... */
+
     if (tconn->kstc_type == kstt_sender) {
-        ConnObject = tconn->sender.kstc_info.FileObject;
+        info = &(tconn->sender.kstc_info);
     } else {
-        LASSERT(tconn->kstc_type == kstt_child);
-        ConnObject = tconn->child.kstc_info.FileObject;
+        info = &(tconn->child.kstc_info);
     }
 
-    DeviceObject = IoGetRelatedDeviceObject(ConnObject);
+    ConnectionObject = info->FileObject;
+    DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
+
+    /* allocate an Irp and setup it */
 
     Irp = KsBuildTdiIrp(DeviceObject);
 
     if (NULL == Irp) {
 
-        /* release the chained mdl */
-        ks_release_mdl(mdl, FALSE);
-
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto errorout;
-    }
-
-    length = KsQueryMdlsSize(mdl);
-
-    LASSERT((ULONG)len <= length);
-
-    ks_get_tconn(tconn);
-
-    TdiBuildSend(
-        Irp,
-        DeviceObject,
-        ConnObject,
-        KsTcpCompletionRoutine,
-        context,
-        (bBuffed ? NewMdl : mdl),
-        (bBuffed ? (tflags | TDI_SEND_NON_BLOCKING) : tflags),
-        (ULONG)len;
-      );
-
-    Status = IoCallDriver(DeviceObject, Irp);
-
-    if (bBuffed) {
-        ks_release_mdl(mdl, FALSE);
-        NewMdl = NULL;
-    }
-
-    if (!NT_SUCCESS(Status)) {
+        status = STATUS_INSUFFICIENT_RESOURCES;
         cfs_enter_debugger();
-        rc = cfs_error_code(Status);
         goto errorout;
     }
 
-    if (bBuffed) {
-        Status = STATUS_SUCCESS;
-        rc  = len;
-        context = NULL;
-    } else {
-        if (bIsNonBlock) {
-            if (InterlockedDecrement(&context->ReferCount) == 0) {
-                Status = Irp->IoStatus.Status;
-            } else {
-                Status = STATUS_PENDING;
-                context = NULL;
-            }
-        } else {
-            if (STATUS_PENDING == Status) {
-                Status = KeWaitForSingleObject(
-                         context->Event,
-                         Executive,
-                         KernelMode,
-                         FALSE,
-                         NULL
-                         );
-
-                if (NT_SUCCESS(Status)) {
-                    Status = Irp->IoStatus.Status;
-                }
-            }
-        }
-
-        if (Status == STATUS_SUCCESS) {
-            rc = (int)(Irp->IoStatus.Information);
-
-            spin_lock(&tconn->kstc_lock);
-            KsTsduMgr->TotalBytes -= rc;
-            spin_unlock(&tconn->kstc_lock);
-
-        } else {
-            rc = cfs_error_code(Status);
-        }
-    }
-
-errorout:
-
-    if (bBuffed) {
-
-        if (NewMdl) {
-            ks_release_mdl(NewMdl, FALSE);
-            NewMdl = NULL;
-        }
+    KeInitializeEvent(
+            &Event,
+            SynchronizationEvent,
+            FALSE
+            );
 
-        if (bNewBuff) {
-            if (!NT_SUCCESS(Status)) {
-                ExFreePool(Buffer);
-                Buffer = NULL;
-            }
-        }
+    TdiBuildDisconnect(
+            Irp,
+            DeviceObject,
+            ConnectionObject,
+            KsDisconectCompletionRoutine,
+            &Event,
+            NULL,
+            flags,
+            NULL,
+            NULL
+            );
 
-    } else {
+    /* issue the Irp to the underlying transport
+       driver to disconnect the connection    */
 
-        if (Status != STATUS_PENDING) {
+    status = IoCallDriver(DeviceObject, Irp);
 
-            if (Irp) {
+    if (STATUS_PENDING == status) {
 
-                /* Freeing the Irp ... */
+        status = KeWaitForSingleObject(
+                     &Event,
+                     Executive,
+                     KernelMode,
+                     FALSE,
+                     NULL
+                     );
 
-                IoFreeIrp(Irp);
-                Irp = NULL;
-            }
-        }
+        status = Irp->IoStatus.Status;
     }
 
-    if (!NT_SUCCESS(Status)) {
+    KsPrint((2, "KsDisconnect: Disconnection is done with Status = %xh (%s) ...\n",
+                status, KsNtStatusToString(status)));
 
-        spin_lock(&tconn->kstc_lock);
+    IoFreeIrp(Irp);
 
-        KsTsduMgr->TotalBytes -= (ULONG)len;
+    if (info->ConnectionInfo) {
 
-        if (bBuffed) {
+        /* disassociate the association between connection/address objects */
 
-            /* attach it to the TsduMgr list if the Tsdu is newly created. */
-            if (bNewTsdu) {
+        status = KsDisassociateAddress(ConnectionObject);
 
-                list_del(&(KsTsdu->Link));
-                KsTsduMgr->NumOfTsdu--;
+        if (!NT_SUCCESS(status)) {
+            cfs_enter_debugger();
+        }
 
-                KsPutKsTsdu(KsTsdu);
-            } else {
-                if (bNewBuff) {
-                    if ( (ulong_ptr)KsTsduBuf + sizeof(KS_TSDU_BUF) ==
-                         (ulong_ptr)KsTsdu + KsTsdu->LastOffset) {
-                        KsTsdu->LastOffset -= sizeof(KS_TSDU_BUF);
-                        KsTsduBuf->TsduType = 0;
-                    } else {
-                        cfs_enter_debugger();
-                        KsTsduBuf->StartOffset = KsTsduBuf->DataLength;
-                    }
-                } else {
-                    if ( (ulong_ptr)KsTsduDat + KsTsduDat->TotalLength ==
-                         (ulong_ptr)KsTsdu + KsTsdu->LastOffset) {
-                        KsTsdu->LastOffset -= KsTsduDat->TotalLength;
-                        KsTsduDat->TsduType = 0;
-                    } else {
-                        cfs_enter_debugger();
-                        KsTsduDat->StartOffset = KsTsduDat->DataLength;
-                    }
-                }
-            }
+        cfs_spin_lock(&(tconn->kstc_lock));
+
+        /* cleanup the tsdumgr Lists */
+        KsCleanupTsdu (tconn);
+
+        /* set the state of the tconn */
+        if (NT_SUCCESS(status)) {
+            tconn->kstc_state = ksts_disconnected;
+        } else {
+            tconn->kstc_state = ksts_associated;
         }
 
-        spin_unlock(&tconn->kstc_lock);
-    }
+        /* free  the connection info to system pool*/
+        ExFreePool(info->ConnectionInfo);
+        info->ConnectionInfo = NULL;
+        info->Remote = NULL;
 
-    /* free the context if is not used at all */
-    if (context) {
-        cfs_free(context);
+        cfs_spin_unlock(&(tconn->kstc_lock));
     }
 
+    status = STATUS_SUCCESS;
+
+errorout:
+
     ks_put_tconn(tconn);
 
-    return rc;
+    return cfs_error_code(status);
 }
 
+
 /*
- * ks_recv_mdl
- *   Receive data from the peer for a stream connection
+ * ks_abort_tconn
+ *   The connection is broken un-expectedly. We need do
+ *   some cleanup.
  *
  * Arguments:
- *   tconn: tdi connection object
- *   mdl:   the mdl chain to contain the incoming data
- *   len:   length of the data
- *   flags: flags of the receiving
+ *   tconn: the tdi connection
  *
  * Return Value:
- *   ks return code
+ *   N/A
  *
  * Notes:
  *   N/A
  */
 
-int
-ks_recv_mdl(
-    ksock_tconn_t * tconn,
-    ksock_mdl_t *   mdl,
-    int             size,
-    int             flags
+void
+ks_abort_tconn(
+    ks_tconn_t *     tconn
     )
 {
-    NTSTATUS        Status = STATUS_SUCCESS;
-    int             rc = 0;
-
-    BOOLEAN         bIsNonBlock;
-    BOOLEAN         bIsExpedited;
-
-    PKS_CHAIN       KsChain;
-    PKS_TSDUMGR     KsTsduMgr;
-    PKS_TSDU        KsTsdu;
-    PKS_TSDU_DAT    KsTsduDat;
-    PKS_TSDU_BUF    KsTsduBuf;
-    PKS_TSDU_MDL    KsTsduMdl;
-
-    PUCHAR          Buffer;
-
-    ULONG           BytesRecved = 0;
-    ULONG           RecvedOnce;
+    PKS_DISCONNECT_WORKITEM WorkItem = NULL;
 
-    bIsNonBlock  = cfs_is_flag_set(flags, MSG_DONTWAIT);
-    bIsExpedited = cfs_is_flag_set(flags, MSG_OOB);
+    WorkItem = &(tconn->kstc_disconnect);
 
     ks_get_tconn(tconn);
+    cfs_spin_lock(&(tconn->kstc_lock));
 
-Again:
-
-    RecvedOnce = 0;
+    if (tconn->kstc_state != ksts_connected) {
+        ks_put_tconn(tconn);
+    } else {
 
-    spin_lock(&(tconn->kstc_lock));
+        if (!cfs_is_flag_set(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY)) {
 
-    if ( tconn->kstc_type != kstt_sender &&
-         tconn->kstc_type != kstt_child) {
+            WorkItem->Flags = TDI_DISCONNECT_ABORT;
+            WorkItem->tconn = tconn;
 
-        rc = -EINVAL;
-        spin_unlock(&(tconn->kstc_lock));
+            cfs_set_flag(tconn->kstc_flags, KS_TCONN_DISCONNECT_BUSY);
 
-        goto errorout;
+            ExQueueWorkItem(
+                    &(WorkItem->WorkItem),
+                    DelayedWorkQueue
+                    );
+        }
     }
 
-    if (tconn->kstc_state != ksts_connected) {
+    cfs_spin_unlock(&(tconn->kstc_lock));
+}
 
-        rc = -ENOTCONN;
-        spin_unlock(&(tconn->kstc_lock));
 
-        goto errorout;
-    }
+/*
+ * ks_query_local_ipaddr
+ *   query the local connection ip address
+ *
+ * Arguments:
+ *   tconn:  the tconn which is connected
+ *
+ * Return Value:
+ *   int: ks error code
+ *
+ * Notes:
+ *   N/A
+ */
 
-    if (tconn->kstc_type == kstt_sender) {
-        KsChain = &(tconn->sender.kstc_recv);
-    } else {
-        LASSERT(tconn->kstc_type == kstt_child);
-        KsChain = &(tconn->child.kstc_recv);
-    }
+int
+ks_query_local_ipaddr(
+    ks_tconn_t *     tconn
+    )
+{
+    PFILE_OBJECT    FileObject = NULL;
+    NTSTATUS        status;
 
-    if (bIsExpedited) {
-        KsTsduMgr = &(KsChain->Expedited);
+    PTRANSPORT_ADDRESS TdiAddress;
+    ULONG              AddressLength;
+
+    if (tconn->kstc_type == kstt_sender) {
+        FileObject = tconn->sender.kstc_info.FileObject;
+    } else if (tconn->kstc_type == kstt_child) {
+        FileObject = tconn->child.kstc_info.FileObject;
     } else {
-        KsTsduMgr = &(KsChain->Normal);
+        status = STATUS_INVALID_PARAMETER;
+        goto errorout;
     }
 
-NextTsdu:
-
-    if (list_empty(&(KsTsduMgr->TsduList))) {
-
-        //
-        // It's a notification event. We need reset it to
-        // un-signaled state in case there no any tsdus.
-        //
+    TdiAddress = &(tconn->kstc_addr.Tdi);
+    AddressLength = MAX_ADDRESS_LENGTH;
 
-        KeResetEvent(&(KsTsduMgr->Event));
+    status =  KsQueryIpAddress(FileObject, TdiAddress, &AddressLength);
 
+    if (NT_SUCCESS(status)) {
+        KsPrint((2, "ks_query_local_ipaddr: Local ip address = %xh port = %xh\n",
+                ((PTDI_ADDRESS_IP)(&(TdiAddress->Address[0].Address)))->in_addr,
+                ((PTDI_ADDRESS_IP)(&(TdiAddress->Address[0].Address)))->sin_port ));
     } else {
+        KsPrint((2, "ks_query_local_ipaddr: Failed to query the connection local ip address.\n"));
+    }
 
-        KsTsdu = list_entry(KsTsduMgr->TsduList.next, KS_TSDU, Link);
-        LASSERT(KsTsdu->Magic == KS_TSDU_MAGIC);
-
-        /* remove the KsTsdu from TsduMgr list to release the lock */
-        list_del(&(KsTsdu->Link));
-        KsTsduMgr->NumOfTsdu--;
-
-        spin_unlock(&(tconn->kstc_lock));
-
-        while ((ULONG)size > BytesRecved) {
-
-            ULONG BytesCopied = 0;
-            ULONG BytesToCopy = 0;
-            ULONG StartOffset = 0;
-
-            KsTsduDat = (PKS_TSDU_DAT)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
-            KsTsduBuf = (PKS_TSDU_BUF)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
-            KsTsduMdl = (PKS_TSDU_MDL)((PUCHAR)KsTsdu + KsTsdu->StartOffset);
-
-            if ( TSDU_TYPE_DAT == KsTsduDat->TsduType ||
-                 TSDU_TYPE_BUF == KsTsduBuf->TsduType ) {
-
-
-                //
-                // Data Tsdu Unit ...
-                //
-
-                if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
-
-                    if (cfs_is_flag_set(KsTsduDat->TsduFlags, KS_TSDU_DAT_RECEIVING)) {
-                        /* data is not ready yet*/
-                        KeResetEvent(&(KsTsduMgr->Event));
-                        printk("ks_recv_mdl: KsTsduDat (%xh) is not ready yet !!!!!!!\n", KsTsduDat);
-                        break;
-                    }
-
-                    Buffer = &KsTsduDat->Data[0];
-                    StartOffset = KsTsduDat->StartOffset;
-                    if (KsTsduDat->DataLength - KsTsduDat->StartOffset > size - BytesRecved) {
-                        /* Recvmsg requst could be statisfied ... */
-                        BytesToCopy = size - BytesRecved;
-                    } else {
-                        BytesToCopy = KsTsduDat->DataLength - KsTsduDat->StartOffset;
-                    }
-
-                } else {
-
-                    if (cfs_is_flag_set(KsTsduBuf->TsduFlags, KS_TSDU_BUF_RECEIVING)) {
-                        /* data is not ready yet*/
-                        KeResetEvent(&(KsTsduMgr->Event));
-                        DbgPrint("ks_recv_mdl: KsTsduBuf (%xh) is not ready yet !!!!!!!\n", KsTsduBuf);
-                        break;
-                    }
-
-                    ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
-                    Buffer = KsTsduBuf->UserBuffer;
-                    StartOffset = KsTsduBuf->StartOffset;
-
-                    if (KsTsduBuf->DataLength - KsTsduBuf->StartOffset > size - BytesRecved) {
-                        /* Recvmsg requst could be statisfied ... */
-                        BytesToCopy = size - BytesRecved;
-                    } else {
-                        BytesToCopy = KsTsduBuf->DataLength - KsTsduBuf->StartOffset;
-                    }
-                }
-
-                if (BytesToCopy > 0) {
-                    Status = TdiCopyBufferToMdl(
-                                    Buffer,
-                                    StartOffset,
-                                    BytesToCopy,
-                                    mdl,
-                                    BytesRecved,
-                                    &BytesCopied
-                                    );
-
-                    if (NT_SUCCESS(Status)) {
-
-                        if (BytesToCopy != BytesCopied) {
-                            cfs_enter_debugger();
-                        }
+errorout:
 
-                        BytesRecved += BytesCopied;
-                        RecvedOnce  += BytesCopied;
+    return cfs_error_code(status);
+}
 
-                    } else {
+int
+KsCalcWhichEngine(ks_tconn_t * tconn)
+{
+    PTRANSPORT_ADDRESS TdiAddress = &(tconn->kstc_addr.Tdi);
+    ULONG addr = ((PTDI_ADDRESS_IP)(&(TdiAddress->Address[0].Address)))->in_addr;
+    ULONG sum = (addr & 0xFF) + ((addr & 0xFF00) >> 8) + ((addr & 0xFF0000) >> 16);
 
-                        cfs_enter_debugger();
+    return (int)(sum % ks_data.ksnd_engine_nums);
+}
 
-                        if (STATUS_BUFFER_OVERFLOW == Status) {
-                        }
-                    }
-                }
+void
+KsQueueTdiEngine(ks_tconn_t * tconn, PKS_TSDUMGR TsduMgr)
+{
+    ks_engine_mgr_t *   engm;
+    ks_engine_slot_t *  engs;
+
+    engm = &ks_data.ksnd_engine_mgr[KsCalcWhichEngine(tconn)];
+    engs = &TsduMgr->Slot;
+
+    if (!engs->queued) {
+        cfs_spin_lock(&engm->lock);
+        if (!engs->queued) {
+            cfs_list_add_tail(&engs->link, &engm->list);
+            engs->queued = TRUE;
+            engs->tconn = tconn;
+            engs->emgr = engm;
+            engs->tsdumgr = TsduMgr;
+            KeSetEvent(&(engm->start),0, FALSE);
+        }
+        cfs_spin_unlock(&engm->lock);
+        KsPrint((4, "KsQueueTdiEngine: TsduMgr=%p is queued to engine %p\n",
+                    TsduMgr, engm));
+    }
+    KeSetEvent(&(engm->start),0, FALSE);
+}
 
-                if (TSDU_TYPE_DAT == KsTsduDat->TsduType) {
+void
+KsRemoveTdiEngine(PKS_TSDUMGR TsduMgr)
+{
+    ks_engine_mgr_t *   engm;
+    ks_engine_slot_t *  engs;
+
+    engs = &TsduMgr->Slot;
+    if (engs->queued) {
+        engm = engs->emgr;
+        LASSERT(engm != NULL);
+        cfs_spin_lock(&engm->lock);
+        if (engs->queued) {
+            cfs_list_del(&engs->link);
+            engs->queued = FALSE;
+            engs->tconn = NULL;
+            engs->emgr = NULL;
+            engs->tsdumgr = NULL;
+        }
+        cfs_spin_unlock(&engm->lock);
+        KsPrint((4, "KsQueueTdiEngine: TsduMgr %p is removed from engine %p\n",
+                    TsduMgr, engm));
+    }
+}
 
-                    KsTsduDat->StartOffset += BytesCopied;
+int
+KsDeliveryIrp(ks_tconn_t * tconn, PIRP irp)
+{
+    PFILE_OBJECT        connobj;
+    PDEVICE_OBJECT      devobj;
+    NTSTATUS            status;
+    int                 rc = 0;
 
-                    if (KsTsduDat->StartOffset == KsTsduDat->DataLength) {
-                        KsTsdu->StartOffset += KsTsduDat->TotalLength;
-                    }
+    /* construct Irp */
+    if (tconn->kstc_type == kstt_sender) {
+        connobj = tconn->sender.kstc_info.FileObject;
+    } else {
+        LASSERT(tconn->kstc_type == kstt_child);
+        connobj = tconn->child.kstc_info.FileObject;
+    }
+    devobj = IoGetRelatedDeviceObject(connobj);
+    
+    /* send irp to transport layer */
+    status = IoCallDriver(devobj, irp);
 
-                } else {
+    /* convert status to linux error code */
+    if (!NT_SUCCESS(status)) {
+        rc = cfs_error_code(status);
+    }
 
-                    ASSERT(TSDU_TYPE_BUF == KsTsduBuf->TsduType);
-                    KsTsduBuf->StartOffset += BytesCopied;
-                    if (KsTsduBuf->StartOffset == KsTsduBuf->DataLength) {
-                        KsTsdu->StartOffset += sizeof(KS_TSDU_BUF);
-                        /* now we need release the buf to system pool */
-                        ExFreePool(KsTsduBuf->UserBuffer);
-                    }
-                }
+    KsPrint((4, "KsDeliveryIrp: tconn=%p irp=%p status=%xh rc=%d.\n",
+                 tconn, irp, status, rc));
+    return rc;
+}
 
-            } else if (TSDU_TYPE_MDL == KsTsduMdl->TsduType) {
+PIRP
+KsBuildSend(ks_tconn_t * tconn, PKS_TSDUMGR TsduMgr,
+            ks_mdl_t * mdl, ulong flags )
+{
+    ks_tdi_tx_t *       context;
+    PIRP                irp = NULL;
+    PFILE_OBJECT        connobj;
+    PDEVICE_OBJECT      devobj;
+    NTSTATUS            status;
+    ULONG               length;
 
-                //
-                // MDL Tsdu Unit ...
-                //
+    int                 rc = 0;
 
-                if (KsTsduMdl->DataLength > size - BytesRecved) {
+    /* query mdl chain total length */
+    length = KsQueryMdlsSize(mdl);
 
-                    /* Recvmsg requst could be statisfied ... */
+    /* we need allocate the ks_tx_t structure from memory pool. */
+    context = cfs_alloc(sizeof(ks_tdi_tx_t), 0);
+    if (!context) {
+        status = STATUS_INSUFFICIENT_RESOURCES;
+        goto errorout;
+    }
 
-                    BytesToCopy = size - BytesRecved;
+    /* intialize the TcpContext */
+    memset(context,0, sizeof(ks_tdi_tx_t));
+    context->Magic = KS_TCP_CONTEXT_MAGIC;
+    context->tconn = tconn;
+    context->CompletionRoutine = KsTcpSendCompletionRoutine;
+    context->TsduMgr = TsduMgr;
+    context->Length = length;
 
-                } else {
+    /* construct Irp */
+    if (tconn->kstc_type == kstt_sender) {
+        connobj = tconn->sender.kstc_info.FileObject;
+    } else {
+        LASSERT(tconn->kstc_type == kstt_child);
+        connobj = tconn->child.kstc_info.FileObject;
+    }
+    devobj = IoGetRelatedDeviceObject(connobj);
+    irp = KsBuildTdiIrp(devobj);
+    if (NULL == irp) {
+        status = STATUS_INSUFFICIENT_RESOURCES;
+        goto errorout;
+    }
 
-                    BytesToCopy = KsTsduMdl->DataLength;
-                }
+    /* grab tconn reference */
+    ks_get_tconn(tconn);
 
-                Status = KsCopyMdlChainToMdlChain(
-                            KsTsduMdl->Mdl,
-                            KsTsduMdl->StartOffset,
-                            mdl,
-                            BytesRecved,
-                            BytesToCopy,
-                            &BytesCopied
-                            );
+    /* delivery the sending request */
+    TdiBuildSend(
+        irp,
+        devobj,
+        connobj,
+        KsTcpCompletionRoutine,
+        context,
+        mdl,
+        flags,
+        length
+      );
 
-                if (NT_SUCCESS(Status)) {
+      return irp;
 
-                    if (BytesToCopy != BytesCopied) {
-                        cfs_enter_debugger();
-                    }
+errorout:
 
-                    KsTsduMdl->StartOffset += BytesCopied;
-                    KsTsduMdl->DataLength  -= BytesCopied;
+    /* free the context if is not used at all */
+    if (context) {
+        ASSERT(context->Magic == KS_TCP_CONTEXT_MAGIC);
+        context->Magic = 'CDAB';
+        cfs_free(context);
+    }
 
-                    BytesRecved += BytesCopied;
-                    RecvedOnce  += BytesCopied;
-                } else {
-                    cfs_enter_debugger();
-                }
+    /* here need free the Irp. */
+    if (irp) {
+        IoFreeIrp(irp);
+        irp = NULL;
+    }
 
-                if (0 == KsTsduMdl->DataLength) {
+    return NULL;
+}
 
-                    //
-                    // Call TdiReturnChainedReceives to release the Tsdu memory
-                    //
+int
+KsDeliveryTsdus(ks_tconn_t * tconn, PKS_TSDUMGR TsduMgr)
+{
+    int                 rc = 0;
+    ulong               length = 0;
+    ulong               tflags = 0;
+    ks_mdl_t *          mdl = NULL;
+    PIRP                irp = NULL;
+    BOOLEAN             expedited;
 
-                    TdiReturnChainedReceives(
-                        &(KsTsduMdl->Descriptor),
-                        1 );
+    LASSERT(tconn->kstc_magic == KS_TCONN_MAGIC);
 
-                    KsTsdu->StartOffset += sizeof(KS_TSDU_MDL);
-                }
+    ks_get_tconn(tconn);
+    ks_lock_tsdumgr(TsduMgr);
 
-            } else {
-                printk("ks_recv_mdl: unknown tsdu slot: slot = %x type = %x Start= %x\n",
-                        KsTsduDat, KsTsduDat->TsduType, KsTsduDat->StartOffset, KsTsduDat->DataLength);
-                printk("        Tsdu = %x Magic=%x: Start = %x Last = %x Length = %x",
-                        KsTsdu, KsTsdu->Magic, KsTsdu->StartOffset, KsTsdu->LastOffset, KsTsdu->TotalLength);
-                cfs_enter_debugger();
-            }
+    if ( tconn->kstc_type != kstt_sender &&
+         tconn->kstc_type != kstt_child) {
+        rc = -EINVAL;
+        ks_unlock_tsdumgr(TsduMgr);
+        goto errorout;
+    }
 
-            if (KsTsdu->StartOffset == KsTsdu->LastOffset) {
+    if (tconn->kstc_state != ksts_connected) {
+        rc = -ENOTCONN;
+        ks_unlock_tsdumgr(TsduMgr);
+        goto errorout;
+    }
 
-                //
-                // KsTsdu is empty now, we need free it ...
-                //
+    if (TsduMgr->OOB) {
+        tflags = TDI_SEND_NON_BLOCKING | TDI_SEND_EXPEDITED;
+    } else {
+        tflags = TDI_SEND_NON_BLOCKING;
+    }
+   
+    if (cfs_list_empty(&TsduMgr->TsduList)) {
+        LASSERT(TsduMgr->TotalBytes == 0);
+        ks_unlock_tsdumgr(TsduMgr);
+        goto errorout;
+    }
 
-                KsPutKsTsdu(KsTsdu);
-                KsTsdu = NULL;
+    /* check whether there's outstanding sending requests */
+    if (TsduMgr->Busy) {
+        rc = -EAGAIN;
+        ks_unlock_tsdumgr(TsduMgr);
+        goto errorout;
+    }
 
-                break;
-            }
+    /* probe all Tsdus and merge buffers together */
+    mdl = KsLockTsdus(tconn, TsduMgr, &tflags, &length);
+    if (NULL == mdl) {
+         if (length == 0) {
+            LASSERT(TsduMgr->TotalBytes == 0);
+            rc = -EAGAIN;
+        } else {
+            rc = -ENOMEM;
         }
+        ks_unlock_tsdumgr(TsduMgr);
+        goto errorout;
+    }
 
-        spin_lock(&(tconn->kstc_lock));
+    KsPrint((4, "KsDeliveryTsdus: tconn=%p TsudMgr=%p, length=%xh/%xh\n",
+                tconn, TsduMgr, length, TsduMgr->TotalBytes));
 
-        /* we need attach the KsTsdu to the list header */
-        if (KsTsdu) {
-            KsTsduMgr->NumOfTsdu++;
-            list_add(&(KsTsdu->Link), &(KsTsduMgr->TsduList));
-        } else if ((ULONG)size > BytesRecved) {
-            goto NextTsdu;
-        }
+    /* build send irp request */
+    irp = KsBuildSend(tconn, TsduMgr, mdl, tflags);
+    if (NULL == irp) {
+        rc = -ENOMEM;
+        ks_unlock_tsdumgr(TsduMgr);
+        goto errorout;
     }
+    TsduMgr->Busy = TRUE;
+    ks_unlock_tsdumgr(TsduMgr);
 
-    if (KsTsduMgr->TotalBytes < RecvedOnce) {
-        cfs_enter_debugger();
-        KsTsduMgr->TotalBytes = 0;
-    } else {
-        KsTsduMgr->TotalBytes -= RecvedOnce;
+    /* delivery mdl chain */
+    LASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+    rc = KsDeliveryIrp(tconn, irp);
+    if (rc < 0) {
+        goto errorout;
     }
 
-    spin_unlock(&(tconn->kstc_lock));
+errorout:
 
-    if (NT_SUCCESS(Status)) {
+    LASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+    ks_put_tconn(tconn);
+    return rc;
+}
 
-        if ((BytesRecved < (ulong_ptr)size) && (!bIsNonBlock)) {
+int
+KsDeliveryEngineThread(void * context)
+{
+    ks_engine_mgr_t *   engm = context;
+    ks_engine_slot_t *  engs;
+    cfs_list_t *        list;
+    ks_tconn_t *        tconn;
 
-            KeWaitForSingleObject(
-                &(KsTsduMgr->Event),
-                Executive,
-                KernelMode,
-                FALSE,
-                NULL
-                );
+    cfs_set_thread_priority(31);
 
-            goto Again;
-        }
+    while (!engm->stop) {
 
-        if (bIsNonBlock && (BytesRecved == 0)) {
-            rc = -EAGAIN;
-        } else {
-            rc = BytesRecved;
+        cfs_wait_event_internal(&engm->start, 0);
+
+        cfs_spin_lock(&engm->lock);
+        if (cfs_list_empty(&engm->list)) {
+            cfs_spin_unlock(&engm->lock);
+            continue;
         }
-    }
 
-errorout:
+        list = engm->list.next;
+        cfs_list_del(list);
+        engs = cfs_list_entry(list, ks_engine_slot_t, link);
+        LASSERT(engs->emgr == engm);
+        LASSERT(engs->queued);
+        engs->emgr = NULL;
+        engs->queued = FALSE;
+        cfs_spin_unlock(&engm->lock);
 
-    ks_put_tconn(tconn);
+        tconn = engs->tconn;
+        LASSERT(tconn->kstc_magic == KS_TCONN_MAGIC);
 
-    if (rc > 0) {
-        KsPrint((1, "ks_recv_mdl: recvieving %d bytes ...\n", rc));
-    } else {
-        KsPrint((0, "ks_recv_mdl: recvieving error code = %d Stauts = %xh ...\n", rc, Status));
+        KsPrint((4, "KsDeliveryEngineThread: %p active: tconn=%p "
+                    "TsduMgr=%p\n", engm, tconn, engs->tsdumgr));
+        KsDeliveryTsdus(tconn, engs->tsdumgr);
+
+        LASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
     }
 
-    /* release the chained mdl */
-    ks_release_mdl(mdl, FALSE);
+    KeSetEvent(&engm->exit, 0, FALSE);
 
-    return (rc);
+    return 0;
 }
 
-
 /*
  * ks_init_tdi_data
  *   initialize the global data in ksockal_data
@@ -6004,17 +5856,17 @@ errorout:
 int
 ks_init_tdi_data()
 {
-    int rc = 0;
+    int rc = 0, i;
 
     /* initialize tconn related globals */
-    RtlZeroMemory(&ks_data, sizeof(ks_data_t));
+    RtlZeroMemory(&ks_data, sizeof(ks_tdi_data_t));
 
-    spin_lock_init(&ks_data.ksnd_tconn_lock);
+    cfs_spin_lock_init(&ks_data.ksnd_tconn_lock);
     CFS_INIT_LIST_HEAD(&ks_data.ksnd_tconns);
     cfs_init_event(&ks_data.ksnd_tconn_exit, TRUE, FALSE);
 
     ks_data.ksnd_tconn_slab = cfs_mem_cache_create(
-        "tcon", sizeof(ksock_tconn_t) , 0, 0);
+        "tcon", sizeof(ks_tconn_t) , 0, 0);
 
     if (!ks_data.ksnd_tconn_slab) {
         rc = -ENOMEM;
@@ -6022,8 +5874,7 @@ ks_init_tdi_data()
     }
 
     /* initialize tsdu related globals */
-
-    spin_lock_init(&ks_data.ksnd_tsdu_lock);
+    cfs_spin_lock_init(&ks_data.ksnd_tsdu_lock);
     CFS_INIT_LIST_HEAD(&ks_data.ksnd_freetsdus);
     ks_data.ksnd_tsdu_size = TDINAL_TSDU_DEFAULT_SIZE; /* 64k */
     ks_data.ksnd_tsdu_slab = cfs_mem_cache_create(
@@ -6031,21 +5882,41 @@ ks_init_tdi_data()
 
     if (!ks_data.ksnd_tsdu_slab) {
         rc = -ENOMEM;
-        cfs_mem_cache_destroy(ks_data.ksnd_tconn_slab);
-        ks_data.ksnd_tconn_slab = NULL;
         goto errorout;
     }
 
-    /* initialize daemon related globals */
-
-    spin_lock_init(&ks_data.ksnd_daemon_lock);
-    CFS_INIT_LIST_HEAD(&ks_data.ksnd_daemons);
-    cfs_init_event(&ks_data.ksnd_daemon_exit, TRUE, FALSE);
+    /* initialize engine threads list */
+    ks_data.ksnd_engine_nums = cfs_num_online_cpus();
+    if (ks_data.ksnd_engine_nums < 4) {
+        ks_data.ksnd_engine_nums = 4;
+    }
+    ks_data.ksnd_engine_mgr = cfs_alloc(sizeof(ks_engine_mgr_t) * 
+                         ks_data.ksnd_engine_nums,CFS_ALLOC_ZERO);
+    if (ks_data.ksnd_engine_mgr == NULL) {
+        rc = -ENOMEM;
+        goto errorout;
+    }
+    for (i = 0; i < ks_data.ksnd_engine_nums; i++) {
+        cfs_spin_lock_init(&ks_data.ksnd_engine_mgr[i].lock);
+        cfs_init_event(&ks_data.ksnd_engine_mgr[i].start, TRUE, FALSE);
+        cfs_init_event(&ks_data.ksnd_engine_mgr[i].exit, TRUE, FALSE);
+        CFS_INIT_LIST_HEAD(&ks_data.ksnd_engine_mgr[i].list);
+        cfs_create_thread(KsDeliveryEngineThread, &ks_data.ksnd_engine_mgr[i], 0);
+    }
 
+    /* register pnp handlers to watch network condition */
     KsRegisterPnpHandlers();
 
 errorout:
 
+    /* do cleanup in case we get failures */
+    if (rc < 0) {
+        if (ks_data.ksnd_tconn_slab) {
+            cfs_mem_cache_destroy(ks_data.ksnd_tconn_slab);
+            ks_data.ksnd_tconn_slab = NULL;
+        }
+    }
+
     return rc;
 }
 
@@ -6068,36 +5939,47 @@ void
 ks_fini_tdi_data()
 {
     PKS_TSDU            KsTsdu = NULL;
-    struct list_head *  list   = NULL;
+    cfs_list_t *        list   = NULL;
+    int i;
 
     /* clean up the pnp handler and address slots */
     KsDeregisterPnpHandlers();
 
+    /* stop all tcp sending engines */
+    for (i = 0; i < ks_data.ksnd_engine_nums; i++) {
+        ks_data.ksnd_engine_mgr[i].stop = TRUE;
+        KeSetEvent(&ks_data.ksnd_engine_mgr[i].start, 0, FALSE);
+    }
+
+    for (i = 0; i < ks_data.ksnd_engine_nums; i++) {
+        cfs_wait_event_internal(&ks_data.ksnd_engine_mgr[i].exit, 0);
+    }
+
     /* we need wait until all the tconn are freed */
-    spin_lock(&(ks_data.ksnd_tconn_lock));
+    cfs_spin_lock(&(ks_data.ksnd_tconn_lock));
 
-    if (list_empty(&(ks_data.ksnd_tconns))) {
+    if (cfs_list_empty(&(ks_data.ksnd_tconns))) {
         cfs_wake_event(&ks_data.ksnd_tconn_exit);
     }
-    spin_unlock(&(ks_data.ksnd_tconn_lock));
+    cfs_spin_unlock(&(ks_data.ksnd_tconn_lock));
 
     /* now wait on the tconn exit event */
-    cfs_wait_event(&ks_data.ksnd_tconn_exit, 0);
+    cfs_wait_event_internal(&ks_data.ksnd_tconn_exit, 0);
 
     /* it's safe to delete the tconn slab ... */
     cfs_mem_cache_destroy(ks_data.ksnd_tconn_slab);
     ks_data.ksnd_tconn_slab = NULL;
 
     /* clean up all the tsud buffers in the free list */
-    spin_lock(&(ks_data.ksnd_tsdu_lock));
-    list_for_each (list, &ks_data.ksnd_freetsdus) {
-        KsTsdu = list_entry (list, KS_TSDU, Link);
+    cfs_spin_lock(&(ks_data.ksnd_tsdu_lock));
+    cfs_list_for_each (list, &ks_data.ksnd_freetsdus) {
+        KsTsdu = cfs_list_entry (list, KS_TSDU, Link);
 
         cfs_mem_cache_free(
                 ks_data.ksnd_tsdu_slab,
                 KsTsdu );
     }
-    spin_unlock(&(ks_data.ksnd_tsdu_lock));
+    cfs_spin_unlock(&(ks_data.ksnd_tsdu_lock));
 
     /* it's safe to delete the tsdu slab ... */
     cfs_mem_cache_destroy(ks_data.ksnd_tsdu_slab);
@@ -6120,13 +6002,13 @@ ks_fini_tdi_data()
  *   N/A
  */
 
-ksock_tconn_t *
+ks_tconn_t *
 ks_create_child_tconn(
-    ksock_tconn_t * parent
+    ks_tconn_t * parent
     )
 {
     NTSTATUS            status;
-    ksock_tconn_t *     backlog;
+    ks_tconn_t *        backlog;
 
     /* allocate the tdi connecton object */
     backlog = ks_create_tconn();
@@ -6200,12 +6082,12 @@ errorout:
 
 void
 ks_replenish_backlogs(
-    ksock_tconn_t * parent,
-    int     nbacklog
+    ks_tconn_t *    parent,
+    int             nbacklog
     )
 {
-    ksock_tconn_t * backlog;
-    int            n = 0;
+    ks_tconn_t *    backlog;
+    int             n = 0;
 
     /* calculate how many backlogs needed */
     if ( ( parent->listener.kstc_listening.num +
@@ -6221,22 +6103,22 @@ ks_replenish_backlogs(
         /* create the backlog child tconn */
         backlog = ks_create_child_tconn(parent);
 
-        spin_lock(&(parent->kstc_lock));
+        cfs_spin_lock(&(parent->kstc_lock));
 
         if (backlog) {
-            spin_lock(&backlog->kstc_lock);
+            cfs_spin_lock(&backlog->kstc_lock);
             /* attch it into the listing list of daemon */
-            list_add( &backlog->child.kstc_link,
+            cfs_list_add( &backlog->child.kstc_link,
                       &parent->listener.kstc_listening.list );
             parent->listener.kstc_listening.num++;
 
             backlog->child.kstc_queued = TRUE;
-            spin_unlock(&backlog->kstc_lock);
+            cfs_spin_unlock(&backlog->kstc_lock);
         } else {
             cfs_enter_debugger();
         }
 
-        spin_unlock(&(parent->kstc_lock));
+        cfs_spin_unlock(&(parent->kstc_lock));
     }
 }
 
@@ -6257,7 +6139,7 @@ ks_replenish_backlogs(
  */
 
 int
-ks_start_listen(ksock_tconn_t *tconn, int nbacklog)
+ks_start_listen(ks_tconn_t *tconn, int nbacklog)
 {
     int rc = 0;
 
@@ -6265,43 +6147,43 @@ ks_start_listen(ksock_tconn_t *tconn, int nbacklog)
     ks_replenish_backlogs(tconn, nbacklog);
 
     /* set the event callback handlers */
-    rc = ks_set_handlers(tconn);
+    rc = KsSetHandlers(tconn);
 
     if (rc < 0) {
         return rc;
     }
 
-    spin_lock(&(tconn->kstc_lock));
+    cfs_spin_lock(&(tconn->kstc_lock));
     tconn->listener.nbacklog = nbacklog;
     tconn->kstc_state = ksts_listening;
     cfs_set_flag(tconn->kstc_flags, KS_TCONN_DAEMON_STARTED);
-    spin_unlock(&(tconn->kstc_lock));
+    cfs_spin_unlock(&(tconn->kstc_lock));
 
     return rc;
 }
 
 void
-ks_stop_listen(ksock_tconn_t *tconn)
+ks_stop_listen(ks_tconn_t *tconn)
 {
-    struct list_head *      list;
-    ksock_tconn_t *         backlog;
+    cfs_list_t *            list;
+    ks_tconn_t *            backlog;
 
     /* reset all tdi event callbacks to NULL */
-    ks_reset_handlers (tconn);
+    KsResetHandlers (tconn);
 
-    spin_lock(&tconn->kstc_lock);
+    cfs_spin_lock(&tconn->kstc_lock);
 
     cfs_clear_flag(tconn->kstc_flags, KS_TCONN_DAEMON_STARTED);
 
     /* cleanup all the listening backlog child connections */
-    list_for_each (list, &(tconn->listener.kstc_listening.list)) {
-        backlog = list_entry(list, ksock_tconn_t, child.kstc_link);
+    cfs_list_for_each (list, &(tconn->listener.kstc_listening.list)) {
+        backlog = cfs_list_entry(list, ks_tconn_t, child.kstc_link);
 
         /* destory and free it */
         ks_put_tconn(backlog);
     }
 
-    spin_unlock(&tconn->kstc_lock);
+    cfs_spin_unlock(&tconn->kstc_lock);
 
     /* wake up it from the waiting on new incoming connections */
     KeSetEvent(&tconn->listener.kstc_accept_event, 0, FALSE);
@@ -6328,19 +6210,19 @@ ks_stop_listen(ksock_tconn_t *tconn)
 
 int
 ks_wait_child_tconn(
-    ksock_tconn_t *  parent,
-    ksock_tconn_t ** child
+    ks_tconn_t *    parent,
+    ks_tconn_t **   child
     )
 {
-    struct list_head * tmp;
-    ksock_tconn_t * backlog = NULL;
+    cfs_list_t * tmp;
+    ks_tconn_t * backlog = NULL;
 
     ks_replenish_backlogs(parent, parent->listener.nbacklog);
 
-    spin_lock(&(parent->kstc_lock));
+    cfs_spin_lock(&(parent->kstc_lock));
 
     if (parent->listener.kstc_listening.num <= 0) {
-        spin_unlock(&(parent->kstc_lock));
+        cfs_spin_unlock(&(parent->kstc_lock));
         return -1;
     }
 
@@ -6348,33 +6230,33 @@ again:
 
     /* check the listening queue and try to search the accepted connecton */
 
-    list_for_each(tmp, &(parent->listener.kstc_listening.list)) {
-        backlog = list_entry (tmp, ksock_tconn_t, child.kstc_link);
+    cfs_list_for_each(tmp, &(parent->listener.kstc_listening.list)) {
+        backlog = cfs_list_entry (tmp, ks_tconn_t, child.kstc_link);
 
-        spin_lock(&(backlog->kstc_lock));
+        cfs_spin_lock(&(backlog->kstc_lock));
 
         if (backlog->child.kstc_accepted) {
 
             LASSERT(backlog->kstc_state == ksts_connected);
             LASSERT(backlog->child.kstc_busy);
 
-            list_del(&(backlog->child.kstc_link));
-            list_add(&(backlog->child.kstc_link),
-                     &(parent->listener.kstc_accepted.list));
+            cfs_list_del(&(backlog->child.kstc_link));
+            cfs_list_add(&(backlog->child.kstc_link),
+                         &(parent->listener.kstc_accepted.list));
             parent->listener.kstc_accepted.num++;
             parent->listener.kstc_listening.num--;
             backlog->child.kstc_queueno = 1;
 
-            spin_unlock(&(backlog->kstc_lock));
+            cfs_spin_unlock(&(backlog->kstc_lock));
 
             break;
         } else {
-            spin_unlock(&(backlog->kstc_lock));
+            cfs_spin_unlock(&(backlog->kstc_lock));
             backlog = NULL;
         }
     }
 
-    spin_unlock(&(parent->kstc_lock));
+    cfs_spin_unlock(&(parent->kstc_lock));
 
     /* we need wait until new incoming connections are requested
        or the case of shuting down the listenig daemon thread  */
@@ -6390,32 +6272,261 @@ again:
                 NULL
                 );
 
-        spin_lock(&(parent->kstc_lock));
+        cfs_spin_lock(&(parent->kstc_lock));
 
         /* check whether it's exptected to exit ? */
         if (!cfs_is_flag_set(parent->kstc_flags, KS_TCONN_DAEMON_STARTED)) {
-            spin_unlock(&(parent->kstc_lock));
+            cfs_spin_unlock(&(parent->kstc_lock));
         } else {
             goto again;
         }
     }
 
+    KsPrint((2, "ks_wait_child_tconn: connection %p accepted.\n", backlog));
+
     if (backlog) {
         /* query the local ip address of the connection */
         ks_query_local_ipaddr(backlog);
+    } else {
+        return -EINTR;
     }
-
     *child = backlog;
 
     return 0;
 }
 
+int
+ks_query_iovs_length(struct iovec  *iov, int niov)
+{
+    int             i;
+    int             total = 0;
+
+    LASSERT(iov != NULL);
+    LASSERT(niov > 0);
+
+    for (i=0; i < niov; i++) {
+        total += iov[i].iov_len;
+    }
+
+    return total;
+}
+
+int
+ks_query_kiovs_length(lnet_kiov_t *kiov, int nkiov)
+{
+    int             i;
+    int             total = 0;
+
+    LASSERT(kiov != NULL);
+    LASSERT(nkiov > 0);
+
+    for (i=0; i < nkiov; i++) {
+        total += kiov[i].kiov_len;
+    }
+
+    return total;
+}
+
+int
+ks_sock_buf_cb(void *tsdu, int ns, int off, char **buf)
+{
+    int rc = 0;
+
+    if (off < ns) {
+        *buf = (char *)tsdu + off;
+        rc = ns - off;
+    }
+    return rc;
+}
+
+int
+ks_sock_iov_cb(void *tsdu, int ns, int off, char **buf)
+{
+    int rc = 0, i;
+    struct iovec *iov = tsdu;
+
+    for (i=0; i < ns; i++) {
+        if ((size_t)off >= iov[i].iov_len) {
+            off -= iov[i].iov_len;
+        } else {
+            *buf = (char *)iov[i].iov_base + off;
+            rc = iov[i].iov_len - off;
+            break;
+        }
+    }
+    return rc;
+}
+
+int
+ks_sock_kiov_cb(void *tsdu, int ns, int off, char **buf)
+{
+    int rc = 0, i;
+    lnet_kiov_t *kiov = tsdu;
+
+    for (i=0; i < ns; i++) {
+        if ((size_t)off >= kiov[i].kiov_len) {
+            off -= kiov[i].kiov_len;
+        } else {
+            *buf = (char *)kiov[i].kiov_page->addr +
+                    kiov[i].kiov_offset + off;
+            rc = kiov[i].kiov_len - off;
+            break;
+        }
+    }
+    return rc;
+}
+
+typedef int (*ks_tsdu_cb_t)(void *tsdu, int ns, int off, char **buf);
+
+int
+ks_sock_io(ks_tconn_t *tconn, void *tsdu, int ns, int reqlen,
+           int flags, int timeout, int out, ks_tsdu_cb_t callback)
+{
+    ULONG       tflags;
+    BOOLEAN     expedited;
+    PKS_TSDUMGR TsduMgr;
+
+    int         rc;
+    int         length;
+    int         total = 0;
+    int64_t     remained;
+    PCHAR       buffer;
+    BOOLEAN     async;
+
+    LASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
+    remained = (int64_t)cfs_time_seconds(timeout);
+
+    /* query tsdu manager */
+    expedited = cfs_is_flag_set(flags, MSG_OOB);
+    TsduMgr = KsQueryTsduMgr(tconn, expedited, (BOOLEAN)out);
+
+    /* check whether equest is nonblocking */
+    if (async = cfs_is_flag_set(flags, MSG_DONTWAIT)) {
+        timeout = 0;
+    }
+
+    ks_get_tconn(tconn);
+    ks_lock_tsdumgr(TsduMgr);
+    if ( tconn->kstc_type != kstt_sender &&
+         tconn->kstc_type != kstt_child) {
+        rc = -EINVAL;
+        goto errorout;
+    }
+
+    while (length = callback(tsdu, ns, total, &buffer)) {
+
+        /* check whether socket is stil valid */
+        if (tconn->kstc_state != ksts_connected) {
+            rc = -ENOTCONN;
+            goto errorout;
+        }
+
+        if (out) {
+            tflags = KsTdiSendFlags(flags);
+            rc = KsWriteTsdus(TsduMgr, buffer, length, tflags);
+        } else {
+            tflags = KsTdiRecvFlags(flags);
+            rc = KsReadTsdus(TsduMgr, buffer, length, tflags);
+        }
+
+        if (rc > 0) {
+            total += rc;
+        } else if (!async && rc == -EAGAIN) {
+            if (timeout) {
+                if (remained) { 
+                    ks_unlock_tsdumgr(TsduMgr);
+                    remained = cfs_wait_event_internal(
+                                    &TsduMgr->Event,
+                                    remained );
+                } else {
+                    goto errorout;
+                }
+            } else {
+                ks_unlock_tsdumgr(TsduMgr);
+                cfs_wait_event_internal(&TsduMgr->Event, 0);
+            }
+            ks_lock_tsdumgr(TsduMgr);
+        } else {
+            break;
+        }
+    }
+
+errorout:
+
+    if (!out) {
+        TsduMgr->Payload = reqlen - total;
+    }
+    ks_unlock_tsdumgr(TsduMgr);
+
+    KsPrint((4, "ks_sock_io: tconn=%p tsdumgr=%p %c total=%xh/%xh rc=%d\n",
+                tconn, TsduMgr, out?'W':'R', total, TsduMgr->TotalBytes, rc));
+
+    if (total) {
+        if (out) {
+            /* signal Tdi sending engine */
+            KsQueueTdiEngine(tconn, TsduMgr);
+        }
+        rc = total;
+    }
+
+    ks_put_tconn(tconn);
+
+    LASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
+    return rc;
+}
+
+int ks_send_buf(ks_tconn_t * tconn, char *buf,
+                int len, int flags, int timeout)
+{
+    return ks_sock_io(tconn, buf, len, len, flags,
+                      timeout, 1, ks_sock_buf_cb);
+}
+
+int ks_recv_buf(ks_tconn_t * tconn, char *buf,
+                int len, int flags, int timeout)
+{
+    return ks_sock_io(tconn, buf, len, len, flags,
+                      timeout, 0, ks_sock_buf_cb);
+}
+
+int ks_send_iovs(ks_tconn_t * tconn, struct iovec *iov,
+                 int niov, int flags, int timeout)
+{
+    int reqlen = ks_query_iovs_length(iov, niov);
+    return ks_sock_io(tconn, iov, niov, reqlen, flags,
+                      timeout, TRUE, ks_sock_iov_cb);
+}
+
+int ks_recv_iovs(ks_tconn_t * tconn, struct iovec *iov,
+                 int niov, int flags, int timeout)
+{
+    int reqlen = ks_query_iovs_length(iov, niov);
+    return ks_sock_io(tconn, iov, niov, reqlen, flags,
+                      timeout, FALSE, ks_sock_iov_cb);
+}
+
+int ks_send_kiovs(ks_tconn_t * tconn, lnet_kiov_t *kiov,
+                  int nkiov, int flags, int timeout)
+{
+    int reqlen = ks_query_kiovs_length(kiov, nkiov);
+    return ks_sock_io(tconn, kiov, nkiov, reqlen, flags,
+                      timeout, TRUE, ks_sock_kiov_cb);
+}
+
+int ks_recv_kiovs(ks_tconn_t * tconn, lnet_kiov_t *kiov,
+                  int nkiov, int flags, int timeout)
+{
+    int reqlen = ks_query_kiovs_length(kiov, nkiov);
+    return ks_sock_io(tconn, kiov, nkiov, reqlen, flags,
+                      timeout, FALSE, ks_sock_kiov_cb);
+}
+
 int libcfs_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask)
 {
     ks_addr_slot_t * slot = NULL;
     PLIST_ENTRY      list = NULL;
 
-    spin_lock(&ks_data.ksnd_addrs_lock);
+    cfs_spin_lock(&ks_data.ksnd_addrs_lock);
 
     list = ks_data.ksnd_addrs_list.Flink;
     while (list != &ks_data.ksnd_addrs_list) {
@@ -6430,7 +6541,7 @@ int libcfs_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask)
         slot = NULL;
     }
 
-    spin_unlock(&ks_data.ksnd_addrs_lock);
+    cfs_spin_unlock(&ks_data.ksnd_addrs_lock);
 
     return (int)(slot == NULL);
 }
@@ -6441,7 +6552,7 @@ int libcfs_ipif_enumerate(char ***names)
     PLIST_ENTRY      list = NULL;
     int              nips = 0;
 
-    spin_lock(&ks_data.ksnd_addrs_lock);
+    cfs_spin_lock(&ks_data.ksnd_addrs_lock);
 
     *names = cfs_alloc(sizeof(char *) * ks_data.ksnd_naddrs, CFS_ALLOC_ZERO);
     if (*names == NULL) {
@@ -6460,7 +6571,7 @@ int libcfs_ipif_enumerate(char ***names)
 
 errorout:
 
-    spin_unlock(&ks_data.ksnd_addrs_lock);
+    cfs_spin_unlock(&ks_data.ksnd_addrs_lock);
     return nips;
 }
 
@@ -6473,8 +6584,8 @@ void libcfs_ipif_free_enumeration(char **names, int n)
 
 int libcfs_sock_listen(struct socket **sockp, __u32 ip, int port, int backlog)
 {
-    int                     rc = 0;
-    ksock_tconn_t *         parent;
+    int                 rc = 0;
+    ks_tconn_t *        parent;
 
     parent = ks_create_tconn();
     if (!parent) {
@@ -6517,7 +6628,7 @@ void libcfs_sock_abort_accept(struct socket *sock)
 {
     LASSERT(sock->kstc_type == kstt_listener);
 
-    spin_lock(&(sock->kstc_lock));
+    cfs_spin_lock(&(sock->kstc_lock));
 
     /* clear the daemon flag */
     cfs_clear_flag(sock->kstc_flags, KS_TCONN_DAEMON_STARTED);
@@ -6525,7 +6636,7 @@ void libcfs_sock_abort_accept(struct socket *sock)
     /* wake up it from the waiting on new incoming connections */
     KeSetEvent(&sock->listener.kstc_accept_event, 0, FALSE);
 
-    spin_unlock(&(sock->kstc_lock));
+    cfs_spin_unlock(&(sock->kstc_lock));
 }
 
 /*
@@ -6550,12 +6661,13 @@ int libcfs_sock_connect(struct socket **sockp, int *fatal,
                         __u32 local_ip, int local_port,
                         __u32 peer_ip, int peer_port)
 {
-    ksock_tconn_t * tconn = NULL;
+    ks_tconn_t *    tconn = NULL;
     int             rc = 0;
 
     *sockp = NULL;
+    if (fatal) *fatal = 0;
 
-    KsPrint((1, "libcfs_sock_connect: connecting to %x:%d with %x:%d...\n",
+    KsPrint((2, "libcfs_sock_connect: connecting to %x:%d with %x:%d...\n",
                 peer_ip, peer_port, local_ip, local_port ));
 
     /* create the tdi connecion structure */
@@ -6571,7 +6683,7 @@ int libcfs_sock_connect(struct socket **sockp, int *fatal,
     /* bind the local ip address with the tconn */
     rc = ks_bind_tconn(tconn, NULL, local_ip, (unsigned short)local_port);
     if (rc < 0) {
-        KsPrint((0, "libcfs_sock_connect: failed to bind address %x:%d...\n",
+        KsPrint((1, "libcfs_sock_connect: failed to bind address %x:%d...\n",
                     local_ip, local_port ));
         ks_free_tconn(tconn);
         goto errorout;
@@ -6580,7 +6692,7 @@ int libcfs_sock_connect(struct socket **sockp, int *fatal,
     /* connect to the remote peer */
     rc = ks_build_tconn(tconn, peer_ip, (unsigned short)peer_port);
     if (rc < 0) {
-        KsPrint((0, "libcfs_sock_connect: failed to connect %x:%d ...\n",
+        KsPrint((1, "libcfs_sock_connect: failed to connect %x:%d ...\n",
                     peer_ip, peer_port ));
 
         ks_put_tconn(tconn);
@@ -6608,7 +6720,7 @@ int libcfs_sock_getaddr(struct socket *socket, int remote, __u32 *ip, int *port)
 {
     PTRANSPORT_ADDRESS  taddr = NULL;
 
-    spin_lock(&socket->kstc_lock);
+    cfs_spin_lock(&socket->kstc_lock);
     if (remote) {
         if (socket->kstc_type == kstt_sender) {
             taddr = socket->sender.kstc_info.Remote;
@@ -6626,72 +6738,58 @@ int libcfs_sock_getaddr(struct socket *socket, int remote, __u32 *ip, int *port)
         if (port != NULL)
             *port = ntohs (addr->sin_port);
     } else {
-        spin_unlock(&socket->kstc_lock);
+        cfs_spin_unlock(&socket->kstc_lock);
         return -ENOTCONN;
     }
 
-    spin_unlock(&socket->kstc_lock);
+    cfs_spin_unlock(&socket->kstc_lock);
     return 0;
 }
 
 int libcfs_sock_write(struct socket *sock, void *buffer, int nob, int timeout)
 {
     int           rc;
-    ksock_mdl_t * mdl;
-
     int           offset = 0;
 
     while (nob > offset) {
 
-        /* lock the user buffer */
-        rc = ks_lock_buffer( (char *)buffer + offset,
-                        FALSE, nob - offset, IoReadAccess, &mdl );
+        rc = ks_send_buf(sock, (char *)buffer + offset, nob - offset, 0, timeout);
 
-        if (rc < 0) {
-            return (rc);
-        }
-
-        /* send out the whole mdl */
-        rc = ks_send_mdl( sock, NULL, mdl, nob - offset, 0 );
-
-        if (rc > 0) {
-            offset += rc;
+        if (rc <= 0) {
+            goto errorout;
         } else {
-            return (rc);
+            offset += rc;
+            rc = 0;
         }
     }
 
-    return (0);
+errorout:
+
+    KsPrint((4, "libcfs_sock_write: sock: %p %d bytes rc: %d\n", sock, offset, rc));
+    return rc;
 }
 
 int libcfs_sock_read(struct socket *sock, void *buffer, int nob, int timeout)
 {
-    int           rc;
-    ksock_mdl_t * mdl;
-
+    int           rc = 0;
     int           offset = 0;
 
     while (nob > offset) {
 
-        /* lock the user buffer */
-        rc = ks_lock_buffer( (char *)buffer + offset,
-                               FALSE, nob - offset, IoWriteAccess, &mdl );
-
-        if (rc < 0) {
-            return (rc);
-        }
-
-        /* recv the requested buffer */
-        rc = ks_recv_mdl( sock, mdl, nob - offset, 0 );
+        rc = ks_recv_buf(sock, (char *)buffer + offset, nob - offset, 0, timeout);
 
-        if (rc > 0) {
-            offset += rc;
+        if (rc <= 0) {
+            goto errorout;
         } else {
-            return (rc);
+            offset += rc;
+            rc = 0;
         }
     }
 
-    return (0);
+errorout:
+
+    KsPrint((4, "libcfs_sock_read: sock: %p %d bytes rc: %d\n", sock, offset, rc));
+    return rc;
 }
 
 void libcfs_sock_release(struct socket *sock)