- Use a spin lock to protect OSKit instead of a recursive mutex

- Remove the now unused recursive mutex code
 - Don't clear the SS_ISCONNECTING flag when soconnect returns EINPROGRESS because it causes a crash during soreceive
 - Lock CONNECTION_ENDPOINT and ADDRESS_FILE structs better
 - Remove incorrect IoMarkIrpPending calls
 - Remove useless ASSERT_LOCKED
 - Don't destroy so_connection when we close a connection
 - Remove useless FileFindConnectionByContext
 - Remove SignalledConnectionsList and SignalledConnectionsLock and simply loop through ConnectionEndpointList for signalled connections
 - Add connections to ConnectionEndpointList in TCPAllocateConnectionEndpoint instead of FileOpenConnection so we don't miss listeners
 - Remove connections from ConnectionEndpointList in TCPFreeConnectionEndpoint instead of FileCloseConnection so we don't miss listeners
 - Use ExInterlockedRemoveHeadList to remove entries in the address file's request lists
 - Remove useless members, flags, and variables in titypes.h and tcp.h
 - Fixes bug 4955 and 4434

svn path=/trunk/; revision=44163
This commit is contained in:
Cameron Gutman 2009-11-14 18:38:02 +00:00
parent 283fdbd510
commit f3d4211e56
18 changed files with 566 additions and 709 deletions

View file

@ -13,7 +13,6 @@ extern KSPIN_LOCK AddressFileListLock;
extern LIST_ENTRY ConnectionEndpointListHead;
extern KSPIN_LOCK ConnectionEndpointListLock;
NTSTATUS FileOpenAddress(
PTDI_REQUEST Request,
PTA_IP_ADDRESS AddrList,
@ -27,8 +26,6 @@ NTSTATUS FileOpenConnection(
PTDI_REQUEST Request,
PVOID ClientContext);
PCONNECTION_ENDPOINT FileFindConnectionByContext( PVOID Context );
NTSTATUS FileCloseConnection(
PTDI_REQUEST Request);

View file

@ -84,11 +84,6 @@ typedef struct _SLEEPING_THREAD {
#define SRF_FIN TCP_FIN
extern LONG TCP_IPIdentification;
extern LIST_ENTRY SignalledConnectionsList;
extern KSPIN_LOCK SignalledConnectionsLock;
extern LIST_ENTRY SleepingThreadsList;
extern FAST_MUTEX SleepingThreadsLock;
extern RECURSIVE_MUTEX TCPLock;
/* accept.c */
NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
@ -105,7 +100,6 @@ NTSTATUS TCPAccept
PVOID Context );
/* tcp.c */
ULONG HandleSignalledConnection( PCONNECTION_ENDPOINT Connection );
PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext );
VOID TCPFreeConnectionEndpoint( PCONNECTION_ENDPOINT Connection );

View file

@ -153,7 +153,6 @@ typedef struct _ADDRESS_FILE {
LIST_ENTRY ListEntry; /* Entry on list */
KSPIN_LOCK Lock; /* Spin lock to manipulate this structure */
OBJECT_FREE_ROUTINE Free; /* Routine to use to free resources for the object */
USHORT Flags; /* Flags for address file (see below) */
IP_ADDRESS Address; /* Address of this address file */
USHORT Family; /* Address family */
USHORT Protocol; /* Protocol number */
@ -213,29 +212,6 @@ typedef struct _ADDRESS_FILE {
BOOLEAN RegisteredChainedReceiveExpeditedHandler;
} ADDRESS_FILE, *PADDRESS_FILE;
/* Address File Flag constants */
#define AFF_VALID 0x0001 /* Address file object is valid for use */
#define AFF_BUSY 0x0002 /* Address file object is exclusive to someone */
#define AFF_DELETE 0x0004 /* Address file object is sheduled to be deleted */
#define AFF_SEND 0x0008 /* A send request is pending */
#define AFF_RECEIVE 0x0010 /* A receive request is pending */
#define AFF_PENDING 0x001C /* A request is pending */
/* Macros for manipulating address file object flags */
#define AF_IS_VALID(ADF) ((ADF)->Flags & AFF_VALID)
#define AF_SET_VALID(ADF) ((ADF)->Flags |= AFF_VALID)
#define AF_CLR_VALID(ADF) ((ADF)->Flags &= ~AFF_VALID)
#define AF_IS_BUSY(ADF) ((ADF)->Flags & AFF_BUSY)
#define AF_SET_BUSY(ADF) ((ADF)->Flags |= AFF_BUSY)
#define AF_CLR_BUSY(ADF) ((ADF)->Flags &= ~AFF_BUSY)
#define AF_IS_PENDING(ADF, X) (ADF->Flags & X)
#define AF_SET_PENDING(ADF, X) (ADF->Flags |= X)
#define AF_CLR_PENDING(ADF, X) (ADF->Flags &= ~X)
/* Structure used to search through Address Files */
typedef struct _AF_SEARCH {
PLIST_ENTRY Next; /* Next address file to check */
@ -306,8 +282,6 @@ typedef struct _CONNECTION_ENDPOINT {
LIST_ENTRY SendRequest; /* Queued send requests */
/* Signals */
LIST_ENTRY SignalList; /* Entry in the list of sockets waiting for
* notification service to the client */
UINT SignalState; /* Active signals from oskit */
} CONNECTION_ENDPOINT, *PCONNECTION_ENDPOINT;

View file

@ -1,61 +0,0 @@
#include <ntddk.h>
#include "recmutex.h"
VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) {
RtlZeroMemory( RecMutex, sizeof(*RecMutex) );
ExInitializeFastMutex( &RecMutex->Mutex );
KeInitializeEvent( &RecMutex->StateLockedEvent,
NotificationEvent, FALSE );
}
/* NOTE: When we leave, the FAST_MUTEX must have been released. The result
* is that we always exit in the same irql as entering */
VOID RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex ) {
NTSTATUS Status = STATUS_SUCCESS;
PVOID CurrentThread = KeGetCurrentThread();
ASSERT(RecMutex);
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
/* Wait for the previous user to unlock the RecMutex state. There might be
* multiple waiters waiting to change the state. We need to check each
* time we get the event whether somebody still has the state locked */
ExAcquireFastMutex( &RecMutex->Mutex );
if( CurrentThread == RecMutex->CurrentThread ) {
RecMutex->LockCount++;
ExReleaseFastMutex( &RecMutex->Mutex );
return;
}
while( RecMutex->LockCount != 0 ) {
ExReleaseFastMutex( &RecMutex->Mutex );
Status = KeWaitForSingleObject( &RecMutex->StateLockedEvent,
UserRequest,
KernelMode,
FALSE,
NULL );
ExAcquireFastMutex( &RecMutex->Mutex );
}
RecMutex->CurrentThread = CurrentThread;
RecMutex->LockCount++;
ExReleaseFastMutex( &RecMutex->Mutex );
}
VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) {
ASSERT(RecMutex);
ExAcquireFastMutex( &RecMutex->Mutex );
ASSERT(RecMutex->LockCount > 0);
RecMutex->LockCount--;
if( !RecMutex->LockCount ) {
KePulseEvent( &RecMutex->StateLockedEvent, IO_NETWORK_INCREMENT,
FALSE );
}
ExReleaseFastMutex( &RecMutex->Mutex );
}

View file

@ -1,21 +0,0 @@
#ifndef _ROSRTL_RECMUTEX_H
#define _ROSRTL_RECMUTEX_H
typedef struct _RECURSIVE_MUTEX {
/* Lock. */
FAST_MUTEX Mutex;
/* Number of times this object was locked */
SIZE_T LockCount;
/* CurrentThread */
PVOID CurrentThread;
/* Notification event which signals that another thread can take over */
KEVENT StateLockedEvent;
} RECURSIVE_MUTEX, *PRECURSIVE_MUTEX;
extern VOID RecursiveMutexInit( PRECURSIVE_MUTEX RecMutex );
extern VOID RecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex );
extern VOID RecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex );
#define ASSERT_LOCKED(x)
#endif/*_ROSRTL_RECMUTEX_H*/

View file

@ -21,9 +21,6 @@
<directory name="datalink">
<file>lan.c</file>
</directory>
<directory name="recmutex">
<file>recmutex.c</file>
</directory>
<directory name="tcpip">
<file>ainfo.c</file>
<file>buffer.c</file>

View file

@ -210,9 +210,8 @@ VOID NTAPI DispCancelListenRequest(
TCPRemoveIRP(Connection, Irp);
TCPAbortListenForSocket(
Connection->AddressFile->Listener,
Connection );
TCPAbortListenForSocket(Connection->AddressFile->Listener,
Connection);
IoReleaseCancelSpinLock(Irp->CancelIrql);
@ -1044,7 +1043,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
Status = STATUS_SUCCESS;
TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
/* Set the event handler. if an event handler is associated with
a specific event, it's flag (RegisteredXxxHandler) is TRUE.
@ -1165,7 +1164,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
Status = STATUS_INVALID_PARAMETER;
}
TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
return Status;
}

View file

@ -295,9 +295,6 @@ NTSTATUS FileOpenAddress(
/* Initialize spin lock that protects the address file object */
KeInitializeSpinLock(&AddrFile->Lock);
/* Set valid flag so the address can be used */
AF_SET_VALID(AddrFile);
/* Return address file object */
Request->Handle.AddressHandle = AddrFile;
@ -328,7 +325,7 @@ NTSTATUS FileCloseAddress(
KIRQL OldIrql;
PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
PDATAGRAM_SEND_REQUEST SendRequest;
PLIST_ENTRY CurrentEntry, NextEntry;
PLIST_ENTRY CurrentEntry;
AddrFile = Request->Handle.AddressHandle;
@ -339,8 +336,6 @@ NTSTATUS FileCloseAddress(
RemoveEntryList(&AddrFile->ListEntry);
TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
/* FIXME: Kill TCP connections on this address file object */
/* Return pending requests with error */
@ -348,43 +343,27 @@ NTSTATUS FileCloseAddress(
TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting receive requests on AddrFile at (0x%X).\n", AddrFile));
/* Go through pending receive request list and cancel them all */
CurrentEntry = AddrFile->ReceiveQueue.Flink;
while (CurrentEntry != &AddrFile->ReceiveQueue) {
NextEntry = CurrentEntry->Flink;
while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
ReceiveRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, ListEntry);
/* Abort the request and free its resources */
TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
(*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_CANCELLED, 0);
TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
CurrentEntry = NextEntry;
/* exFreePool(ReceiveRequest); FIXME: WTF? */
}
TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting send requests on address file at (0x%X).\n", AddrFile));
/* Go through pending send request list and cancel them all */
CurrentEntry = AddrFile->TransmitQueue.Flink;
while (CurrentEntry != &AddrFile->TransmitQueue) {
NextEntry = CurrentEntry->Flink;
SendRequest = CONTAINING_RECORD(CurrentEntry,
DATAGRAM_SEND_REQUEST, ListEntry);
/* Abort the request and free its resources */
TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, &AddrFile->Lock))) {
SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, ListEntry);
(*SendRequest->Complete)(SendRequest->Context, STATUS_CANCELLED, 0);
exFreePool(SendRequest);
TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
CurrentEntry = NextEntry;
}
TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
/* Protocol specific handling */
switch (AddrFile->Protocol) {
case IPPROTO_TCP:
TCPFreePort( AddrFile->Port );
if( AddrFile->Listener ) {
TCPClose( AddrFile->Listener );
exFreePool( AddrFile->Listener );
}
if( AddrFile->Listener )
TCPClose( AddrFile->Listener );
break;
case IPPROTO_UDP:
@ -433,48 +412,11 @@ NTSTATUS FileOpenConnection(
/* Return connection endpoint file object */
Request->Handle.ConnectionContext = Connection;
/* Add connection endpoint to global list */
ExInterlockedInsertTailList(
&ConnectionEndpointListHead,
&Connection->ListEntry,
&ConnectionEndpointListLock);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return STATUS_SUCCESS;
}
/*
* FUNCTION: Find a connection by examining the context field. This
* is needed in some situations where a FIN reply is needed after a
* socket is formally broken.
* ARGUMENTS:
* Request = Pointer to TDI request structure for this request
* RETURNS:
* Status of operation
*/
PCONNECTION_ENDPOINT FileFindConnectionByContext( PVOID Context ) {
PLIST_ENTRY Entry;
KIRQL OldIrql;
PCONNECTION_ENDPOINT Connection = NULL;
TcpipAcquireSpinLock( &ConnectionEndpointListLock, &OldIrql );
for( Entry = ConnectionEndpointListHead.Flink;
Entry != &ConnectionEndpointListHead;
Entry = Entry->Flink ) {
Connection =
CONTAINING_RECORD( Entry, CONNECTION_ENDPOINT, ListEntry );
if( Connection->SocketContext == Context ) break;
else Connection = NULL;
}
TcpipReleaseSpinLock( &ConnectionEndpointListLock, OldIrql );
return Connection;
}
/*
* FUNCTION: Closes an connection file object
* ARGUMENTS:
@ -486,20 +428,13 @@ NTSTATUS FileCloseConnection(
PTDI_REQUEST Request)
{
PCONNECTION_ENDPOINT Connection;
KIRQL OldIrql;
TI_DbgPrint(MID_TRACE, ("Called.\n"));
Connection = Request->Handle.ConnectionContext;
TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
RemoveEntryList(&Connection->ListEntry);
TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
TCPClose( Connection );
TCPFreeConnectionEndpoint(Connection);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
return STATUS_SUCCESS;

View file

@ -44,16 +44,3 @@ VOID TcpipReleaseFastMutex( PFAST_MUTEX Mutex ) {
ExReleaseFastMutex( Mutex );
}
VOID TcpipRecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) {
RecursiveMutexInit( RecMutex );
}
VOID TcpipRecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex ) {
//TI_DbgPrint(DEBUG_LOCK,("Locking\n"));
RecursiveMutexEnter( RecMutex );
}
VOID TcpipRecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) {
//TI_DbgPrint(DEBUG_LOCK,("Unlocking\n"));
RecursiveMutexLeave( RecMutex );
}

View file

@ -45,11 +45,3 @@ VOID TcpipAcquireFastMutex( PFAST_MUTEX Mutex ) {
VOID TcpipReleaseFastMutex( PFAST_MUTEX Mutex ) {
}
VOID TcpipRecursiveMutexInit( PRECURSIVE_MUTEX RecMutex ) {
}
VOID TcpipRecursiveMutexEnter( PRECURSIVE_MUTEX RecMutex ) {
}
VOID TcpipRecursiveMutexLeave( PRECURSIVE_MUTEX RecMutex ) {
}

View file

@ -79,7 +79,7 @@ VOID DGDeliverData(
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
if (AddrFile->Protocol == IPPROTO_UDP)
{
@ -136,7 +136,7 @@ VOID DGDeliverData(
&SrcAddress->Address.IPv4Address,
sizeof(SrcAddress->Address.IPv4Address) );
TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
/* Complete the receive request */
if (Current->BufferSize < DataSize)
@ -144,11 +144,11 @@ VOID DGDeliverData(
else
Current->Complete(Current->Context, STATUS_SUCCESS, DataSize);
TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
}
}
TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
}
else if (AddrFile->RegisteredReceiveDatagramHandler)
{
@ -157,8 +157,6 @@ VOID DGDeliverData(
ReceiveHandler = AddrFile->ReceiveDatagramHandler;
HandlerContext = AddrFile->ReceiveDatagramHandlerContext;
TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
if (SrcAddress->Type == IP_ADDRESS_V4)
{
AddressLength = sizeof(IPv4_RAW_ADDRESS);
@ -170,6 +168,8 @@ VOID DGDeliverData(
SourceAddress = SrcAddress->Address.IPv6Address;
}
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
Status = (*ReceiveHandler)(HandlerContext,
AddressLength,
SourceAddress,
@ -184,7 +184,7 @@ VOID DGDeliverData(
}
else
{
TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
TI_DbgPrint(MAX_TRACE, ("Discarding datagram.\n"));
}
@ -228,76 +228,67 @@ NTSTATUS DGReceiveDatagram(
* This is the high level interface for receiving DG datagrams
*/
{
KIRQL OldIrql;
NTSTATUS Status;
PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
KIRQL OldIrql;
TI_DbgPrint(MAX_TRACE, ("Called.\n"));
TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
if (AF_IS_VALID(AddrFile))
ReceiveRequest = exAllocatePool(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST));
if (ReceiveRequest)
{
ReceiveRequest = exAllocatePool(NonPagedPool, sizeof(DATAGRAM_RECEIVE_REQUEST));
if (ReceiveRequest)
/* Initialize a receive request */
/* Extract the remote address filter from the request (if any) */
if ((ConnInfo->RemoteAddressLength != 0) &&
(ConnInfo->RemoteAddress))
{
/* Initialize a receive request */
/* Extract the remote address filter from the request (if any) */
if ((ConnInfo->RemoteAddressLength != 0) &&
(ConnInfo->RemoteAddress))
Status = AddrGetAddress(ConnInfo->RemoteAddress,
&ReceiveRequest->RemoteAddress,
&ReceiveRequest->RemotePort);
if (!NT_SUCCESS(Status))
{
Status = AddrGetAddress(ConnInfo->RemoteAddress,
&ReceiveRequest->RemoteAddress,
&ReceiveRequest->RemotePort);
if (!NT_SUCCESS(Status))
{
TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
exFreePool(ReceiveRequest);
return Status;
}
exFreePool(ReceiveRequest);
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
return Status;
}
else
{
ReceiveRequest->RemotePort = 0;
AddrInitIPv4(&ReceiveRequest->RemoteAddress, 0);
}
IoMarkIrpPending(Irp);
ReceiveRequest->ReturnInfo = ReturnInfo;
ReceiveRequest->Buffer = BufferData;
ReceiveRequest->BufferSize = ReceiveLength;
ReceiveRequest->UserComplete = Complete;
ReceiveRequest->UserContext = Context;
ReceiveRequest->Complete =
(PDATAGRAM_COMPLETION_ROUTINE)DGReceiveComplete;
ReceiveRequest->Context = ReceiveRequest;
ReceiveRequest->AddressFile = AddrFile;
ReceiveRequest->Irp = Irp;
/* Queue receive request */
InsertTailList(&AddrFile->ReceiveQueue, &ReceiveRequest->ListEntry);
AF_SET_PENDING(AddrFile, AFF_RECEIVE);
TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
TI_DbgPrint(MAX_TRACE, ("Leaving (pending %08x).\n", ReceiveRequest));
return STATUS_PENDING;
}
}
else
{
Status = STATUS_INSUFFICIENT_RESOURCES;
ReceiveRequest->RemotePort = 0;
AddrInitIPv4(&ReceiveRequest->RemoteAddress, 0);
}
IoMarkIrpPending(Irp);
ReceiveRequest->ReturnInfo = ReturnInfo;
ReceiveRequest->Buffer = BufferData;
ReceiveRequest->BufferSize = ReceiveLength;
ReceiveRequest->UserComplete = Complete;
ReceiveRequest->UserContext = Context;
ReceiveRequest->Complete =
(PDATAGRAM_COMPLETION_ROUTINE)DGReceiveComplete;
ReceiveRequest->Context = ReceiveRequest;
ReceiveRequest->AddressFile = AddrFile;
ReceiveRequest->Irp = Irp;
/* Queue receive request */
InsertTailList(&AddrFile->ReceiveQueue, &ReceiveRequest->ListEntry);
TI_DbgPrint(MAX_TRACE, ("Leaving (pending %08x).\n", ReceiveRequest));
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
return STATUS_PENDING;
}
else
{
Status = STATUS_INVALID_ADDRESS;
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
Status = STATUS_INSUFFICIENT_RESOURCES;
}
TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
TI_DbgPrint(MAX_TRACE, ("Leaving with errors (0x%X).\n", Status));
return Status;

View file

@ -195,6 +195,9 @@ NTSTATUS RawIPSendDatagram(
USHORT RemotePort;
NTSTATUS Status;
PNEIGHBOR_CACHE_ENTRY NCE;
KIRQL OldIrql;
KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
AddrFile, ConnInfo, BufferData, DataSize));
@ -209,13 +212,17 @@ NTSTATUS RawIPSendDatagram(
break;
default:
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
return STATUS_UNSUCCESSFUL;
}
TI_DbgPrint(MID_TRACE,("About to get route to destination\n"));
if(!(NCE = RouteGetRouteToDestination( &RemoteAddress )))
{
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
return STATUS_NETWORK_UNREACHABLE;
}
LocalAddress = AddrFile->Address;
if (AddrIsUnspecified(&LocalAddress))
@ -237,18 +244,24 @@ NTSTATUS RawIPSendDatagram(
DataSize );
if( !NT_SUCCESS(Status) )
{
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
return Status;
}
TI_DbgPrint(MID_TRACE,("About to send datagram\n"));
if (!NT_SUCCESS(Status = IPSendDatagram( &Packet, NCE, RawIpSendPacketComplete, NULL )))
{
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
FreeNdisPacket(Packet.NdisPacket);
return Status;
}
TI_DbgPrint(MID_TRACE,("Leaving\n"));
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
return STATUS_SUCCESS;
}

View file

@ -10,6 +10,7 @@
#include "precomp.h"
/* Listener->Lock MUST be acquired */
NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
PCONNECTION_ENDPOINT Connection,
PTDI_REQUEST_KERNEL Request ) {
@ -26,18 +27,15 @@ NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
WhoIsConnecting = (PTDI_CONNECTION_INFORMATION)
Request->ReturnConnectionInformation;
TcpipRecursiveMutexEnter(&TCPLock);
Status = TCPTranslateError
( OskitTCPAccept( Listener->SocketContext,
&Connection->SocketContext,
Connection,
&OutAddr,
sizeof(OutAddr),
&OutAddrLen,
Request->RequestFlags & TDI_QUERY_ACCEPT ? 0 : 1 ) );
TcpipRecursiveMutexLeave(&TCPLock);
TI_DbgPrint(DEBUG_TCP,("Status %x\n", Status));
if( NT_SUCCESS(Status) && Status != STATUS_PENDING ) {
@ -71,11 +69,14 @@ NTSTATUS TCPServiceListeningSocket( PCONNECTION_ENDPOINT Listener,
NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) {
NTSTATUS Status = STATUS_SUCCESS;
SOCKADDR_IN AddressToBind;
KIRQL OldIrql;
ASSERT(Connection);
ASSERT_KM_POINTER(Connection->SocketContext);
ASSERT_KM_POINTER(Connection->AddressFile);
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
TI_DbgPrint(DEBUG_TCP,("TCPListen started\n"));
TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext %x\n",
@ -89,8 +90,6 @@ NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) {
TI_DbgPrint(DEBUG_TCP,("AddressToBind - %x:%x\n", AddressToBind.sin_addr, AddressToBind.sin_port));
TcpipRecursiveMutexEnter( &TCPLock );
Status = TCPTranslateError( OskitTCPBind( Connection->SocketContext,
&AddressToBind,
sizeof(AddressToBind) ) );
@ -98,7 +97,7 @@ NTSTATUS TCPListen( PCONNECTION_ENDPOINT Connection, UINT Backlog ) {
if (NT_SUCCESS(Status))
Status = TCPTranslateError( OskitTCPListen( Connection->SocketContext, Backlog ) );
TcpipRecursiveMutexLeave( &TCPLock );
KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(DEBUG_TCP,("TCPListen finished %x\n", Status));
@ -137,12 +136,17 @@ NTSTATUS TCPAccept ( PTDI_REQUEST Request,
{
NTSTATUS Status;
PTDI_BUCKET Bucket;
KIRQL OldIrql;
TI_DbgPrint(DEBUG_TCP,("TCPAccept started\n"));
KeAcquireSpinLock(&Listener->Lock, &OldIrql);
Status = TCPServiceListeningSocket( Listener, Connection,
(PTDI_REQUEST_KERNEL)Request );
KeReleaseSpinLock(&Listener->Lock, OldIrql);
if( Status == STATUS_PENDING ) {
Bucket = exAllocatePool( NonPagedPool, sizeof(*Bucket) );
@ -150,8 +154,8 @@ NTSTATUS TCPAccept ( PTDI_REQUEST Request,
Bucket->AssociatedEndpoint = Connection;
Bucket->Request.RequestNotifyObject = Complete;
Bucket->Request.RequestContext = Context;
IoMarkIrpPending((PIRP)Context);
ExInterlockedInsertTailList( &Listener->ListenRequest, &Bucket->Entry, &Listener->Lock );
ExInterlockedInsertTailList( &Listener->ListenRequest, &Bucket->Entry,
&Listener->Lock );
} else
Status = STATUS_NO_MEMORY;
}

View file

@ -15,56 +15,30 @@ int TCPSocketState(void *ClientData,
void *WhichConnection,
OSK_UINT NewState ) {
PCONNECTION_ENDPOINT Connection = WhichConnection;
ULONG OldState;
KIRQL OldIrql;
ASSERT_LOCKED(&TCPLock);
TI_DbgPrint(MID_TRACE,("Flags: %c%c%c%c\n",
TI_DbgPrint(DEBUG_TCP,("Connection: %x Flags: %c%c%c%c%c\n",
Connection,
NewState & SEL_CONNECT ? 'C' : 'c',
NewState & SEL_READ ? 'R' : 'r',
NewState & SEL_FIN ? 'F' : 'f',
NewState & SEL_ACCEPT ? 'A' : 'a'));
NewState & SEL_ACCEPT ? 'A' : 'a',
NewState & SEL_WRITE ? 'W' : 'w'));
if (!Connection)
{
return 0;
}
KeAcquireSpinLockAtDpcLevel(&Connection->Lock);
TI_DbgPrint(DEBUG_TCP,("Called: NewState %x (Conn %x) (Change %x)\n",
NewState, Connection,
Connection ? Connection->SignalState ^ NewState :
Connection->SignalState ^ NewState,
NewState));
if( !Connection ) {
TI_DbgPrint(DEBUG_TCP,("Socket closing.\n"));
Connection = FileFindConnectionByContext( WhichSocket );
if( !Connection )
return 0;
else
TI_DbgPrint(DEBUG_TCP,("Found socket %x\n", Connection));
}
OldState = Connection->SignalState;
Connection->SignalState |= NewState;
TcpipRecursiveMutexLeave(&TCPLock);
/* We must not be locked when handling signalled connections
* because a completion could trigger another IOCTL which
* would cause a deadlock
*/
NewState = HandleSignalledConnection(Connection);
TcpipRecursiveMutexEnter(&TCPLock);
KeAcquireSpinLock(&SignalledConnectionsLock, &OldIrql);
if ((NewState == 0 || NewState == SEL_FIN) &&
(OldState != 0 && OldState != SEL_FIN))
{
RemoveEntryList(&Connection->SignalList);
}
else if (NewState != 0 && NewState != SEL_FIN)
{
InsertTailList(&SignalledConnectionsList, &Connection->SignalList);
}
KeReleaseSpinLock(&SignalledConnectionsLock, OldIrql);
KeReleaseSpinLockFromDpcLevel(&Connection->Lock);
return 0;
}
@ -86,8 +60,6 @@ int TCPPacketSend(void *ClientData, OSK_PCHAR data, OSK_UINT len ) {
IP_ADDRESS RemoteAddress, LocalAddress;
PIPv4_HEADER Header;
ASSERT_LOCKED(&TCPLock);
if( *data == 0x45 ) { /* IPv4 */
Header = (PIPv4_HEADER)data;
LocalAddress.Type = IP_ADDRESS_V4;
@ -181,8 +153,6 @@ void *TCPMalloc( void *ClientData,
void *v;
ULONG Signature;
ASSERT_LOCKED(&TCPLock);
#if 0 != MEM_PROFILE
static OSK_UINT *Sizes = NULL, *Counts = NULL, ArrayAllocated = 0;
static OSK_UINT ArrayUsed = 0, AllocationCount = 0;
@ -258,8 +228,6 @@ void TCPFree( void *ClientData,
void *data, OSK_PCHAR File, OSK_UINT Line ) {
ULONG Signature;
ASSERT_LOCKED(&TCPLock);
UntrackFL( (PCHAR)File, Line, data, FOURCC('f','b','s','d') );
data = (void *)((char *) data - sizeof(ULONG));
Signature = *((ULONG *) data);

View file

@ -15,12 +15,12 @@
LONG TCP_IPIdentification = 0;
static BOOLEAN TCPInitialized = FALSE;
static NPAGED_LOOKASIDE_LIST TCPSegmentList;
LIST_ENTRY SignalledConnectionsList;
KSPIN_LOCK SignalledConnectionsLock;
RECURSIVE_MUTEX TCPLock;
PORT_SET TCPPorts;
ULONG HandleSignalledConnection( PCONNECTION_ENDPOINT Connection ) {
static VOID DrainSignals() {
PCONNECTION_ENDPOINT Connection;
PLIST_ENTRY CurrentEntry, NextEntry;
KIRQL OldIrql;
NTSTATUS Status = STATUS_SUCCESS;
PTCP_COMPLETION_ROUTINE Complete;
PTDI_BUCKET Bucket;
@ -28,279 +28,290 @@ ULONG HandleSignalledConnection( PCONNECTION_ENDPOINT Connection ) {
PIRP Irp;
PMDL Mdl;
TI_DbgPrint(MID_TRACE,("Handling signalled state on %x (%x)\n",
Connection, Connection->SocketContext));
if( Connection->SignalState & SEL_FIN ) {
TI_DbgPrint(DEBUG_TCP, ("EOF From socket\n"));
Connection->SignalState &= ~SEL_READ;
while ((Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest,
&Connection->Lock )) != NULL)
{
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
exFreePool(Bucket);
}
Connection->SignalState &= ~SEL_WRITE;
while ((Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest,
&Connection->Lock )) != NULL)
{
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
exFreePool(Bucket);
}
Connection->SignalState &= ~SEL_ACCEPT;
while ((Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,
&Connection->Lock )) != NULL)
{
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
/* We have to notify oskittcp of the abortion */
TCPAbortListenForSocket(Connection->AddressFile->Listener,
Connection);
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
exFreePool(Bucket);
}
Connection->SignalState &= ~SEL_CONNECT;
while ((Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest,
&Connection->Lock )) != NULL)
{
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
exFreePool(Bucket);
}
}
/* Things that can happen when we try the initial connection */
if( Connection->SignalState & SEL_CONNECT ) {
Connection->SignalState &= ~SEL_CONNECT;
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest,
&Connection->Lock )) != NULL ) {
TI_DbgPrint(DEBUG_TCP, ("Connect Event\n"));
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
TI_DbgPrint(DEBUG_TCP,
("Completing Request %x\n", Bucket->Request.RequestContext));
Complete( Bucket->Request.RequestContext, STATUS_SUCCESS, 0 );
/* Frees the bucket allocated in TCPConnect */
exFreePool( Bucket );
}
}
if( Connection->SignalState & SEL_ACCEPT ) {
/* Handle readable on a listening socket --
* TODO: Implement filtering
*/
TI_DbgPrint(DEBUG_TCP,("Accepting new connection on %x (Queue: %s)\n",
Connection,
IsListEmpty(&Connection->ListenRequest) ?
"empty" : "nonempty"));
Connection->SignalState &= ~SEL_ACCEPT;
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,
&Connection->Lock )) != NULL ) {
PIO_STACK_LOCATION IrpSp;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
IrpSp = IoGetCurrentIrpStackLocation( Irp );
TI_DbgPrint(DEBUG_TCP,("Getting the socket\n"));
Status = TCPServiceListeningSocket
( Connection->AddressFile->Listener,
Bucket->AssociatedEndpoint,
(PTDI_REQUEST_KERNEL)&IrpSp->Parameters );
TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n"));
if( Status == STATUS_PENDING ) {
Connection->SignalState |= SEL_ACCEPT;
ExInterlockedInsertHeadList( &Connection->ListenRequest, &Bucket->Entry, &Connection->Lock );
break;
} else {
Complete( Bucket->Request.RequestContext, Status, 0 );
exFreePool( Bucket );
}
}
}
/* Things that happen after we're connected */
if( Connection->SignalState & SEL_READ ) {
TI_DbgPrint(DEBUG_TCP,("Readable: irp list %s\n",
IsListEmpty(&Connection->ReceiveRequest) ?
"empty" : "nonempty"));
Connection->SignalState &= ~SEL_READ;
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest,
&Connection->Lock )) != NULL ) {
OSK_UINT RecvLen = 0, Received = 0;
PVOID RecvBuffer = 0;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
Mdl = Irp->MdlAddress;
TI_DbgPrint(DEBUG_TCP,
("Getting the user buffer from %x\n", Mdl));
NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
TI_DbgPrint(DEBUG_TCP,
("Reading %d bytes to %x\n", RecvLen, RecvBuffer));
TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
TI_DbgPrint
(DEBUG_TCP,
("Connection->SocketContext: %x\n",
Connection->SocketContext));
TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
Status = TCPTranslateError
( OskitTCPRecv( Connection->SocketContext,
RecvBuffer,
RecvLen,
&Received,
0 ) );
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Received));
if( Status == STATUS_SUCCESS ) {
TI_DbgPrint(DEBUG_TCP,("Received %d bytes with status %x\n",
Received, Status));
Complete( Bucket->Request.RequestContext,
STATUS_SUCCESS, Received );
exFreePool( Bucket );
} else if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList
( &Connection->ReceiveRequest, &Bucket->Entry, &Connection->Lock );
Connection->SignalState |= SEL_READ;
break;
} else {
TI_DbgPrint(DEBUG_TCP,
("Completing Receive request: %x %x\n",
Bucket->Request, Status));
Complete( Bucket->Request.RequestContext, Status, 0 );
exFreePool( Bucket );
}
}
}
if( Connection->SignalState & SEL_WRITE ) {
TI_DbgPrint(DEBUG_TCP,("Writeable: irp list %s\n",
IsListEmpty(&Connection->SendRequest) ?
"empty" : "nonempty"));
Connection->SignalState &= ~SEL_WRITE;
while( (Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest,
&Connection->Lock )) != NULL ) {
OSK_UINT SendLen = 0, Sent = 0;
PVOID SendBuffer = 0;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
Mdl = Irp->MdlAddress;
TI_DbgPrint(DEBUG_TCP,
("Getting the user buffer from %x\n", Mdl));
NdisQueryBuffer( Mdl, &SendBuffer, &SendLen );
TI_DbgPrint(DEBUG_TCP,
("Writing %d bytes to %x\n", SendLen, SendBuffer));
TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
TI_DbgPrint
(DEBUG_TCP,
("Connection->SocketContext: %x\n",
Connection->SocketContext));
Status = TCPTranslateError
( OskitTCPSend( Connection->SocketContext,
SendBuffer,
SendLen,
&Sent,
0 ) );
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Sent));
if( Status == STATUS_SUCCESS ) {
TI_DbgPrint(DEBUG_TCP,("Sent %d bytes with status %x\n",
Sent, Status));
Complete( Bucket->Request.RequestContext,
STATUS_SUCCESS, Sent );
exFreePool( Bucket );
} else if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList
( &Connection->SendRequest, &Bucket->Entry, &Connection->Lock );
Connection->SignalState |= SEL_WRITE;
break;
} else {
TI_DbgPrint(DEBUG_TCP,
("Completing Send request: %x %x\n",
Bucket->Request, Status));
Complete( Bucket->Request.RequestContext, Status, 0 );
exFreePool( Bucket );
}
}
}
return Connection->SignalState;
}
static VOID DrainSignals() {
PCONNECTION_ENDPOINT Connection;
PLIST_ENTRY CurrentEntry, NextEntry;
ULONG NewState;
KIRQL OldIrql;
KeAcquireSpinLock(&SignalledConnectionsLock, &OldIrql);
CurrentEntry = SignalledConnectionsList.Flink;
while (CurrentEntry != &SignalledConnectionsList)
KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
CurrentEntry = ConnectionEndpointListHead.Flink;
while (CurrentEntry != &ConnectionEndpointListHead)
{
NextEntry = CurrentEntry->Flink;
KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
Connection = CONTAINING_RECORD( CurrentEntry, CONNECTION_ENDPOINT,
SignalList );
ListEntry );
KeReleaseSpinLock(&SignalledConnectionsLock, OldIrql);
NewState = HandleSignalledConnection(Connection);
KeAcquireSpinLock(&SignalledConnectionsLock, &OldIrql);
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
if (NewState == SEL_FIN || NewState == 0)
{
RemoveEntryList(CurrentEntry);
TI_DbgPrint(MID_TRACE,("Handling signalled state on %x (%x)\n",
Connection, Connection->SocketContext));
if( !Connection->SocketContext || Connection->SignalState & SEL_FIN ) {
KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(DEBUG_TCP, ("EOF From socket\n"));
while ((Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest,
&Connection->Lock )) != NULL)
{
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
exFreePool(Bucket);
}
while ((Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest,
&Connection->Lock )) != NULL)
{
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
exFreePool(Bucket);
}
while ((Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,
&Connection->Lock )) != NULL)
{
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
exFreePool(Bucket);
}
while ((Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest,
&Connection->Lock )) != NULL)
{
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
exFreePool(Bucket);
}
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
}
CurrentEntry = NextEntry;
/* Things that can happen when we try the initial connection */
if( Connection->SignalState & SEL_CONNECT ) {
KeReleaseSpinLock(&Connection->Lock, OldIrql);
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest,
&Connection->Lock )) != NULL ) {
TI_DbgPrint(DEBUG_TCP, ("Connect Event\n"));
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
TI_DbgPrint(DEBUG_TCP,
("Completing Request %x\n", Bucket->Request.RequestContext));
Complete( Bucket->Request.RequestContext, STATUS_SUCCESS, 0 );
/* Frees the bucket allocated in TCPConnect */
exFreePool( Bucket );
}
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
}
if( Connection->SignalState & SEL_ACCEPT ) {
/* Handle readable on a listening socket --
* TODO: Implement filtering
*/
KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(DEBUG_TCP,("Accepting new connection on %x (Queue: %s)\n",
Connection,
IsListEmpty(&Connection->ListenRequest) ?
"empty" : "nonempty"));
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,
&Connection->Lock )) != NULL ) {
PIO_STACK_LOCATION IrpSp;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
IrpSp = IoGetCurrentIrpStackLocation( Irp );
TI_DbgPrint(DEBUG_TCP,("Getting the socket\n"));
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
Status = TCPServiceListeningSocket
( Connection->AddressFile->Listener,
Bucket->AssociatedEndpoint,
(PTDI_REQUEST_KERNEL)&IrpSp->Parameters );
KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n"));
if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList( &Connection->ListenRequest, &Bucket->Entry,
&Connection->Lock );
break;
} else {
Complete( Bucket->Request.RequestContext, Status, 0 );
exFreePool( Bucket );
}
}
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
}
/* Things that happen after we're connected */
if( Connection->SignalState & SEL_READ &&
Connection->SignalState & SEL_CONNECT ) {
TI_DbgPrint(DEBUG_TCP,("Readable: irp list %s\n",
IsListEmpty(&Connection->ReceiveRequest) ?
"empty" : "nonempty"));
KeReleaseSpinLock(&Connection->Lock, OldIrql);
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest,
&Connection->Lock )) != NULL ) {
OSK_UINT RecvLen = 0, Received = 0;
PVOID RecvBuffer = 0;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
Mdl = Irp->MdlAddress;
TI_DbgPrint(DEBUG_TCP,
("Getting the user buffer from %x\n", Mdl));
NdisQueryBuffer( Mdl, &RecvBuffer, &RecvLen );
TI_DbgPrint(DEBUG_TCP,
("Reading %d bytes to %x\n", RecvLen, RecvBuffer));
TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
TI_DbgPrint
(DEBUG_TCP,
("Connection->SocketContext: %x\n",
Connection->SocketContext));
TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
Status = TCPTranslateError
( OskitTCPRecv( Connection->SocketContext,
RecvBuffer,
RecvLen,
&Received,
0 ) );
KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Received));
if( Status == STATUS_SUCCESS ) {
TI_DbgPrint(DEBUG_TCP,("Received %d bytes with status %x\n",
Received, Status));
Complete( Bucket->Request.RequestContext,
STATUS_SUCCESS, Received );
exFreePool( Bucket );
} else if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList( &Connection->ReceiveRequest, &Bucket->Entry,
&Connection->Lock );
break;
} else {
TI_DbgPrint(DEBUG_TCP,
("Completing Receive request: %x %x\n",
Bucket->Request, Status));
Complete( Bucket->Request.RequestContext, Status, 0 );
exFreePool( Bucket );
}
}
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
}
if( Connection->SignalState & SEL_WRITE &&
Connection->SignalState & SEL_CONNECT ) {
TI_DbgPrint(DEBUG_TCP,("Writeable: irp list %s\n",
IsListEmpty(&Connection->SendRequest) ?
"empty" : "nonempty"));
KeReleaseSpinLock(&Connection->Lock, OldIrql);
while( (Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest,
&Connection->Lock )) != NULL ) {
OSK_UINT SendLen = 0, Sent = 0;
PVOID SendBuffer = 0;
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Complete = Bucket->Request.RequestNotifyObject;
Irp = Bucket->Request.RequestContext;
Mdl = Irp->MdlAddress;
TI_DbgPrint(DEBUG_TCP,
("Getting the user buffer from %x\n", Mdl));
NdisQueryBuffer( Mdl, &SendBuffer, &SendLen );
TI_DbgPrint(DEBUG_TCP,
("Writing %d bytes to %x\n", SendLen, SendBuffer));
TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
TI_DbgPrint
(DEBUG_TCP,
("Connection->SocketContext: %x\n",
Connection->SocketContext));
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
Status = TCPTranslateError
( OskitTCPSend( Connection->SocketContext,
SendBuffer,
SendLen,
&Sent,
0 ) );
KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Sent));
if( Status == STATUS_SUCCESS ) {
TI_DbgPrint(DEBUG_TCP,("Sent %d bytes with status %x\n",
Sent, Status));
Complete( Bucket->Request.RequestContext,
STATUS_SUCCESS, Sent );
exFreePool( Bucket );
} else if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList( &Connection->SendRequest, &Bucket->Entry,
&Connection->Lock );
break;
} else {
TI_DbgPrint(DEBUG_TCP,
("Completing Send request: %x %x\n",
Bucket->Request, Status));
Complete( Bucket->Request.RequestContext, Status, 0 );
exFreePool( Bucket );
}
}
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
}
KeReleaseSpinLock(&Connection->Lock, OldIrql);
if (!Connection->SocketContext)
{
TCPFreeConnectionEndpoint(Connection);
}
CurrentEntry = NextEntry;
KeAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
}
KeReleaseSpinLock(&SignalledConnectionsLock, OldIrql);
KeReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
}
PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
@ -314,7 +325,7 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
RtlZeroMemory(Connection, sizeof(CONNECTION_ENDPOINT));
/* Initialize spin lock that protects the connection endpoint file object */
TcpipInitializeSpinLock(&Connection->Lock);
KeInitializeSpinLock(&Connection->Lock);
InitializeListHead(&Connection->ConnectRequest);
InitializeListHead(&Connection->ListenRequest);
InitializeListHead(&Connection->ReceiveRequest);
@ -323,19 +334,32 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
/* Save client context pointer */
Connection->ClientContext = ClientContext;
/* Add connection endpoint to global list */
ExInterlockedInsertTailList(&ConnectionEndpointListHead,
&Connection->ListEntry,
&ConnectionEndpointListLock);
return Connection;
}
VOID TCPFreeConnectionEndpoint( PCONNECTION_ENDPOINT Connection ) {
KIRQL OldIrql;
TI_DbgPrint(DEBUG_TCP, ("Freeing TCP Endpoint\n"));
TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
RemoveEntryList(&Connection->ListEntry);
TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
exFreePool( Connection );
}
NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
UINT Family, UINT Type, UINT Proto ) {
NTSTATUS Status;
KIRQL OldIrql;
TcpipRecursiveMutexEnter(&TCPLock);
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
TI_DbgPrint(DEBUG_TCP,("Called: Connection %x, Family %d, Type %d, "
"Proto %d\n",
@ -352,7 +376,7 @@ NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext %x\n",
Connection->SocketContext));
TcpipRecursiveMutexLeave(&TCPLock);
KeReleaseSpinLock(&Connection->Lock, OldIrql);
return Status;
}
@ -370,13 +394,9 @@ VOID TCPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
IPPacket->TotalSize,
IPPacket->HeaderSize));
TcpipRecursiveMutexEnter( &TCPLock );
OskitTCPReceiveDatagram( IPPacket->Header,
IPPacket->TotalSize,
IPPacket->HeaderSize );
TcpipRecursiveMutexLeave( &TCPLock );
}
/* event.c */
@ -447,10 +467,7 @@ TimerThread(PVOID Context)
PsTerminateSystemThread(Status);
}
TcpipRecursiveMutexEnter( &TCPLock );
TimerOskitTCP( Next == NextFast, Next == NextSlow );
TcpipRecursiveMutexLeave( &TCPLock );
if (Next == NextSlow) {
DrainSignals();
}
@ -483,9 +500,6 @@ NTSTATUS TCPStartup(VOID)
{
NTSTATUS Status;
TcpipRecursiveMutexInit( &TCPLock );
KeInitializeSpinLock( &SignalledConnectionsLock );
InitializeListHead( &SignalledConnectionsList );
Status = TCPMemStartup();
if ( ! NT_SUCCESS(Status) ) {
return Status;
@ -497,10 +511,8 @@ NTSTATUS TCPStartup(VOID)
return Status;
}
TcpipRecursiveMutexEnter(&TCPLock);
RegisterOskitTCPEventHandlers( &EventHandlers );
InitOskitTCP();
TcpipRecursiveMutexLeave(&TCPLock);
/* Register this protocol with IP layer */
IPRegisterProtocol(IPPROTO_TCP, TCPReceive);
@ -545,9 +557,7 @@ NTSTATUS TCPShutdown(VOID)
TCPInitialized = FALSE;
TcpipRecursiveMutexEnter(&TCPLock);
DeinitOskitTCP();
TcpipRecursiveMutexLeave(&TCPLock);
PortsShutdown( &TCPPorts );
@ -597,6 +607,7 @@ NTSTATUS TCPConnect
USHORT RemotePort;
PTDI_BUCKET Bucket;
PNEIGHBOR_CACHE_ENTRY NCE;
KIRQL OldIrql;
TI_DbgPrint(DEBUG_TCP,("TCPConnect: Called\n"));
@ -625,7 +636,7 @@ NTSTATUS TCPConnect
AddressToBind = AddressToConnect;
AddressToBind.sin_addr.s_addr = NCE->Interface->Unicast.Address.IPv4Address;
TcpipRecursiveMutexEnter(&TCPLock);
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
Status = TCPTranslateError
( OskitTCPBind( Connection->SocketContext,
@ -640,26 +651,29 @@ NTSTATUS TCPConnect
Status = TCPTranslateError
( OskitTCPConnect( Connection->SocketContext,
Connection,
&AddressToConnect,
sizeof(AddressToConnect) ) );
KeReleaseSpinLock(&Connection->Lock, OldIrql);
if (Status == STATUS_PENDING)
{
Bucket = exAllocatePool( NonPagedPool, sizeof(*Bucket) );
if( !Bucket ) return STATUS_NO_MEMORY;
if( !Bucket )
{
return STATUS_NO_MEMORY;
}
Bucket->Request.RequestNotifyObject = (PVOID)Complete;
Bucket->Request.RequestContext = Context;
IoMarkIrpPending((PIRP)Context);
ExInterlockedInsertTailList( &Connection->ConnectRequest, &Bucket->Entry, &Connection->Lock );
ExInterlockedInsertTailList( &Connection->ConnectRequest, &Bucket->Entry,
&Connection->Lock );
}
} else {
KeReleaseSpinLock(&Connection->Lock, OldIrql);
}
TcpipRecursiveMutexLeave(&TCPLock);
return Status;
}
@ -671,12 +685,11 @@ NTSTATUS TCPDisconnect
PTCP_COMPLETION_ROUTINE Complete,
PVOID Context ) {
NTSTATUS Status = STATUS_INVALID_PARAMETER;
ASSERT_LOCKED(&TCPLock);
KIRQL OldIrql;
TI_DbgPrint(DEBUG_TCP,("started\n"));
TcpipRecursiveMutexEnter(&TCPLock);
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
if (Flags & TDI_DISCONNECT_RELEASE)
Status = TCPTranslateError(OskitTCPDisconnect(Connection->SocketContext));
@ -684,7 +697,7 @@ NTSTATUS TCPDisconnect
if ((Flags & TDI_DISCONNECT_ABORT) || !Flags)
Status = TCPTranslateError(OskitTCPShutdown(Connection->SocketContext, FWRITE | FREAD));
TcpipRecursiveMutexLeave(&TCPLock);
KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(DEBUG_TCP,("finished %x\n", Status));
@ -694,20 +707,20 @@ NTSTATUS TCPDisconnect
NTSTATUS TCPClose
( PCONNECTION_ENDPOINT Connection ) {
NTSTATUS Status;
KIRQL OldIrql;
PVOID Socket;
TI_DbgPrint(DEBUG_TCP,("TCPClose started\n"));
/* Make our code remove all pending IRPs */
Connection->SignalState |= SEL_FIN;
HandleSignalledConnection(Connection);
TcpipRecursiveMutexEnter(&TCPLock);
Status = TCPTranslateError( OskitTCPClose( Connection->SocketContext ) );
if (Status == STATUS_SUCCESS)
Connection->SocketContext = NULL;
TcpipRecursiveMutexLeave(&TCPLock);
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
Socket = Connection->SocketContext;
Connection->SocketContext = NULL;
Status = TCPTranslateError( OskitTCPClose( Socket ) );
if (!NT_SUCCESS(Status))
{
Connection->SocketContext = Socket;
}
KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(DEBUG_TCP,("TCPClose finished %x\n", Status));
@ -726,17 +739,18 @@ NTSTATUS TCPReceiveData
UINT DataLen, Received = 0;
NTSTATUS Status;
PTDI_BUCKET Bucket;
KIRQL OldIrql;
TI_DbgPrint(DEBUG_TCP,("Called for %d bytes (on socket %x)\n",
ReceiveLength, Connection->SocketContext));
ASSERT_KM_POINTER(Connection->SocketContext);
NdisQueryBuffer( Buffer, &DataBuffer, &DataLen );
TI_DbgPrint(DEBUG_TCP,("TCP>|< Got an MDL %x (%x:%d)\n", Buffer, DataBuffer, DataLen));
TcpipRecursiveMutexEnter(&TCPLock);
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
ASSERT_KM_POINTER(Connection->SocketContext);
Status = TCPTranslateError
( OskitTCPRecv
@ -746,7 +760,7 @@ NTSTATUS TCPReceiveData
&Received,
ReceiveFlags ) );
TcpipRecursiveMutexLeave(&TCPLock);
KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(DEBUG_TCP,("OskitTCPReceive: %x, %d\n", Status, Received));
@ -763,9 +777,8 @@ NTSTATUS TCPReceiveData
Bucket->Request.RequestContext = Context;
*BytesReceived = 0;
IoMarkIrpPending((PIRP)Context);
ExInterlockedInsertTailList( &Connection->ReceiveRequest, &Bucket->Entry, &Connection->Lock );
ExInterlockedInsertTailList( &Connection->ReceiveRequest, &Bucket->Entry,
&Connection->Lock );
TI_DbgPrint(DEBUG_TCP,("Queued read irp\n"));
} else {
TI_DbgPrint(DEBUG_TCP,("Got status %x, bytes %d\n", Status, Received));
@ -788,8 +801,9 @@ NTSTATUS TCPSendData
UINT Sent = 0;
NTSTATUS Status;
PTDI_BUCKET Bucket;
KIRQL OldIrql;
ASSERT_LOCKED(&TCPLock);
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
TI_DbgPrint(DEBUG_TCP,("Called for %d bytes (on socket %x)\n",
SendLength, Connection->SocketContext));
@ -800,14 +814,12 @@ NTSTATUS TCPSendData
TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext = %x\n",
Connection->SocketContext));
TcpipRecursiveMutexEnter(&TCPLock);
Status = TCPTranslateError
( OskitTCPSend( Connection->SocketContext,
(OSK_PCHAR)BufferData, SendLength,
&Sent, 0 ) );
TcpipRecursiveMutexLeave(&TCPLock);
KeReleaseSpinLock(&Connection->Lock, OldIrql);
TI_DbgPrint(DEBUG_TCP,("OskitTCPSend: %x, %d\n", Status, Sent));
@ -823,10 +835,9 @@ NTSTATUS TCPSendData
Bucket->Request.RequestNotifyObject = Complete;
Bucket->Request.RequestContext = Context;
*BytesSent = 0;
IoMarkIrpPending((PIRP)Context);
ExInterlockedInsertTailList( &Connection->SendRequest, &Bucket->Entry, &Connection->Lock );
ExInterlockedInsertTailList( &Connection->SendRequest, &Bucket->Entry,
&Connection->Lock );
TI_DbgPrint(DEBUG_TCP,("Queued write irp\n"));
} else {
TI_DbgPrint(DEBUG_TCP,("Got status %x, bytes %d\n", Status, Sent));
@ -865,14 +876,15 @@ NTSTATUS TCPGetSockAddress
OSK_UI16 LocalPort, RemotePort;
PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address;
NTSTATUS Status;
KIRQL OldIrql;
TcpipRecursiveMutexEnter(&TCPLock);
KeAcquireSpinLock(&Connection->Lock, &OldIrql);
Status = TCPTranslateError(OskitTCPGetAddress(Connection->SocketContext,
&LocalAddress, &LocalPort,
&RemoteAddress, &RemotePort));
TcpipRecursiveMutexLeave(&TCPLock);
KeReleaseSpinLock(&Connection->Lock, OldIrql);
if (!NT_SUCCESS(Status))
return Status;

View file

@ -172,6 +172,9 @@ NTSTATUS UDPSendDatagram(
USHORT RemotePort;
NTSTATUS Status;
PNEIGHBOR_CACHE_ENTRY NCE;
KIRQL OldIrql;
KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
AddrFile, ConnInfo, BufferData, DataSize));
@ -186,10 +189,12 @@ NTSTATUS UDPSendDatagram(
break;
default:
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
return STATUS_UNSUCCESSFUL;
}
if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
return STATUS_NETWORK_UNREACHABLE;
}
@ -213,14 +218,20 @@ NTSTATUS UDPSendDatagram(
DataSize );
if( !NT_SUCCESS(Status) )
{
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
return Status;
}
if (!NT_SUCCESS(Status = IPSendDatagram( &Packet, NCE, UDPSendPacketComplete, NULL )))
{
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
FreeNdisPacket(Packet.NdisPacket);
return Status;
}
KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
return STATUS_SUCCESS;
}

View file

@ -123,7 +123,7 @@ extern int OskitTCPSend( void *socket,
OSK_UINT *OutLen,
OSK_UINT Flags );
extern int OskitTCPConnect( void *socket, void *connection,
extern int OskitTCPConnect( void *socket,
void *nam, OSK_UINT namelen );
extern int OskitTCPClose( void *socket );
@ -131,7 +131,7 @@ extern int OskitTCPBind( void *socket,
void *nam, OSK_UINT namelen );
extern int OskitTCPAccept( void *socket, void **new_socket,
void *addr_out,
void *context, void *addr_out,
OSK_UINT addr_len,
OSK_UINT *out_addr_len,
OSK_UINT finish_accept );
@ -187,4 +187,27 @@ void fbsd_free( void *data, char *file, unsigned line, ... );
#define FREAD 0x0001
#define FWRITE 0x0002
/* Don't define this unless your are insane or aicom */
//#define LOCK_SPAM
#ifdef LOCK_SPAM
#define OSKLock() if (!KeTryToAcquireSpinLockAtDpcLevel(&OSKLock)) \
{ \
DbgPrint("OSKLock WAIT (%s)\n", __FUNCTION__); \
KeAcquireSpinLockAtDpcLevel(&OSKLock); \
} \
DbgPrint("OSKLock >>>> (%s)\n", __FUNCTION__)
#define OSKUnlock() KeReleaseSpinLockFromDpcLevel(&OSKLock); \
DbgPrint("OSKLock <<<< (%s)\n", __FUNCTION__)
#else
#define OSKLock() KeAcquireSpinLockAtDpcLevel(&OSKLock)
#define OSKUnlock() KeReleaseSpinLockFromDpcLevel(&OSKLock)
#endif
#define OSKLockAndRaise(x) KeRaiseIrql(DISPATCH_LEVEL, x); \
OSKLock()
#define OSKUnlockAndLower(x) OSKUnlock(); \
KeLowerIrql(x)
#endif/*OSKITTCP_H*/

View file

@ -23,6 +23,8 @@ OSKITTCP_EVENT_HANDLERS OtcpEvent = { 0 };
//OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA;
OSK_UINT OskitDebugTraceLevel = 0;
KSPIN_LOCK OSKLock;
/* SPL */
unsigned cpl;
unsigned net_imask;
@ -45,6 +47,7 @@ void fbsd_free( void *data, char *file, unsigned line, ... ) {
void InitOskitTCP() {
OS_DbgPrint(OSK_MID_TRACE,("Init Called\n"));
KeInitializeSpinLock(&OSKLock);
OS_DbgPrint(OSK_MID_TRACE,("MB Init\n"));
mbinit();
OS_DbgPrint(OSK_MID_TRACE,("Rawip Init\n"));
@ -66,12 +69,19 @@ void DeinitOskitTCP() {
}
void TimerOskitTCP( int FastTimer, int SlowTimer ) {
KIRQL OldIrql;
/* This function is a special case in which we cannot use OSKLock/OSKUnlock
* because we don't enter with the connection lock held */
OSKLockAndRaise(&OldIrql);
if ( SlowTimer ) {
tcp_slowtimo();
}
if ( FastTimer ) {
tcp_fasttimo();
}
OSKUnlockAndLower(OldIrql);
}
void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
@ -115,12 +125,16 @@ int OskitTCPSocket( void *context,
int proto )
{
struct socket *so;
OSKLock();
int error = socreate(domain, &so, type, proto);
if( !error ) {
so->so_connection = context;
so->so_state |= SS_NBIO;
*aso = so;
}
OSKUnlock();
return error;
}
@ -153,8 +167,11 @@ int OskitTCPRecv( void *connection,
OS_DbgPrint(OSK_MID_TRACE,("Reading %d bytes from TCP:\n", Len));
OSKLock();
error = soreceive( connection, NULL, &uio, NULL, NULL /* SCM_RIGHTS */,
&tcp_flags );
OSKUnlock();
*OutLen = Len - uio.uio_resid;
return error;
@ -182,14 +199,15 @@ int OskitTCPBind( void *socket,
addr.sa_family = addr.sa_len;
addr.sa_len = sizeof(struct sockaddr);
OSKLock();
error = sobind(so, &sabuf);
OSKUnlock();
OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
return (error);
}
int OskitTCPConnect( void *socket, void *connection,
void *nam, OSK_UINT namelen ) {
int OskitTCPConnect( void *socket, void *nam, OSK_UINT namelen ) {
struct socket *so = socket;
int error = EFAULT;
struct mbuf sabuf;
@ -197,8 +215,7 @@ int OskitTCPConnect( void *socket, void *connection,
OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
so->so_connection = connection;
OSKLock();
if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
error = EALREADY;
goto done;
@ -217,7 +234,9 @@ int OskitTCPConnect( void *socket, void *connection,
error = soconnect(so, &sabuf);
if (error)
if (error == EINPROGRESS)
goto done;
else if (error)
goto bad;
if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
@ -232,34 +251,49 @@ bad:
error = EINTR;
done:
OSKUnlock();
OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
return (error);
}
int OskitTCPDisconnect(void *socket)
{
int error;
if (!socket)
return OSK_ESHUTDOWN;
return sodisconnect(socket);
OSKLock();
error = sodisconnect(socket);
OSKUnlock();
return error;
}
int OskitTCPShutdown( void *socket, int disconn_type ) {
int error;
if (!socket)
return OSK_ESHUTDOWN;
return soshutdown( socket, disconn_type );
OSKLock();
error = soshutdown( socket, disconn_type );
OSKUnlock();
return error;
}
int OskitTCPClose( void *socket ) {
struct socket *so = socket;
int error;
if (!socket)
return OSK_ESHUTDOWN;
so->so_connection = 0;
soclose( so );
return 0;
OSKLock();
error = soclose( socket );
OSKUnlock();
return error;
}
int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
@ -281,7 +315,10 @@ int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
uio.uio_rw = UIO_WRITE;
uio.uio_procp = NULL;
OSKLock();
error = sosend( socket, NULL, &uio, NULL, NULL, 0 );
OSKUnlock();
*OutLen = Len - uio.uio_resid;
return error;
@ -289,6 +326,7 @@ int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
int OskitTCPAccept( void *socket,
void **new_socket,
void *context,
void *AddrOut,
OSK_UINT AddrLen,
OSK_UINT *OutAddrLen,
@ -317,11 +355,12 @@ int OskitTCPAccept( void *socket,
/* that's a copyin actually */
namelen = *OutAddrLen;
OSKLock();
s = splnet();
#if 0
if ((head->so_options & SO_ACCEPTCONN) == 0) {
splx(s);
OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: head->so_options = %x, wanted bit %x\n",
head->so_options, SO_ACCEPTCONN));
error = EINVAL;
@ -333,39 +372,10 @@ int OskitTCPAccept( void *socket,
head->so_q, head->so_state));
if ((head->so_state & SS_NBIO) && head->so_q == NULL) {
splx(s);
error = EWOULDBLOCK;
goto out;
}
OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
while (head->so_q == NULL && head->so_error == 0) {
if (head->so_state & SS_CANTRCVMORE) {
head->so_error = ECONNABORTED;
break;
}
OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH,
"accept", 0);
if (error) {
splx(s);
goto out;
}
OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
}
OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
#if 0
if (head->so_error) {
OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
error = head->so_error;
head->so_error = 0;
splx(s);
goto out;
}
OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
#endif
/*
* At this point we know that there is at least one connection
* ready to be accepted. Remove it from the queue.
@ -384,19 +394,20 @@ int OskitTCPAccept( void *socket,
head->so_q = so->so_q;
head->so_qlen--;
*newso = so;
/*so->so_state &= ~SS_COMP;*/
mnam.m_data = (char *)&sa;
mnam.m_len = sizeof(sa);
(void) soaccept(so, &mnam);
error = soaccept(so, &mnam);
if (error)
goto out;
so->so_state = SS_NBIO | SS_ISCONNECTED;
so->so_state |= SS_NBIO | SS_ISCONNECTED;
so->so_q = so->so_q0 = NULL;
so->so_qlen = 0;
so->so_head = 0;
so->so_connection = context;
*newso = so;
OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
if (name) {
@ -406,9 +417,10 @@ int OskitTCPAccept( void *socket,
*OutAddrLen = namelen; /* copyout actually */
}
OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
splx(s);
}
out:
splx(s);
OSKUnlock();
OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Returning %d\n", error));
return (error);
}
@ -421,10 +433,20 @@ out:
void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
OSK_UINT IpHeaderLen ) {
struct mbuf *Ip = m_devget( (char *)Data, Len, 0, NULL, NULL );
struct mbuf *Ip;
struct ip *iph;
KIRQL OldIrql;
if( !Ip ) return; /* drop the segment */
/* This function is a special case in which we cannot use OSKLock/OSKUnlock
* because we don't enter with the connection lock held */
OSKLockAndRaise(&OldIrql);
Ip = m_devget( (char *)Data, Len, 0, NULL, NULL );
if( !Ip )
{
OSKUnlockAndLower(OldIrql);
return; /* drop the segment */
}
//memcpy( Ip->m_data, Data, Len );
Ip->m_pkthdr.len = IpHeaderLen;
@ -439,6 +461,7 @@ void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
IpHeaderLen));
tcp_input(Ip, IpHeaderLen);
OSKUnlockAndLower(OldIrql);
/* The buffer Ip is freed by tcp_input */
}
@ -450,6 +473,7 @@ int OskitTCPSetSockOpt(void *socket,
int size)
{
struct mbuf *m;
int error;
if (!socket)
return OSK_ESHUTDOWN;
@ -457,16 +481,23 @@ int OskitTCPSetSockOpt(void *socket,
if (size >= MLEN)
return OSK_EINVAL;
OSKLock();
m = m_get(M_WAIT, MT_SOOPTS);
if (!m)
{
OSKUnlock();
return OSK_ENOMEM;
}
m->m_len = size;
memcpy(m->m_data, buffer, size);
/* m is freed by sosetopt */
return sosetopt(socket, level, optname, m);
error = sosetopt(socket, level, optname, m);
OSKUnlock();
return error;
}
int OskitTCPGetSockOpt(void *socket,
@ -481,6 +512,7 @@ int OskitTCPGetSockOpt(void *socket,
if (!socket)
return OSK_ESHUTDOWN;
OSKLock();
error = sogetopt(socket, level, optname, &m);
if (!error)
{
@ -489,6 +521,7 @@ int OskitTCPGetSockOpt(void *socket,
if (!buffer || oldsize < m->m_len)
{
m_freem(m);
OSKUnlock();
return OSK_EINVAL;
}
@ -496,6 +529,7 @@ int OskitTCPGetSockOpt(void *socket,
m_freem(m);
}
OSKUnlock();
return error;
}
@ -507,7 +541,11 @@ int OskitTCPListen( void *socket, int backlog ) {
return OSK_ESHUTDOWN;
OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
OSKLock();
error = solisten( socket, backlog );
OSKUnlock();
OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
return error;
@ -524,11 +562,13 @@ int OskitTCPSetAddress( void *socket,
if (!socket)
return OSK_ESHUTDOWN;
OSKLock();
inp = (struct inpcb *)so->so_pcb;
inp->inp_laddr.s_addr = LocalAddress;
inp->inp_lport = LocalPort;
inp->inp_faddr.s_addr = RemoteAddress;
inp->inp_fport = RemotePort;
OSKUnlock();
return 0;
}
@ -544,11 +584,13 @@ int OskitTCPGetAddress( void *socket,
if (!socket)
return OSK_ESHUTDOWN;
OSKLock();
inp = (struct inpcb *)so->so_pcb;
*LocalAddress = inp->inp_laddr.s_addr;
*LocalPort = inp->inp_lport;
*RemoteAddress = inp->inp_faddr.s_addr;
*RemotePort = inp->inp_fport;
OSKUnlock();
return 0;
}