RECURSIVE_MUTEX TCPLock;
PORT_SET TCPPorts;
-static VOID HandleSignalledConnection( PCONNECTION_ENDPOINT Connection ) {
+ULONG HandleSignalledConnection( PCONNECTION_ENDPOINT Connection ) {
NTSTATUS Status = STATUS_SUCCESS;
PTCP_COMPLETION_ROUTINE Complete;
PTDI_BUCKET Bucket;
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;
- /* We have to notify oskittcp of the abortion */
- TCPDisconnect
- ( Connection,
- TDI_DISCONNECT_RELEASE | TDI_DISCONNECT_ABORT,
- NULL,
- NULL,
- Bucket->Request.RequestNotifyObject,
- (PIRP)Bucket->Request.RequestContext );
-
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;
- /* We have to notify oskittcp of the abortion */
- TCPDisconnect
- ( Connection,
- TDI_DISCONNECT_RELEASE,
- NULL,
- NULL,
- Bucket->Request.RequestNotifyObject,
- (PIRP)Bucket->Request.RequestContext );
-
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
exFreePool(Bucket);
}
+ Connection->SignalState &= ~SEL_ACCEPT;
while ((Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,
&Connection->Lock )) != NULL)
{
Connection);
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
+
+ exFreePool(Bucket);
}
+ Connection->SignalState &= ~SEL_CONNECT;
while ((Entry = ExInterlockedRemoveHeadList( &Connection->ConnectRequest,
&Connection->Lock )) != NULL)
{
Complete = Bucket->Request.RequestNotifyObject;
Complete( Bucket->Request.RequestContext, STATUS_CANCELLED, 0 );
- }
- Connection->SignalState = 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 ) {
IsListEmpty(&Connection->ListenRequest) ?
"empty" : "nonempty"));
+ Connection->SignalState &= ~SEL_ACCEPT;
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ListenRequest,
&Connection->Lock )) != NULL ) {
PIO_STACK_LOCATION IrpSp;
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 {
IsListEmpty(&Connection->ReceiveRequest) ?
"empty" : "nonempty"));
+ Connection->SignalState &= ~SEL_READ;
while( (Entry = ExInterlockedRemoveHeadList( &Connection->ReceiveRequest,
&Connection->Lock )) != NULL ) {
OSK_UINT RecvLen = 0, Received = 0;
} else if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList
( &Connection->ReceiveRequest, &Bucket->Entry, &Connection->Lock );
+ Connection->SignalState |= SEL_READ;
break;
} else {
TI_DbgPrint(DEBUG_TCP,
IsListEmpty(&Connection->SendRequest) ?
"empty" : "nonempty"));
+ Connection->SignalState &= ~SEL_WRITE;
while( (Entry = ExInterlockedRemoveHeadList( &Connection->SendRequest,
&Connection->Lock )) != NULL ) {
OSK_UINT SendLen = 0, Sent = 0;
} else if( Status == STATUS_PENDING ) {
ExInterlockedInsertHeadList
( &Connection->SendRequest, &Bucket->Entry, &Connection->Lock );
+ Connection->SignalState |= SEL_WRITE;
break;
} else {
TI_DbgPrint(DEBUG_TCP,
}
}
- Connection->SignalState = 0;
- Connection->Signalled = FALSE;
+ return Connection->SignalState;
}
-VOID DrainSignals() {
+static VOID DrainSignals() {
PCONNECTION_ENDPOINT Connection;
- PLIST_ENTRY ListEntry;
+ PLIST_ENTRY CurrentEntry, NextEntry;
+ ULONG NewState;
+ KIRQL OldIrql;
- while( (ListEntry = ExInterlockedRemoveHeadList(&SignalledConnectionsList,
- &SignalledConnectionsLock)) != NULL) {
- Connection = CONTAINING_RECORD( ListEntry, CONNECTION_ENDPOINT,
+ KeAcquireSpinLock(&SignalledConnectionsLock, &OldIrql);
+ CurrentEntry = SignalledConnectionsList.Flink;
+ while (CurrentEntry != &SignalledConnectionsList)
+ {
+ NextEntry = CurrentEntry->Flink;
+ Connection = CONTAINING_RECORD( CurrentEntry, CONNECTION_ENDPOINT,
SignalList );
- HandleSignalledConnection( Connection );
+
+ KeReleaseSpinLock(&SignalledConnectionsLock, OldIrql);
+ NewState = HandleSignalledConnection(Connection);
+ KeAcquireSpinLock(&SignalledConnectionsLock, &OldIrql);
+
+ if (NewState == SEL_FIN || NewState == 0)
+ {
+ RemoveEntryList(CurrentEntry);
+ }
+
+ CurrentEntry = NextEntry;
}
+ KeReleaseSpinLock(&SignalledConnectionsLock, OldIrql);
}
PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID ClientContext ) {
IPPacket->TotalSize,
IPPacket->HeaderSize );
- DrainSignals();
-
TcpipRecursiveMutexLeave( &TCPLock );
}
}
NTSTATUS TCPTranslateError( int OskitError ) {
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
+ NTSTATUS Status;
switch( OskitError ) {
case 0: Status = STATUS_SUCCESS; break;
- case OSK_EADDRNOTAVAIL:
+ case OSK_EADDRNOTAVAIL: Status = STATUS_INVALID_ADDRESS; break;
case OSK_EAFNOSUPPORT: Status = STATUS_INVALID_CONNECTION; break;
case OSK_ECONNREFUSED:
case OSK_ECONNRESET: Status = STATUS_REMOTE_NOT_LISTENING; break;
- case OSK_EINPROGRESS:
- case OSK_EAGAIN: Status = STATUS_PENDING; break;
- default: Status = STATUS_INVALID_CONNECTION; break;
+ case OSK_EWOULDBLOCK:
+ case OSK_EINPROGRESS: Status = STATUS_PENDING; break;
+ case OSK_EINVAL: Status = STATUS_INVALID_PARAMETER; break;
+ case OSK_ENOMEM:
+ case OSK_ENOBUFS: Status = STATUS_INSUFFICIENT_RESOURCES; break;
+ case OSK_ESHUTDOWN: Status = STATUS_FILE_CLOSED; break;
+ case OSK_EMSGSIZE: Status = STATUS_BUFFER_TOO_SMALL; break;
+ case OSK_ETIMEDOUT: Status = STATUS_TIMEOUT; break;
+ case OSK_ENETUNREACH: Status = STATUS_NETWORK_UNREACHABLE; break;
+ case OSK_EFAULT: Status = STATUS_ACCESS_VIOLATION; break;
+ default:
+ DbgPrint("OskitTCP returned unhandled error code: %d\n", OskitError);
+ Status = STATUS_INVALID_CONNECTION;
+ break;
}
TI_DbgPrint(DEBUG_TCP,("Error %d -> %x\n", OskitError, Status));
return STATUS_NETWORK_UNREACHABLE;
}
- if (Connection->State & SEL_FIN)
- {
- return STATUS_REMOTE_DISCONNECT;
- }
-
/* Freed in TCPSocketState */
TI_DbgPrint(DEBUG_TCP,
("Connecting to address %x:%x\n",
Status = TCPTranslateError
( OskitTCPBind( Connection->SocketContext,
- Connection,
&AddressToBind,
sizeof(AddressToBind) ) );
PTDI_CONNECTION_INFORMATION ReturnInfo,
PTCP_COMPLETION_ROUTINE Complete,
PVOID Context ) {
- NTSTATUS Status;
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
ASSERT_LOCKED(&TCPLock);
TI_DbgPrint(DEBUG_TCP,("started\n"));
- switch( Flags & (TDI_DISCONNECT_ABORT | TDI_DISCONNECT_RELEASE) ) {
- case 0:
- case TDI_DISCONNECT_ABORT:
- Flags = 0;
- break;
+ if (Flags & TDI_DISCONNECT_RELEASE)
+ Status = TCPTranslateError(OskitTCPDisconnect(Connection->SocketContext));
- case TDI_DISCONNECT_ABORT | TDI_DISCONNECT_RELEASE:
- Flags = 2;
- break;
-
- case TDI_DISCONNECT_RELEASE:
- Flags = 1;
- break;
- }
-
- Status = TCPTranslateError
- ( OskitTCPShutdown( Connection->SocketContext, Flags ) );
+ if ((Flags & TDI_DISCONNECT_ABORT) || !Flags)
+ Status = TCPTranslateError(OskitTCPShutdown(Connection->SocketContext, FWRITE | FREAD));
TI_DbgPrint(DEBUG_TCP,("finished %x\n", Status));
ASSERT_LOCKED(&TCPLock);
/* Make our code remove all pending IRPs */
- Connection->State |= SEL_FIN;
- DrainSignals();
+ Connection->SignalState |= SEL_FIN;
+ HandleSignalledConnection(Connection);
Status = TCPTranslateError( OskitTCPClose( Connection->SocketContext ) );
+ if (Status == STATUS_SUCCESS)
+ Connection->SocketContext = NULL;
TI_DbgPrint(DEBUG_TCP,("TCPClose finished %x\n", Status));
ASSERT_KM_POINTER(Connection->SocketContext);
- /* Closing */
- if (Connection->State & SEL_FIN)
- {
- *BytesReceived = 0;
- return STATUS_REMOTE_DISCONNECT;
- }
-
NdisQueryBuffer( Buffer, &DataBuffer, &DataLen );
TI_DbgPrint(DEBUG_TCP,("TCP>|< Got an MDL %x (%x:%d)\n", Buffer, DataBuffer, DataLen));
TI_DbgPrint(DEBUG_TCP,("Connection->SocketContext = %x\n",
Connection->SocketContext));
- /* Closing */
- if (Connection->State & SEL_FIN)
- {
- *BytesSent = 0;
- return STATUS_REMOTE_DISCONNECT;
- }
Status = TCPTranslateError
( OskitTCPSend( Connection->SocketContext,
OSK_UINT LocalAddress, RemoteAddress;
OSK_UI16 LocalPort, RemotePort;
PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address;
+ NTSTATUS Status;
ASSERT_LOCKED(&TCPLock);
- OskitTCPGetAddress
- ( Connection->SocketContext,
- &LocalAddress, &LocalPort,
- &RemoteAddress, &RemotePort );
+ Status = TCPTranslateError(OskitTCPGetAddress(Connection->SocketContext,
+ &LocalAddress, &LocalPort,
+ &RemoteAddress, &RemotePort));
+ if (!NT_SUCCESS(Status))
+ return Status;
AddressIP->TAAddressCount = 1;
AddressIP->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
AddressIP->Address[0].Address[0].sin_port = GetRemote ? RemotePort : LocalPort;
AddressIP->Address[0].Address[0].in_addr = GetRemote ? RemoteAddress : LocalAddress;
- return STATUS_SUCCESS;
+ return Status;
}
VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) {