Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
4.8 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // udpsock.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the class UDPSocket.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 02/06/2000 Original version.
  16. //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include <proxypch.h>
  19. #include <malloc.h>
  20. #include <udpsock.h>
  21. inline BOOL UDPSocket::createReceiveThread()
  22. {
  23. // check if the processing is still going on
  24. if (!closing)
  25. {
  26. return IASRequestThread(this) ? TRUE : FALSE;
  27. }
  28. else
  29. {
  30. SetEvent(idle);
  31. return TRUE;
  32. }
  33. }
  34. UDPSocket::UDPSocket() throw ()
  35. : receiver(NULL),
  36. sock(INVALID_SOCKET),
  37. closing(FALSE),
  38. idle(NULL)
  39. {
  40. CallbackRoutine = startRoutine;
  41. }
  42. UDPSocket::~UDPSocket() throw ()
  43. {
  44. if (idle) { CloseHandle(idle); }
  45. if (sock != INVALID_SOCKET) { closesocket(sock); }
  46. }
  47. BOOL UDPSocket::open(
  48. PacketReceiver* sink,
  49. ULONG_PTR recvKey,
  50. const SOCKADDR_IN* address
  51. ) throw ()
  52. {
  53. receiver = sink;
  54. key = recvKey;
  55. if (address)
  56. {
  57. localAddress = *address;
  58. }
  59. sock = WSASocket(
  60. AF_INET,
  61. SOCK_DGRAM,
  62. 0,
  63. NULL,
  64. 0,
  65. WSA_FLAG_OVERLAPPED
  66. );
  67. if (sock == INVALID_SOCKET) { return FALSE; }
  68. int error = bind(
  69. sock,
  70. localAddress,
  71. sizeof(localAddress)
  72. );
  73. if (error) { return FALSE; }
  74. idle = CreateEventW(
  75. NULL,
  76. TRUE,
  77. FALSE,
  78. NULL
  79. );
  80. if (!idle) { return FALSE; }
  81. BOOL threadCreated = createReceiveThread();
  82. if (!threadCreated)
  83. {
  84. SetEvent(idle);
  85. }
  86. return threadCreated;
  87. }
  88. void UDPSocket::close() throw ()
  89. {
  90. if (sock != INVALID_SOCKET)
  91. {
  92. closing = TRUE;
  93. closesocket(sock);
  94. sock = INVALID_SOCKET;
  95. WaitForSingleObject(idle, INFINITE);
  96. }
  97. if (idle)
  98. {
  99. CloseHandle(idle);
  100. idle = NULL;
  101. }
  102. }
  103. BOOL UDPSocket::send(
  104. const SOCKADDR_IN& to,
  105. const BYTE* buf,
  106. ULONG buflen
  107. ) throw ()
  108. {
  109. WSABUF wsabuf = { buflen, (CHAR*)buf };
  110. ULONG bytesSent;
  111. return !WSASendTo(
  112. sock,
  113. &wsabuf,
  114. 1,
  115. &bytesSent,
  116. 0,
  117. (const SOCKADDR*)&to,
  118. sizeof(to),
  119. NULL,
  120. NULL
  121. );
  122. }
  123. bool UDPSocket::receive() throw ()
  124. {
  125. // Return value from the function. Indicates whether or not the caller
  126. // should call UDPSocket::receive() again
  127. bool shouldCallAgain = false;
  128. WSABUF wsabuf = { sizeof(buffer), (CHAR*)buffer };
  129. ULONG bytesReceived;
  130. ULONG flags = 0;
  131. SOCKADDR_IN remoteAddress;
  132. int remoteAddressLength;
  133. remoteAddressLength = sizeof(remoteAddress);
  134. int error = WSARecvFrom(
  135. sock,
  136. &wsabuf,
  137. 1,
  138. &bytesReceived,
  139. &flags,
  140. (SOCKADDR*)&remoteAddress,
  141. &remoteAddressLength,
  142. NULL,
  143. NULL
  144. );
  145. if (error)
  146. {
  147. error = WSAGetLastError();
  148. switch (error)
  149. {
  150. case WSAECONNRESET:
  151. {
  152. shouldCallAgain = true;
  153. break;
  154. }
  155. case WSAENOBUFS:
  156. {
  157. shouldCallAgain = true;
  158. Sleep(5);
  159. break;
  160. }
  161. default:
  162. {
  163. // Don't report errors while closing.
  164. if (!closing)
  165. {
  166. receiver->onReceiveError(*this, key, error);
  167. }
  168. // There's no point getting another thread if the socket's no good, so
  169. // we'll just exit.
  170. SetEvent(idle);
  171. }
  172. }
  173. }
  174. else
  175. {
  176. // Save the buffer locally.
  177. PBYTE packet = (PBYTE)_alloca(bytesReceived);
  178. memcpy(packet, buffer, bytesReceived);
  179. // Get a replacement. Reuse the current thread if the allocation
  180. // of the new one failed
  181. shouldCallAgain = (createReceiveThread()? false : true);
  182. // Invoke the callback.
  183. receiver->onReceive(*this, key, remoteAddress, packet, bytesReceived);
  184. }
  185. return shouldCallAgain;
  186. }
  187. void UDPSocket::startRoutine(PIAS_CALLBACK This) throw ()
  188. {
  189. UDPSocket* receiveSocket = static_cast<UDPSocket*>(This);
  190. while (receiveSocket->receive())
  191. {
  192. }
  193. }