diff --git a/srtcore/channel.cpp b/srtcore/channel.cpp index 38ce5b598..16f3ff556 100644 --- a/srtcore/channel.cpp +++ b/srtcore/channel.cpp @@ -143,6 +143,14 @@ srt::CChannel::CChannel() , m_bBindMasked(true) #endif { +#ifdef _WIN32 + SecureZeroMemory((PVOID)&m_SendOverlapped, sizeof(WSAOVERLAPPED)); + m_SendOverlapped.hEvent = WSACreateEvent(); + if (m_SendOverlapped.hEvent == NULL) { + LOGC(kmlog.Error, log << CONID() << "IPE: WSACreateEvent failed with error: " << NET_ERROR); + throw CUDTException(MJ_SETUP, MN_NORES, NET_ERROR); + } +#endif #ifdef SRT_ENABLE_PKTINFO // Do the check for ancillary data buffer size, kinda assertion static const size_t CMSG_MAX_SPACE = sizeof (CMSGNodeIPv4) + sizeof (CMSGNodeIPv6); @@ -158,7 +166,12 @@ srt::CChannel::CChannel() #endif } -srt::CChannel::~CChannel() {} +srt::CChannel::~CChannel() +{ +#ifdef _WIN32 + WSACloseEvent(m_SendOverlapped.hEvent); +#endif +} void srt::CChannel::createSocket(int family) { @@ -774,18 +787,32 @@ int srt::CChannel::sendto(const sockaddr_any& addr, CPacket& packet, const socka #else DWORD size = (DWORD)(CPacket::HDR_SIZE + packet.getLength()); int addrsize = addr.size(); - WSAOVERLAPPED overlapped; - SecureZeroMemory((PVOID)&overlapped, sizeof(WSAOVERLAPPED)); - int res = ::WSASendTo(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, 0, addr.get(), addrsize, &overlapped, NULL); - if (res == SOCKET_ERROR && NET_ERROR == WSA_IO_PENDING) + int res = ::WSASendTo(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, 0, addr.get(), addrsize, &m_SendOverlapped, NULL); + + if (res == SOCKET_ERROR) { - DWORD dwFlags = 0; - const bool bCompleted = WSAGetOverlappedResult(m_iSocket, &overlapped, &size, true, &dwFlags); - WSACloseEvent(overlapped.hEvent); - res = bCompleted ? 0 : -1; + if (NET_ERROR == WSA_IO_PENDING) + { + res = WSAWaitForMultipleEvents(1, &m_SendOverlapped.hEvent, TRUE, 100 /*ms*/, FALSE); + if (res == WAIT_FAILED) + { + LOGC(kslog.Warn, log << "CChannel::WSAWaitForMultipleEvents: failed with " << NET_ERROR); + res = -1; + } + else + { + DWORD dwFlags = 0; + const bool bCompleted = WSAGetOverlappedResult(m_iSocket, &m_SendOverlapped, &size, false, &dwFlags); + res = bCompleted ? 0 : -1; + } + } + else + { + LOGC(kmlog.Error, log << CONID() << "WSASendTo failed with error: " << NET_ERROR); + } } - + WSAResetEvent(m_SendOverlapped.hEvent); res = (0 == res) ? size : -1; #endif diff --git a/srtcore/channel.h b/srtcore/channel.h index 83650d24b..2c67acbc8 100644 --- a/srtcore/channel.h +++ b/srtcore/channel.h @@ -176,6 +176,9 @@ class CChannel private: UDPSOCKET m_iSocket; // socket descriptor +#ifdef _WIN32 + mutable WSAOVERLAPPED m_SendOverlapped; +#endif // Mutable because when querying original settings // this comprises the cache for extracted values,