PageRenderTime 56ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/lhnet.c

https://gitlab.com/xonotic/darkplaces
C | 1437 lines | 1303 code | 80 blank | 54 comment | 314 complexity | 3b8528fcab9024e3dd7088af654beb27 MD5 | raw file
Possible License(s): GPL-2.0
  1. // Written by Forest Hale 2003-06-15 and placed into public domain.
  2. #ifdef WIN32
  3. #ifdef _MSC_VER
  4. #pragma comment(lib, "ws2_32.lib")
  5. #endif
  6. # ifndef NOSUPPORTIPV6
  7. // Windows XP or higher is required for getaddrinfo, but the inclusion of wspiapi provides fallbacks for older versions
  8. # define _WIN32_WINNT 0x0501
  9. # endif
  10. # include <winsock2.h>
  11. # include <ws2tcpip.h>
  12. # ifdef USE_WSPIAPI_H
  13. # include <wspiapi.h>
  14. # endif
  15. #endif
  16. #ifndef STANDALONETEST
  17. #include "quakedef.h"
  18. #endif
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <time.h>
  22. #include <string.h>
  23. #ifndef WIN32
  24. #include <unistd.h>
  25. #include <sys/types.h>
  26. #include <sys/socket.h>
  27. #include <sys/ioctl.h>
  28. #include <errno.h>
  29. #include <netdb.h>
  30. #include <netinet/in.h>
  31. #include <arpa/inet.h>
  32. #ifndef NOSUPPORTIPV6
  33. #include <net/if.h>
  34. #endif
  35. #endif
  36. #ifdef __MORPHOS__
  37. #include <proto/socket.h>
  38. #endif
  39. // for Z_Malloc/Z_Free in quake
  40. #ifndef STANDALONETEST
  41. #include "zone.h"
  42. #include "sys.h"
  43. #include "netconn.h"
  44. #else
  45. #define Con_Print printf
  46. #define Con_Printf printf
  47. #define Z_Malloc malloc
  48. #define Z_Free free
  49. #endif
  50. #include "lhnet.h"
  51. #if defined(WIN32)
  52. // as of Visual Studio 2015, EWOULDBLOCK and ECONNREFUSED are real things, with different values than we want when talking to WinSock, so we have to undef them here or change the rest of the code.
  53. #undef EWOULDBLOCK
  54. #undef ECONNREFUSED
  55. #define EWOULDBLOCK WSAEWOULDBLOCK
  56. #define ECONNREFUSED WSAECONNREFUSED
  57. #define SOCKETERRNO WSAGetLastError()
  58. #define IOC_VENDOR 0x18000000
  59. #define _WSAIOW(x,y) (IOC_IN|(x)|(y))
  60. #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
  61. #define SOCKLEN_T int
  62. #elif defined(__MORPHOS__)
  63. #define ioctlsocket IoctlSocket
  64. #define closesocket CloseSocket
  65. #define SOCKETERRNO Errno()
  66. #define SOCKLEN_T int
  67. #else
  68. #define ioctlsocket ioctl
  69. #define closesocket close
  70. #define SOCKETERRNO errno
  71. #define SOCKLEN_T socklen_t
  72. #endif
  73. #ifdef MSG_DONTWAIT
  74. #define LHNET_RECVFROM_FLAGS MSG_DONTWAIT
  75. #define LHNET_SENDTO_FLAGS 0
  76. #else
  77. #define LHNET_RECVFROM_FLAGS 0
  78. #define LHNET_SENDTO_FLAGS 0
  79. #endif
  80. typedef struct lhnetaddressnative_s
  81. {
  82. lhnetaddresstype_t addresstype;
  83. int port;
  84. union
  85. {
  86. struct sockaddr sock;
  87. struct sockaddr_in in;
  88. #ifndef NOSUPPORTIPV6
  89. struct sockaddr_in6 in6;
  90. #endif
  91. }
  92. addr;
  93. }
  94. lhnetaddressnative_t;
  95. // to make LHNETADDRESS_FromString resolve repeated hostnames faster, cache them
  96. #define MAX_NAMECACHE 64
  97. static struct namecache_s
  98. {
  99. lhnetaddressnative_t address;
  100. double expirationtime;
  101. char name[64];
  102. }
  103. namecache[MAX_NAMECACHE];
  104. static int namecacheposition = 0;
  105. int LHNETADDRESS_FromPort(lhnetaddress_t *vaddress, lhnetaddresstype_t addresstype, int port)
  106. {
  107. lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
  108. if (!address)
  109. return 0;
  110. switch(addresstype)
  111. {
  112. default:
  113. break;
  114. case LHNETADDRESSTYPE_LOOP:
  115. // local:port (loopback)
  116. memset(address, 0, sizeof(*address));
  117. address->addresstype = LHNETADDRESSTYPE_LOOP;
  118. address->port = port;
  119. return 1;
  120. case LHNETADDRESSTYPE_INET4:
  121. // 0.0.0.0:port (INADDR_ANY, binds to all interfaces)
  122. memset(address, 0, sizeof(*address));
  123. address->addresstype = LHNETADDRESSTYPE_INET4;
  124. address->port = port;
  125. address->addr.in.sin_family = AF_INET;
  126. address->addr.in.sin_port = htons((unsigned short)port);
  127. return 1;
  128. #ifndef NOSUPPORTIPV6
  129. case LHNETADDRESSTYPE_INET6:
  130. // [0:0:0:0:0:0:0:0]:port (IN6ADDR_ANY, binds to all interfaces)
  131. memset(address, 0, sizeof(*address));
  132. address->addresstype = LHNETADDRESSTYPE_INET6;
  133. address->port = port;
  134. address->addr.in6.sin6_family = AF_INET6;
  135. address->addr.in6.sin6_port = htons((unsigned short)port);
  136. return 1;
  137. #endif
  138. }
  139. return 0;
  140. }
  141. #ifndef NOSUPPORTIPV6
  142. static int LHNETADDRESS_Resolve(lhnetaddressnative_t *address, const char *name, int port)
  143. {
  144. char port_buff [16];
  145. struct addrinfo hints;
  146. struct addrinfo* addrinf;
  147. int err;
  148. dpsnprintf (port_buff, sizeof (port_buff), "%d", port);
  149. port_buff[sizeof (port_buff) - 1] = '\0';
  150. memset(&hints, 0, sizeof (hints));
  151. hints.ai_family = AF_UNSPEC;
  152. hints.ai_socktype = SOCK_DGRAM;
  153. //hints.ai_flags = AI_PASSIVE;
  154. err = getaddrinfo(name, port_buff, &hints, &addrinf);
  155. if (err != 0 || addrinf == NULL)
  156. return 0;
  157. if (addrinf->ai_addr->sa_family != AF_INET6 && addrinf->ai_addr->sa_family != AF_INET)
  158. {
  159. freeaddrinfo (addrinf);
  160. return 0;
  161. }
  162. // great it worked
  163. if (addrinf->ai_addr->sa_family == AF_INET6)
  164. {
  165. address->addresstype = LHNETADDRESSTYPE_INET6;
  166. memcpy(&address->addr.in6, addrinf->ai_addr, sizeof(address->addr.in6));
  167. }
  168. else
  169. {
  170. address->addresstype = LHNETADDRESSTYPE_INET4;
  171. memcpy(&address->addr.in, addrinf->ai_addr, sizeof(address->addr.in));
  172. }
  173. address->port = port;
  174. freeaddrinfo (addrinf);
  175. return 1;
  176. }
  177. int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
  178. {
  179. lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
  180. int i, port, d1, d2, d3, d4, resolved;
  181. size_t namelen;
  182. unsigned char *a;
  183. char name[128];
  184. #ifdef STANDALONETEST
  185. char string2[128];
  186. #endif
  187. const char* addr_start;
  188. const char* addr_end = NULL;
  189. const char* port_name = NULL;
  190. int addr_family = AF_UNSPEC;
  191. if (!address || !string || !*string)
  192. return 0;
  193. memset(address, 0, sizeof(*address));
  194. address->addresstype = LHNETADDRESSTYPE_NONE;
  195. port = 0;
  196. // If it's a bracketed IPv6 address
  197. if (string[0] == '[')
  198. {
  199. const char* end_bracket = strchr(string, ']');
  200. if (end_bracket == NULL)
  201. return 0;
  202. if (end_bracket[1] == ':')
  203. port_name = end_bracket + 2;
  204. else if (end_bracket[1] != '\0')
  205. return 0;
  206. addr_family = AF_INET6;
  207. addr_start = &string[1];
  208. addr_end = end_bracket;
  209. }
  210. else
  211. {
  212. const char* first_colon;
  213. addr_start = string;
  214. // If it's a numeric non-bracket IPv6 address (-> no port),
  215. // or it's a numeric IPv4 address, or a name, with a port
  216. first_colon = strchr(string, ':');
  217. if (first_colon != NULL)
  218. {
  219. const char* last_colon = strrchr(first_colon + 1, ':');
  220. // If it's an numeric IPv4 address, or a name, with a port
  221. if (last_colon == NULL)
  222. {
  223. addr_end = first_colon;
  224. port_name = first_colon + 1;
  225. }
  226. else
  227. addr_family = AF_INET6;
  228. }
  229. }
  230. if (addr_end != NULL)
  231. namelen = addr_end - addr_start;
  232. else
  233. namelen = strlen (addr_start);
  234. if (namelen >= sizeof(name))
  235. namelen = sizeof(name) - 1;
  236. memcpy (name, addr_start, namelen);
  237. name[namelen] = 0;
  238. if (port_name)
  239. port = atoi(port_name);
  240. if (port == 0)
  241. port = defaultport;
  242. // handle loopback
  243. if (!strcmp(name, "local"))
  244. {
  245. address->addresstype = LHNETADDRESSTYPE_LOOP;
  246. address->port = port;
  247. return 1;
  248. }
  249. // try to parse as dotted decimal ipv4 address first
  250. // note this supports partial ip addresses
  251. d1 = d2 = d3 = d4 = 0;
  252. #if _MSC_VER >= 1400
  253. #define sscanf sscanf_s
  254. #endif
  255. if (addr_family != AF_INET6 &&
  256. sscanf(name, "%d.%d.%d.%d", &d1, &d2, &d3, &d4) >= 1 && (unsigned int)d1 < 256 && (unsigned int)d2 < 256 && (unsigned int)d3 < 256 && (unsigned int)d4 < 256)
  257. {
  258. // parsed a valid ipv4 address
  259. address->addresstype = LHNETADDRESSTYPE_INET4;
  260. address->port = port;
  261. address->addr.in.sin_family = AF_INET;
  262. address->addr.in.sin_port = htons((unsigned short)port);
  263. a = (unsigned char *)&address->addr.in.sin_addr;
  264. a[0] = d1;
  265. a[1] = d2;
  266. a[2] = d3;
  267. a[3] = d4;
  268. #ifdef STANDALONETEST
  269. LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
  270. printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n", string, string2);
  271. #endif
  272. return 1;
  273. }
  274. for (i = 0;i < MAX_NAMECACHE;i++)
  275. if (!strcmp(namecache[i].name, name))
  276. break;
  277. #ifdef STANDALONETEST
  278. if (i < MAX_NAMECACHE)
  279. #else
  280. if (i < MAX_NAMECACHE && realtime < namecache[i].expirationtime)
  281. #endif
  282. {
  283. *address = namecache[i].address;
  284. address->port = port;
  285. if (address->addresstype == LHNETADDRESSTYPE_INET6)
  286. {
  287. address->addr.in6.sin6_port = htons((unsigned short)port);
  288. return 1;
  289. }
  290. else if (address->addresstype == LHNETADDRESSTYPE_INET4)
  291. {
  292. address->addr.in.sin_port = htons((unsigned short)port);
  293. return 1;
  294. }
  295. return 0;
  296. }
  297. for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
  298. namecache[namecacheposition].name[i] = name[i];
  299. namecache[namecacheposition].name[i] = 0;
  300. #ifndef STANDALONETEST
  301. namecache[namecacheposition].expirationtime = realtime + 12 * 3600; // 12 hours
  302. #endif
  303. // try resolving the address (handles dns and other ip formats)
  304. resolved = LHNETADDRESS_Resolve(address, name, port);
  305. if (resolved)
  306. {
  307. #ifdef STANDALONETEST
  308. const char *protoname;
  309. switch (address->addresstype)
  310. {
  311. case LHNETADDRESSTYPE_INET6:
  312. protoname = "ipv6";
  313. break;
  314. case LHNETADDRESSTYPE_INET4:
  315. protoname = "ipv4";
  316. break;
  317. default:
  318. protoname = "UNKNOWN";
  319. break;
  320. }
  321. LHNETADDRESS_ToString(vaddress, string2, sizeof(string2), 1);
  322. Con_Printf("LHNETADDRESS_Resolve(\"%s\") returned %s address %s\n", string, protoname, string2);
  323. #endif
  324. namecache[namecacheposition].address = *address;
  325. }
  326. else
  327. {
  328. #ifdef STANDALONETEST
  329. printf("name resolution failed on address \"%s\"\n", name);
  330. #endif
  331. namecache[namecacheposition].address.addresstype = LHNETADDRESSTYPE_NONE;
  332. }
  333. namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
  334. return resolved;
  335. }
  336. #else
  337. int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
  338. {
  339. lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
  340. int i, port, namelen, d1, d2, d3, d4;
  341. struct hostent *hostentry;
  342. unsigned char *a;
  343. const char *colon;
  344. char name[128];
  345. #ifdef STANDALONETEST
  346. char string2[128];
  347. #endif
  348. if (!address || !string || !*string)
  349. return 0;
  350. memset(address, 0, sizeof(*address));
  351. address->addresstype = LHNETADDRESSTYPE_NONE;
  352. port = 0;
  353. colon = strrchr(string, ':');
  354. if (colon && (colon == strchr(string, ':') || (string[0] == '[' && colon - string > 0 && colon[-1] == ']')))
  355. // EITHER: colon is the ONLY colon OR: colon comes after [...] delimited IPv6 address
  356. // fixes misparsing of IPv6 addresses without port
  357. {
  358. port = atoi(colon + 1);
  359. }
  360. else
  361. colon = string + strlen(string);
  362. if (port == 0)
  363. port = defaultport;
  364. namelen = colon - string;
  365. if (namelen > 127)
  366. namelen = 127;
  367. if (string[0] == '[' && namelen > 0 && string[namelen-1] == ']') // ipv6
  368. {
  369. string++;
  370. namelen -= 2;
  371. }
  372. memcpy(name, string, namelen);
  373. name[namelen] = 0;
  374. // handle loopback
  375. if (!strcmp(name, "local"))
  376. {
  377. address->addresstype = LHNETADDRESSTYPE_LOOP;
  378. address->port = port;
  379. return 1;
  380. }
  381. // try to parse as dotted decimal ipv4 address first
  382. // note this supports partial ip addresses
  383. d1 = d2 = d3 = d4 = 0;
  384. #if _MSC_VER >= 1400
  385. #define sscanf sscanf_s
  386. #endif
  387. if (sscanf(name, "%d.%d.%d.%d", &d1, &d2, &d3, &d4) >= 1 && (unsigned int)d1 < 256 && (unsigned int)d2 < 256 && (unsigned int)d3 < 256 && (unsigned int)d4 < 256)
  388. {
  389. // parsed a valid ipv4 address
  390. address->addresstype = LHNETADDRESSTYPE_INET4;
  391. address->port = port;
  392. address->addr.in.sin_family = AF_INET;
  393. address->addr.in.sin_port = htons((unsigned short)port);
  394. a = (unsigned char *)&address->addr.in.sin_addr;
  395. a[0] = d1;
  396. a[1] = d2;
  397. a[2] = d3;
  398. a[3] = d4;
  399. #ifdef STANDALONETEST
  400. LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
  401. printf("manual parsing of ipv4 dotted decimal address \"%s\" successful: %s\n", string, string2);
  402. #endif
  403. return 1;
  404. }
  405. for (i = 0;i < MAX_NAMECACHE;i++)
  406. if (!strcmp(namecache[i].name, name))
  407. break;
  408. #ifdef STANDALONETEST
  409. if (i < MAX_NAMECACHE)
  410. #else
  411. if (i < MAX_NAMECACHE && realtime < namecache[i].expirationtime)
  412. #endif
  413. {
  414. *address = namecache[i].address;
  415. address->port = port;
  416. if (address->addresstype == LHNETADDRESSTYPE_INET6)
  417. {
  418. #ifndef NOSUPPORTIPV6
  419. address->addr.in6.sin6_port = htons((unsigned short)port);
  420. return 1;
  421. #endif
  422. }
  423. else if (address->addresstype == LHNETADDRESSTYPE_INET4)
  424. {
  425. address->addr.in.sin_port = htons((unsigned short)port);
  426. return 1;
  427. }
  428. return 0;
  429. }
  430. // try gethostbyname (handles dns and other ip formats)
  431. hostentry = gethostbyname(name);
  432. if (hostentry)
  433. {
  434. if (hostentry->h_addrtype == AF_INET6)
  435. {
  436. #ifndef NOSUPPORTIPV6
  437. // great it worked
  438. address->addresstype = LHNETADDRESSTYPE_INET6;
  439. address->port = port;
  440. address->addr.in6.sin6_family = hostentry->h_addrtype;
  441. address->addr.in6.sin6_port = htons((unsigned short)port);
  442. memcpy(&address->addr.in6.sin6_addr, hostentry->h_addr_list[0], sizeof(address->addr.in6.sin6_addr));
  443. for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
  444. namecache[namecacheposition].name[i] = name[i];
  445. namecache[namecacheposition].name[i] = 0;
  446. #ifndef STANDALONETEST
  447. namecache[namecacheposition].expirationtime = realtime + 12 * 3600; // 12 hours
  448. #endif
  449. namecache[namecacheposition].address = *address;
  450. namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
  451. #ifdef STANDALONETEST
  452. LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
  453. printf("gethostbyname(\"%s\") returned ipv6 address %s\n", string, string2);
  454. #endif
  455. return 1;
  456. #endif
  457. }
  458. else if (hostentry->h_addrtype == AF_INET)
  459. {
  460. // great it worked
  461. address->addresstype = LHNETADDRESSTYPE_INET4;
  462. address->port = port;
  463. address->addr.in.sin_family = hostentry->h_addrtype;
  464. address->addr.in.sin_port = htons((unsigned short)port);
  465. memcpy(&address->addr.in.sin_addr, hostentry->h_addr_list[0], sizeof(address->addr.in.sin_addr));
  466. for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
  467. namecache[namecacheposition].name[i] = name[i];
  468. namecache[namecacheposition].name[i] = 0;
  469. #ifndef STANDALONETEST
  470. namecache[namecacheposition].expirationtime = realtime + 12 * 3600; // 12 hours
  471. #endif
  472. namecache[namecacheposition].address = *address;
  473. namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
  474. #ifdef STANDALONETEST
  475. LHNETADDRESS_ToString(address, string2, sizeof(string2), 1);
  476. printf("gethostbyname(\"%s\") returned ipv4 address %s\n", string, string2);
  477. #endif
  478. return 1;
  479. }
  480. }
  481. #ifdef STANDALONETEST
  482. printf("gethostbyname failed on address \"%s\"\n", name);
  483. #endif
  484. for (i = 0;i < (int)sizeof(namecache[namecacheposition].name)-1 && name[i];i++)
  485. namecache[namecacheposition].name[i] = name[i];
  486. namecache[namecacheposition].name[i] = 0;
  487. #ifndef STANDALONETEST
  488. namecache[namecacheposition].expirationtime = realtime + 12 * 3600; // 12 hours
  489. #endif
  490. namecache[namecacheposition].address.addresstype = LHNETADDRESSTYPE_NONE;
  491. namecacheposition = (namecacheposition + 1) % MAX_NAMECACHE;
  492. return 0;
  493. }
  494. #endif
  495. int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stringbuffersize, int includeport)
  496. {
  497. lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
  498. const unsigned char *a;
  499. if (!address || !string || stringbuffersize < 1)
  500. return 0;
  501. *string = 0;
  502. switch(address->addresstype)
  503. {
  504. default:
  505. break;
  506. case LHNETADDRESSTYPE_LOOP:
  507. if (includeport)
  508. {
  509. if (stringbuffersize >= 12)
  510. {
  511. dpsnprintf(string, stringbuffersize, "local:%d", address->port);
  512. return 1;
  513. }
  514. }
  515. else
  516. {
  517. if (stringbuffersize >= 6)
  518. {
  519. memcpy(string, "local", 6);
  520. return 1;
  521. }
  522. }
  523. break;
  524. case LHNETADDRESSTYPE_INET4:
  525. a = (const unsigned char *)(&address->addr.in.sin_addr);
  526. if (includeport)
  527. {
  528. if (stringbuffersize >= 22)
  529. {
  530. dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d:%d", a[0], a[1], a[2], a[3], address->port);
  531. return 1;
  532. }
  533. }
  534. else
  535. {
  536. if (stringbuffersize >= 16)
  537. {
  538. dpsnprintf(string, stringbuffersize, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
  539. return 1;
  540. }
  541. }
  542. break;
  543. #ifndef NOSUPPORTIPV6
  544. case LHNETADDRESSTYPE_INET6:
  545. a = (const unsigned char *)(&address->addr.in6.sin6_addr);
  546. if (includeport)
  547. {
  548. if (stringbuffersize >= 88)
  549. {
  550. dpsnprintf(string, stringbuffersize, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d", a[0] * 256 + a[1], a[2] * 256 + a[3], a[4] * 256 + a[5], a[6] * 256 + a[7], a[8] * 256 + a[9], a[10] * 256 + a[11], a[12] * 256 + a[13], a[14] * 256 + a[15], address->port);
  551. return 1;
  552. }
  553. }
  554. else
  555. {
  556. if (stringbuffersize >= 80)
  557. {
  558. dpsnprintf(string, stringbuffersize, "%x:%x:%x:%x:%x:%x:%x:%x", a[0] * 256 + a[1], a[2] * 256 + a[3], a[4] * 256 + a[5], a[6] * 256 + a[7], a[8] * 256 + a[9], a[10] * 256 + a[11], a[12] * 256 + a[13], a[14] * 256 + a[15]);
  559. return 1;
  560. }
  561. }
  562. break;
  563. #endif
  564. }
  565. return 0;
  566. }
  567. int LHNETADDRESS_GetAddressType(const lhnetaddress_t *address)
  568. {
  569. if (address)
  570. return address->addresstype;
  571. else
  572. return LHNETADDRESSTYPE_NONE;
  573. }
  574. const char *LHNETADDRESS_GetInterfaceName(const lhnetaddress_t *vaddress, char *ifname, size_t ifnamelength)
  575. {
  576. #ifndef NOSUPPORTIPV6
  577. lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
  578. if (address && address->addresstype == LHNETADDRESSTYPE_INET6)
  579. {
  580. #ifndef _WIN32
  581. if (if_indextoname(address->addr.in6.sin6_scope_id, ifname) == ifname)
  582. return ifname;
  583. #else
  584. // The Win32 API doesn't have if_indextoname() until Windows Vista,
  585. // but luckily it just uses the interface ID as the interface name
  586. if (dpsnprintf(ifname, ifnamelength, "%lu", address->addr.in6.sin6_scope_id) > 0)
  587. return ifname;
  588. #endif
  589. }
  590. #endif
  591. return NULL;
  592. }
  593. int LHNETADDRESS_GetPort(const lhnetaddress_t *address)
  594. {
  595. if (!address)
  596. return -1;
  597. return address->port;
  598. }
  599. int LHNETADDRESS_SetPort(lhnetaddress_t *vaddress, int port)
  600. {
  601. lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
  602. if (!address)
  603. return 0;
  604. address->port = port;
  605. switch(address->addresstype)
  606. {
  607. case LHNETADDRESSTYPE_LOOP:
  608. return 1;
  609. case LHNETADDRESSTYPE_INET4:
  610. address->addr.in.sin_port = htons((unsigned short)port);
  611. return 1;
  612. #ifndef NOSUPPORTIPV6
  613. case LHNETADDRESSTYPE_INET6:
  614. address->addr.in6.sin6_port = htons((unsigned short)port);
  615. return 1;
  616. #endif
  617. default:
  618. return 0;
  619. }
  620. }
  621. int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t *vaddress2)
  622. {
  623. lhnetaddressnative_t *address1 = (lhnetaddressnative_t *)vaddress1;
  624. lhnetaddressnative_t *address2 = (lhnetaddressnative_t *)vaddress2;
  625. if (!address1 || !address2)
  626. return 1;
  627. if (address1->addresstype != address2->addresstype)
  628. return 1;
  629. switch(address1->addresstype)
  630. {
  631. case LHNETADDRESSTYPE_LOOP:
  632. if (address1->port != address2->port)
  633. return -1;
  634. return 0;
  635. case LHNETADDRESSTYPE_INET4:
  636. if (address1->addr.in.sin_family != address2->addr.in.sin_family)
  637. return 1;
  638. if (memcmp(&address1->addr.in.sin_addr, &address2->addr.in.sin_addr, sizeof(address1->addr.in.sin_addr)))
  639. return 1;
  640. if (address1->port != address2->port)
  641. return -1;
  642. return 0;
  643. #ifndef NOSUPPORTIPV6
  644. case LHNETADDRESSTYPE_INET6:
  645. if (address1->addr.in6.sin6_family != address2->addr.in6.sin6_family)
  646. return 1;
  647. if (memcmp(&address1->addr.in6.sin6_addr, &address2->addr.in6.sin6_addr, sizeof(address1->addr.in6.sin6_addr)))
  648. return 1;
  649. if (address1->port != address2->port)
  650. return -1;
  651. return 0;
  652. #endif
  653. default:
  654. return 1;
  655. }
  656. }
  657. typedef struct lhnetpacket_s
  658. {
  659. void *data;
  660. int length;
  661. int sourceport;
  662. int destinationport;
  663. time_t timeout;
  664. #ifndef STANDALONETEST
  665. double sentdoubletime;
  666. #endif
  667. struct lhnetpacket_s *next, *prev;
  668. }
  669. lhnetpacket_t;
  670. static int lhnet_active;
  671. static lhnetsocket_t lhnet_socketlist;
  672. static lhnetpacket_t lhnet_packetlist;
  673. static int lhnet_default_dscp = 0;
  674. #ifdef WIN32
  675. static int lhnet_didWSAStartup = 0;
  676. static WSADATA lhnet_winsockdata;
  677. #endif
  678. void LHNET_Init(void)
  679. {
  680. if (lhnet_active)
  681. return;
  682. lhnet_socketlist.next = lhnet_socketlist.prev = &lhnet_socketlist;
  683. lhnet_packetlist.next = lhnet_packetlist.prev = &lhnet_packetlist;
  684. lhnet_active = 1;
  685. #ifdef WIN32
  686. lhnet_didWSAStartup = !WSAStartup(MAKEWORD(1, 1), &lhnet_winsockdata);
  687. if (!lhnet_didWSAStartup)
  688. Con_Print("LHNET_Init: WSAStartup failed, networking disabled\n");
  689. #endif
  690. }
  691. int LHNET_DefaultDSCP(int dscp)
  692. {
  693. #ifdef IP_TOS
  694. int prev = lhnet_default_dscp;
  695. if(dscp >= 0)
  696. lhnet_default_dscp = dscp;
  697. return prev;
  698. #else
  699. return -1;
  700. #endif
  701. }
  702. void LHNET_Shutdown(void)
  703. {
  704. lhnetpacket_t *p;
  705. if (!lhnet_active)
  706. return;
  707. while (lhnet_socketlist.next != &lhnet_socketlist)
  708. LHNET_CloseSocket(lhnet_socketlist.next);
  709. while (lhnet_packetlist.next != &lhnet_packetlist)
  710. {
  711. p = lhnet_packetlist.next;
  712. p->prev->next = p->next;
  713. p->next->prev = p->prev;
  714. Z_Free(p);
  715. }
  716. #ifdef WIN32
  717. if (lhnet_didWSAStartup)
  718. {
  719. lhnet_didWSAStartup = 0;
  720. WSACleanup();
  721. }
  722. #endif
  723. lhnet_active = 0;
  724. }
  725. static const char *LHNETPRIVATE_StrError(void)
  726. {
  727. #ifdef WIN32
  728. int i = WSAGetLastError();
  729. switch (i)
  730. {
  731. case WSAEINTR: return "WSAEINTR";
  732. case WSAEBADF: return "WSAEBADF";
  733. case WSAEACCES: return "WSAEACCES";
  734. case WSAEFAULT: return "WSAEFAULT";
  735. case WSAEINVAL: return "WSAEINVAL";
  736. case WSAEMFILE: return "WSAEMFILE";
  737. case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
  738. case WSAEINPROGRESS: return "WSAEINPROGRESS";
  739. case WSAEALREADY: return "WSAEALREADY";
  740. case WSAENOTSOCK: return "WSAENOTSOCK";
  741. case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
  742. case WSAEMSGSIZE: return "WSAEMSGSIZE";
  743. case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
  744. case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
  745. case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
  746. case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
  747. case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
  748. case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
  749. case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
  750. case WSAEADDRINUSE: return "WSAEADDRINUSE";
  751. case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
  752. case WSAENETDOWN: return "WSAENETDOWN";
  753. case WSAENETUNREACH: return "WSAENETUNREACH";
  754. case WSAENETRESET: return "WSAENETRESET";
  755. case WSAECONNABORTED: return "WSAECONNABORTED";
  756. case WSAECONNRESET: return "WSAECONNRESET";
  757. case WSAENOBUFS: return "WSAENOBUFS";
  758. case WSAEISCONN: return "WSAEISCONN";
  759. case WSAENOTCONN: return "WSAENOTCONN";
  760. case WSAESHUTDOWN: return "WSAESHUTDOWN";
  761. case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
  762. case WSAETIMEDOUT: return "WSAETIMEDOUT";
  763. case WSAECONNREFUSED: return "WSAECONNREFUSED";
  764. case WSAELOOP: return "WSAELOOP";
  765. case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
  766. case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
  767. case WSAEHOSTUNREACH: return "WSAEHOSTUNREACH";
  768. case WSAENOTEMPTY: return "WSAENOTEMPTY";
  769. case WSAEPROCLIM: return "WSAEPROCLIM";
  770. case WSAEUSERS: return "WSAEUSERS";
  771. case WSAEDQUOT: return "WSAEDQUOT";
  772. case WSAESTALE: return "WSAESTALE";
  773. case WSAEREMOTE: return "WSAEREMOTE";
  774. case WSAEDISCON: return "WSAEDISCON";
  775. case 0: return "no error";
  776. default: return "unknown WSAE error";
  777. }
  778. #else
  779. return strerror(errno);
  780. #endif
  781. }
  782. void LHNET_SleepUntilPacket_Microseconds(int microseconds)
  783. {
  784. #ifdef FD_SET
  785. fd_set fdreadset;
  786. struct timeval tv;
  787. int lastfd;
  788. lhnetsocket_t *s;
  789. FD_ZERO(&fdreadset);
  790. lastfd = 0;
  791. for (s = lhnet_socketlist.next;s != &lhnet_socketlist;s = s->next)
  792. {
  793. if (s->address.addresstype == LHNETADDRESSTYPE_INET4 || s->address.addresstype == LHNETADDRESSTYPE_INET6)
  794. {
  795. if (lastfd < s->inetsocket)
  796. lastfd = s->inetsocket;
  797. #if defined(WIN32) && !defined(_MSC_VER)
  798. FD_SET((int)s->inetsocket, &fdreadset);
  799. #else
  800. FD_SET((unsigned int)s->inetsocket, &fdreadset);
  801. #endif
  802. }
  803. }
  804. tv.tv_sec = microseconds / 1000000;
  805. tv.tv_usec = microseconds % 1000000;
  806. select(lastfd + 1, &fdreadset, NULL, NULL, &tv);
  807. #else
  808. Sys_Sleep(microseconds);
  809. #endif
  810. }
  811. lhnetsocket_t *LHNET_OpenSocket_Connectionless(lhnetaddress_t *address)
  812. {
  813. lhnetsocket_t *lhnetsocket, *s;
  814. if (!address)
  815. return NULL;
  816. lhnetsocket = (lhnetsocket_t *)Z_Malloc(sizeof(*lhnetsocket));
  817. if (lhnetsocket)
  818. {
  819. memset(lhnetsocket, 0, sizeof(*lhnetsocket));
  820. lhnetsocket->address = *address;
  821. switch(lhnetsocket->address.addresstype)
  822. {
  823. case LHNETADDRESSTYPE_LOOP:
  824. if (lhnetsocket->address.port == 0)
  825. {
  826. // allocate a port dynamically
  827. // this search will always terminate because there is never
  828. // an allocated socket with port 0, so if the number wraps it
  829. // will find the port is unused, and then refuse to use port
  830. // 0, causing an intentional failure condition
  831. lhnetsocket->address.port = 1024;
  832. for (;;)
  833. {
  834. for (s = lhnet_socketlist.next;s != &lhnet_socketlist;s = s->next)
  835. if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
  836. break;
  837. if (s == &lhnet_socketlist)
  838. break;
  839. lhnetsocket->address.port++;
  840. }
  841. }
  842. // check if the port is available
  843. for (s = lhnet_socketlist.next;s != &lhnet_socketlist;s = s->next)
  844. if (s->address.addresstype == lhnetsocket->address.addresstype && s->address.port == lhnetsocket->address.port)
  845. break;
  846. if (s == &lhnet_socketlist && lhnetsocket->address.port != 0)
  847. {
  848. lhnetsocket->next = &lhnet_socketlist;
  849. lhnetsocket->prev = lhnetsocket->next->prev;
  850. lhnetsocket->next->prev = lhnetsocket;
  851. lhnetsocket->prev->next = lhnetsocket;
  852. return lhnetsocket;
  853. }
  854. break;
  855. case LHNETADDRESSTYPE_INET4:
  856. #ifndef NOSUPPORTIPV6
  857. case LHNETADDRESSTYPE_INET6:
  858. #endif
  859. #ifdef WIN32
  860. if (lhnet_didWSAStartup)
  861. {
  862. #endif
  863. #ifndef NOSUPPORTIPV6
  864. if ((lhnetsocket->inetsocket = socket(address->addresstype == LHNETADDRESSTYPE_INET6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
  865. #else
  866. if ((lhnetsocket->inetsocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1)
  867. #endif
  868. {
  869. #ifdef WIN32
  870. u_long _false = 0;
  871. #endif
  872. #ifdef MSG_DONTWAIT
  873. if (1)
  874. #else
  875. #ifdef WIN32
  876. u_long _true = 1;
  877. #else
  878. char _true = 1;
  879. #endif
  880. if (ioctlsocket(lhnetsocket->inetsocket, FIONBIO, &_true) != -1)
  881. #endif
  882. {
  883. #ifdef IPV6_V6ONLY
  884. // We need to set this flag to tell the OS that we only listen on IPv6. If we don't
  885. // most OSes will create a dual-protocol socket that also listens on IPv4. In this case
  886. // if an IPv4 socket is already bound to the port we want, our bind() call will fail.
  887. int ipv6_only = 1;
  888. if (address->addresstype != LHNETADDRESSTYPE_INET6
  889. || setsockopt (lhnetsocket->inetsocket, IPPROTO_IPV6, IPV6_V6ONLY,
  890. (const char *)&ipv6_only, sizeof(ipv6_only)) == 0
  891. #ifdef WIN32
  892. // The Win32 API only supports IPV6_V6ONLY since Windows Vista, but fortunately
  893. // the default value is what we want on Win32 anyway (IPV6_V6ONLY = true)
  894. || SOCKETERRNO == WSAENOPROTOOPT
  895. #endif
  896. )
  897. #endif
  898. {
  899. lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
  900. SOCKLEN_T namelen;
  901. int bindresult;
  902. #if defined(SOL_RFC1149) && defined(RFC1149_1149ONLY)
  903. // we got reports of massive lags when this protocol was chosen as transport
  904. // so better turn it off
  905. {
  906. int rfc1149only = 0;
  907. int rfc1149enabled = 0;
  908. if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_1149ONLY, &rfc1149only))
  909. Con_Printf("LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_1149ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
  910. if(setsockopt(lhnetsocket->inetsocket, SOL_RFC1149, RFC1149_ENABLED, &rfc1149enabled))
  911. Con_Printf("LHNET_OpenSocket_Connectionless: warning: setsockopt(RFC1149_ENABLED) returned error: %s\n", LHNETPRIVATE_StrError());
  912. }
  913. #endif
  914. #ifndef NOSUPPORTIPV6
  915. if (address->addresstype == LHNETADDRESSTYPE_INET6)
  916. {
  917. namelen = sizeof(localaddress->addr.in6);
  918. bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
  919. if (bindresult != -1)
  920. {
  921. if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
  922. {
  923. // If getsockname failed, we can assume the bound socket is useless.
  924. bindresult = -1;
  925. }
  926. }
  927. }
  928. else
  929. #endif
  930. {
  931. namelen = sizeof(localaddress->addr.in);
  932. bindresult = bind(lhnetsocket->inetsocket, &localaddress->addr.sock, namelen);
  933. if (bindresult != -1)
  934. {
  935. if (getsockname(lhnetsocket->inetsocket, &localaddress->addr.sock, &namelen))
  936. {
  937. // If getsockname failed, we can assume the bound socket is useless.
  938. bindresult = -1;
  939. }
  940. }
  941. }
  942. if (bindresult != -1)
  943. {
  944. int i = 1;
  945. // enable broadcast on this socket
  946. setsockopt(lhnetsocket->inetsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i));
  947. #ifdef IP_TOS
  948. {
  949. // enable DSCP for ToS support
  950. int tos = lhnet_default_dscp << 2;
  951. if (setsockopt(lhnetsocket->inetsocket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(tos)))
  952. {
  953. // Error in setsockopt - fine, we'll simply set no TOS then.
  954. }
  955. }
  956. #endif
  957. lhnetsocket->next = &lhnet_socketlist;
  958. lhnetsocket->prev = lhnetsocket->next->prev;
  959. lhnetsocket->next->prev = lhnetsocket;
  960. lhnetsocket->prev->next = lhnetsocket;
  961. #ifdef WIN32
  962. if (ioctlsocket(lhnetsocket->inetsocket, SIO_UDP_CONNRESET, &_false) == -1)
  963. Con_DPrintf("LHNET_OpenSocket_Connectionless: ioctlsocket SIO_UDP_CONNRESET returned error: %s\n", LHNETPRIVATE_StrError());
  964. #endif
  965. return lhnetsocket;
  966. }
  967. else
  968. Con_Printf("LHNET_OpenSocket_Connectionless: bind returned error: %s\n", LHNETPRIVATE_StrError());
  969. }
  970. #ifdef IPV6_V6ONLY
  971. else
  972. Con_Printf("LHNET_OpenSocket_Connectionless: setsockopt(IPV6_V6ONLY) returned error: %s\n", LHNETPRIVATE_StrError());
  973. #endif
  974. }
  975. else
  976. Con_Printf("LHNET_OpenSocket_Connectionless: ioctlsocket returned error: %s\n", LHNETPRIVATE_StrError());
  977. closesocket(lhnetsocket->inetsocket);
  978. }
  979. else
  980. Con_Printf("LHNET_OpenSocket_Connectionless: socket returned error: %s\n", LHNETPRIVATE_StrError());
  981. #ifdef WIN32
  982. }
  983. else
  984. Con_Print("LHNET_OpenSocket_Connectionless: can't open a socket (WSAStartup failed during LHNET_Init)\n");
  985. #endif
  986. break;
  987. default:
  988. break;
  989. }
  990. Z_Free(lhnetsocket);
  991. }
  992. return NULL;
  993. }
  994. void LHNET_CloseSocket(lhnetsocket_t *lhnetsocket)
  995. {
  996. if (lhnetsocket)
  997. {
  998. // unlink from socket list
  999. if (lhnetsocket->next == NULL)
  1000. return; // invalid!
  1001. lhnetsocket->next->prev = lhnetsocket->prev;
  1002. lhnetsocket->prev->next = lhnetsocket->next;
  1003. lhnetsocket->next = NULL;
  1004. lhnetsocket->prev = NULL;
  1005. // no special close code for loopback, just inet
  1006. if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4 || lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
  1007. {
  1008. closesocket(lhnetsocket->inetsocket);
  1009. }
  1010. Z_Free(lhnetsocket);
  1011. }
  1012. }
  1013. lhnetaddress_t *LHNET_AddressFromSocket(lhnetsocket_t *sock)
  1014. {
  1015. if (sock)
  1016. return &sock->address;
  1017. else
  1018. return NULL;
  1019. }
  1020. int LHNET_Read(lhnetsocket_t *lhnetsocket, void *content, int maxcontentlength, lhnetaddress_t *vaddress)
  1021. {
  1022. lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
  1023. int value = 0;
  1024. if (!lhnetsocket || !address || !content || maxcontentlength < 1)
  1025. return -1;
  1026. if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
  1027. {
  1028. time_t currenttime;
  1029. lhnetpacket_t *p, *pnext;
  1030. // scan for any old packets to timeout while searching for a packet
  1031. // that is waiting to be delivered to this socket
  1032. currenttime = time(NULL);
  1033. for (p = lhnet_packetlist.next;p != &lhnet_packetlist;p = pnext)
  1034. {
  1035. pnext = p->next;
  1036. if (p->timeout < currenttime)
  1037. {
  1038. // unlink and free
  1039. p->next->prev = p->prev;
  1040. p->prev->next = p->next;
  1041. Z_Free(p);
  1042. continue;
  1043. }
  1044. #ifndef STANDALONETEST
  1045. if (cl_netlocalping.value && (realtime - cl_netlocalping.value * (1.0 / 2000.0)) < p->sentdoubletime)
  1046. continue;
  1047. #endif
  1048. if (value == 0 && p->destinationport == lhnetsocket->address.port)
  1049. {
  1050. if (p->length <= maxcontentlength)
  1051. {
  1052. lhnetaddressnative_t *localaddress = (lhnetaddressnative_t *)&lhnetsocket->address;
  1053. *address = *localaddress;
  1054. address->port = p->sourceport;
  1055. memcpy(content, p->data, p->length);
  1056. value = p->length;
  1057. }
  1058. else
  1059. value = -1;
  1060. // unlink and free
  1061. p->next->prev = p->prev;
  1062. p->prev->next = p->next;
  1063. Z_Free(p);
  1064. }
  1065. }
  1066. }
  1067. else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
  1068. {
  1069. SOCKLEN_T inetaddresslength;
  1070. address->addresstype = LHNETADDRESSTYPE_NONE;
  1071. inetaddresslength = sizeof(address->addr.in);
  1072. value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
  1073. if (value > 0)
  1074. {
  1075. address->addresstype = LHNETADDRESSTYPE_INET4;
  1076. address->port = ntohs(address->addr.in.sin_port);
  1077. return value;
  1078. }
  1079. else if (value < 0)
  1080. {
  1081. int e = SOCKETERRNO;
  1082. if (e == EWOULDBLOCK)
  1083. return 0;
  1084. switch (e)
  1085. {
  1086. case ECONNREFUSED:
  1087. Con_Print("Connection refused\n");
  1088. return 0;
  1089. }
  1090. Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
  1091. }
  1092. }
  1093. #ifndef NOSUPPORTIPV6
  1094. else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
  1095. {
  1096. SOCKLEN_T inetaddresslength;
  1097. address->addresstype = LHNETADDRESSTYPE_NONE;
  1098. inetaddresslength = sizeof(address->addr.in6);
  1099. value = recvfrom(lhnetsocket->inetsocket, (char *)content, maxcontentlength, LHNET_RECVFROM_FLAGS, &address->addr.sock, &inetaddresslength);
  1100. if (value > 0)
  1101. {
  1102. address->addresstype = LHNETADDRESSTYPE_INET6;
  1103. address->port = ntohs(address->addr.in6.sin6_port);
  1104. return value;
  1105. }
  1106. else if (value == -1)
  1107. {
  1108. int e = SOCKETERRNO;
  1109. if (e == EWOULDBLOCK)
  1110. return 0;
  1111. switch (e)
  1112. {
  1113. case ECONNREFUSED:
  1114. Con_Print("Connection refused\n");
  1115. return 0;
  1116. }
  1117. Con_DPrintf("LHNET_Read: recvfrom returned error: %s\n", LHNETPRIVATE_StrError());
  1118. }
  1119. }
  1120. #endif
  1121. return value;
  1122. }
  1123. int LHNET_Write(lhnetsocket_t *lhnetsocket, const void *content, int contentlength, const lhnetaddress_t *vaddress)
  1124. {
  1125. lhnetaddressnative_t *address = (lhnetaddressnative_t *)vaddress;
  1126. int value = -1;
  1127. if (!lhnetsocket || !address || !content || contentlength < 1)
  1128. return -1;
  1129. if (lhnetsocket->address.addresstype != address->addresstype)
  1130. return -1;
  1131. if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_LOOP)
  1132. {
  1133. lhnetpacket_t *p;
  1134. p = (lhnetpacket_t *)Z_Malloc(sizeof(*p) + contentlength);
  1135. p->data = (void *)(p + 1);
  1136. memcpy(p->data, content, contentlength);
  1137. p->length = contentlength;
  1138. p->sourceport = lhnetsocket->address.port;
  1139. p->destinationport = address->port;
  1140. p->timeout = time(NULL) + 10;
  1141. p->next = &lhnet_packetlist;
  1142. p->prev = p->next->prev;
  1143. p->next->prev = p;
  1144. p->prev->next = p;
  1145. #ifndef STANDALONETEST
  1146. p->sentdoubletime = realtime;
  1147. #endif
  1148. value = contentlength;
  1149. }
  1150. else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET4)
  1151. {
  1152. value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, LHNET_SENDTO_FLAGS, (struct sockaddr *)&address->addr.in, sizeof(struct sockaddr_in));
  1153. if (value == -1)
  1154. {
  1155. if (SOCKETERRNO == EWOULDBLOCK)
  1156. return 0;
  1157. Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
  1158. }
  1159. }
  1160. #ifndef NOSUPPORTIPV6
  1161. else if (lhnetsocket->address.addresstype == LHNETADDRESSTYPE_INET6)
  1162. {
  1163. value = sendto(lhnetsocket->inetsocket, (char *)content, contentlength, 0, (struct sockaddr *)&address->addr.in6, sizeof(struct sockaddr_in6));
  1164. if (value == -1)
  1165. {
  1166. if (SOCKETERRNO == EWOULDBLOCK)
  1167. return 0;
  1168. Con_DPrintf("LHNET_Write: sendto returned error: %s\n", LHNETPRIVATE_StrError());
  1169. }
  1170. }
  1171. #endif
  1172. return value;
  1173. }
  1174. #ifdef STANDALONETEST
  1175. int main(int argc, char **argv)
  1176. {
  1177. #if 1
  1178. char *buffer = "test", buffer2[1024];
  1179. int blen = strlen(buffer);
  1180. int b2len = 1024;
  1181. lhnetsocket_t *sock1;
  1182. lhnetsocket_t *sock2;
  1183. lhnetaddress_t myaddy1;
  1184. lhnetaddress_t myaddy2;
  1185. lhnetaddress_t myaddy3;
  1186. lhnetaddress_t localhostaddy1;
  1187. lhnetaddress_t localhostaddy2;
  1188. int test1;
  1189. int test2;
  1190. printf("calling LHNET_Init\n");
  1191. LHNET_Init();
  1192. printf("calling LHNET_FromPort twice to create two local addresses\n");
  1193. LHNETADDRESS_FromPort(&myaddy1, LHNETADDRESSTYPE_INET4, 4000);
  1194. LHNETADDRESS_FromPort(&myaddy2, LHNETADDRESSTYPE_INET4, 4001);
  1195. LHNETADDRESS_FromString(&localhostaddy1, "127.0.0.1", 4000);
  1196. LHNETADDRESS_FromString(&localhostaddy2, "127.0.0.1", 4001);
  1197. printf("calling LHNET_OpenSocket_Connectionless twice to create two local sockets\n");
  1198. sock1 = LHNET_OpenSocket_Connectionless(&myaddy1);
  1199. sock2 = LHNET_OpenSocket_Connectionless(&myaddy2);
  1200. printf("calling LHNET_Write to send a packet from the first socket to the second socket\n");
  1201. test1 = LHNET_Write(sock1, buffer, blen, &localhostaddy2);
  1202. printf("sleeping briefly\n");
  1203. #ifdef WIN32
  1204. Sleep (100);
  1205. #else
  1206. usleep (100000);
  1207. #endif
  1208. printf("calling LHNET_Read on the second socket to read the packet sent from the first socket\n");
  1209. test2 = LHNET_Read(sock2, buffer2, b2len - 1, &myaddy3);
  1210. if (test2 > 0)
  1211. Con_Printf("socket to socket test succeeded\n");
  1212. else
  1213. Con_Printf("socket to socket test failed\n");
  1214. #ifdef WIN32
  1215. printf("press any key to exit\n");
  1216. getchar();
  1217. #endif
  1218. printf("calling LHNET_Shutdown\n");
  1219. LHNET_Shutdown();
  1220. printf("exiting\n");
  1221. return 0;
  1222. #else
  1223. lhnetsocket_t *sock[16], *sendsock;
  1224. int i;
  1225. int numsockets;
  1226. int count;
  1227. int length;
  1228. int port;
  1229. time_t oldtime;
  1230. time_t newtime;
  1231. char *sendmessage;
  1232. int sendmessagelength;
  1233. lhnetaddress_t destaddress;
  1234. lhnetaddress_t receiveaddress;
  1235. lhnetaddress_t sockaddress[16];
  1236. char buffer[1536], addressstring[128], addressstring2[128];
  1237. if ((argc == 2 || argc == 5) && (port = atoi(argv[1])) >= 1 && port < 65535)
  1238. {
  1239. printf("calling LHNET_Init()\n");
  1240. LHNET_Init();
  1241. numsockets = 0;
  1242. LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_LOOP, port);
  1243. LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET4, port);
  1244. LHNETADDRESS_FromPort(&sockaddress[numsockets++], LHNETADDRESSTYPE_INET6, port+1);
  1245. sendsock = NULL;
  1246. sendmessage = NULL;
  1247. sendmessagelength = 0;
  1248. for (i = 0;i < numsockets;i++)
  1249. {
  1250. LHNETADDRESS_ToString(&sockaddress[i], addressstring, sizeof(addressstring), 1);
  1251. printf("calling LHNET_OpenSocket_Connectionless(<%s>)\n", addressstring);
  1252. if ((sock[i] = LHNET_OpenSocket_Connectionless(&sockaddress[i])))
  1253. {
  1254. LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
  1255. printf("opened socket successfully (address \"%s\")\n", addressstring2);
  1256. }
  1257. else
  1258. {
  1259. printf("failed to open socket\n");
  1260. if (i == 0)
  1261. {
  1262. LHNET_Shutdown();
  1263. return -1;
  1264. }
  1265. }
  1266. }
  1267. count = 0;
  1268. if (argc == 5)
  1269. {
  1270. count = atoi(argv[2]);
  1271. if (LHNETADDRESS_FromString(&destaddress, argv[3], -1))
  1272. {
  1273. sendmessage = argv[4];
  1274. sendmessagelength = strlen(sendmessage);
  1275. sendsock = NULL;
  1276. for (i = 0;i < numsockets;i++)
  1277. if (sock[i] && LHNETADDRESS_GetAddressType(&destaddress) == LHNETADDRESS_GetAddressType(&sockaddress[i]))
  1278. sendsock = sock[i];
  1279. if (sendsock == NULL)
  1280. {
  1281. printf("Could not find an open socket matching the addresstype (%i) of destination address, switching to listen only mode\n", LHNETADDRESS_GetAddressType(&destaddress));
  1282. argc = 2;
  1283. }
  1284. }
  1285. else
  1286. {
  1287. printf("LHNETADDRESS_FromString did not like the address \"%s\", switching to listen only mode\n", argv[3]);
  1288. argc = 2;
  1289. }
  1290. }
  1291. printf("started, now listening for \"exit\" on the opened sockets\n");
  1292. oldtime = time(NULL);
  1293. for(;;)
  1294. {
  1295. #ifdef WIN32
  1296. Sleep(1);
  1297. #else
  1298. usleep(1);
  1299. #endif
  1300. for (i = 0;i < numsockets;i++)
  1301. {
  1302. if (sock[i])
  1303. {
  1304. length = LHNET_Read(sock[i], buffer, sizeof(buffer), &receiveaddress);
  1305. if (length < 0)
  1306. printf("localsock read error: length < 0");
  1307. else if (length > 0 && length < (int)sizeof(buffer))
  1308. {
  1309. buffer[length] = 0;
  1310. LHNETADDRESS_ToString(&receiveaddress, addressstring, sizeof(addressstring), 1);
  1311. LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
  1312. printf("received message \"%s\" from \"%s\" on socket \"%s\"\n", buffer, addressstring, addressstring2);
  1313. if (!strcmp(buffer, "exit"))
  1314. break;
  1315. }
  1316. }
  1317. }
  1318. if (i < numsockets)
  1319. break;
  1320. if (argc == 5 && count > 0)
  1321. {
  1322. newtime = time(NULL);
  1323. if (newtime != oldtime)
  1324. {
  1325. LHNETADDRESS_ToString(&destaddress, addressstring, sizeof(addressstring), 1);
  1326. LHNETADDRESS_ToString(LHNET_AddressFromSocket(sendsock), addressstring2, sizeof(addressstring2), 1);
  1327. printf("calling LHNET_Write(<%s>, \"%s\", %i, <%s>)\n", addressstring2, sendmessage, sendmessagelength, addressstring);
  1328. length = LHNET_Write(sendsock, sendmessage, sendmessagelength, &destaddress);
  1329. if (length == sendmessagelength)
  1330. printf("sent successfully\n");
  1331. else
  1332. printf("LH_Write failed, returned %i (length of message was %i)\n", length, strlen(argv[4]));
  1333. oldtime = newtime;
  1334. count--;
  1335. if (count <= 0)
  1336. printf("Done sending, still listening for \"exit\"\n");
  1337. }
  1338. }
  1339. }
  1340. for (i = 0;i < numsockets;i++)
  1341. {
  1342. if (sock[i])
  1343. {
  1344. LHNETADDRESS_ToString(LHNET_AddressFromSocket(sock[i]), addressstring2, sizeof(addressstring2), 1);
  1345. printf("calling LHNET_CloseSocket(<%s>)\n", addressstring2);
  1346. LHNET_CloseSocket(sock[i]);
  1347. }
  1348. }
  1349. printf("calling LHNET_Shutdown()\n");
  1350. LHNET_Shutdown();
  1351. return 0;
  1352. }
  1353. printf("Testing code for lhnet.c\nusage: lhnettest <localportnumber> [<sendnumberoftimes> <sendaddress:port> <sendmessage>]\n");
  1354. return -1;
  1355. #endif
  1356. }
  1357. #endif