NTSTATUS CloseWskEventSocket() { if (!netlink_server_socket) { return STATUS_SUCCESS; } KEVENT CompletionEvent = {0}; PIRP irp = NULL; NTSTATUS status = InitWskData(&irp, &CompletionEvent); if (!NT_SUCCESS(status)) { return status; } status = ((PWSK_PROVIDER_BASIC_DISPATCH)netlink_server_socket->Dispatch)->WskCloseSocket(netlink_server_socket, irp); if (STATUS_PENDING == status) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); status = irp->IoStatus.Status; } IoFreeIrp(irp); WskDeregister(&gWskEventRegistration); return status; }
NTSTATUS NTAPI Bind( __in PWSK_SOCKET WskSocket, __in PSOCKADDR LocalAddress ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; if (g_SocketsState != INITIALIZED || !WskSocket || !LocalAddress) return STATUS_INVALID_PARAMETER; Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { return Status; } Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskBind( WskSocket, LocalAddress, 0, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } IoFreeIrp(Irp); return Status; }
PWSK_SOCKET NTAPI WSKCreateSocket( IN ADDRESS_FAMILY AddressFamily, IN USHORT SocketType, IN ULONG Protocol, IN ULONG Flags ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; PWSK_SOCKET WskSocket = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; TRACE_ENTER(); if (g_SocketsState != INITIALIZED) { TRACE_EXIT(); return NULL; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "WSKCreateSocket()::InitWskData() failed with status 0x%08X\n", Status); TRACE_EXIT(); return NULL; } Status = g_WskProvider.Dispatch->WskSocket( g_WskProvider.Client, AddressFamily, SocketType, Protocol, Flags, NULL, NULL, NULL, NULL, NULL, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } if (!NT_SUCCESS(Status)) { TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "WSKCreateSocket()::Dispatch::WskSocket() failed with status 0x%08X\n", Status); } WskSocket = NT_SUCCESS(Status) ? (PWSK_SOCKET)Irp->IoStatus.Information : NULL; IoFreeIrp(Irp); TRACE_EXIT(); return (PWSK_SOCKET)WskSocket; }
NTSTATUS NTAPI SetEventCallbacks( __in PWSK_SOCKET Socket, __in LONG mask ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; PWSK_SOCKET WskSocket = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; if (g_SocketsState != INITIALIZED) { return Status; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { return Status; } WSK_EVENT_CALLBACK_CONTROL callbackControl; callbackControl.NpiId = &NPI_WSK_INTERFACE_ID; // Set the event flags for the event callback functions that // are to be enabled on the socket callbackControl.EventMask = mask; // Initiate the control operation on the socket Status = ((PWSK_PROVIDER_BASIC_DISPATCH)Socket->Dispatch)->WskControlSocket( Socket, WskSetOption, SO_WSK_EVENT_CALLBACK, SOL_SOCKET, sizeof(WSK_EVENT_CALLBACK_CONTROL), &callbackControl, 0, NULL, NULL, Irp ); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } IoFreeIrp(Irp); return Status; }
LONG NTAPI ReceiveFrom( __in PWSK_SOCKET WskSocket, __out PVOID Buffer, __in ULONG BufferSize, __out_opt PSOCKADDR RemoteAddress, __out_opt PULONG ControlFlags ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; WSK_BUF WskBuffer = { 0 }; LONG BytesReceived = SOCKET_ERROR; NTSTATUS Status = STATUS_UNSUCCESSFUL; if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || !BufferSize) return SOCKET_ERROR; Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer); if (!NT_SUCCESS(Status)) { return SOCKET_ERROR; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { FreeWskBuffer(&WskBuffer); return SOCKET_ERROR; } Status = ((PWSK_PROVIDER_DATAGRAM_DISPATCH) WskSocket->Dispatch)->WskReceiveFrom( WskSocket, &WskBuffer, 0, RemoteAddress, 0, NULL, ControlFlags, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } BytesReceived = NT_SUCCESS(Status) ? (LONG) Irp->IoStatus.Information : SOCKET_ERROR; IoFreeIrp(Irp); FreeWskBuffer(&WskBuffer); return BytesReceived; }
PWSK_SOCKET NTAPI CreateSocket( __in ADDRESS_FAMILY AddressFamily, __in USHORT SocketType, __in ULONG Protocol, __in PVOID *SocketContext, __in PWSK_CLIENT_LISTEN_DISPATCH Dispatch, __in ULONG Flags ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; PWSK_SOCKET WskSocket = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; if (g_SocketsState != INITIALIZED) { return NULL; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { return NULL; } Status = g_WskProvider.Dispatch->WskSocket( g_WskProvider.Client, AddressFamily, SocketType, Protocol, Flags, SocketContext, Dispatch, NULL, NULL, NULL, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } WskSocket = NT_SUCCESS(Status) ? (PWSK_SOCKET) Irp->IoStatus.Information : NULL; IoFreeIrp(Irp); return (PWSK_SOCKET) WskSocket; }
NTSTATUS NTAPI ControlSocket( __in PWSK_SOCKET WskSocket, __in ULONG RequestType, __in ULONG ControlCode, __in ULONG Level, __in SIZE_T InputSize, __in_opt PVOID InputBuffer, __in SIZE_T OutputSize, __out_opt PVOID OutputBuffer, __out_opt SIZE_T *OutputSizeReturned ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; if (g_SocketsState != INITIALIZED || !WskSocket) return SOCKET_ERROR; Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { WDRBD_ERROR("InitWskData() failed with status 0x%08X\n", Status); return SOCKET_ERROR; } Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskControlSocket( WskSocket, RequestType, // WskSetOption, ControlCode, // SIO_WSK_QUERY_RECEIVE_BACKLOG, Level, // IPPROTO_IPV6, InputSize, // sizeof(optionValue), InputBuffer, // NULL, OutputSize, // sizeof(int), OutputBuffer, // &backlog, OutputSizeReturned, // NULL, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } IoFreeIrp(Irp); return Status; }
PWSK_SOCKET NTAPI SocketConnect( __in USHORT SocketType, __in ULONG Protocol, __in PSOCKADDR RemoteAddress, __in PSOCKADDR LocalAddress ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; PWSK_SOCKET WskSocket = NULL; if (g_SocketsState != INITIALIZED || !RemoteAddress || !LocalAddress) return NULL; Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { return NULL; } Status = g_WskProvider.Dispatch->WskSocketConnect( g_WskProvider.Client, SocketType, Protocol, LocalAddress, RemoteAddress, 0, NULL, NULL, NULL, NULL, NULL, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } WskSocket = NT_SUCCESS(Status) ? (PWSK_SOCKET) Irp->IoStatus.Information : NULL; IoFreeIrp(Irp); return WskSocket; }
NTSTATUS NTAPI Connect( __in PWSK_SOCKET WskSocket, __in PSOCKADDR RemoteAddress ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; if (g_SocketsState != INITIALIZED || !WskSocket || !RemoteAddress) return STATUS_INVALID_PARAMETER; Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { return Status; } Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskConnect( WskSocket, RemoteAddress, 0, Irp); if (Status == STATUS_PENDING) { LARGE_INTEGER nWaitTime; nWaitTime = RtlConvertLongToLargeInteger(-1 * 1000 * 1000 * 10); if ((Status = KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, &nWaitTime)) == STATUS_TIMEOUT) { IoCancelIrp(Irp); KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); } } if (Status == STATUS_SUCCESS) { Status = Irp->IoStatus.Status; } IoFreeIrp(Irp); return Status; }
NTSTATUS NTAPI GetRemoteAddress( __in PWSK_SOCKET WskSocket, __out PSOCKADDR pRemoteAddress ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { return SOCKET_ERROR; } Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskGetRemoteAddress(WskSocket, pRemoteAddress, Irp); if (Status != STATUS_SUCCESS) { if (Status == STATUS_PENDING) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } if (Status != STATUS_SUCCESS) { if (Status != STATUS_INVALID_DEVICE_STATE) { WDRBD_TRACE("STATUS_INVALID_DEVICE_STATE....\n"); } else if (Status != STATUS_FILE_FORCED_CLOSED) { WDRBD_TRACE("STATUS_FILE_FORCED_CLOSED....\n"); } else { WDRBD_TRACE("0x%x....\n", Status); } } } IoFreeIrp(Irp); return Status; }
NTSTATUS NTAPI WSKBind( IN PWSK_SOCKET WskSocket, IN PSOCKADDR LocalAddress ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; TRACE_ENTER(); if (g_SocketsState != INITIALIZED || !WskSocket || !LocalAddress) { TRACE_EXIT(); return STATUS_INVALID_PARAMETER; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "WSKBind()::InitWskData() failed with status 0x%08X\n", Status); TRACE_EXIT(); return Status; } Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH)WskSocket->Dispatch)->WskBind( WskSocket, LocalAddress, 0, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } IoFreeIrp(Irp); TRACE_EXIT(); return Status; }
NTSTATUS NTAPI Disconnect( __in PWSK_SOCKET WskSocket ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; LARGE_INTEGER nWaitTime; nWaitTime.QuadPart = (-1 * 1000 * 10000); // wait 1000ms relative if (g_SocketsState != INITIALIZED || !WskSocket) return STATUS_INVALID_PARAMETER; Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { return Status; } Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskDisconnect( WskSocket, NULL, 0,//WSK_FLAG_ABORTIVE,=> when disconnecting, ABORTIVE was going to standalone, and then we removed ABORTIVE Irp); if (Status == STATUS_PENDING) { Status = KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, &nWaitTime); if(STATUS_TIMEOUT == Status) { // DW-712 timeout process for fast closesocket in congestion mode, instead of WSK_FLAG_ABORTIVE WDRBD_INFO("Timeout... Cancel Disconnect socket:%p\n",WskSocket); IoCancelIrp(Irp); KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); } Status = Irp->IoStatus.Status; } IoFreeIrp(Irp); return Status; }
LONG NTAPI Receive( __in PWSK_SOCKET WskSocket, __out PVOID Buffer, __in ULONG BufferSize, __in ULONG Flags, __in ULONG Timeout ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; WSK_BUF WskBuffer = { 0 }; LONG BytesReceived = SOCKET_ERROR; NTSTATUS Status = STATUS_UNSUCCESSFUL; struct task_struct *thread = current; PVOID waitObjects[2]; int wObjCount = 1; if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || !BufferSize) return SOCKET_ERROR; if ((int) BufferSize <= 0) { return SOCKET_ERROR; } Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer); if (!NT_SUCCESS(Status)) { return SOCKET_ERROR; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { FreeWskBuffer(&WskBuffer); return SOCKET_ERROR; } Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskReceive( WskSocket, &WskBuffer, Flags, Irp); if (Status == STATUS_PENDING) { LARGE_INTEGER nWaitTime; LARGE_INTEGER *pTime; if (Timeout <= 0 || Timeout == MAX_SCHEDULE_TIMEOUT) { pTime = 0; } else { nWaitTime = RtlConvertLongToLargeInteger(-1 * Timeout * 1000 * 10); pTime = &nWaitTime; } waitObjects[0] = (PVOID) &CompletionEvent; if (thread->has_sig_event) { waitObjects[1] = (PVOID) &thread->sig_event; wObjCount = 2; } Status = KeWaitForMultipleObjects(wObjCount, &waitObjects[0], WaitAny, Executive, KernelMode, FALSE, pTime, NULL); switch (Status) { case STATUS_WAIT_0: // waitObjects[0] CompletionEvent if (Irp->IoStatus.Status == STATUS_SUCCESS) { BytesReceived = (LONG) Irp->IoStatus.Information; } else { #ifdef _WIN32_LOGLINK DbgPrint("RECV(%s) wsk(0x%p) multiWait err(0x%x:%s)\n", thread->comm, WskSocket, Irp->IoStatus.Status, GetSockErrorString(Irp->IoStatus.Status)); #else WDRBD_INFO("RECV(%s) wsk(0x%p) multiWait err(0x%x:%s)\n", thread->comm, WskSocket, Irp->IoStatus.Status, GetSockErrorString(Irp->IoStatus.Status)); #endif if(Irp->IoStatus.Status) { BytesReceived = -ECONNRESET; } } break; case STATUS_WAIT_1: BytesReceived = -EINTR; break; case STATUS_TIMEOUT: BytesReceived = -EAGAIN; break; default: BytesReceived = SOCKET_ERROR; break; } } else { if (Status == STATUS_SUCCESS) { BytesReceived = (LONG) Irp->IoStatus.Information; #ifdef _WIN32_LOGLINK DbgPrint("(%s) Rx No pending and data(%d) is avail\n", current->comm, BytesReceived); #else WDRBD_INFO("(%s) Rx No pending and data(%d) is avail\n", current->comm, BytesReceived); #endif } else { #ifdef _WIN32_LOGLINK DbgPrint("WskReceive Error Status=0x%x\n", Status); // EVENT_LOG! #else WDRBD_TRACE("WskReceive Error Status=0x%x\n", Status); // EVENT_LOG! #endif } } if (BytesReceived == -EINTR || BytesReceived == -EAGAIN) { // cancel irp in wsk subsystem IoCancelIrp(Irp); KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); if (Irp->IoStatus.Information > 0) { //WDRBD_INFO("rx canceled but rx data(%d) avaliable.\n", Irp->IoStatus.Information); BytesReceived = Irp->IoStatus.Information; } } IoFreeIrp(Irp); FreeWskBuffer(&WskBuffer); return BytesReceived; }
LONG NTAPI SendLocal( __in PWSK_SOCKET WskSocket, __in PVOID Buffer, __in ULONG BufferSize, __in ULONG Flags, __in ULONG Timeout ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; WSK_BUF WskBuffer = { 0 }; LONG BytesSent = SOCKET_ERROR; NTSTATUS Status = STATUS_UNSUCCESSFUL; if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || ((int) BufferSize <= 0)) return SOCKET_ERROR; Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer); if (!NT_SUCCESS(Status)) { return SOCKET_ERROR; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { FreeWskBuffer(&WskBuffer); return SOCKET_ERROR; } Flags |= WSK_FLAG_NODELAY; Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskSend( WskSocket, &WskBuffer, Flags, Irp); if (Status == STATUS_PENDING) { LARGE_INTEGER nWaitTime; LARGE_INTEGER *pTime; if (Timeout <= 0 || Timeout == MAX_SCHEDULE_TIMEOUT) { pTime = NULL; } else { nWaitTime = RtlConvertLongToLargeInteger(-1 * Timeout * 1000 * 10); pTime = &nWaitTime; } Status = KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, pTime); switch (Status) { case STATUS_TIMEOUT: IoCancelIrp(Irp); KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); BytesSent = -EAGAIN; break; case STATUS_WAIT_0: if (NT_SUCCESS(Irp->IoStatus.Status)) { BytesSent = (LONG) Irp->IoStatus.Information; } else { #ifdef _WIN32_LOGLINK DbgPrint("(%s) sent error(%s)\n", current->comm, GetSockErrorString(Irp->IoStatus.Status)); #else WDRBD_WARN("(%s) sent error(%s)\n", current->comm, GetSockErrorString(Irp->IoStatus.Status)); #endif switch (Irp->IoStatus.Status) { case STATUS_IO_TIMEOUT: BytesSent = -EAGAIN; break; case STATUS_INVALID_DEVICE_STATE: BytesSent = -EAGAIN; break; default: BytesSent = -ECONNRESET; break; } } break; default: #ifdef _WIN32_LOGLINK DbgPrint("KeWaitForSingleObject failed. status 0x%x\n", Status); #else WDRBD_ERROR("KeWaitForSingleObject failed. status 0x%x\n", Status); #endif BytesSent = SOCKET_ERROR; } } else { if (Status == STATUS_SUCCESS) { BytesSent = (LONG) Irp->IoStatus.Information; #ifdef _WIN32_LOGLINK DbgPrint("(%s) WskSend No pending: but sent(%d)!\n", current->comm, BytesSent); #else WDRBD_WARN("(%s) WskSend No pending: but sent(%d)!\n", current->comm, BytesSent); #endif } else { #ifdef _WIN32_LOGLINK DbgPrint("(%s) WskSend error(0x%x)\n", current->comm, Status); #else WDRBD_WARN("(%s) WskSend error(0x%x)\n", current->comm, Status); #endif BytesSent = SOCKET_ERROR; } } IoFreeIrp(Irp); FreeWskBuffer(&WskBuffer); return BytesSent; }
LONG NTAPI Send( __in PWSK_SOCKET WskSocket, __in PVOID Buffer, __in ULONG BufferSize, __in ULONG Flags, __in ULONG Timeout, __in KEVENT *send_buf_kill_event, __in struct drbd_transport *transport, __in enum drbd_stream stream ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; WSK_BUF WskBuffer = { 0 }; LONG BytesSent = SOCKET_ERROR; // DRBC_CHECK_WSK: SOCKET_ERROR be mixed EINVAL? NTSTATUS Status = STATUS_UNSUCCESSFUL; if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || ((int) BufferSize <= 0)) return SOCKET_ERROR; Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer); if (!NT_SUCCESS(Status)) { return SOCKET_ERROR; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { FreeWskBuffer(&WskBuffer); return SOCKET_ERROR; } Flags |= WSK_FLAG_NODELAY; Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskSend( WskSocket, &WskBuffer, Flags, Irp); if (Status == STATUS_PENDING) { LARGE_INTEGER nWaitTime; LARGE_INTEGER *pTime; int retry_count = 0; retry: if (Timeout <= 0 || Timeout == MAX_SCHEDULE_TIMEOUT) { pTime = NULL; } else { nWaitTime = RtlConvertLongToLargeInteger(-1 * Timeout * 1000 * 10); pTime = &nWaitTime; } { struct task_struct *thread = current; PVOID waitObjects[2]; int wObjCount = 1; waitObjects[0] = (PVOID) &CompletionEvent; #ifndef _WIN32_SEND_BUFFING // in send-buffering, Netlink , call_usermodehelper are distinguished to SendLocal // KILL event is only used in send-buffering thread while send block. // WIN32_V9_REFACTO_:required to refactoring that input param, log message are simplized. #else #endif Status = KeWaitForMultipleObjects(wObjCount, &waitObjects[0], WaitAny, Executive, KernelMode, FALSE, pTime, NULL); switch (Status) { case STATUS_TIMEOUT: #ifdef _WIN32_SEND_BUFFING if (wObjCount == 1) { retry_count++; WDRBD_WARN("(%s) sent timeout=%d sz=%d retry_count=%d WskSocket=%p IRP=%p\n", current->comm, Timeout, BufferSize, retry_count,WskSocket, Irp); // required to refactroing about retrying method. goto retry; } #endif if (transport != NULL) { if (!drbd_stream_send_timed_out(transport, stream)) { goto retry; } } IoCancelIrp(Irp); KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); BytesSent = -EAGAIN; break; case STATUS_WAIT_0: if (NT_SUCCESS(Irp->IoStatus.Status)) { BytesSent = (LONG)Irp->IoStatus.Information; } else { WDRBD_WARN("tx error(%s) wsk(0x%p)\n", GetSockErrorString(Irp->IoStatus.Status), WskSocket); switch (Irp->IoStatus.Status) { case STATUS_IO_TIMEOUT: BytesSent = -EAGAIN; break; case STATUS_INVALID_DEVICE_STATE: BytesSent = -EAGAIN; break; default: BytesSent = -ECONNRESET; break; } } break; //case STATUS_WAIT_1: // common: sender or send_bufferinf thread's kill signal // IoCancelIrp(Irp); // KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); // BytesSent = -EINTR; // break; default: WDRBD_ERROR("Wait failed. status 0x%x\n", Status); BytesSent = SOCKET_ERROR; } } } else { if (Status == STATUS_SUCCESS) { BytesSent = (LONG) Irp->IoStatus.Information; WDRBD_WARN("(%s) WskSend No pending: but sent(%d)!\n", current->comm, BytesSent); } else { WDRBD_WARN("(%s) WskSend error(0x%x)\n", current->comm, Status); BytesSent = SOCKET_ERROR; } } IoFreeIrp(Irp); FreeWskBuffer(&WskBuffer); return BytesSent; }
LONG NTAPI WSKSendTo_NBL( IN PWSK_SOCKET WskSocket, IN PNET_BUFFER_LIST NetBufferList, IN ULONG BufferOffset, __in_opt PSOCKADDR RemoteAddress ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; WSK_BUF WskBuffer = { 0 }; LONG BytesSent = SOCKET_ERROR; NTSTATUS Status = STATUS_UNSUCCESSFUL; TRACE_ENTER(); if (g_SocketsState != INITIALIZED || !WskSocket || !NetBufferList) { TRACE_EXIT(); return SOCKET_ERROR; } Status = InitWskBuffer_NBL(NetBufferList, BufferOffset, &WskBuffer); if (!NT_SUCCESS(Status)) { TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "WSKSendTo_NBL()::InitWskBuffer_NBL() failed with status 0x%08X\n", Status); TRACE_EXIT(); return SOCKET_ERROR; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "WSKSendTo_NBL()::InitWskData() failed with status 0x%08X\n", Status); FreeWskBuffer_NBL(&WskBuffer); TRACE_EXIT(); return SOCKET_ERROR; } Status = ((PWSK_PROVIDER_DATAGRAM_DISPATCH)WskSocket->Dispatch)->WskSendTo( WskSocket, &WskBuffer, 0, RemoteAddress, 0, NULL, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } BytesSent = NT_SUCCESS(Status) ? (LONG)Irp->IoStatus.Information : SOCKET_ERROR; IoFreeIrp(Irp); FreeWskBuffer_NBL(&WskBuffer); TRACE_EXIT(); return BytesSent; }
PWSK_SOCKET CreateSocketEvent( __in ADDRESS_FAMILY AddressFamily, __in USHORT SocketType, __in ULONG Protocol, __in ULONG Flags ) { KEVENT CompletionEvent = {0}; PIRP irp = NULL; PWSK_SOCKET socket = NULL; NTSTATUS status; status = InitWskData(&irp, &CompletionEvent); if (!NT_SUCCESS(status)) { return NULL; } WSK_EVENT_CALLBACK_CONTROL callbackControl; callbackControl.NpiId = (PNPIID)&NPI_WSK_INTERFACE_ID; callbackControl.EventMask = WSK_EVENT_ACCEPT; status = gWskEventProviderNPI.Dispatch->WskControlClient( gWskEventProviderNPI.Client, WSK_SET_STATIC_EVENT_CALLBACKS, sizeof(callbackControl), &callbackControl, 0, NULL, NULL, NULL); if (!NT_SUCCESS(status)) { IoFreeIrp(irp); WDRBD_ERROR("Failed to WskControlClient(). status(0x%x)\n", status); return NULL; } status = gWskEventProviderNPI.Dispatch->WskSocket( gWskEventProviderNPI.Client, AddressFamily, SocketType, Protocol, Flags, NULL, &ClientListenDispatch, NULL, NULL, NULL, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); status = irp->IoStatus.Status; } if (NT_SUCCESS(status)) { socket = (PWSK_SOCKET)irp->IoStatus.Information; } else { WDRBD_ERROR("Failed to WskSocket(). status(0x%x)\n", status); } IoFreeIrp(irp); return (PWSK_SOCKET)socket; }
PWSK_SOCKET NTAPI Accept( __in PWSK_SOCKET WskSocket, __out_opt PSOCKADDR LocalAddress, __out_opt PSOCKADDR RemoteAddress, __out_opt NTSTATUS *RetStaus, __in int timeout ) { KEVENT CompletionEvent = { 0 }; PIRP Irp = NULL; NTSTATUS Status = STATUS_UNSUCCESSFUL; PWSK_SOCKET AcceptedSocket = NULL; struct task_struct *thread = current; PVOID waitObjects[2]; int wObjCount = 1; if (g_SocketsState != INITIALIZED || !WskSocket) { *RetStaus = SOCKET_ERROR; return NULL; } Status = InitWskData(&Irp, &CompletionEvent); if (!NT_SUCCESS(Status)) { *RetStaus = Status; return NULL; } Status = ((PWSK_PROVIDER_LISTEN_DISPATCH) WskSocket->Dispatch)->WskAccept( WskSocket, 0, NULL, NULL, LocalAddress, RemoteAddress, Irp); if (Status == STATUS_PENDING) { LARGE_INTEGER nWaitTime; LARGE_INTEGER *pTime; if (timeout <= 0 || timeout == MAX_SCHEDULE_TIMEOUT) { pTime = 0; } else { nWaitTime = RtlConvertLongToLargeInteger(-1 * timeout * 10000000); pTime = &nWaitTime; } waitObjects[0] = (PVOID) &CompletionEvent; if (thread->has_sig_event) { waitObjects[1] = (PVOID) &thread->sig_event; wObjCount = 2; } Status = KeWaitForMultipleObjects(wObjCount, &waitObjects[0], WaitAny, Executive, KernelMode, FALSE, pTime, NULL); switch (Status) { case STATUS_WAIT_0: break; case STATUS_WAIT_0 + 1: IoCancelIrp(Irp); KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); *RetStaus = -EINTR; break; case STATUS_TIMEOUT: IoCancelIrp(Irp); KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL); *RetStaus = STATUS_TIMEOUT; break; default: WDRBD_ERROR("Unexpected Error Status=0x%x\n", Status); break; } } else { if (Status != STATUS_SUCCESS) { WDRBD_TRACE("Accept Error Status=0x%x\n", Status); } } AcceptedSocket = (Status == STATUS_SUCCESS) ? (PWSK_SOCKET) Irp->IoStatus.Information : NULL; IoFreeIrp(Irp); return AcceptedSocket; }