Author: cgutman Date: Fri Jul 8 16:34:49 2011 New Revision: 52572
URL: http://svn.reactos.org/svn/reactos?rev=52572&view=rev Log: [IP] - Complete waiting requests upon socket error - Fixes connect() stall forever if the remote side is not listening
Modified: trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c trunk/reactos/lib/drivers/oskittcp/oskittcp/sleep.c
Modified: trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/transport/tc... ============================================================================== --- trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/ip/transport/tcp/tcp.c [iso-8859-1] Fri Jul 8 16:34:49 2011 @@ -60,20 +60,31 @@ Connection, Connection->SocketContext));
/* Things that can happen when we try the initial connection */ - if( Connection->SignalState & (SEL_CONNECT | SEL_FIN) ) { + if( Connection->SignalState & (SEL_CONNECT | SEL_FIN | SEL_ERROR) ) { while (!IsListEmpty(&Connection->ConnectRequest)) { Entry = RemoveHeadList( &Connection->ConnectRequest );
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
- Bucket->Status = (Connection->SignalState & SEL_CONNECT) ? STATUS_SUCCESS : STATUS_CANCELLED; + if (Connection->SignalState & SEL_ERROR) + { + Bucket->Status = TCPTranslateError(OskitTCPGetSocketError(Connection->SocketContext)); + } + else if (Connection->SignalState & SEL_FIN) + { + Bucket->Status = STATUS_CANCELLED; + } + else + { + Bucket->Status = STATUS_SUCCESS; + } Bucket->Information = 0;
CompleteBucket(Connection, Bucket); } }
- if( Connection->SignalState & (SEL_ACCEPT | SEL_FIN) ) { + if( Connection->SignalState & (SEL_ACCEPT | SEL_FIN | SEL_ERROR) ) { /* Handle readable on a listening socket -- * TODO: Implement filtering */ @@ -94,25 +105,28 @@
TI_DbgPrint(DEBUG_TCP,("Getting the socket\n"));
- if (Connection->SignalState & SEL_ACCEPT) + if (Connection->SignalState & SEL_ERROR) + { + Status = TCPTranslateError(OskitTCPGetSocketError(Connection->SocketContext)); + } + else if (Connection->SignalState & SEL_FIN) + { + Status = STATUS_CANCELLED; + } + else { Status = TCPServiceListeningSocket(Connection->AddressFile->Listener, Bucket->AssociatedEndpoint, (PTDI_REQUEST_KERNEL)&IrpSp->Parameters); } - else - { - /* We got here because of a SEL_FIN event */ - Status = STATUS_CANCELLED; - }
TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n"));
- if( Status == STATUS_PENDING && !(Connection->SignalState & SEL_FIN) ) { + if( Status == STATUS_PENDING ) { InsertHeadList( &Connection->ListenRequest, &Bucket->Entry ); break; } else { - Bucket->Status = (Status == STATUS_PENDING) ? STATUS_CANCELLED : Status; + Bucket->Status = Status; Bucket->Information = 0; DereferenceObject(Bucket->AssociatedEndpoint);
@@ -122,7 +136,7 @@ }
/* Things that happen after we're connected */ - if( Connection->SignalState & (SEL_READ | SEL_FIN) ) { + if( Connection->SignalState & (SEL_READ | SEL_FIN | SEL_ERROR) ) { TI_DbgPrint(DEBUG_TCP,("Readable: irp list %s\n", IsListEmpty(&Connection->ReceiveRequest) ? "empty" : "nonempty")); @@ -153,7 +167,16 @@ Connection->SocketContext)); TI_DbgPrint(DEBUG_TCP, ("RecvBuffer: %x\n", RecvBuffer));
- if (Connection->SignalState & SEL_READ) + if (Connection->SignalState & SEL_ERROR) + { + Status = TCPTranslateError(OskitTCPGetSocketError(Connection->SocketContext)); + } + else if (Connection->SignalState & SEL_FIN) + { + /* We got here because of a SEL_FIN event */ + Status = STATUS_CANCELLED; + } + else { Status = TCPTranslateError(OskitTCPRecv(Connection->SocketContext, RecvBuffer, @@ -161,15 +184,10 @@ &Received, 0)); } - else - { - /* We got here because of a SEL_FIN event */ - Status = STATUS_CANCELLED; - }
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Received));
- if( Status == STATUS_PENDING && !(Connection->SignalState & SEL_FIN) ) { + if( Status == STATUS_PENDING ) { InsertHeadList( &Connection->ReceiveRequest, &Bucket->Entry ); break; } else { @@ -177,14 +195,14 @@ ("Completing Receive request: %x %x\n", Bucket->Request, Status));
- Bucket->Status = (Status == STATUS_PENDING) ? STATUS_CANCELLED : Status; + Bucket->Status = Status; Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? Received : 0;
CompleteBucket(Connection, Bucket); } } } - if( Connection->SignalState & (SEL_WRITE | SEL_FIN) ) { + if( Connection->SignalState & (SEL_WRITE | SEL_FIN | SEL_ERROR) ) { TI_DbgPrint(DEBUG_TCP,("Writeable: irp list %s\n", IsListEmpty(&Connection->SendRequest) ? "empty" : "nonempty")); @@ -214,7 +232,16 @@ ("Connection->SocketContext: %x\n", Connection->SocketContext));
- if (Connection->SignalState & SEL_WRITE) + if (Connection->SignalState & SEL_ERROR) + { + Status = TCPTranslateError(OskitTCPGetSocketError(Connection->SocketContext)); + } + else if (Connection->SignalState & SEL_FIN) + { + /* We got here because of a SEL_FIN event */ + Status = STATUS_CANCELLED; + } + else { Status = TCPTranslateError(OskitTCPSend(Connection->SocketContext, SendBuffer, @@ -222,15 +249,10 @@ &Sent, 0)); } - else - { - /* We got here because of a SEL_FIN event */ - Status = STATUS_CANCELLED; - }
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", Sent));
- if( Status == STATUS_PENDING && !(Connection->SignalState & SEL_FIN) ) { + if( Status == STATUS_PENDING ) { InsertHeadList( &Connection->SendRequest, &Bucket->Entry ); break; } else { @@ -238,20 +260,29 @@ ("Completing Send request: %x %x\n", Bucket->Request, Status));
- Bucket->Status = (Status == STATUS_PENDING) ? STATUS_CANCELLED : Status; + Bucket->Status = Status; Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? Sent : 0;
CompleteBucket(Connection, Bucket); } } } - if( Connection->SignalState & (SEL_WRITE | SEL_FIN) ) { + if( Connection->SignalState & (SEL_WRITE | SEL_FIN | SEL_ERROR) ) { while (!IsListEmpty(&Connection->ShutdownRequest)) { Entry = RemoveHeadList( &Connection->ShutdownRequest );
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry ); - - if (!(Connection->SignalState & SEL_FIN)) + + if (Connection->SignalState & SEL_ERROR) + { + Status = TCPTranslateError(OskitTCPGetSocketError(Connection->SocketContext)); + } + else if (Connection->SignalState & SEL_FIN) + { + /* We were cancelled by a FIN */ + Status = STATUS_CANCELLED; + } + else { /* See if we can satisfy this after the events */ if (IsListEmpty(&Connection->SendRequest)) @@ -265,12 +296,7 @@ Status = STATUS_PENDING; } } - else - { - /* We were cancelled by a FIN */ - Status = STATUS_CANCELLED; - } - + if( Status == STATUS_PENDING ) { InsertHeadList( &Connection->ShutdownRequest, &Bucket->Entry ); break;
Modified: trunk/reactos/lib/drivers/oskittcp/oskittcp/sleep.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/oskittcp/oskitt... ============================================================================== --- trunk/reactos/lib/drivers/oskittcp/oskittcp/sleep.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/oskittcp/oskittcp/sleep.c [iso-8859-1] Fri Jul 8 16:34:49 2011 @@ -40,6 +40,10 @@ (so->so_state & SS_CANTSENDMORE)) { OS_DbgPrint(OSK_MID_TRACE,("Socket writeable\n")); flags |= SEL_WRITE; + } + if (so->so_error) { + OS_DbgPrint(OSK_MID_TRACE,("Socket error\n")); + flags |= SEL_ERROR; } if (!so->so_pcb) { OS_DbgPrint(OSK_MID_TRACE,("Socket dying\n"));