PageRenderTime 50ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/net_win32.c

https://gitlab.com/fzwoch/fodquake
C | 381 lines | 317 code | 61 blank | 3 comment | 64 complexity | fa7fea43be341c61358088dfb41601ff MD5 | raw file
Possible License(s): GPL-2.0
  1. #include <winsock2.h>
  2. #warning Fix this up.
  3. struct ip6_scope_id
  4. {
  5. union
  6. {
  7. struct
  8. {
  9. u_long Zone : 28;
  10. u_long Level : 4;
  11. };
  12. u_long Value;
  13. };
  14. };
  15. struct in_addr6
  16. {
  17. u_char s6_addr[16]; /* IPv6 address */
  18. };
  19. typedef struct sockaddr_in6 {
  20. short sin6_family;
  21. u_short sin6_port;
  22. u_long sin6_flowinfo;
  23. struct in_addr6 sin6_addr;
  24. union
  25. {
  26. u_long sin6_scope_id;
  27. struct ip6_scope_id sin6_scope_struct;
  28. };
  29. };
  30. #include "quakedef.h"
  31. #include "net.h"
  32. #include "sys_net.h"
  33. typedef unsigned int socklen_t;
  34. struct addrinfo
  35. {
  36. int ai_flags;
  37. int ai_family;
  38. int ai_socktype;
  39. int ai_protocol;
  40. size_t ai_addrlen;
  41. char* ai_canonname;
  42. struct sockaddr * ai_addr;
  43. struct addrinfo * ai_next;
  44. };
  45. struct SysNetData
  46. {
  47. HANDLE dll_ws2_32;
  48. int (WSAAPI *pgetaddrinfo)(const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res);
  49. int (WSAAPI *pfreeaddrinfo)(struct addrinfo *tofree);
  50. };
  51. struct SysSocket
  52. {
  53. int s;
  54. int domain;
  55. };
  56. struct SysNetData *Winsock_Init()
  57. {
  58. struct SysNetData *sdata;
  59. WSADATA winsockdata;
  60. WORD wVersionRequested;
  61. int r;
  62. wVersionRequested = MAKEWORD(1, 1);
  63. r = WSAStartup(wVersionRequested, &winsockdata);
  64. if (!r) /* success == 0 */
  65. {
  66. sdata = malloc(sizeof(*sdata));
  67. sdata->dll_ws2_32 = LoadLibrary("ws2_32.dll");
  68. if (sdata->dll_ws2_32)
  69. {
  70. sdata->pgetaddrinfo = (void*)GetProcAddress(sdata->dll_ws2_32, "getaddrinfo");
  71. sdata->pfreeaddrinfo = (void*)GetProcAddress(sdata->dll_ws2_32, "freeaddrinfo");
  72. }
  73. return sdata;
  74. }
  75. return 0;
  76. }
  77. void Winsock_Shutdown(struct SysNetData *netdata)
  78. {
  79. WSACleanup();
  80. FreeLibrary(netdata->dll_ws2_32);
  81. free(netdata);
  82. }
  83. struct SysNetData *Sys_Net_Init()
  84. {
  85. return Winsock_Init();
  86. }
  87. void Sys_Net_Shutdown(struct SysNetData *netdata)
  88. {
  89. Winsock_Shutdown(netdata);
  90. }
  91. qboolean Sys_Net_ResolveName(struct SysNetData *netdata, const char *name, struct netaddr *address)
  92. {
  93. int r;
  94. struct addrinfo *addr;
  95. struct addrinfo *origaddr;
  96. qboolean ret;
  97. ret = false;
  98. if (netdata->pgetaddrinfo)
  99. {
  100. r = netdata->pgetaddrinfo(name, 0, 0, &origaddr);
  101. if (r == 0)
  102. {
  103. addr = origaddr;
  104. while(addr)
  105. {
  106. if (addr->ai_family == AF_INET)
  107. {
  108. address->type = NA_IPV4;
  109. *(unsigned int *)address->addr.ipv4.address = *(unsigned int *)&((struct sockaddr_in *)addr->ai_addr)->sin_addr.s_addr;
  110. ret = true;
  111. break;
  112. }
  113. if (addr->ai_family == AF_INET6)
  114. {
  115. address->type = NA_IPV6;
  116. memcpy(address->addr.ipv6.address, &((struct sockaddr_in6 *)addr->ai_addr)->sin6_addr, sizeof(address->addr.ipv6.address));
  117. ret = true;
  118. break;
  119. }
  120. addr = addr->ai_next;
  121. }
  122. netdata->pfreeaddrinfo(origaddr);
  123. }
  124. }
  125. return ret;
  126. }
  127. qboolean Sys_Net_ResolveAddress(struct SysNetData *netdata, const struct netaddr *address, char *output, unsigned int outputsize)
  128. {
  129. int r;
  130. socklen_t addrsize;
  131. union
  132. {
  133. struct sockaddr_in addr;
  134. struct sockaddr_in6 addr6;
  135. } addr;
  136. if (address->type == NA_IPV4)
  137. {
  138. addr.addr.sin_family = AF_INET;
  139. addr.addr.sin_port = htons(address->addr.ipv4.port);
  140. *(unsigned int *)&addr.addr.sin_addr.s_addr = *(unsigned int *)address->addr.ipv4.address;
  141. addrsize = sizeof(addr.addr);
  142. }
  143. else if (address->type == NA_IPV6)
  144. {
  145. addr.addr6.sin6_family = AF_INET6;
  146. addr.addr6.sin6_port = htons(address->addr.ipv6.port);
  147. addr.addr6.sin6_flowinfo = 0;
  148. memcpy(&addr.addr6.sin6_addr, address->addr.ipv6.address, sizeof(addr.addr6.sin6_addr));
  149. addr.addr6.sin6_scope_id = 0;
  150. addrsize = sizeof(addr.addr6);
  151. }
  152. else
  153. return false;
  154. // r = getnameinfo((struct sockaddr *)&addr, addrsize, output, outputsize, 0, 0, NI_NAMEREQD);
  155. // if (r == 0)
  156. // return true;
  157. return false;
  158. }
  159. struct SysSocket *Sys_Net_CreateSocket(struct SysNetData *netdata, enum netaddrtype addrtype)
  160. {
  161. struct SysSocket *s;
  162. int domain;
  163. int r;
  164. int one;
  165. one = 1;
  166. if (addrtype == NA_IPV4)
  167. domain = AF_INET;
  168. else if (addrtype == NA_IPV6)
  169. domain = AF_INET6;
  170. else
  171. return 0;
  172. s = malloc(sizeof(*s));
  173. if (s)
  174. {
  175. s->s = socket(domain, SOCK_DGRAM, 0);
  176. if (s->s != -1)
  177. {
  178. r = ioctlsocket(s->s, FIONBIO, &one);
  179. if (r == 0)
  180. {
  181. s->domain = domain;
  182. return s;
  183. }
  184. }
  185. free(s);
  186. }
  187. return 0;
  188. }
  189. void Sys_Net_DeleteSocket(struct SysNetData *netdata, struct SysSocket *socket)
  190. {
  191. closesocket(socket->s);
  192. free(socket);
  193. }
  194. qboolean Sys_Net_Bind(struct SysNetData *netdata, struct SysSocket *socket, unsigned short port)
  195. {
  196. int r;
  197. socklen_t addrsize;
  198. union
  199. {
  200. struct sockaddr_in addr;
  201. struct sockaddr_in6 addr6;
  202. } addr;
  203. if (socket->domain == AF_INET)
  204. {
  205. addr.addr.sin_family = AF_INET;
  206. addr.addr.sin_port = htons(port);
  207. *(unsigned int *)&addr.addr.sin_addr.s_addr = 0;
  208. addrsize = sizeof(addr.addr);
  209. }
  210. else if (socket->domain == AF_INET6)
  211. {
  212. addr.addr6.sin6_family = AF_INET6;
  213. addr.addr6.sin6_port = htons(port);
  214. addr.addr6.sin6_flowinfo = 0;
  215. memset(&addr.addr6.sin6_addr, 0, sizeof(addr.addr6.sin6_addr));
  216. addr.addr6.sin6_scope_id = 0;
  217. addrsize = sizeof(addr.addr6);
  218. }
  219. r = bind(socket->s, (struct sockaddr *)&addr, addrsize);
  220. if (r == 0)
  221. return true;
  222. return false;
  223. }
  224. int Sys_Net_Send(struct SysNetData *netdata, struct SysSocket *socket, const void *data, int datalen, const struct netaddr *address)
  225. {
  226. int r;
  227. if (address)
  228. {
  229. unsigned int addrsize;
  230. union
  231. {
  232. struct sockaddr_in addr;
  233. struct sockaddr_in6 addr6;
  234. } addr;
  235. if (socket->domain == AF_INET)
  236. {
  237. addr.addr.sin_family = AF_INET;
  238. addr.addr.sin_port = htons(address->addr.ipv4.port);
  239. *(unsigned int *)&addr.addr.sin_addr.s_addr = *(unsigned int *)address->addr.ipv4.address;
  240. addrsize = sizeof(addr.addr);
  241. }
  242. else if (socket->domain == AF_INET6)
  243. {
  244. addr.addr6.sin6_family = AF_INET6;
  245. addr.addr6.sin6_port = htons(address->addr.ipv6.port);
  246. memcpy(&addr.addr6.sin6_addr, address->addr.ipv6.address, sizeof(addr.addr6.sin6_addr));
  247. addr.addr6.sin6_flowinfo = 0;
  248. addr.addr6.sin6_scope_id = 0;
  249. addrsize = sizeof(addr.addr6);
  250. }
  251. r = sendto(socket->s, data, datalen, 0, (struct sockaddr *)&addr, addrsize);
  252. }
  253. else
  254. r = send(socket->s, data, datalen, 0);
  255. if (r == -1)
  256. {
  257. if (WSAGetLastError() == WSAEWOULDBLOCK)
  258. return 0;
  259. }
  260. return r;
  261. }
  262. int Sys_Net_Receive(struct SysNetData *netdata, struct SysSocket *socket, void *data, int datalen, struct netaddr *address)
  263. {
  264. int r;
  265. int err;
  266. if (address)
  267. {
  268. socklen_t fromlen;
  269. union
  270. {
  271. struct sockaddr_in addr;
  272. struct sockaddr_in6 addr6;
  273. } addr;
  274. if (socket->domain == AF_INET)
  275. fromlen = sizeof(addr.addr);
  276. else if (socket->domain == AF_INET6)
  277. fromlen = sizeof(addr.addr6);
  278. r = recvfrom(socket->s, data, datalen, 0, (struct sockaddr *)&addr, &fromlen);
  279. if (r >= 0)
  280. {
  281. if (socket->domain == AF_INET)
  282. {
  283. if (fromlen != sizeof(addr.addr))
  284. return -1;
  285. address->type = NA_IPV4;
  286. address->addr.ipv4.port = htons(addr.addr.sin_port);
  287. *(unsigned int *)address->addr.ipv4.address = *(unsigned int *)&addr.addr.sin_addr.s_addr;
  288. }
  289. else if (socket->domain == AF_INET6)
  290. {
  291. if (fromlen != sizeof(addr.addr6))
  292. return -1;
  293. address->type = NA_IPV6;
  294. address->addr.ipv6.port = htons(addr.addr6.sin6_port);
  295. memcpy(address->addr.ipv6.address, &addr.addr6.sin6_addr, sizeof(address->addr.ipv6.address));
  296. }
  297. }
  298. }
  299. else
  300. r = recv(socket->s, data, datalen, 0);
  301. if (r == -1)
  302. {
  303. err = WSAGetLastError();
  304. if (err == WSAEWOULDBLOCK)
  305. return 0;
  306. else if (err == WSAEINVAL) /* Windows returns this if you try to read from a socket before you write to it */
  307. return 0;
  308. }
  309. return r;
  310. }
  311. void Sys_Net_Wait(struct SysNetData *netdata, struct SysSocket *socket, unsigned int timeout_us)
  312. {
  313. struct timeval tv;
  314. fd_set rfds;
  315. FD_ZERO(&rfds);
  316. FD_SET(socket->s, &rfds);
  317. tv.tv_sec = timeout_us / 1000000;
  318. tv.tv_usec = timeout_us % 1000000;
  319. select(socket->s + 1, &rfds, 0, 0, &tv);
  320. }