diff --git a/reactos/lib/msafd/include/msafd.h b/reactos/lib/msafd/include/msafd.h index 799c2c30e06..46e55c7c21c 100644 --- a/reactos/lib/msafd/include/msafd.h +++ b/reactos/lib/msafd/include/msafd.h @@ -460,6 +460,12 @@ VOID SockProcessQueuedAsyncSelect( PIO_STATUS_BLOCK IoStatusBlock ); +VOID +SockReenableAsyncSelectEvent ( + IN PSOCKET_INFORMATION Socket, + IN ULONG Event + ); + DWORD MsafdReturnWithErrno( NTSTATUS Status, LPINT Errno, DWORD Received, LPDWORD ReturnedBytes ); diff --git a/reactos/lib/msafd/misc/dllmain.c b/reactos/lib/msafd/misc/dllmain.c index e2206e7dcd2..df13911d807 100644 --- a/reactos/lib/msafd/misc/dllmain.c +++ b/reactos/lib/msafd/misc/dllmain.c @@ -974,6 +974,9 @@ WSPAccept( sizeof(RemoteAddress)); NtClose( SockEvent ); + + /* Re-enable Async Event */ + SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); AFD_DbgPrint(MID_TRACE,("Socket %x\n", AcceptSocket)); @@ -1054,6 +1057,16 @@ WSPConnect( SocketAddress->sa_data, SocketAddressLength - sizeof(SocketAddress->sa_family)); + /* + * Disable FD_WRITE and FD_CONNECT + * The latter fixes a race condition where the FD_CONNECT is re-enabled + * at the end of this function right after the Async Thread disables it. + * This should only happen at the *next* WSPConnect + */ + if (Socket->SharedData.AsyncEvents & FD_CONNECT) { + Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; + } + /* Tell AFD that we want Connection Data back, have it allocate a buffer */ if (lpCalleeData != NULL) { InConnectDataLength = lpCalleeData->len; @@ -1074,6 +1087,11 @@ WSPConnect( ConnectInfo->UseSAN = FALSE; ConnectInfo->Unknown = 0; + /* FIXME: Handle Async Connect */ + if (Socket->SharedData.NonBlocking) { + AFD_DbgPrint(MIN_TRACE, ("Async Connect UNIMPLEMENTED!\n")); + } + /* Send IOCTL */ Status = NtDeviceIoControlFile((HANDLE)Handle, SockEvent, @@ -1100,6 +1118,12 @@ WSPConnect( lpCalleeData->len); } + /* Re-enable Async Event */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + + /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ + SockReenableAsyncSelectEvent(Socket, FD_CONNECT); + AFD_DbgPrint(MID_TRACE,("Ending\n")); NtClose( SockEvent ); @@ -1717,7 +1741,6 @@ VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBl return; } - for (x = 1; x; x<<=1) { switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x) { case AFD_EVENT_RECEIVE: @@ -1756,6 +1779,7 @@ VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBl } break; + /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ case AFD_EVENT_CONNECT: if (0 != (Socket->SharedData.AsyncEvents & FD_CONNECT) && 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CONNECT)) { /* Make the Notifcation */ @@ -1842,6 +1866,7 @@ VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData) AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT; } + /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ if (lNetworkEvents & FD_CONNECT) { AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL; } @@ -1908,6 +1933,51 @@ VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock) return; } +VOID +SockReenableAsyncSelectEvent ( + IN PSOCKET_INFORMATION Socket, + IN ULONG Event + ) +{ + PASYNC_DATA AsyncData; + + /* Make sure the event is actually disabled */ + if (!(Socket->SharedData.AsyncDisabledEvents & Event)) { + return; + } + + /* Re-enable it */ + Socket->SharedData.AsyncDisabledEvents &= ~Event; + + /* Return if no more events are being polled */ + if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 ) { + return; + } + + /* Wait on new events */ + AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA)); + + /* Create the Asynch Thread if Needed */ + SockCreateOrReferenceAsyncThread(); + + /* Increase the sequence number to stop anything else */ + Socket->SharedData.SequenceNumber++; + + /* Set up the Async Data */ + AsyncData->ParentSocket = Socket; + AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; + + /* Begin Async Select by using I/O Completion */ + NtSetIoCompletion(SockAsyncCompletionPort, + (PVOID)&SockProcessQueuedAsyncSelect, + AsyncData, + 0, + 0); + + /* All done */ + return; +} + BOOL STDCALL DllMain(HANDLE hInstDll, diff --git a/reactos/lib/msafd/misc/sndrcv.c b/reactos/lib/msafd/misc/sndrcv.c index ebe963fd58b..e5c0a277ea0 100644 --- a/reactos/lib/msafd/misc/sndrcv.c +++ b/reactos/lib/msafd/misc/sndrcv.c @@ -58,7 +58,7 @@ WSPAsyncSelect( Socket->SharedData.AsyncDisabledEvents = 0; Socket->SharedData.SequenceNumber++; - /* Return if there are no more Events */ + /* Return if there are no more Events */ if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0) { HeapFree(GetProcessHeap(), 0, AsyncData); return 0; @@ -76,7 +76,7 @@ WSPAsyncSelect( 0); /* Return */ - return 0; + return ERROR_SUCCESS; } @@ -207,6 +207,13 @@ WSPRecv( *ReceiveFlags = MSG_PARTIAL | MSG_OOB; break; case STATUS_RECEIVE_PARTIAL: *ReceiveFlags = MSG_PARTIAL; break; } + + /* Re-enable Async Event */ + if (*ReceiveFlags == MSG_OOB) { + SockReenableAsyncSelectEvent(Socket, FD_OOB); + } else { + SockReenableAsyncSelectEvent(Socket, FD_READ); + } return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead ); @@ -337,6 +344,9 @@ WSPRecvFrom( case STATUS_RECEIVE_PARTIAL: *ReceiveFlags = MSG_PARTIAL; break; } + /* Re-enable Async Event */ + SockReenableAsyncSelectEvent(Socket, FD_READ); + return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesRead ); } @@ -448,6 +458,9 @@ WSPSend( return WSA_IO_PENDING; } + /* Re-enable Async Event */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); + AFD_DbgPrint(MID_TRACE,("Leaving (Success, %d)\n", IOSB->Information)); return MsafdReturnWithErrno @@ -572,6 +585,9 @@ WSPSendTo( if (Status == STATUS_PENDING) { return WSA_IO_PENDING; } + + /* Re-enable Async Event */ + SockReenableAsyncSelectEvent(Socket, FD_WRITE); return MsafdReturnWithErrno ( Status, lpErrno, IOSB->Information, lpNumberOfBytesSent );