Commit in reactos on MAIN
ChangeLog+501.220 -> 1.221
drivers/net/afd/afd/dispatch.c+45-171.10 -> 1.11
                   /tdi.c+18-211.11 -> 1.12
drivers/net/afd/include/afd.h+4-21.14 -> 1.15
drivers/net/tcpip/notes.txt+27added 1.1
                 /makefile+4-21.15 -> 1.16
drivers/net/tcpip/include/address.h+31.6 -> 1.7
                         /checksum.h+24-51.2 -> 1.3
                         /ip.h+5-41.8 -> 1.9
                         /tcp.h+36-271.4 -> 1.5
                         /titypes.h+22-41.5 -> 1.6
drivers/net/tcpip/network/icmp.c+1-11.6 -> 1.7
                         /receive.c+1-11.7 -> 1.8
                         /transmit.c+3-31.7 -> 1.8
drivers/net/tcpip/tcpip/address.c+25-21.9 -> 1.10
                       /checksum.c+27-201.2 -> 1.3
                       /dispatch.c+42-181.8 -> 1.9
                       /fileobjs.c+5-21.10 -> 1.11
                       /routines.c+53-121.10 -> 1.11
drivers/net/tcpip/tcpip/i386/checksum.S+249added 1.1
drivers/net/tcpip/transport/tcp/tcp.c+843-2091.8 -> 1.9
lib/msafd/include/msafd.h+71.6 -> 1.7
lib/msafd/misc/dllmain.c+43-191.11 -> 1.12
+1537-369
2 added + 21 modified, total 23 files
2004-03-04  Casper S. Hornstrup  <chorns@users.sourceforge.net>

	* drivers/net/tcpip/tcpip/i386: New directory.
	* drivers/net/tcpip/tcpip/i386/checksum.S: New file.
	* drivers/net/tcpip/notes.txt: New file.
	* drivers/net/afd/afd/dispatch.c (AfdDispCompleteListen): Signal ACCEPT
	network event.
	(AfdDispEventSelect): Reference event handle.
	* drivers/net/afd/afd/tdi.c (TdiListen): Remove unused event.
	Move Iosb and RequestConnectionInfo to AFD_LISTEN_REQUEST structure.
	* drivers/net/afd/include/afd.h (AFDFCB): Replace EventObjects with
	EventObject of type PKEVENT.
	* drivers/net/tcpip/makefile (ARCH_OBJECTS): New variable.
	(TARGET_OBJECTS): Add ARCH_OBJECTS.
	* drivers/net/tcpip/include/address.h (AddrCloneAddress): New prototype.
	* drivers/net/tcpip/include/checksum.h (ChecksumFold, csum_partial): New
	prototype.
	(TCPv4Checksum): New macro.
	(CorrectChecksum): Rename to IPv4CorrectChecksum.
	(TCPv4CorrectChecksum): New macro.
	* drivers/net/tcpip/include/ip.h (IPv4_DF_MASK): New constant.
	* drivers/net/tcpip/include/tcp.h (TCP_XXX): Correct constants.
	(TCPCreateSegment, TCPFreeSegment, TCPAddSegment): Prototype.
	* drivers/net/tcpip/include/titypes.h (TCP_SEND_REQUEST): Add SequenceNumber
	and AckNumber.
	(TCP_SEGMENT): New structure.
	(CONNECTION_ENDPOINT): Add ListenRequest and ReceivedSegments.
	* drivers/net/tcpip/network/transmit.c (SendFragments): Release memory
	for Data on failure.
	* drivers/net/tcpip/tcpip/address.c (AddrCloneAddress): New function.
	* drivers/net/tcpip/tcpip/checksum.c (ChecksumFold): Factor out folding
	from ChecksumCompute.
	* drivers/net/tcpip/tcpip/dispatch.c (DispTdiListen): Support asynchronous
	operation.
	* drivers/net/tcpip/tcpip/fileobjs.c (FileOpenAddress): Don't cast to
	PTDI_ADDRESS_IP.
	Initialize ReceivedSegments.
	* drivers/net/tcpip/tcpip/routines.c (DisplayIPHeader): New function.
	(DisplayIPPacket): Call DisplayIPHeader().
	(DisplayTCPHeader): Change format strings.
	* drivers/net/tcpip/transport/tcp/tcp.c (IPIdentification,
	TCPSegmentList): Add.
	(TCPCreateSegment, TCPFreeSegment, TCPAddSegment,
	TCPBuildAndTransmitSendRequest2, TCPiSelectISS, TCPiReceiveListen,
	TCPiReceiveSynSent, TCPiReceiveSynReceived, TCPiReceiveData): New
	function.
	(TCPiBuildPacket): Build segment.
	(TCPStartup): Initialize TCPSegmentList.
	(TCPShutdown): Cleanup TCPSegmentList.

reactos
ChangeLog 1.220 -> 1.221
diff -u -r1.220 -r1.221
--- ChangeLog	25 Feb 2004 20:27:56 -0000	1.220
+++ ChangeLog	4 Mar 2004 20:45:38 -0000	1.221
@@ -1,3 +1,53 @@
+2004-03-04  Casper S. Hornstrup  <chorns@users.sourceforge.net>
+
+	* drivers/net/tcpip/tcpip/i386: New directory.
+	* drivers/net/tcpip/tcpip/i386/checksum.S: New file.
+	* drivers/net/tcpip/notes.txt: New file.
+	* drivers/net/afd/afd/dispatch.c (AfdDispCompleteListen): Signal ACCEPT
+	network event.
+	(AfdDispEventSelect): Reference event handle.
+	* drivers/net/afd/afd/tdi.c (TdiListen): Remove unused event.
+	Move Iosb and RequestConnectionInfo to AFD_LISTEN_REQUEST structure.
+	* drivers/net/afd/include/afd.h (AFDFCB): Replace EventObjects with
+	EventObject of type PKEVENT.
+	* drivers/net/tcpip/makefile (ARCH_OBJECTS): New variable.
+	(TARGET_OBJECTS): Add ARCH_OBJECTS.
+	* drivers/net/tcpip/include/address.h (AddrCloneAddress): New prototype.
+	* drivers/net/tcpip/include/checksum.h (ChecksumFold, csum_partial): New
+	prototype.
+	(TCPv4Checksum): New macro.
+	(CorrectChecksum): Rename to IPv4CorrectChecksum.
+	(TCPv4CorrectChecksum): New macro.
+	* drivers/net/tcpip/include/ip.h (IPv4_DF_MASK): New constant.
+	* drivers/net/tcpip/include/tcp.h (TCP_XXX): Correct constants.
+	(TCPCreateSegment, TCPFreeSegment, TCPAddSegment): Prototype.
+	* drivers/net/tcpip/include/titypes.h (TCP_SEND_REQUEST): Add SequenceNumber
+	and AckNumber.
+	(TCP_SEGMENT): New structure.
+	(CONNECTION_ENDPOINT): Add ListenRequest and ReceivedSegments.
+	* drivers/net/tcpip/network/transmit.c (SendFragments): Release memory
+	for Data on failure.
+	* drivers/net/tcpip/tcpip/address.c (AddrCloneAddress): New function.
+	* drivers/net/tcpip/tcpip/checksum.c (ChecksumFold): Factor out folding
+	from ChecksumCompute.
+	* drivers/net/tcpip/tcpip/dispatch.c (DispTdiListen): Support asynchronous
+	operation.
+	* drivers/net/tcpip/tcpip/fileobjs.c (FileOpenAddress): Don't cast to
+	PTDI_ADDRESS_IP.
+	Initialize ReceivedSegments.
+	* drivers/net/tcpip/tcpip/routines.c (DisplayIPHeader): New function.
+	(DisplayIPPacket): Call DisplayIPHeader().
+	(DisplayTCPHeader): Change format strings.
+	* drivers/net/tcpip/transport/tcp/tcp.c (IPIdentification,
+	TCPSegmentList): Add.
+	(TCPCreateSegment, TCPFreeSegment, TCPAddSegment,
+	TCPBuildAndTransmitSendRequest2, TCPiSelectISS, TCPiReceiveListen,
+	TCPiReceiveSynSent, TCPiReceiveSynReceived, TCPiReceiveData): New
+	function.
+	(TCPiBuildPacket): Build segment.
+	(TCPStartup): Initialize TCPSegmentList.
+	(TCPShutdown): Cleanup TCPSegmentList.
+
 2004-02-25  Casper S. Hornstrup  <chorns@users.sourceforge.net>
 
 	* drivers/net/tcpip/datalink/loopback.c: Reformat.

reactos/drivers/net/afd/afd
dispatch.c 1.10 -> 1.11
diff -u -r1.10 -r1.11
--- dispatch.c	10 Feb 2004 17:12:41 -0000	1.10
+++ dispatch.c	4 Mar 2004 20:45:38 -0000	1.11
@@ -139,9 +139,25 @@
 {
   PAFD_LISTEN_REQUEST ListenRequest = (PAFD_LISTEN_REQUEST) Context;
 
-  AFD_DbgPrint(MAX_TRACE, ("Called. ListenRequest (0x%X).\n", ListenRequest));
+  /* FIXME: Protect ListenRequest->Fcb->ListenRequestQueue */
+  RemoveEntryList(&ListenRequest->ListEntry);
 
-  AFD_DbgPrint(MAX_TRACE, ("Fcb (0x%X).\n", ListenRequest->Fcb));
+  AFD_DbgPrint(MAX_TRACE, ("Completed ListenRequest at (0x%X).\n", ListenRequest));
+
+  if (NT_SUCCESS(ListenRequest->Iosb.Status))
+    {
+	  if (ListenRequest->Fcb->EventObject != NULL)
+	    {
+          /* FIXME: Protect ListenRequest->Fcb */
+          ListenRequest->Fcb->NetworkEvents.lNetworkEvents |= FD_ACCEPT;
+          ListenRequest->Fcb->NetworkEvents.iErrorCode[FD_ACCEPT_BIT] = NO_ERROR;
+	      KeSetEvent(ListenRequest->Fcb->EventObject, EVENT_INCREMENT, FALSE);
+	    }
+    }
+
+  ExFreePool(ListenRequest->RequestConnectionInfo);
+  ListenRequest->RequestConnectionInfo = NULL;
+  ExFreePool(ListenRequest);
 
   return STATUS_SUCCESS;
 }
@@ -197,14 +213,14 @@
 
             if (NT_SUCCESS(Status))
               {
-		            ListenRequest = ExAllocateFromNPagedLookasideList(&ListenRequestLookasideList);
+                ListenRequest = ExAllocateFromNPagedLookasideList(&ListenRequestLookasideList);
                 if (ListenRequest != NULL)
                   {
                     ListenRequest->Fcb = FCB;
                     /* FIXME: Protect ListenRequestQueue */
                     InsertTailList(&FCB->ListenRequestQueue, &ListenRequest->ListEntry);
 
-                    Status = TdiListen(FCB->TdiConnectionObject, AfdDispCompleteListen, ListenRequest);
+                    Status = TdiListen(ListenRequest, AfdDispCompleteListen, ListenRequest);
                     if ((Status == STATUS_PENDING) || NT_SUCCESS(Status))
                       {
                         if (Status != STATUS_PENDING)
@@ -630,8 +646,8 @@
   UINT OutputBufferLength;
   PFILE_REQUEST_EVENTSELECT Request;
   PFILE_REPLY_EVENTSELECT Reply;
+  PKEVENT Event;
   PAFDFCB FCB;
-  ULONG i;
 
   InputBufferLength  = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
   OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
@@ -644,20 +660,32 @@
     Request = (PFILE_REQUEST_EVENTSELECT)Irp->AssociatedIrp.SystemBuffer;
     Reply   = (PFILE_REPLY_EVENTSELECT)Irp->AssociatedIrp.SystemBuffer;
 
-    FCB->NetworkEvents.lNetworkEvents = Request->lNetworkEvents;
-    for (i = 0; i < FD_MAX_EVENTS; i++) {
-      if ((Request->lNetworkEvents & (1 << i)) > 0) {
-        FCB->EventObjects[i] = Request->hEventObject;
-      } else {
-        /* The effect of any previous call to this function is cancelled */
-        FCB->EventObjects[i] = (WSAEVENT)0;
-      }
-    }
+	/* FIXME: Need to ObDereferenceObject(FCB->EventObject) this somewhere */
+	Status = ObReferenceObjectByHandle(
+      Request->hEventObject,
+      0,
+      ExEventObjectType,
+      UserMode,
+      (PVOID*)&Event,
+      NULL);
+    if (NT_SUCCESS(Status)) {
+      FCB->NetworkEvents.lNetworkEvents = Request->lNetworkEvents;
+	  FCB->EventObject = Event;
+      Reply->Status = NO_ERROR;
+      Status = STATUS_SUCCESS;
+	}
+	else
+	{
+	  AFD_DbgPrint(MID_TRACE, ("Bad event handle (0x%X).\n", Status));
 
-    Reply->Status = NO_ERROR;
-    Status = STATUS_SUCCESS;
-  } else
+	  Reply->Status = WSAEINVAL;
+      Status = STATUS_SUCCESS;
+    }
+  }
+  else
+  {
     Status = STATUS_INVALID_PARAMETER;
+  }
 
   AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
 

reactos/drivers/net/afd/afd
tdi.c 1.11 -> 1.12
diff -u -r1.11 -r1.12
--- tdi.c	2 Mar 2004 18:18:13 -0000	1.11
+++ tdi.c	4 Mar 2004 20:45:38 -0000	1.12
@@ -199,6 +199,7 @@
   EaInfo->EaValueLength = sizeof(TA_IP_ADDRESS);
   Address = (PTA_IP_ADDRESS)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH + 1); /* 0-terminated */
   TdiBuildAddressIPv4(Address, Name);
+
   Status = TdiOpenDevice(DeviceName,
                          EaLength,
                          EaInfo,
@@ -414,13 +415,13 @@
 
 
 NTSTATUS TdiListen(
-  PFILE_OBJECT ConnectionObject,
+  PAFD_LISTEN_REQUEST ListenRequest,
   PIO_COMPLETION_ROUTINE  CompletionRoutine,
   PVOID CompletionContext)
 /*
  * FUNCTION: Listen on a connection endpoint for a connection request from a remote peer
  * ARGUMENTS:
- *     ConnectionObject  = Pointer to connection endpoint file object
+ *     ListenRequest     = Pointer to listen request object
  *     CompletionRoutine = Routine to be called when IRP is completed
  *     CompletionContext = Context for CompletionRoutine
  * RETURNS:
@@ -428,35 +429,34 @@
  *     May return STATUS_PENDING
  */
 {
-  PTDI_CONNECTION_INFORMATION RequestConnectionInfo;
-  //PTDI_CONNECTION_INFORMATION ReturnConnectionInfo;
+  PFILE_OBJECT ConnectionObject;
   PDEVICE_OBJECT DeviceObject;
-  IO_STATUS_BLOCK Iosb;
   NTSTATUS Status;
-  KEVENT Event;
   PIRP Irp;
 
   AFD_DbgPrint(MAX_TRACE, ("Called\n"));
 
+  ConnectionObject = ListenRequest->Fcb->TdiConnectionObject;
   assert(ConnectionObject);
 
   DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
 
-  Status = TdiBuildNullConnectionInfo(&RequestConnectionInfo, TDI_ADDRESS_TYPE_IP);
+  Status = TdiBuildNullConnectionInfo(&ListenRequest->RequestConnectionInfo,
+    TDI_ADDRESS_TYPE_IP);
   if (!NT_SUCCESS(Status))
-     return Status;
-
-  KeInitializeEvent(&Event, NotificationEvent, FALSE);
+    return Status;
 
   Irp = TdiBuildInternalDeviceControlIrp(TDI_LISTEN,              /* Sub function */
                                          DeviceObject,            /* Device object */
                                          ConnectionObject,        /* File object */
-                                         &Event,                  /* Event */
-                                         &Iosb);                  /* Status */
-  if (!Irp) {
-    ExFreePool(RequestConnectionInfo);
-    return STATUS_INSUFFICIENT_RESOURCES;
-  }
+                                         NULL,                    /* Event */
+                                         &ListenRequest->Iosb);   /* Status */
+  if (Irp == NULL)
+    {
+      ExFreePool(ListenRequest->RequestConnectionInfo);
+	  ListenRequest->RequestConnectionInfo = NULL;
+      return STATUS_INSUFFICIENT_RESOURCES;
+    }
 
   TdiBuildListen(Irp,                    /* IRP */
                  DeviceObject,           /* Device object */
@@ -464,13 +464,10 @@
                  CompletionRoutine,      /* Completion routine */
                  CompletionContext,      /* Completion routine context */
                  0,                      /* Flags */
-                 RequestConnectionInfo,  /* Request connection information */
+                 ListenRequest->RequestConnectionInfo,  /* Request connection information */
                  NULL /* ReturnConnectionInfo */);  /* Return connection information */
 
-  Status = TdiCall(Irp, DeviceObject, NULL /* Don't wait for completion */, &Iosb);
-
-  ExFreePool(RequestConnectionInfo);
-  //ExFreePool(ReturnConnectionInfo);
+  Status = TdiCall(Irp, DeviceObject, NULL /* Don't wait for completion */, &ListenRequest->Iosb);
 
   return Status;
 }

reactos/drivers/net/afd/include
afd.h 1.14 -> 1.15
diff -u -r1.14 -r1.15
--- afd.h	2 Mar 2004 18:18:13 -0000	1.14
+++ afd.h	4 Mar 2004 20:45:38 -0000	1.15
@@ -75,7 +75,7 @@
     LIST_ENTRY          ListenRequestQueue;
     /* For WSAEventSelect() */
     WSANETWORKEVENTS    NetworkEvents;
-    WSAEVENT            EventObjects[FD_MAX_EVENTS];
+    PKEVENT             EventObject;
 } AFDFCB, *PAFDFCB;
 
 /* Socket states */
@@ -99,6 +99,8 @@
 typedef struct _AFD_LISTEN_REQUEST {
   LIST_ENTRY ListEntry;
   PAFDFCB Fcb;
+  PTDI_CONNECTION_INFORMATION RequestConnectionInfo;
+  IO_STATUS_BLOCK Iosb;
 } AFD_LISTEN_REQUEST, *PAFD_LISTEN_REQUEST;
 
 typedef struct IPSNMP_INFO {
@@ -363,7 +365,7 @@
   PFILE_OBJECT ConnectionObject);
 
 NTSTATUS TdiListen(
-  PFILE_OBJECT ConnectionObject,
+  PAFD_LISTEN_REQUEST Request,
   PIO_COMPLETION_ROUTINE  CompletionRoutine,
   PVOID CompletionContext);
 

reactos/drivers/net/tcpip
notes.txt added at 1.1
diff -N notes.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ notes.txt	4 Mar 2004 20:45:38 -0000	1.1
@@ -0,0 +1,27 @@
+
+RFC 791 - Internet Protocol
+http://www.faqs.org/rfcs/rfc791.html
+
+RFC 792 - Internet Control Message Protocol
+http://www.faqs.org/rfcs/rfc792.html
+
+RFC 793 - Transmission Control Protocol
+http://www.faqs.org/rfcs/rfc793.html
+
+RFC 826 - Ethernet Address Resolution Protocol
+http://www.faqs.org/rfcs/rfc826.html
+
+RFC 1122 - Requirements for Internet Hosts - Communication Layers
+http://www.faqs.org/rfcs/rfc1122.html
+
+RFC 1123 - Requirements for Internet Hosts - Application and Support
+http://www.faqs.org/rfcs/rfc1123.html
+
+RFC 2398 - Some Testing Tools for TCP Implementors
+http://www.faqs.org/rfcs/rfc2398.html
+
+RFC 2525 - Known TCP Implementation Problems
+http://www.faqs.org/rfcs/rfc2525.html
+
+RFC 2581 - TCP Congestion Control
+http://www.faqs.org/rfcs/rfc2581.html
\ No newline at end of file

reactos/drivers/net/tcpip
makefile 1.15 -> 1.16
diff -u -r1.15 -r1.16
--- makefile	2 Mar 2004 18:18:14 -0000	1.15
+++ makefile	4 Mar 2004 20:45:38 -0000	1.16
@@ -1,4 +1,4 @@
-# $Id: makefile,v 1.15 2004/03/02 18:18:14 navaraf Exp $
+# $Id: makefile,v 1.16 2004/03/04 20:45:38 chorns Exp $
 
 PATH_TO_TOP = ../../..
 
@@ -34,6 +34,7 @@
                    transport/tcp/tcp_input.o transport/tcp/tcp_ipv4.o \
                    transport/tcp/tcp_output.o transport/tcp/tcp_timer.o
 UDP_OBJECTS      = transport/udp/udp.o
+ARCH_OBJECTS     = tcpip/i386/checksum.o
 
 TARGET_OBJECTS = \
   $(TCPIP_OBJECTS) \
@@ -42,7 +43,8 @@
   $(DATAGRAM_OBJECTS) \
   $(RAWIP_OBJECTS) \
   $(TCP_OBJECTS) \
-  $(UDP_OBJECTS)
+  $(UDP_OBJECTS) \
+  $(ARCH_OBJECTS)
 
 include $(PATH_TO_TOP)/rules.mak
 

reactos/drivers/net/tcpip/include
address.h 1.6 -> 1.7
diff -u -r1.6 -r1.7
--- address.h	2 Mar 2004 18:18:14 -0000	1.6
+++ address.h	4 Mar 2004 20:45:38 -0000	1.7
@@ -61,6 +61,9 @@
 PIP_ADDRESS AddrBuildIPv4(
     IPv4_RAW_ADDRESS Address);
 
+PIP_ADDRESS AddrCloneAddress(
+    PIP_ADDRESS Address);
+
 PADDRESS_ENTRY AddrLocateADEv4(
     IPv4_RAW_ADDRESS Address);
 

reactos/drivers/net/tcpip/include
checksum.h 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- checksum.h	2 Aug 2000 00:21:35 -0000	1.2
+++ checksum.h	4 Mar 2004 20:45:38 -0000	1.3
@@ -8,20 +8,39 @@
 #define __CHECKSUM_H
 
 
+ULONG ChecksumFold(
+  ULONG Sum);
+
 ULONG ChecksumCompute(
     PVOID Data,
     UINT Count,
     ULONG Seed);
 
-#define IPv4Checksum(Data, Count, Seed)(ChecksumCompute(Data, Count, Seed))
+unsigned int
+csum_partial(
+  const unsigned char * buff,
+  int len,
+  unsigned int sum);
+
+#define IPv4Checksum(Data, Count, Seed)(~ChecksumFold(ChecksumCompute(Data, Count, Seed)))
+#define TCPv4Checksum(Data, Count, Seed)(~ChecksumFold(csum_partial(Data, Count, Seed)))
+//#define TCPv4Checksum(Data, Count, Seed)(~ChecksumFold(ChecksumCompute(Data, Count, Seed)))
 
 /*
  * Macro to check for a correct checksum
- * BOOLEAN CorrectChecksum(PVOID Data, UINT Count)
+ * BOOLEAN IPv4CorrectChecksum(PVOID Data, UINT Count)
  */
-#define CorrectChecksum(Data, Count) \
+#define IPv4CorrectChecksum(Data, Count) \
     (BOOLEAN)(IPv4Checksum(Data, Count, 0) == DH2N(0x0000FFFF))
 
-#endif /* __CHECKSUM_H */
+/*
+ * Macro to check for a correct checksum
+ * BOOLEAN TCPv4CorrectChecksum(PTCPv4_PSEUDO_HEADER TcpPseudoHeader,
+ *   PVOID Data, UINT Count)
+ */
+#define TCPv4CorrectChecksum(TcpPseudoHeader, Data, Count) \
+    (BOOLEAN)(TCPv4Checksum(Data, Count, \
+      TCPv4Checksum(TcpPseudoHeader, sizeof(TCPv4_PSEUDO_HEADER), \
+      0)) == DH2N(0x0000FFFF))
 
-/* EOF */
+#endif /* __CHECKSUM_H */

reactos/drivers/net/tcpip/include
ip.h 1.8 -> 1.9
diff -u -r1.8 -r1.9
--- ip.h	2 Mar 2004 18:18:14 -0000	1.8
+++ ip.h	4 Mar 2004 20:45:38 -0000	1.9
@@ -49,8 +49,9 @@
     IPv4_RAW_ADDRESS DstAddr;    /* Destination Address */
 } IPv4_HEADER, *PIPv4_HEADER;
 
-#define IPv4_FRAGOFS_MASK       0x1FFF
-#define IPv4_MF_MASK            0x2000
+#define IPv4_FRAGOFS_MASK       0x1FFF /* Fragment offset mask (host byte order) */
+#define IPv4_MF_MASK            0x2000 /* More fragments (host byte order) */
+#define IPv4_DF_MASK            0x4000 /* Don't fragment (host byte order) */
 #define IPv4_MAX_HEADER_SIZE    60
 
 /* Packet completion handler prototype */
@@ -60,7 +61,7 @@
     NDIS_STATUS NdisStatus);
 
 /* Structure for an IP packet */
-typedef struct IP_PACKET {
+typedef struct _IP_PACKET {
     DEFINE_TAG
     ULONG RefCount;                     /* Reference count for this object */
     OBJECT_FREE_ROUTINE Free;           /* Routine used to free resources for the object */
@@ -81,7 +82,7 @@
 
 
 /* Packet context */
-typedef struct PACKET_CONTEXT {
+typedef struct _PACKET_CONTEXT {
     PACKET_COMPLETION_ROUTINE Complete;   /* Transport level completion handler */
     PVOID Context;                        /* Context information for handler */
     PACKET_COMPLETION_ROUTINE DLComplete; /* Data link level completion handler. Also

reactos/drivers/net/tcpip/include
tcp.h 1.4 -> 1.5
diff -u -r1.4 -r1.5
--- tcp.h	25 Dec 2003 14:06:14 -0000	1.4
+++ tcp.h	4 Mar 2004 20:45:38 -0000	1.5
@@ -7,27 +7,26 @@
 #ifndef __TCP_H
 #define __TCP_H
 
-
 /* TCPv4 header structure */
-typedef struct TCP_HEADER {
-  USHORT SourcePort; /* Source port */
-  USHORT DestPort;   /* Destination port */
-  USHORT SeqNum;     /* Sequence number */
-  USHORT AckNum;     /* Acknowledgment number */
-  UCHAR  DataOfs;    /* Data offset (leftmost 4 bits) */
-  UCHAR  Flags;      /* Control bits (rightmost 6 bits) */
-  USHORT Window;     /* Maximum acceptable receive window */
-  USHORT Checksum;   /* Checksum of segment */
-  USHORT Urgent;     /* Pointer to urgent data */
-} __attribute__((packed)) TCP_HEADER, *PTCP_HEADER;
+typedef struct TCPv4_HEADER {
+  USHORT SourcePort;        /* Source port */
+  USHORT DestinationPort;   /* Destination port */
+  ULONG  SequenceNumber;    /* Sequence number */
+  ULONG  AckNumber;         /* Acknowledgement number */
+  UCHAR  DataOffset;        /* Data offset; 32-bit words (leftmost 4 bits) */
+  UCHAR  Flags;             /* Control bits (rightmost 6 bits) */
+  USHORT Window;            /* Maximum acceptable receive window */
+  USHORT Checksum;          /* Checksum of segment */
+  USHORT Urgent;            /* Pointer to urgent data */
+} __attribute__((packed)) TCPv4_HEADER, *PTCPv4_HEADER;
 
 /* TCPv4 header flags */
-#define TCP_URG   0x04
-#define TCP_ACK   0x08
-#define TCP_PSH   0x10
-#define TCP_RST   0x20
-#define TCP_SYN   0x40
-#define TCP_FIN   0x80
+#define TCP_URG   0x20
+#define TCP_ACK   0x10
+#define TCP_PSH   0x08
+#define TCP_RST   0x04
+#define TCP_SYN   0x02
+#define TCP_FIN   0x01
 
 
 #define TCPOPT_END_OF_LIST  0x0
@@ -38,13 +37,13 @@
 
 
 /* TCPv4 pseudo header */
-typedef struct TCP_PSEUDO_HEADER {
-  ULONG SourceAddress; /* Source address */
-  ULONG DestAddress;   /* Destination address */
-  UCHAR Zero;          /* Reserved */
-  UCHAR Protocol;      /* Protocol */
-  USHORT TCPLength;    /* Size of TCP segment */
-} __attribute__((packed)) TCP_PSEUDO_HEADER, *PTCP_PSEUDO_HEADER;
+typedef struct TCPv4_PSEUDO_HEADER {
+  ULONG SourceAddress;      /* Source address */
+  ULONG DestinationAddress; /* Destination address */
+  UCHAR Zero;               /* Reserved */
+  UCHAR Protocol;           /* Protocol */
+  USHORT TCPLength;         /* Size of TCP segment */
+} __attribute__((packed)) TCPv4_PSEUDO_HEADER, *PTCPv4_PSEUDO_HEADER;
 
 
 /* Retransmission timeout constants */
@@ -72,6 +71,18 @@
 #define SRF_FIN   TCP_FIN
 
 
+PTCP_SEGMENT TCPCreateSegment(
+  PIP_PACKET IPPacket,
+  ULONG SequenceNumber,
+  ULONG SegmentLength);
+
+VOID TCPFreeSegment(
+  PTCP_SEGMENT Segment);
+
+VOID TCPAddSegment(
+  PCONNECTION_ENDPOINT Connection,
+  PTCP_SEGMENT Segment);
+
 inline NTSTATUS TCPBuildSendRequest(
     PTCP_SEND_REQUEST *SendRequest,
     PDATAGRAM_SEND_REQUEST *DGSendRequest,
@@ -113,5 +124,3 @@
   VOID);
 
 #endif /* __TCP_H */
-
-/* EOF */

reactos/drivers/net/tcpip/include
titypes.h 1.5 -> 1.6
diff -u -r1.5 -r1.6
--- titypes.h	2 Feb 2004 21:02:48 -0000	1.5
+++ titypes.h	4 Mar 2004 20:45:38 -0000	1.6
@@ -266,6 +266,8 @@
   PVOID Context;                        /* Pointer to context information */
   PVOID ProtocolContext;                /* Protocol specific context */
   ULONG Flags;                          /* Protocol specific flags */
+  ULONG SequenceNumber;                 /* Sequence number (network byte order) */
+  ULONG AckNumber;                      /* Acknowledgement number (network byte order) */
 } TCP_SEND_REQUEST, *PTCP_SEND_REQUEST;
 
 #define InitializeTCPSendRequest( \
@@ -296,6 +298,15 @@
 } CONNECTION_STATE, *PCONNECTION_STATE;
 
 
+/* Structure for an TCP segment */
+typedef struct _TCP_SEGMENT {
+  LIST_ENTRY ListEntry;
+  PIP_PACKET IPPacket;        /* Pointer to IP packet */
+  ULONG SequenceNumber;       /* Sequence number of first byte in segment */
+  ULONG Length;               /* Number of bytes in segment */
+} TCP_SEGMENT, *PTCP_SEGMENT;
+
+
 /* Transport connection context structure A.K.A. Transmission Control Block
    (TCB) in TCP terminology. The FileObject->FsContext2 field holds a pointer
    to this structure */
@@ -324,14 +335,21 @@
   ULONG SendISS;              /* Initial send sequence number */
 
   /* Receive sequence variables */
-  ULONG RecvNext;             /* Sequence number of last data block received */
-  ULONG RecvWindow;           /* Maximum allowed number of octets in a segment */
-  ULONG RecvUrgentPointer;    /* Sequence number of start of urgent data */
-  ULONG RecvIRS;              /* Initial receive sequence number */
+  ULONG ReceiveNext;          /* Sequence number of last data block received */
+  ULONG ReceiveWindow;        /* Maximum allowed number of octets in a segment */
+  ULONG ReceiveUrgentPointer; /* Sequence number of start of urgent data */
+  ULONG ReceiveIRS;           /* Initial receive sequence number */
 
   /* Statistics for computing the retransmission timeout */
   ULONG TimestampSend;        /* Timestamp when sending a segment */
   ULONG TimestampAck;         /* Timestamp when receiving acknowledgment */
+
+  /* Requests */
+  PTDI_REQUEST ListenRequest; /* Queued listen request */
+
+  /* Queues */
+  LIST_ENTRY ReceivedSegments;
+
 } CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT;
 
 

reactos/drivers/net/tcpip/network
icmp.c 1.6 -> 1.7
diff -u -r1.6 -r1.7
--- icmp.c	4 Jul 2001 20:40:23 -0000	1.6
+++ icmp.c	4 Mar 2004 20:45:39 -0000	1.7
@@ -182,7 +182,7 @@
     TI_DbgPrint(DEBUG_ICMP, ("Checksum (0x%X).\n", ICMPHeader->Checksum));
 
     /* Checksum ICMP header and data */
-    if (!CorrectChecksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize)) {
+    if (!IPv4CorrectChecksum(IPPacket->Data, IPPacket->TotalSize - IPPacket->HeaderSize)) {
         TI_DbgPrint(DEBUG_ICMP, ("Bad ICMP checksum.\n"));
         /* Discard packet */
         return;

reactos/drivers/net/tcpip/network
receive.c 1.7 -> 1.8
diff -u -r1.7 -r1.8
--- receive.c	10 Nov 2002 13:52:13 -0000	1.7
+++ receive.c	4 Mar 2004 20:45:39 -0000	1.8
@@ -552,7 +552,7 @@
   }
 
   /* Checksum IPv4 header */
-  if (!CorrectChecksum(IPPacket->Header, IPPacket->HeaderSize)) {
+  if (!IPv4CorrectChecksum(IPPacket->Header, IPPacket->HeaderSize)) {
     TI_DbgPrint(MIN_TRACE, ("Datagram received with bad checksum. Checksum field (0x%X)\n",
       WN2H(((PIPv4_HEADER)IPPacket->Header)->Checksum)));
     /* Discard packet */

reactos/drivers/net/tcpip/network
transmit.c 1.7 -> 1.8
diff -u -r1.7 -r1.8
--- transmit.c	24 Sep 2002 15:10:35 -0000	1.7
+++ transmit.c	4 Mar 2004 20:45:39 -0000	1.8
@@ -104,13 +104,13 @@
         IPPacket, NCE, PathMTU));
 
     IFC = ExAllocatePool(NonPagedPool, sizeof(IPFRAGMENT_CONTEXT));
-    if (!IFC)
+    if (IFC == NULL)
         return STATUS_INSUFFICIENT_RESOURCES;
 
     /* We allocate a buffer for a PathMTU sized packet and reuse
        it for all fragments */
     Data = ExAllocatePool(NonPagedPool, MaxLLHeaderSize + PathMTU);
-    if (!IFC->Header) {
+    if (Data == NULL) {
         ExFreePool(IFC);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
@@ -118,7 +118,7 @@
     /* Allocate NDIS packet */
     NdisAllocatePacket(&NdisStatus, &IFC->NdisPacket, GlobalPacketPool);
     if (NdisStatus != NDIS_STATUS_SUCCESS) {
-        //ExFreePool(Data); // RobD - why are we trying to free this here?, not allocated yet!
+        ExFreePool(Data);
         ExFreePool(IFC);
         return STATUS_INSUFFICIENT_RESOURCES;
     }

reactos/drivers/net/tcpip/tcpip
address.c 1.9 -> 1.10
diff -u -r1.9 -r1.10
--- address.c	2 Mar 2004 18:18:14 -0000	1.9
+++ address.c	4 Mar 2004 20:45:39 -0000	1.10
@@ -289,7 +289,7 @@
 /*
  * FUNCTION: Build an IPv4 style address
  * ARGUMENTS:
- *     Address = Raw IPv4 address
+ *     Address = Raw IPv4 address (network byte order)
  * RETURNS:
  *     Pointer to IP address structure, NULL if there was not enough free
  *     non-paged memory
@@ -300,7 +300,7 @@
     PIP_ADDRESS IPAddress;
 
     IPAddress = ExAllocatePool(NonPagedPool, sizeof(IP_ADDRESS));
-    if (IPAddress) {
+    if (IPAddress != NULL) {
         IPAddress->RefCount            = 1;
         IPAddress->Type                = IP_ADDRESS_V4;
         IPAddress->Address.IPv4Address = Address;
@@ -312,6 +312,29 @@
 
 
 /*
+ * FUNCTION: Clone an IP address
+ * ARGUMENTS:
+ *     IPAddress = Pointer to IP address
+ * RETURNS:
+ *     Pointer to new IP address structure, NULL if there was not enough free
+ *     non-paged memory
+ */
+PIP_ADDRESS AddrCloneAddress(
+  PIP_ADDRESS Address)
+{
+  if (Address->Type == IP_ADDRESS_V4)
+    {
+      return AddrBuildIPv4(Address->Address.IPv4Address);
+    }
+  else
+    {
+      TI_DbgPrint(MIN_TRACE, ("Cannot clone IPv6 address.\n"));
+      return NULL;
+    }
+}
+
+
+/*
  * FUNCTION: Locates and returns an address entry using IPv4 adress as argument
  * ARGUMENTS:
  *     Address = Raw IPv4 address

reactos/drivers/net/tcpip/tcpip
checksum.c 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- checksum.c	2 Aug 2000 00:21:36 -0000	1.2
+++ checksum.c	4 Mar 2004 20:45:39 -0000	1.3
@@ -12,10 +12,22 @@
 #include <checksum.h>
 
 
+ULONG ChecksumFold(
+  ULONG Sum)
+{
+  /* Fold 32-bit sum to 16 bits */
+  while (Sum >> 16)
+    {
+      Sum = (Sum & 0xFFFF) + (Sum >> 16);
+    }
+
+  return Sum;
+}
+
 ULONG ChecksumCompute(
-    PVOID Data,
-    UINT Count,
-    ULONG Seed)
+  PVOID Data,
+  UINT Count,
+  ULONG Seed)
 /*
  * FUNCTION: Calculate checksum of a buffer
  * ARGUMENTS:
@@ -26,25 +38,20 @@
  *     Checksum of buffer
  */
 {
-    /* FIXME: This should be done in assembler */
+  register ULONG Sum = Seed;
 
-    register ULONG Sum = Seed;
-
-    while (Count > 1) {
-        Sum             += *(PUSHORT)Data;
-        Count           -= 2;
-        (ULONG_PTR)Data += 2;
+  while (Count > 1)
+    {
+      Sum += *(PUSHORT)Data;
+      Count -= 2;
+      (ULONG_PTR)Data += 2;
     }
 
-    /* Add left-over byte, if any */
-    if (Count > 0)
-        Sum += *(PUCHAR)Data;
-
-    /* Fold 32-bit sum to 16 bits */
-    while (Sum >> 16)
-        Sum = (Sum & 0xFFFF) + (Sum >> 16);
+  /* Add left-over byte, if any */
+  if (Count > 0)
+    {
+      Sum += *(PUCHAR)Data;
+    }
 
-    return ~Sum;
+  return Sum;
 }
-
-/* EOF */

reactos/drivers/net/tcpip/tcpip
dispatch.c 1.8 -> 1.9
diff -u -r1.8 -r1.9
--- dispatch.c	2 Mar 2004 18:18:14 -0000	1.8
+++ dispatch.c	4 Mar 2004 20:45:39 -0000	1.9
@@ -529,8 +529,9 @@
   PTDI_REQUEST_KERNEL Parameters;
   PTRANSPORT_CONTEXT TranContext;
   PIO_STACK_LOCATION IrpSp;
-  TDI_REQUEST Request;
+  PTDI_REQUEST Request;
   NTSTATUS Status;
+  KIRQL OldIrql;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -539,28 +540,51 @@
   /* Get associated connection endpoint file object. Quit if none exists */
 
   TranContext = IrpSp->FileObject->FsContext;
-  if (!TranContext) {
-    TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
-    return STATUS_INVALID_CONNECTION;
-  }
+  if (TranContext == NULL)
+    {
+      TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
+      return STATUS_INVALID_CONNECTION;
+    }
 
   Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
-  if (!Connection) {
-    TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
-    return STATUS_INVALID_CONNECTION;
-  }
+  if (Connection == NULL)
+    {
+      TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
+      return STATUS_INVALID_CONNECTION;
+    }
 
   Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
 
-  /* Initialize a connect request */
-  Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
-  Request.RequestNotifyObject      = DispDataRequestComplete;
-  Request.RequestContext           = Irp;
-
-  Status = TCPListen(
-    &Request,
-    Parameters->RequestConnectionInformation,
-    Parameters->ReturnConnectionInformation);
+  /* Initialize a listen request */
+  Request = (PTDI_REQUEST) ExAllocatePool(NonPagedPool, sizeof(TDI_REQUEST));
+  if (Request == NULL)
+    {
+      return STATUS_NO_MEMORY;
+    }
+
+  Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);
+  if (NT_SUCCESS(Status))
+    {
+      Request->Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
+      Request->RequestNotifyObject      = DispDataRequestComplete;
+      Request->RequestContext           = Irp;
+
+      Status = TCPListen(
+        Request,
+        Parameters->RequestConnectionInformation,
+        Parameters->ReturnConnectionInformation);
+      if (Status != STATUS_PENDING)
+        {
+          IoAcquireCancelSpinLock(&OldIrql);
+          IoSetCancelRoutine(Irp, NULL);
+          IoReleaseCancelSpinLock(OldIrql);
+        }
+    }
+
+  if (Status != STATUS_PENDING)
+    {
+      ExFreePool(Request);
+    }
 
   return Status;
 }

reactos/drivers/net/tcpip/tcpip
fileobjs.c 1.10 -> 1.11
diff -u -r1.10 -r1.11
--- fileobjs.c	7 Feb 2004 12:03:11 -0000	1.10
+++ fileobjs.c	4 Mar 2004 20:45:39 -0000	1.11
@@ -296,13 +296,13 @@
   switch (Protocol) {
   case IPPROTO_TCP:
     /* FIXME: If specified port is 0, a port is chosen dynamically */
-    AddrFile->Port = ((PTDI_ADDRESS_IP)Address->Address)->sin_port;
+    AddrFile->Port = Address->Address[0].Address[0].sin_port;
     AddrFile->Send = TCPSendDatagram;
     break;
 
   case IPPROTO_UDP:
     /* FIXME: If specified port is 0, a port is chosen dynamically */
-    AddrFile->Port = ((PTDI_ADDRESS_IP)Address->Address)->sin_port;
+    AddrFile->Port = Address->Address[0].Address[0].sin_port;
     AddrFile->Send = UDPSendDatagram;
     break;
 
@@ -449,6 +449,9 @@
   /* Save client context pointer */
   Connection->ClientContext = ClientContext;
 
+  /* Initialize receive queue */
+  InitializeListHead(&Connection->ReceivedSegments);
+
   /* Return connection endpoint file object */
   Request->Handle.ConnectionContext = Connection;
 

reactos/drivers/net/tcpip/tcpip
routines.c 1.10 -> 1.11
diff -u -r1.10 -r1.11
--- routines.c	2 Mar 2004 18:18:14 -0000	1.10
+++ routines.c	4 Mar 2004 20:45:39 -0000	1.11
@@ -480,6 +480,33 @@
 
 #ifdef DBG
 
+static VOID DisplayIPHeader(
+    PUCHAR Header,
+    UINT Length)
+{
+    /* FIXME: IPv4 only */
+    PIPv4_HEADER IPHeader = (PIPv4_HEADER)Header;
+
+    DbgPrint("IPv4 header:\n");
+    DbgPrint("VerIHL: 0x%x (version 0x%x, length %d 32-bit words)\n",
+      IPHeader->VerIHL, (IPHeader->VerIHL & 0xF0) >> 4, IPHeader->VerIHL & 0x0F);
+    DbgPrint("  Tos: %d\n", IPHeader->Tos);
+    DbgPrint("  TotalLength: %d\n", WN2H(IPHeader->TotalLength));
+    DbgPrint("  Id: %d\n", WN2H(IPHeader->Id));
+    DbgPrint("  FlagsFragOfs: 0x%x (offset 0x%x)\n", WN2H(IPHeader->FlagsFragOfs), WN2H(IPHeader->FlagsFragOfs) & IPv4_FRAGOFS_MASK);
+    if ((WN2H(IPHeader->FlagsFragOfs) & IPv4_DF_MASK) > 0) DbgPrint("    IPv4_DF - Don't fragment\n");
+    if ((WN2H(IPHeader->FlagsFragOfs) & IPv4_MF_MASK) > 0) DbgPrint("    IPv4_MF - More fragments\n");
+    DbgPrint("  Ttl: %d\n", IPHeader->Ttl);
+    DbgPrint("  Protocol: %d\n", IPHeader->Protocol);
+    DbgPrint("  Checksum: 0x%x\n", WN2H(IPHeader->Checksum));
+    DbgPrint("  SrcAddr: %d.%d.%d.%d\n",
+      ((IPHeader->SrcAddr >> 0) & 0xFF), ((IPHeader->SrcAddr >> 8) & 0xFF),
+      ((IPHeader->SrcAddr >> 16) & 0xFF), ((IPHeader->SrcAddr >> 24) & 0xFF));
+    DbgPrint("  DstAddr: %d.%d.%d.%d\n",
+      ((IPHeader->DstAddr >> 0) & 0xFF), ((IPHeader->DstAddr >> 8) & 0xFF),
+      ((IPHeader->DstAddr >> 16) & 0xFF), ((IPHeader->DstAddr >> 24) & 0xFF));
+}
+
 VOID DisplayIPPacket(
     PIP_PACKET IPPacket)
 {
@@ -488,6 +515,7 @@
     UINT Length;
     PNDIS_BUFFER Buffer;
     PNDIS_BUFFER NextBuffer;
+    PUCHAR CharBuffer;
 
     if ((DebugTraceLevel & (DEBUG_BUFFER | DEBUG_IP)) != (DEBUG_BUFFER | DEBUG_IP)) {
         return;
@@ -528,6 +556,19 @@
         }
         DbgPrint("\n");
     }
+
+    if (IPPacket->NdisPacket) {
+        NdisQueryPacket(IPPacket->NdisPacket, NULL, NULL, NULL, &Length);
+        Length -= MaxLLHeaderSize;
+        CharBuffer = ExAllocatePool(NonPagedPool, Length);
+        Length = CopyPacketToBuffer(CharBuffer, IPPacket->NdisPacket, MaxLLHeaderSize, Length);
+        DisplayIPHeader(CharBuffer, Length);
+        ExFreePool(CharBuffer);
+    } else {
+        CharBuffer = IPPacket->Header;
+        Length = IPPacket->ContigSize;
+        DisplayIPHeader(CharBuffer, Length);
+    }
 }
 
 
@@ -537,32 +578,31 @@
 {
     /* FIXME: IPv4 only */
     PIPv4_HEADER IPHeader = (PIPv4_HEADER)Header;
-    PTCP_HEADER TCPHeader;
+    PTCPv4_HEADER TCPHeader;
 
     if (IPHeader->Protocol != IPPROTO_TCP) {
         DbgPrint("This is not a TCP datagram. Protocol is %d\n", IPHeader->Protocol);
         return;
     }
 
-    DbgPrint("VerIHL: 0x%x\n", IPHeader->VerIHL);
-    TCPHeader = (PTCP_HEADER)((PUCHAR)IPHeader + (IPHeader->VerIHL & 0x0F) * 4);
+    TCPHeader = (PTCPv4_HEADER)((PUCHAR)IPHeader + (IPHeader->VerIHL & 0x0F) * 4);
 
     DbgPrint("TCP header:\n");
     DbgPrint("  SourcePort: %d\n", WN2H(TCPHeader->SourcePort));
-    DbgPrint("  DestPort: %d\n", WN2H(TCPHeader->DestPort));
-    DbgPrint("  SeqNum: %d\n", WN2H(TCPHeader->SeqNum));
-    DbgPrint("  AckNum: %d\n", WN2H(TCPHeader->AckNum));
-    DbgPrint("  DataOfs: %d (%d)\n", TCPHeader->DataOfs, TCPHeader->DataOfs & 0x0F);
+    DbgPrint("  DestinationPort: %d\n", WN2H(TCPHeader->DestinationPort));
+    DbgPrint("  SequenceNumber: 0x%x\n", DN2H(TCPHeader->SequenceNumber));
+    DbgPrint("  AckNumber: 0x%x\n", DN2H(TCPHeader->AckNumber));
+    DbgPrint("  DataOffset: 0x%x (0x%x) 32-bit words\n", TCPHeader->DataOffset, TCPHeader->DataOffset >> 4);
     DbgPrint("  Flags: 0x%x (0x%x)\n", TCPHeader->Flags, TCPHeader->Flags & 0x3F);
     if ((TCPHeader->Flags & TCP_URG) > 0) DbgPrint("    TCP_URG - Urgent Pointer field significant\n");
-    if ((TCPHeader->Flags & TCP_ACK) > 0) DbgPrint("    TCP_ACK - Acknowledgment field significant\n");
+    if ((TCPHeader->Flags & TCP_ACK) > 0) DbgPrint("    TCP_ACK - Acknowledgement field significant\n");
     if ((TCPHeader->Flags & TCP_PSH) > 0) DbgPrint("    TCP_PSH - Push Function\n");
     if ((TCPHeader->Flags & TCP_RST) > 0) DbgPrint("    TCP_RST - Reset the connection\n");
     if ((TCPHeader->Flags & TCP_SYN) > 0) DbgPrint("    TCP_SYN - Synchronize sequence numbers\n");
     if ((TCPHeader->Flags & TCP_FIN) > 0) DbgPrint("    TCP_FIN - No more data from sender\n");
-    DbgPrint("  Window: %d\n", WN2H(TCPHeader->Window));
-    DbgPrint("  Checksum: %d\n", WN2H(TCPHeader->Checksum));
-    DbgPrint("  Urgent: %d\n", WN2H(TCPHeader->Urgent));
+    DbgPrint("  Window: 0x%x\n", WN2H(TCPHeader->Window));
+    DbgPrint("  Checksum: 0x%x\n", WN2H(TCPHeader->Checksum));
+    DbgPrint("  Urgent: 0x%x\n", WN2H(TCPHeader->Urgent));
 }
 
 
@@ -592,8 +632,9 @@
 
     if (IPPacket->NdisPacket) {
         NdisQueryPacket(IPPacket->NdisPacket, NULL, NULL, NULL, &Length);
+        Length -= MaxLLHeaderSize;
         Buffer = ExAllocatePool(NonPagedPool, Length);
-        Length = CopyPacketToBuffer(Buffer, IPPacket->NdisPacket, 0, Length);
+        Length = CopyPacketToBuffer(Buffer, IPPacket->NdisPacket, MaxLLHeaderSize, Length);
         DisplayTCPHeader(Buffer, Length);
         ExFreePool(Buffer);
     } else {

reactos/drivers/net/tcpip/tcpip/i386
checksum.S added at 1.1
diff -N checksum.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ checksum.S	4 Mar 2004 20:45:39 -0000	1.1
@@ -0,0 +1,249 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		IP/TCP/UDP checksumming routines
+ *
+ * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
+ *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *		Tom May, <ftom@netcom.com>
+ *              Pentium Pro/II routines:
+ *              Alexander Kjeldaas <astor@guardian.no>
+ *              Finn Arne Gangstad <finnag@guardian.no>
+ *		Lots of code moved from tcp.c and ip.c; see those files
+ *		for more names.
+ *
+ * Changes:     Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ *			     handling.
+ *		Andi Kleen,  add zeroing on error
+ *                   converted to pure assembler
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+				
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*	
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+ */
+		
+.text
+.align 4
+.globl _csum_partial								
+		
+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
+
+	  /*		
+	   * Experiments with Ethernet and SLIP connections show that buff
+	   * is aligned on either a 2-byte or 4-byte boundary.  We get at
+	   * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+	   * alignment for the unrolled loop.
+	   */		
+_csum_partial:	
+	pushl %esi
+	pushl %ebx
+	movl 20(%esp),%eax	# Function arg: unsigned int sum
+	movl 16(%esp),%ecx	# Function arg: int len
+	movl 12(%esp),%esi	# Function arg: unsigned char *buff
+	testl $3, %esi		# Check alignment.
+	jz 2f			# Jump if alignment is ok.
+	testl $1, %esi		# Check alignment.
+	jz 10f			# Jump if alignment is boundary of 2bytes.
+
+	# buf is odd
+	dec %ecx
+	jl 8f
+	movzbl (%esi), %ebx
+	adcl %ebx, %eax
+	roll $8, %eax
+	inc %esi
+	testl $2, %esi
+	jz 2f
+10:
+	subl $2, %ecx		# Alignment uses up two bytes.
+	jae 1f			# Jump if we had at least two bytes.
+	addl $2, %ecx		# ecx was < 2.  Deal with it.
+	jmp 4f
+1:	movw (%esi), %bx
+	addl $2, %esi
+	addw %bx, %ax
+	adcl $0, %eax
+2:
+	movl %ecx, %edx
+	shrl $5, %ecx
+	jz 2f
+	testl %esi, %esi
+1:	movl (%esi), %ebx
+	adcl %ebx, %eax
+	movl 4(%esi), %ebx
+	adcl %ebx, %eax
+	movl 8(%esi), %ebx
+	adcl %ebx, %eax
+	movl 12(%esi), %ebx
+	adcl %ebx, %eax
+	movl 16(%esi), %ebx
+	adcl %ebx, %eax
+	movl 20(%esi), %ebx
+	adcl %ebx, %eax
+	movl 24(%esi), %ebx
+	adcl %ebx, %eax
+	movl 28(%esi), %ebx
+	adcl %ebx, %eax
+	lea 32(%esi), %esi
+	dec %ecx
+	jne 1b
+	adcl $0, %eax
+2:	movl %edx, %ecx
+	andl $0x1c, %edx
+	je 4f
+	shrl $2, %edx		# This clears CF
+3:	adcl (%esi), %eax
+	lea 4(%esi), %esi
+	dec %edx
+	jne 3b
+	adcl $0, %eax
+4:	andl $3, %ecx
+	jz 7f
+	cmpl $2, %ecx
+	jb 5f
+	movw (%esi),%cx
+	leal 2(%esi),%esi
+	je 6f
+	shll $16,%ecx
+5:	movb (%esi),%cl
+6:	addl %ecx,%eax
+	adcl $0, %eax 
+7:	
+	testl $1, 12(%esp)
+	jz 8f
+	roll $8, %eax
+8:
+	popl %ebx
+	popl %esi
+	ret
+
+#else
+
+/* Version for PentiumII/PPro */
+
+csum_partial:
+	pushl %esi
+	pushl %ebx
+	movl 20(%esp),%eax	# Function arg: unsigned int sum
+	movl 16(%esp),%ecx	# Function arg: int len
+	movl 12(%esp),%esi	# Function arg:	const unsigned char *buf
+
+	testl $3, %esi         
+	jnz 25f                 
+10:
+	movl %ecx, %edx
+	movl %ecx, %ebx
+	andl $0x7c, %ebx
+	shrl $7, %ecx
+	addl %ebx,%esi
+	shrl $2, %ebx  
+	negl %ebx
+	lea 45f(%ebx,%ebx,2), %ebx
+	testl %esi, %esi
+	jmp *%ebx
+
+	# Handle 2-byte-aligned regions
+20:	addw (%esi), %ax
+	lea 2(%esi), %esi
+	adcl $0, %eax
+	jmp 10b
+25:
+	testl $1, %esi         
+	jz 30f                 
+	# buf is odd
+	dec %ecx
+	jl 90f
+	movzbl (%esi), %ebx
+	addl %ebx, %eax
+	adcl $0, %eax
+	roll $8, %eax
+	inc %esi
+	testl $2, %esi
+	jz 10b
+
+30:	subl $2, %ecx          
+	ja 20b                 
+	je 32f
+	addl $2, %ecx
+	jz 80f
+	movzbl (%esi),%ebx	# csumming 1 byte, 2-aligned
+	addl %ebx, %eax
+	adcl $0, %eax
+	jmp 80f
+32:
+	addw (%esi), %ax	# csumming 2 bytes, 2-aligned
+	adcl $0, %eax
+	jmp 80f
+
+40: 
+	addl -128(%esi), %eax
+	adcl -124(%esi), %eax
+	adcl -120(%esi), %eax
+	adcl -116(%esi), %eax   
+	adcl -112(%esi), %eax   
+	adcl -108(%esi), %eax
+	adcl -104(%esi), %eax
+	adcl -100(%esi), %eax
+	adcl -96(%esi), %eax
+	adcl -92(%esi), %eax
+	adcl -88(%esi), %eax
+	adcl -84(%esi), %eax
+	adcl -80(%esi), %eax
+	adcl -76(%esi), %eax
+	adcl -72(%esi), %eax
+	adcl -68(%esi), %eax
+	adcl -64(%esi), %eax     
+	adcl -60(%esi), %eax     
+	adcl -56(%esi), %eax     
+	adcl -52(%esi), %eax   
+	adcl -48(%esi), %eax   
+	adcl -44(%esi), %eax
+	adcl -40(%esi), %eax
+	adcl -36(%esi), %eax
+	adcl -32(%esi), %eax
+	adcl -28(%esi), %eax
+	adcl -24(%esi), %eax
+	adcl -20(%esi), %eax
+	adcl -16(%esi), %eax
+	adcl -12(%esi), %eax
+	adcl -8(%esi), %eax
+	adcl -4(%esi), %eax
+45:
+	lea 128(%esi), %esi
+	adcl $0, %eax
+	dec %ecx
+	jge 40b
+	movl %edx, %ecx
+50:	andl $3, %ecx
+	jz 80f
+
+	# Handle the last 1-3 bytes without jumping
+	notl %ecx		# 1->2, 2->1, 3->0, higher bits are masked
+	movl $0xffffff,%ebx	# by the shll and shrl instructions
+	shll $3,%ecx
+	shrl %cl,%ebx
+	andl -128(%esi),%ebx	# esi is 4-aligned so should be ok
+	addl %ebx,%eax
+	adcl $0,%eax
+80: 
+	testl $1, 12(%esp)
+	jz 90f
+	roll $8, %eax
+90: 
+	popl %ebx
+	popl %esi
+	ret
+				
+#endif

reactos/drivers/net/tcpip/transport/tcp
tcp.c 1.8 -> 1.9
diff -u -r1.8 -r1.9
--- tcp.c	10 Feb 2004 17:12:41 -0000	1.8
+++ tcp.c	4 Mar 2004 20:45:39 -0000	1.9
@@ -12,36 +12,159 @@
 #include <pool.h>
 #include <address.h>
 #include <datagram.h>
+#include <checksum.h>
 #include <routines.h>
 
 
 static BOOLEAN TCPInitialized = FALSE;
+static LONG IPIdentification = 0;
+static NPAGED_LOOKASIDE_LIST TCPSegmentList;
+
+
+PTCP_SEGMENT TCPCreateSegment(
+  PIP_PACKET IPPacket,
+  ULONG SequenceNumber,
+  ULONG SegmentLength)
+/*
+ * FUNCTION: Creates a TCP segment object
+ * ARGUMENTS:
+ *     IPPacket       = Pointer to IP packet containing segment data
+ *     SequenceNumber = Sequence number of first byte in the segment
+ *     SegmentLength  = Number of bytes in the segment
+ * RETURNS:
+ *     Pointer to the created TCP segment. NULL if there was not enough free resources.
+ */
+{
+  PTCP_SEGMENT Segment;
+
+  ASSERT(IPPacket);
+
+  Segment = ExAllocateFromNPagedLookasideList(&TCPSegmentList);
+  if (Segment == NULL)
+    return NULL;
+
+  Segment->IPPacket = IPPacket;
+  Segment->SequenceNumber = SequenceNumber;
+  Segment->Length = SegmentLength;
+
+  TI_DbgPrint(DEBUG_TCP, ("Created TCP segment (SequenceNumber %d, Length %d)\n",
+    Segment->SequenceNumber, Segment->Length));
+
+  return Segment;
+}
+
+
+VOID TCPFreeSegment(
+  PTCP_SEGMENT Segment)
+/*
+ * FUNCTION: Frees a TCP segment object
+ * ARGUMENTS:
+ *     Segment = Pointer to an TCP segment structure
+ */
+{
+  ASSERT(Segment);
+
+  ExFreeToNPagedLookasideList(&TCPSegmentList, Segment);
+}
+
+
+VOID TCPAddSegment(
+  PCONNECTION_ENDPOINT Connection,
+  PTCP_SEGMENT Segment)
+/*
+ * FUNCTION: Adds a TCP segment object to the receive queue of a connection
+ * ARGUMENTS:
+ *     Connection = Pointer to connection endpoint
+ *     Segment    = Pointer to TCP segment object
+ * RETURNS:
+ *     Nothing.
+ */
+{
+  PLIST_ENTRY CurrentEntry;
+  PLIST_ENTRY NextEntry;
+  PTCP_SEGMENT Current;
+
+  ASSERT(Connection);
+  ASSERT(Segment);
+
+  /* FIXME: Handle sequence number wraparound */
+
+  /* If all segments arrive in-order then all segments will be put last in the
+     receive queue when they arrive */
+
+  if (IsListEmpty(&Connection->ReceivedSegments))
+    {
+      /* This is the first segment received since the connection was created
+         or since all data is delivered to the client */
+      InsertTailList(&Connection->ReceivedSegments, &Segment->ListEntry);
+      return;
+    }
+
+  CurrentEntry = Connection->ReceivedSegments.Blink;
+  Current = CONTAINING_RECORD(CurrentEntry, TCP_SEGMENT, ListEntry);
+  if (Segment->SequenceNumber >= Current->SequenceNumber)
+    {
+      /* This segment has the highest sequence number yet received since the
+         connection was created */
+      InsertTailList(&Connection->ReceivedSegments, &Segment->ListEntry);
+      return;
+    }
+
+
+  TI_DbgPrint(MIN_TRACE, ("FIXME: Cannot handle segments that arrive out-of-order.\n"));
+
+#if 0
+  do
+    {
+      if (SequenceNumber + Length...)
+        {
+        }
+
+      CurrentEntry = CurrentEntry->Blink;
+      Current = CONTAINING_RECORD(CurrentEntry, TCP_SEGMENT, ListEntry);
+    }
+  while (CurrentEntry != &Connection->ReceivedSegments);
+#endif
+}
 
 
 NTSTATUS TCPiAddHeaderIPv4(
   PDATAGRAM_SEND_REQUEST SendRequest,
+  PCONNECTION_ENDPOINT Connection,
   PIP_ADDRESS LocalAddress,
   USHORT LocalPort,
-  PIP_PACKET IPPacket)
+  PIP_PACKET IPPacket,
+  PTCPv4_HEADER *pTcpHeader,
+  PULONG pTcpHeaderLength)
 /*
  * FUNCTION: Adds an IPv4 and TCP header to an IP packet
  * ARGUMENTS:
- *     SendRequest  = Pointer to send request
- *     LocalAddress = Pointer to our local address
- *     LocalPort    = The port we send this segment from
- *     IPPacket     = Pointer to IP packet
+ *     SendRequest      = Pointer to send request
+ *     Connection       = Pointer to connection endpoint
+ *     LocalAddress     = Pointer to our local address
+ *     LocalPort        = The port we send this segment from
+ *     IPPacket         = Pointer to IP packet
+ *     TcpHeader        = Address of pointer to TCPv4 header (out)
+ *     pTcpHeaderLength = Address of buffer for length of TCP header
  * RETURNS:
  *     Status of operation
  */
 {
   PIPv4_HEADER IPHeader;
-  PTCP_HEADER TCPHeader;
+  PTCPv4_HEADER TCPHeader;
   PVOID Header;
 	ULONG BufferSize;
   NDIS_STATUS NdisStatus;
   PNDIS_BUFFER HeaderBuffer;
+  PTCP_SEND_REQUEST TcpSendRequest = (PTCP_SEND_REQUEST)SendRequest->Context;
+
+  ASSERT(SendRequest);
+  ASSERT(Connection);
+  ASSERT(LocalAddress);
+  ASSERT(IPPacket);
+  ASSERT(pTcpHeader);
 
-	BufferSize = MaxLLHeaderSize + sizeof(IPv4_HEADER) + sizeof(TCP_HEADER);
+	BufferSize = MaxLLHeaderSize + sizeof(IPv4_HEADER) + sizeof(TCPv4_HEADER);
   Header     = ExAllocatePool(NonPagedPool, BufferSize);
   if (!Header)
     return STATUS_INSUFFICIENT_RESOURCES;
@@ -61,7 +184,8 @@
 
   /* Chain header at front of NDIS packet */
   NdisChainBufferAtFront(IPPacket->NdisPacket, HeaderBuffer);
-  
+
+  IPPacket->ContigSize = BufferSize;
   IPPacket->Header     = (PVOID)((ULONG_PTR)Header + MaxLLHeaderSize);
   IPPacket->HeaderSize = 20;
 
@@ -74,7 +198,7 @@
   /* Length of header and data */
   IPHeader->TotalLength = WH2N((USHORT)IPPacket->TotalSize);
   /* Identification */
-  IPHeader->Id = 0;
+  IPHeader->Id = WH2N((USHORT)InterlockedIncrement(&IPIdentification));
   /* One fragment at offset 0 */
   IPHeader->FlagsFragOfs = 0;
   /* Time-to-Live is 128 */
@@ -89,18 +213,23 @@
   IPHeader->DstAddr = SendRequest->RemoteAddress->Address.IPv4Address;
 
   /* Build TCP header */
-  TCPHeader = (PTCP_HEADER)((ULONG_PTR)IPHeader + sizeof(IPv4_HEADER));
+  TCPHeader = (PTCPv4_HEADER)((ULONG_PTR)IPHeader + sizeof(IPv4_HEADER));
   /* Port values are already big-endian values */
-  TCPHeader->SourcePort = LocalPort;
-  TCPHeader->DestPort   = SendRequest->RemotePort;
-  TCPHeader->SeqNum     = 0;
-  TCPHeader->AckNum     = 0;
-  TCPHeader->DataOfs    = 0;
-  TCPHeader->Flags      = SendRequest->Flags;
-  TCPHeader->Window     = 0;
+  TCPHeader->SourcePort      = LocalPort;
+  TCPHeader->DestinationPort = SendRequest->RemotePort;
+  /* TcpSendRequest->SequenceNumber is already a big-endian value */
+  TCPHeader->SequenceNumber  = TcpSendRequest->SequenceNumber;
+  /* TcpSendRequest->AckNumber is already a big-endian value */
+  TCPHeader->AckNumber       = ((SendRequest->Flags & SRF_ACK) > 0) ? TcpSendRequest->AckNumber : 0;
+  TCPHeader->DataOffset      = (sizeof(TCPv4_HEADER) / 4) << 4;
+  TCPHeader->Flags           = SendRequest->Flags;
+  TCPHeader->Window          = 0;
   /* FIXME: Calculate TCP checksum and put it in TCP header */
-  TCPHeader->Checksum   = 0;
-  TCPHeader->Urgent     = 0;
+  TCPHeader->Checksum        = 0;
+  TCPHeader->Urgent          = 0;
+
+  *pTcpHeader = TCPHeader;
+  *pTcpHeaderLength = sizeof(TCPv4_HEADER);
 
   return STATUS_SUCCESS;
 }
@@ -121,7 +250,7 @@
  * RETURNS:
  *     Status of operation
  * NOTES:
- *     The ProcotolContext field in the send request structure (pointed to
+ *     The Context field in the send request structure (pointed to
  *     by the Context field) contains a pointer to the CONNECTION_ENDPOINT
  *     structure for the connection
  */
@@ -129,19 +258,32 @@
   NTSTATUS Status;
   PIP_PACKET Packet;
   NDIS_STATUS NdisStatus;
-  PDATAGRAM_SEND_REQUEST SendRequest = (PDATAGRAM_SEND_REQUEST)Context;
+  PDATAGRAM_SEND_REQUEST SendRequest;
+  PCONNECTION_ENDPOINT Connection;
+  ULONG Checksum;
+  TCPv4_PSEUDO_HEADER TcpPseudoHeader;
+  PTCPv4_HEADER TcpHeader;
+  ULONG TcpHeaderLength;
+
+  ASSERT(LocalAddress);
+  ASSERT(IPPacket);
 
   TI_DbgPrint(MAX_TRACE, ("Called.\n"));
 
+  SendRequest = (PDATAGRAM_SEND_REQUEST)Context;
+  ASSERT(SendRequest);
+  Connection = (PCONNECTION_ENDPOINT)SendRequest->Context;
+  ASSERT(Connection);
+
   /* Prepare packet */
 
-  /* FIXME: Assumes IPv4*/
+  /* FIXME: Assumes IPv4 */
   Packet = IPCreatePacket(IP_ADDRESS_V4);
-  if (!Packet)
+  if (Packet == NULL)
     return STATUS_INSUFFICIENT_RESOURCES;
 
   Packet->TotalSize = sizeof(IPv4_HEADER) +
-                      sizeof(TCP_HEADER)  +
+                      sizeof(TCPv4_HEADER)  +
                       SendRequest->BufferSize;
 
   /* Allocate NDIS packet */
@@ -153,7 +295,8 @@
 
   switch (SendRequest->RemoteAddress->Type) {
   case IP_ADDRESS_V4:
-    Status = TCPiAddHeaderIPv4(SendRequest, LocalAddress, LocalPort, Packet);
+    Status = TCPiAddHeaderIPv4(SendRequest, Connection, LocalAddress,
+      LocalPort, Packet, &TcpHeader, &TcpHeaderLength);
     break;
   case IP_ADDRESS_V6:
     /* FIXME: Support IPv6 */
@@ -169,10 +312,40 @@
     return Status;
   }
 
-  /* Chain data after header */
-  NdisChainBufferAtBack(Packet->NdisPacket, SendRequest->Buffer);
+  /* Build pseudo TCP header which is used to prevent misrouted segments */
+  TcpPseudoHeader.SourceAddress = LocalAddress->Address.IPv4Address;
+  TcpPseudoHeader.DestinationAddress = SendRequest->RemoteAddress->Address.IPv4Address;
+  TcpPseudoHeader.Zero = 0;
+  TcpPseudoHeader.Protocol = IPPROTO_TCP;
+  /* Length of TCP header and segment data */
+  TcpPseudoHeader.TCPLength = WH2N(TcpHeaderLength + SendRequest->BufferSize);
+  Checksum = TCPv4Checksum((PUCHAR)&TcpPseudoHeader, sizeof(TCPv4_PSEUDO_HEADER), 0);
+
+  /* Add checksum for TCP header */
+  Checksum = TCPv4Checksum((PUCHAR)TcpHeader, TcpHeaderLength, ~Checksum);
+
+  /* Chain data after header if it exists */
+  if (SendRequest->Buffer != NULL)
+    {
+      PVOID Data;
+      UINT Size;
+      PNDIS_BUFFER NdisBuffer = SendRequest->Buffer;
+      NdisChainBufferAtBack(Packet->NdisPacket, NdisBuffer);
+      /* Add checksum for segment data */
+      /* FIXME: Verify that there is no problem for chained buffers with an odd length */
+      while (NdisBuffer != NULL)
+        {
+          NdisQueryBuffer(NdisBuffer, &Data, &Size);
+          DbgPrint("Checksum7:(%d bytes)\n", Size);
+          Checksum = TCPv4Checksum(Data, Size, ~Checksum);
+          NdisGetNextBuffer(NdisBuffer, &NdisBuffer);
+        }
+    }
 
-  //DISPLAY_IP_PACKET(Packet);
+  TcpHeader->Checksum = Checksum;
+  DbgPrint("Checksum8: (0x%x)\n", Checksum);
+
+  DISPLAY_TCP_PACKET(Packet);
 
   *IPPacket = Packet;
 
@@ -196,14 +369,19 @@
   PVOID CompleteContext;
   PTCP_SEND_REQUEST SendRequest = (PTCP_SEND_REQUEST)Context;
 
+  TI_DbgPrint(MAX_TRACE, ("Called.\n"));
+
   Complete        = SendRequest->Complete;
   CompleteContext = SendRequest->Context;
   ExFreePool(SendRequest);
 
-  TI_DbgPrint(MAX_TRACE, ("Calling completion routine.\n"));
+  if (Complete != NULL)
+    {
+      TI_DbgPrint(MAX_TRACE, ("Calling completion routine.\n"));
 
-  /* Call upper level completion routine */
-  (*Complete)(CompleteContext, Status, Count);
+      /* Call upper level completion routine */
+      (*Complete)(CompleteContext, Status, Count);
+    }
 
   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 }
@@ -237,7 +415,7 @@
  *     Connection    = Connection endpoint
  *     Complete      = Completion routine
  *     Context       = Pointer to context information
- *     Buffer        = Pointer to NDIS buffer to send
+ *     Buffer        = Pointer to NDIS buffer to send (optional)
  *     BufferSize    = Size of Buffer
  *     Flags         = Protocol specific flags
  * RETURNS:
@@ -247,6 +425,9 @@
   PDATAGRAM_SEND_REQUEST DGSendReq;
   NTSTATUS Status;
 
+  ASSERT(SendRequest);
+  ASSERT(Connection);
+
   Status = BuildTCPSendRequest(
     SendRequest,
     Complete,
@@ -261,7 +442,8 @@
     Connection->RemotePort,       /* Port of remote peer */
     Buffer,                       /* Buffer */
     BufferSize,                   /* Size of buffer */
-    TCPiSendRequestComplete,      /* Completion function */
+    (DATAGRAM_COMPLETION_ROUTINE)
+      TCPiSendRequestComplete,    /* Completion function */
     *SendRequest,                 /* Context for completion function */
     TCPiBuildPacket,              /* Packet build function */
     Flags);                       /* Protocol specific flags */
@@ -288,9 +470,9 @@
  * FUNCTION: Allocates and intializes a TCP send request
  * ARGUMENTS:
  *     Connection    = Connection endpoint
- *     Complete      = Completion routine
+ *     Complete      = Completion routine (optional)
  *     Context       = Pointer to context information
- *     Buffer        = Pointer to NDIS buffer to send
+ *     Buffer        = Pointer to NDIS buffer to send (optional)
  *     BufferSize    = Size of Buffer
  *     Flags         = Protocol specific flags
  * RETURNS:
@@ -301,6 +483,67 @@
   PTCP_SEND_REQUEST TCPSendRequest;
   NTSTATUS Status;
 
+  ASSERT(Connection);
+
+  TI_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+  Status = TCPBuildSendRequest(
+    &TCPSendRequest,
+    &DGSendRequest,
+    Connection,                   /* Connection endpoint */
+    Complete,                     /* Completion routine */
+    Context,                      /* Completion routine context */
+    Buffer,                       /* Buffer */
+    BufferSize,                   /* Size of buffer */
+    Flags);                       /* Protocol specific flags */
+  if (!NT_SUCCESS(Status))
+    return Status;
+
+  Status = DGTransmit(
+    Connection->AddressFile,
+    DGSendRequest);
+  if (!NT_SUCCESS(Status)) {
+    ExFreePool(DGSendRequest);
+    ExFreePool(TCPSendRequest);
+    return Status;
+  }
+
+  return STATUS_SUCCESS;
+}
+
+
+inline NTSTATUS TCPBuildAndTransmitSendRequest2(
+    PCONNECTION_ENDPOINT Connection,
+    DATAGRAM_COMPLETION_ROUTINE Complete,
+    PVOID Context,
+    PNDIS_BUFFER Buffer,
+    DWORD BufferSize,
+    ULONG Flags,
+    ULONG SequenceNumber,
+    ULONG AckNumber)
+/*
+ * FUNCTION: Allocates and intializes a TCP send request
+ * ARGUMENTS:
+ *     Connection     = Connection endpoint
+ *     Complete       = Completion routine (optional)
+ *     Context        = Pointer to context information
+ *     Buffer         = Pointer to NDIS buffer to send
+ *     BufferSize     = Size of Buffer
+ *     Flags          = Protocol specific flags
+ *     SequenceNumber = Sequence number (host byte order)
+ *     AckNumber      = Acknowledgement number (host byte order)
+ * RETURNS:
+ *     Status of operation
+ */
+{
+  PDATAGRAM_SEND_REQUEST DGSendRequest;
+  PTCP_SEND_REQUEST TCPSendRequest;
+  NTSTATUS Status;
+
+  ASSERT(Connection);
+
+  TI_DbgPrint(MAX_TRACE, ("Called.\n"));
+
   Status = TCPBuildSendRequest(
     &TCPSendRequest,
     &DGSendRequest,
@@ -313,6 +556,10 @@
   if (!NT_SUCCESS(Status))
     return Status;
 
+  /* Set extra information and convert to network byte order if necessary */
+  TCPSendRequest->SequenceNumber = DH2N(SequenceNumber);
+  TCPSendRequest->AckNumber = DH2N(AckNumber);
+
   Status = DGTransmit(
     Connection->AddressFile,
     DGSendRequest);
@@ -335,7 +582,7 @@
  * ARGUMENTS:
  *     Request    = Pointer to TDI request
  *     ConnInfo   = Pointer to connection information
- *     ReturnInfo = Pointer to structure for return information
+ *     ReturnInfo = Pointer to structure for return information (optional)
  * RETURNS:
  *     Status of operation
  * NOTES:
@@ -353,6 +600,9 @@
   PVOID DataBuffer;
   ULONG Size;
 
+  ASSERT(Request);
+  ASSERT(ConnInfo);
+
   TI_DbgPrint(MID_TRACE, ("Called.\n"));
 
   Connection = Request->Handle.ConnectionContext;
@@ -427,7 +677,7 @@
  * ARGUMENTS:
  *     Request    = Pointer to TDI request
  *     ConnInfo   = Pointer to connection information
- *     ReturnInfo = Pointer to structure for return information
+ *     ReturnInfo = Pointer to structure for return information (optional)
  * RETURNS:
  *     Status of operation
  * NOTES:
@@ -441,6 +691,9 @@
   NTSTATUS Status;
   KIRQL OldIrql;
 
+  ASSERT(Request);
+  ASSERT(ConnInfo);
+
   TI_DbgPrint(MID_TRACE, ("Called.\n"));
 
   Connection = Request->Handle.ConnectionContext;
@@ -453,8 +706,9 @@
     return STATUS_UNSUCCESSFUL;
   }
 
-  Connection->LocalAddress = Connection->AddressFile->ADE->Address;
-  Connection->LocalPort    = Connection->AddressFile->Port;
+  Connection->LocalAddress  = Connection->AddressFile->ADE->Address;
+  Connection->LocalPort     = Connection->AddressFile->Port;
+  Connection->ListenRequest = Request;
 
   TI_DbgPrint(MIN_TRACE, ("Connection->LocalAddress (%s).\n", A2S(Connection->LocalAddress)));
   TI_DbgPrint(MIN_TRACE, ("Connection->LocalPort (%d).\n", Connection->LocalPort));
@@ -488,209 +742,535 @@
  *     Status of operation
  */
 {
+  ASSERT(Request);
+  ASSERT(ConnInfo);
+  ASSERT(Buffer);
+
   return STATUS_SUCCESS;
 }
 
 
-static VOID TCPiReceive(
+static inline ULONG TCPiSelectISS(
+  PCONNECTION_ENDPOINT Connection)
+{
+  ASSERT(Connection);
+
+  TI_DbgPrint(MIN_TRACE, ("Select ISS.\n"));
+  return 0x10000;
+}
+
+
+static inline VOID TCPiReceiveListen(
   PADDRESS_FILE AddrFile,
   PIP_PACKET IPPacket,
-  PTCP_HEADER TCPHeader)
+  PTCPv4_HEADER TCPHeader)
 {
-  register CONNECTION_STATE State;
+  ASSERT(AddrFile);
+  ASSERT(IPPacket);
+  ASSERT(TCPHeader);
 
-  if (AddrFile->Connection == NULL || AddrFile->Connection->State == ctClosed)
+  /* FIXME: Protect AddrFile->Connection */
+
+  if ((TCPHeader->Flags & TCP_RST) > 0)
     {
-      if ((TCPHeader->Flags & TCP_RST) == 0)
-        {
-          /* FIXME: Send RST
-           * If the ACK bit is off, sequence number zero is used,
-           *
-           * <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
-           *
-           * If the ACK bit is on,
-           *
-           * <SEQ=SEG.ACK><CTL=RST>
-           */
-          TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
-        }
+      /* Discard */
+      TI_DbgPrint(DEBUG_TCP, ("Discard.\n"));
       return;
     }
 
-  if (AddrFile->Connection->State == ctListen)
+  if ((TCPHeader->Flags & TCP_ACK) > 0)
     {
-      if ((TCPHeader->Flags & TCP_RST) > 0)
+      /* FIXME: Send RST (if no RST)
+          <SEQ=SEG.ACK><CTL=RST> */
+      TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+      return;
+    }
+
+  if ((TCPHeader->Flags & TCP_SYN) > 0)
+    {
+      PCONNECTION_ENDPOINT Connection = AddrFile->Connection;
+      register UCHAR DelayedControls;
+      register NTSTATUS Status;
+
+      /* FIXME: If the SEG.PRC is greater than the TCB.PRC then if allowed by
+          the user and the system set TCB.PRC<-SEG.PRC, if not allowed
+          send a reset and return. */
+      if (FALSE)
         {
-          /* Discard */
+          /* FIXME: Send RST (if no RST)
+            * <SEQ=SEG.ACK><CTL=RST>
+            */
+          TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
           return;
         }
 
-      if ((TCPHeader->Flags & TCP_ACK) > 0)
+      /* Set RCV.NXT to SEG.SEQ+1, IRS is set to SEG.SEQ and any other
+        control or text should be queued for processing later.  ISS
+        should be selected and a SYN segment sent of the form:
+
+          <SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
+
+        SND.NXT is set to ISS+1 and SND.UNA to ISS.  The connection
+        state should be changed to SYN-RECEIVED.  Note that any other
+        incoming control or data (combined with SYN) will be processed
+        in the SYN-RECEIVED state, but processing of SYN and ACK should
+        not be repeated.  If the listen was not fully specified (i.e.,
+        the foreign socket was not fully specified), then the
+        unspecified fields should be filled in now.
+      */
+      TI_DbgPrint(DEBUG_TCP, ("Go to ctSynReceived connection state.\n"));
+
+      Connection->RemotePort = TCPHeader->SourcePort;
+      /* FIXME: IPv4 only */
+      Connection->RemoteAddress = AddrCloneAddress(&IPPacket->SrcAddr);
+      if (Connection->RemoteAddress == NULL)
         {
-          /* FIXME: Send RST
-             <SEQ=SEG.ACK><CTL=RST> */
+          /* FIXME: Send RST (if no RST)
+           * <SEQ=SEG.ACK><CTL=RST>
+           */
           TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
           return;
         }
 
-      if ((TCPHeader->Flags & TCP_SYN) > 0)
+      Connection->ReceiveNext = DN2H(TCPHeader->SequenceNumber) + 1;
+      Connection->ReceiveIRS = DN2H(TCPHeader->SequenceNumber);
+      Connection->State = ctSynReceived;
+
+      Connection->SendISS = TCPiSelectISS(Connection);
+      Connection->SendNext = Connection->SendISS + 1;
+      Connection->SendUnacknowledged = Connection->SendISS;
+
+      DelayedControls = TCPHeader->Flags & (~(TCP_SYN | TCP_ACK));
+      if (DelayedControls > 0)
         {
-          /* FIXME: If the SEG.PRC is greater than the TCB.PRC then if allowed by
-             the user and the system set TCB.PRC<-SEG.PRC, if not allowed
-             send a reset and return. */
-          if (FALSE)
-            {
-              /* FIXME: Send RST
-               * <SEQ=SEG.ACK><CTL=RST>
-               */
-              TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
-              return;
-            }
+          TI_DbgPrint(MIN_TRACE, ("FIXME: Queue controls (0x%x) for later processing.\n", DelayedControls));
+        }
 
-           /* Set RCV.NXT to SEG.SEQ+1, IRS is set to SEG.SEQ and any other
-              control or text should be queued for processing later.  ISS
-              should be selected and a SYN segment sent of the form:
+        TI_DbgPrint(MIN_TRACE, ("IPPacket->HeaderSize: %d\n", IPPacket->HeaderSize));
+        TI_DbgPrint(MIN_TRACE, ("TCPHeader->DataOffset: %d\n", TCPHeader->DataOffset));
+        TI_DbgPrint(MIN_TRACE, ("IPPacket->TotalSize: %d\n", IPPacket->TotalSize));
 
-                <SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
+      if (IPPacket->HeaderSize + (TCPHeader->DataOffset & 0x0F) > IPPacket->TotalSize)
+        {
+          TI_DbgPrint(MIN_TRACE, ("FIXME: Queue segment data (%d bytes) for later processing.\n",
+            (IPPacket->HeaderSize + (TCPHeader->DataOffset & 0x0F)) - IPPacket->TotalSize));
+        }
 
-              SND.NXT is set to ISS+1 and SND.UNA to ISS.  The connection
-              state should be changed to SYN-RECEIVED.  Note that any other
-              incoming control or data (combined with SYN) will be processed
-              in the SYN-RECEIVED state, but processing of SYN and ACK should
-              not be repeated.  If the listen was not fully specified (i.e.,
-              the foreign socket was not fully specified), then the
-              unspecified fields should be filled in now.
-            */
-          TI_DbgPrint(MIN_TRACE, ("FIXME: Go to ctSynReceived connection state.\n"));
+      /* Issue SYN/ACK segment */
+      Status = TCPBuildAndTransmitSendRequest2(
+        Connection,               /* Connection endpoint */
+        NULL,                     /* Completion routine */
+        NULL,                     /* Completion routine context */
+        NULL,                     /* Buffer */
+        0,                        /* Size of buffer */
+        SRF_SYN | SRF_ACK,        /* Protocol specific flags */
+        Connection->SendISS,      /* Sequence number */
+        Connection->ReceiveNext); /* Acknowledgement number */
+      if (!NT_SUCCESS(Status))
+        {
+          /* FIXME: Send RST (if no RST)
+           * <SEQ=SEG.ACK><CTL=RST>
+           */
+          TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
           return;
         }
 
-      /* Discard the segment as it is invalid */
+      ASSERT(Connection->ListenRequest != NULL);
+
+      TI_DbgPrint(DEBUG_TCP, ("Completing listen request at %p.\n", Connection->ListenRequest));
+
+      /* Complete the listen request */
+      (*((DATAGRAM_COMPLETION_ROUTINE)Connection->ListenRequest->RequestNotifyObject))(
+        Connection->ListenRequest->RequestContext,
+        STATUS_SUCCESS,
+        0);
       return;
     }
 
-  if (AddrFile->Connection->State == ctSynSent)
+  /* Discard the segment as it is invalid */
+  TI_DbgPrint(DEBUG_TCP, ("Discard.\n"));
+}
+
+
+static inline VOID TCPiReceiveSynSent(
+  PADDRESS_FILE AddrFile,
+  PIP_PACKET IPPacket,
+  PTCPv4_HEADER TCPHeader)
+{
+  ASSERT(AddrFile);
+  ASSERT(IPPacket);
+  ASSERT(TCPHeader);
+
+  /* FIXME: Protect AddrFile->Connection */
+
+  if ((TCPHeader->Flags & TCP_ACK) > 0)
+    {
+      /* FIXME: If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send a reset (unless
+          the RST bit is set, if so drop the segment and return)
+          <SEQ=SEG.ACK><CTL=RST> */
+      TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+      return;
+    }
+
+  /* FIXME: If SND.UNA =< SEG.ACK =< SND.NXT then the ACK is acceptable. */
+
+  if ((TCPHeader->Flags & TCP_RST) > 0)
+    {
+      if (TRUE /* ACK is acceptable */)
+        {
+          AddrFile->Connection->State = ctClosed;
+          /* FIXME: Signal client */
+          TI_DbgPrint(MIN_TRACE, ("FIXME: Signal client.\n"));
+        }
+      else
+        {
+          /* Discard segment */
+          TI_DbgPrint(DEBUG_TCP, ("Discard.\n"));
+        }
+      return;
+    }
+
+  /* FIXME: If the security/compartment in the segment does not exactly
+      match the security/compartment in the TCB */
+  if (FALSE)
     {
       if ((TCPHeader->Flags & TCP_ACK) > 0)
         {
-          /* FIXME: If SEG.ACK =< ISS, or SEG.ACK > SND.NXT, send a reset (unless
-             the RST bit is set, if so drop the segment and return)
-             <SEQ=SEG.ACK><CTL=RST> */
+          /* FIXME: Send RST (if no RST)
+              <SEQ=SEG.ACK><CTL=RST> */
           TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
-          return;
         }
-
-      /* FIXME: If SND.UNA =< SEG.ACK =< SND.NXT then the ACK is acceptable. */
-
-      if ((TCPHeader->Flags & TCP_RST) > 0)
+      else
         {
-          if (TRUE /* ACK is acceptable */)
-            {
-              AddrFile->Connection->State = ctClosed;
-              /* FIXME: Signal client */
-              TI_DbgPrint(MIN_TRACE, ("FIXME: Signal client.\n"));
-            }
-          else
-            {
-              /* Discard segment */
-            }
-          return;
+          /* FIXME: Send RST (if no RST)
+              <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK> */
+          TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
         }
+      return;
+    }
 
-      /* FIXME: If the security/compartment in the segment does not exactly
-         match the security/compartment in the TCB */
+  if ((TCPHeader->Flags & TCP_ACK) > 0)
+    {
+      /* FIXME: If the precedence in the segment does not match the precedence in the TCB */
       if (FALSE)
         {
-          if ((TCPHeader->Flags & TCP_ACK) > 0)
+          /* FIXME: Send RST (if no RST)
+              <SEQ=SEG.ACK><CTL=RST> */
+          TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+          return;
+        }
+      else
+        {
+          /* FIXME: If the precedence in the segment is higher than the precedence
+              in the TCB then if allowed by the user and the system raise
+              the precedence in the TCB to that in the segment, if not
+              allowed to raise the prec then send a reset. */
+          if (FALSE)
             {
-              /* FIXME: Send RST
-                 <SEQ=SEG.ACK><CTL=RST> */
+              /* FIXME: Send RST (if no RST)
+                  <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK> */
               TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+              return;
             }
           else
             {
-              /* FIXME: Send RST
-                 <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK> */
-              TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+              /* Continue */
             }
-          return;
         }
+      TI_DbgPrint(MIN_TRACE, ("?.\n"));
+      return; /* ??? */
+    }
 
-      if ((TCPHeader->Flags & TCP_ACK) > 0)
+  /* The ACK is ok, or there is no ACK, and it the segment did not contain a RST */
+
+  if ((TCPHeader->Flags & TCP_SYN) > 0)
+    {
+      /* FIXME: The security/compartment and precedence are acceptable */
+      if (TRUE)
         {
-          /* FIXME: If the precedence in the segment does not match the precedence in the TCB */
-          if (FALSE)
+          PCONNECTION_ENDPOINT Connection = AddrFile->Connection;
+          register NTSTATUS Status;
+
+          /* FIXME: RCV.NXT is set to SEG.SEQ+1, IRS is set to
+              SEG.SEQ.  SND.UNA should be advanced to equal SEG.ACK (if there
+              is an ACK), and any segments on the retransmission queue which
+              are thereby acknowledged should be removed.
+
+              If SND.UNA > ISS (our SYN has been ACKed), change the connection
+              state to ESTABLISHED, form an ACK segment
+
+                <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
+
+              Data or controls which were queued for
+              transmission may be included.  If there are other controls or
+              text in the segment then continue processing at the sixth step
+              below where the URG bit is checked, otherwise return.
+
+              Otherwise enter SYN-RECEIVED, form a SYN,ACK segment
+
+                <SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
+
+              and send it.  If there are other controls or text in the
+              segment, queue them for processing after the ESTABLISHED state
+              has been reached, return. */
+
+          Connection->ReceiveNext = DN2H(TCPHeader->SequenceNumber) + 1;
+          Connection->ReceiveIRS = DN2H(TCPHeader->SequenceNumber);
+
+          if ((TCPHeader->Flags & TCP_ACK) > 0)
             {
-              /* FIXME: Send RST
-                 <SEQ=SEG.ACK><CTL=RST> */
-              TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
-              return;
+              /* FIXME: Remove any outstanding segments on the retransmission queue that is acknowledged by this */
+              TI_DbgPrint(MIN_TRACE, ("FIXME: Maybe remove outstanding segments on the retransmission queue.\n"));
+              Connection->SendUnacknowledged = TCPHeader->AckNumber;
             }
-          else
+
+          if (Connection->SendUnacknowledged > Connection->SendISS)
             {
-              /* FIXME: If the precedence in the segment is higher than the precedence
-                 in the TCB then if allowed by the user and the system raise
-                 the precedence in the TCB to that in the segment, if not
-                 allowed to raise the prec then send a reset. */
-              if (FALSE)
+              TI_DbgPrint(DEBUG_TCP, ("Go to ctEstablished connection state.\n"));
+              Connection->State = ctEstablished;
+
+              TI_DbgPrint(MIN_TRACE, ("FIXME: Controls or segment data queued for transmission may be sent.\n"));
+
+              /* Issue ACK segment */
+              Status = TCPBuildAndTransmitSendRequest2(
+                Connection,               /* Connection endpoint */
+                NULL,                     /* Completion routine */
+                NULL,                     /* Completion routine context */
+                NULL,                     /* Buffer */
+                0,                        /* Size of buffer */
+                SRF_ACK,                  /* Protocol specific flags */
+                Connection->SendNext,     /* Sequence number */
+                Connection->ReceiveNext); /* Acknowledgement number */
+              if (!NT_SUCCESS(Status))
                 {
-                  /* FIXME: Send RST
-                     <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK> */
+                  /* FIXME: Send RST (if no RST)
+                  * <SEQ=SEG.ACK><CTL=RST>
+                  */
                   TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
                   return;
                 }
-              else
+            }
+          else
+            {
+              TI_DbgPrint(MIN_TRACE, ("Go to ctSynReceived connection state.\n"));
+              Connection->State = ctSynReceived;
+
+              TI_DbgPrint(MIN_TRACE, ("FIXME: Controls or segment data queued for transmission may be sent.\n"));
+
+              /* Issue SYN/ACK segment */
+              Status = TCPBuildAndTransmitSendRequest2(
+                Connection,               /* Connection endpoint */
+                NULL,                     /* Completion routine */
+                NULL,                     /* Completion routine context */
+                NULL,                     /* Buffer */
+                0,                        /* Size of buffer */
+                SRF_SYN | SRF_ACK,        /* Protocol specific flags */
+                Connection->SendISS,      /* Sequence number */
+                Connection->ReceiveNext); /* Acknowledgement number */
+              if (!NT_SUCCESS(Status))
                 {
-                  /* Continue */
+                  /* FIXME: Send RST (if no RST)
+                  * <SEQ=SEG.ACK><CTL=RST>
+                  */
+                  TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+                  return;
                 }
             }
-          return;
         }
+      else
+        {
+          /* FIXME: What happens here? */
+        }
+    }
 
-      /* The ACK is ok, or there is no ACK, and it the segment did not contain a RST */
+  /* FIXME: Send RST (if no RST)
+      <SEQ=SEG.ACK><CTL=RST> */
+  TI_DbgPrint(MIN_TRACE, ("FIXME: Send RST.\n"));
+}
 
-      if ((TCPHeader->Flags & TCP_SYN) > 0)
-        {
-          /* FIXME: The security/compartment and precedence are acceptable */
-          if (TRUE)
-            {
-              /* FIXME: RCV.NXT is set to SEG.SEQ+1, IRS is set to
-                 SEG.SEQ.  SND.UNA should be advanced to equal SEG.ACK (if there
-                 is an ACK), and any segments on the retransmission queue which
-                 are thereby acknowledged should be removed.
+/*
+ * Returns TRUE if processing should be continued, FALSE if not
+ */
+static inline BOOLEAN TCPiReceiveSynReceived(
+  PADDRESS_FILE AddrFile,
+  PIP_PACKET IPPacket,
+  PTCPv4_HEADER TCPHeader)
+{
+  PCONNECTION_ENDPOINT Connection = AddrFile->Connection;
 
-                 If SND.UNA > ISS (our SYN has been ACKed), change the connection
-                 state to ESTABLISHED, form an ACK segment
+  ASSERT(AddrFile);
+  ASSERT(IPPacket);
+  ASSERT(TCPHeader);
 
-                   <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
+  /* FIXME: Protect AddrFile->Connection */
 
-                 Data or controls which were queued for
-                 transmission may be included.  If there are other controls or
-                 text in the segment then continue processing at the sixth step
-                 below where the URG bit is checked, otherwise return.
+  /* FIXME: If SND.UNA =< SEG.ACK =< SND.NXT then enter ESTABLISHED state
+     and continue processing.
 
-                 Otherwise enter SYN-RECEIVED, form a SYN,ACK segment
+        If the segment acknowledgment is not acceptable, form a
[truncated at 1000 lines; 460 more skipped]

reactos/lib/msafd/include
msafd.h 1.6 -> 1.7
diff -u -r1.6 -r1.7
--- msafd.h	2 Mar 2004 18:18:15 -0000	1.6
+++ msafd.h	4 Mar 2004 20:45:39 -0000	1.7
@@ -18,6 +18,13 @@
 #include <afd/shared.h>
 #include <debug.h>
 
+/*typedef _MSAFD_LISTEN_REQUEST
+{
+  LIST_ENTRY ListEntry;
+  HANDLE Socket;
+} MSAFD_LISTEN_REQUEST, *PMSAFD_LISTEN_REQUEST;*/
+
+
 extern HANDLE GlobalHeap;
 extern WSPUPCALLTABLE Upcalls;
 extern LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;

reactos/lib/msafd/misc
dllmain.c 1.11 -> 1.12
diff -u -r1.11 -r1.12
--- dllmain.c	10 Feb 2004 17:12:41 -0000	1.11
+++ dllmain.c	4 Mar 2004 20:45:39 -0000	1.12
@@ -23,6 +23,9 @@
 /* To make the linker happy */
 VOID STDCALL KeBugCheck (ULONG	BugCheckCode) {}
 
+/* FIXME: Protect me */
+static LIST_ENTRY MsAfdListenRequests; /* Queue of listen reqests */
+
 
 HANDLE GlobalHeap;
 WSPUPCALLTABLE Upcalls;
@@ -358,6 +361,7 @@
  *     0, or SOCKET_ERROR if the socket could not be bound
  */
 {
+  //PAFD_LISTEN_REQUEST MsafdRequest;
   FILE_REQUEST_LISTEN Request;
   FILE_REPLY_LISTEN Reply;
   IO_STATUS_BLOCK Iosb;
@@ -365,28 +369,38 @@
 
   AFD_DbgPrint(MAX_TRACE, ("s (0x%X)  backlog (%d).\n", s, backlog));
 
+/*  MsafdRequest = (PMSAFD_LISTEN_REQUEST)HeapAlloc(
+    GlobalHeap, 0, sizeof(MSAFD_LISTEN_REQUEST));
+  if (MsafdRequest == NULL)
+  {
+      AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+      *lpErrno = WSAENOBUFS;
+      return SOCKET_ERROR;
+    }*/
+
   Request.Backlog = backlog;
 
   Status = NtDeviceIoControlFile(
     (HANDLE)s,
     NULL,
-		NULL,
-		NULL,
-		&Iosb,
-		IOCTL_AFD_LISTEN,
-		&Request,
-		sizeof(FILE_REQUEST_LISTEN),
-		&Reply,
-		sizeof(FILE_REPLY_LISTEN));
-  if (Status == STATUS_PENDING) {
-    AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
-    /* FIXME: Wait only for blocking sockets */
-		Status = NtWaitForSingleObject((HANDLE)s, FALSE, NULL);
-  }
-
-  if (!NT_SUCCESS(Status)) {
+	NULL,
+	NULL,
+	&Iosb,
+	IOCTL_AFD_LISTEN,
+	&Request,
+	sizeof(FILE_REQUEST_LISTEN),
+	&Reply,
+	sizeof(FILE_REPLY_LISTEN));
+  if (Status == STATUS_PENDING)
+    {
+      //AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
+      //InsertTailList(&MsAfdListenRequests, &MsafdRequest->ListEntry);
+    }
+  else if (!NT_SUCCESS(Status))
+    {
+      //HeapFree(GlobalHeap, 0, MsafdRequest);
 	  *lpErrno = Reply.Status;
-    return SOCKET_ERROR;
+      return SOCKET_ERROR;
 	}
 
   return 0;
@@ -841,10 +855,13 @@
  */
 {
   HMODULE hWS2_32;
-  INT Status;
+  NTSTATUS Status;
+  INT Error;
 
   AFD_DbgPrint(MAX_TRACE, ("wVersionRequested (0x%X) \n", wVersionRequested));
 
+  Status = NO_ERROR;
+
   EnterCriticalSection(&InitCriticalSection);
 
   Upcalls = UpcallTable;
@@ -859,17 +876,22 @@
         lpWPUCompleteOverlappedRequest = (LPWPUCOMPLETEOVERLAPPEDREQUEST)
           GetProcAddress(hWS2_32, "WPUCompleteOverlappedRequest");
         if (lpWPUCompleteOverlappedRequest != NULL) {
-          Status = NO_ERROR;
           StartupCount++;
+        } else {
+          AFD_DbgPrint(MIN_TRACE, ("GetProcAddress() failed for WPUCompleteOverlappedRequest\n"));
+          CloseCommandChannel();
+          Error = WSASYSNOTREADY;
         }
       } else {
         AFD_DbgPrint(MIN_TRACE, ("GetModuleHandle() failed for ws2_32.dll\n"));
+        CloseCommandChannel();
+        Error = WSASYSNOTREADY;
       }
     } else {
       AFD_DbgPrint(MIN_TRACE, ("Cannot open afd.sys\n"));
+      Error = WSASYSNOTREADY;
     }
   } else {
-    Status = NO_ERROR;
     StartupCount++;
   }
 
@@ -969,6 +991,8 @@
 
         InitializeCriticalSection(&InitCriticalSection);
 
+        InitializeListHead(&MsAfdListenRequests);
+
         GlobalHeap = GetProcessHeap();
 
         CreateHelperDLLDatabase();
CVSspam 0.2.8