/platform/win/scaffold/socket.d

https://github.com/wolfwood/djehuty · D · 300 lines · 207 code · 70 blank · 23 comment · 36 complexity · ab36e61aeb1f9757871fc8156111a248 MD5 · raw file

  1. /*
  2. * socket.d
  3. *
  4. * This file implements the Scaffold for platform specific Socket
  5. * operations in Windows.
  6. *
  7. * Author: Dave Wilkinson
  8. *
  9. */
  10. module scaffold.socket;
  11. pragma(lib, "WS2_32.lib");
  12. import platform.win.common;
  13. import platform.win.main;
  14. import platform.vars.socket;
  15. import core.string;
  16. import core.main;
  17. import core.definitions;
  18. import core.unicode;
  19. import io.console;
  20. //XXX: WS2tcpip.h
  21. struct ADDRINFOW {
  22. int ai_flags; // AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST
  23. int ai_family; // PF_xxx
  24. int ai_socktype; // SOCK_xxx
  25. int ai_protocol; // 0 or IPPROTO_xxx for IPv4 and IPv6
  26. size_t ai_addrlen; // Length of ai_addr
  27. PWSTR ai_canonname; // Canonical name for nodename
  28. sockaddr* ai_addr; // Binary address
  29. ADDRINFOW* ai_next; // Next structure in linked list
  30. }
  31. alias ADDRINFOW* PADDRINFOW;
  32. extern(System)
  33. INT GetAddrInfoW(
  34. PCWSTR pNodeName,
  35. PCWSTR pServiceName,
  36. ADDRINFOW * pHints,
  37. PADDRINFOW * ppResult
  38. );
  39. // SOCKET
  40. bool SocketOpen(ref SocketPlatformVars sockVars, ref string hostname, ref ushort port)
  41. {
  42. WSADATA wsaData;
  43. int iResult;
  44. if (!sockVars.inited)
  45. {
  46. iResult = WSAStartup((2 | (2 << 8)), &wsaData);
  47. if (!iResult)
  48. {
  49. sockVars.inited = true;
  50. }
  51. else
  52. {
  53. Console.putln("wsastartup, error");
  54. return false;
  55. }
  56. }
  57. ADDRINFOW *result = null;
  58. ADDRINFOW *ptr = null;
  59. ADDRINFOW hints = ADDRINFOW.init;
  60. ptr = &hints;
  61. hints.ai_family = AF_UNSPEC;
  62. hints.ai_socktype = SOCK_STREAM;
  63. hints.ai_protocol = IPPROTO_TCP;
  64. //OutputDebugStringA("getaddr start\n");
  65. wstring portstr = Unicode.toUtf16(toStr(port));
  66. wstring hname = Unicode.toUtf16(hostname);
  67. hname ~= '\0';
  68. iResult = GetAddrInfoW(hname.ptr, portstr.ptr, &hints, &result);
  69. //OutputDebugStringA("getaddr done\n");
  70. if (iResult)
  71. {
  72. //file an error event
  73. Console.putln("getaddrinfow, error");
  74. return false;
  75. }
  76. sockVars.m_skt = INVALID_SOCKET;
  77. // sockVars.m_skt = socket(result.ai_family, result.ai_socktype, result.ai_protocol);
  78. sockVars.m_skt = socket(result.ai_family, result.ai_socktype, result.ai_protocol);
  79. if (sockVars.m_skt == INVALID_SOCKET)
  80. {
  81. //file an error event
  82. if (sockVars.init_ref == 0)
  83. { WSACleanup(); }
  84. Console.putln("socket, error");
  85. return false;
  86. }
  87. iResult = connect(sockVars.m_skt, result.ai_addr, result.ai_addrlen);
  88. if (iResult == SOCKET_ERROR)
  89. {
  90. //file an error event
  91. closesocket(sockVars.m_skt);
  92. sockVars.m_skt = INVALID_SOCKET;
  93. if (sockVars.init_ref == 0)
  94. {
  95. WSACleanup();
  96. }
  97. Console.putln("connect, error");
  98. return false;
  99. }
  100. sockVars.init_ref++;
  101. return true;
  102. }
  103. bool SocketBind(ref SocketPlatformVars sockVars, ref ushort port)
  104. {
  105. WSADATA wsaData;
  106. int iResult;
  107. if (!sockVars.inited)
  108. {
  109. iResult = WSAStartup((2 | (2 << 8)), &wsaData);
  110. if (!iResult)
  111. {
  112. sockVars.inited = true;
  113. }
  114. else
  115. {
  116. return false;
  117. }
  118. }
  119. if (iResult)
  120. {
  121. //file an error event
  122. return false;
  123. }
  124. sockVars.m_bind_skt = INVALID_SOCKET;
  125. sockVars.m_bind_skt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  126. if (sockVars.m_bind_skt == INVALID_SOCKET)
  127. {
  128. //file an error event
  129. if (sockVars.init_ref == 0){ WSACleanup(); }
  130. return false;
  131. }
  132. sockaddr_in service;
  133. service.sin_family = AF_INET;
  134. service.sin_addr.s_addr = inet_addr(cast(char *)("127.0.0.1".ptr));
  135. service.sin_port = htons(27015);
  136. iResult = bind(sockVars.m_bind_skt, cast(sockaddr*)&service, service.sizeof);
  137. if (iResult == SOCKET_ERROR)
  138. {
  139. //file an error event
  140. closesocket(sockVars.m_bind_skt);
  141. sockVars.m_bind_skt = INVALID_SOCKET;
  142. if (sockVars.init_ref == 0)
  143. {
  144. WSACleanup();
  145. }
  146. return false;
  147. }
  148. sockVars.init_ref++;
  149. return true;
  150. }
  151. bool SocketListen(ref SocketPlatformVars sockVars)
  152. {
  153. if (listen(sockVars.m_bind_skt, 16) == SOCKET_ERROR)
  154. {
  155. return false;
  156. }
  157. return true;
  158. }
  159. bool SocketAccept(ref SocketPlatformVars sockVars)
  160. {
  161. if ((sockVars.m_skt = accept(sockVars.m_bind_skt, null, null)) == SOCKET_ERROR)
  162. {
  163. return false;
  164. }
  165. return true;
  166. }
  167. void SocketClose(ref SocketPlatformVars sockVars)
  168. {
  169. closesocket(sockVars.m_skt);
  170. if (sockVars.init_ref <= 1 && sockVars.inited)
  171. {
  172. sockVars.init_ref = 0;
  173. WSACleanup();
  174. sockVars.inited = false;
  175. }
  176. else
  177. {
  178. sockVars.init_ref--;
  179. }
  180. }
  181. bool SocketRead(ref SocketPlatformVars sockVars, ubyte* buffer, ulong len)
  182. {
  183. ulong progress = 0;
  184. ulong ret = 0;
  185. ulong amt = len;
  186. int cur_amt;
  187. ubyte* cur = buffer;
  188. while (progress < len)
  189. {
  190. cur_amt = cast(int)(amt & 0x7FFFFFFF);
  191. ret = recv(sockVars.m_skt, cur, cur_amt, 0);
  192. if (ret == SOCKET_ERROR) { return false; }
  193. progress += ret;
  194. amt -= ret;
  195. cur += ret;
  196. if (ret <= 0) { return false; }
  197. }
  198. return true;
  199. }
  200. ulong SocketReadAvailable(ref SocketPlatformVars sockVars, ubyte* buffer, ulong len)
  201. {
  202. //ulong total = recv(sockVars.m_skt, null, 0, MSG_PEEK);
  203. //if (total == 0) { return 0; }
  204. int cur_amt = cast(int)(len & 0x7FFFFFFF);
  205. long ret = recv(sockVars.m_skt, buffer, cur_amt, 0);
  206. if (ret < 0)
  207. {
  208. // error
  209. return 0;
  210. }
  211. return cast(ulong)ret;
  212. }
  213. bool SocketWrite(ref SocketPlatformVars sockVars, ubyte* buffer, ulong len)
  214. {
  215. ulong progress = 0;
  216. ulong ret = 0;
  217. ulong amt = len;
  218. int cur_amt;
  219. ubyte* cur = buffer;
  220. while (progress < len)
  221. {
  222. cur_amt = cast(int)(amt & 0x7FFFFFFF);
  223. ret = send(sockVars.m_skt, cur, cur_amt, 0);
  224. progress += ret;
  225. amt -= ret;
  226. cur += ret;
  227. if (ret == 0) { return false; }
  228. }
  229. return true;
  230. }