sockutil.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. #include "precompile.h"
  2. #include "sockutil.h"
  3. #include "strutil.h"
  4. //define replaced by cmake synatx
  5. //#pragma comment(lib, "ws2_32.lib")
  6. TOOLKIT_API int winsock_init()
  7. {
  8. WSADATA wsaData;
  9. return WSAStartup(0x0202, &wsaData);
  10. }
  11. TOOLKIT_API int winsock_term()
  12. {
  13. return WSACleanup();
  14. }
  15. TOOLKIT_API char* get_local_ip(char *buf, int n)
  16. {
  17. char name[64];
  18. struct hostent * he;
  19. gethostname(name, sizeof(name));
  20. he = gethostbyname(name);
  21. if (he) {
  22. if (he->h_addr_list[0]) {
  23. return strncpy(buf, inet_ntoa(*(struct in_addr*)he->h_addr_list[0]), n);
  24. }
  25. }
  26. return NULL;
  27. }
  28. // < 0 : error
  29. // < n : timeout
  30. // ==n : ok
  31. TOOLKIT_API int tsend_n(int fd, const char *buf, int n, long timeout/* = -1 */)
  32. {
  33. struct timeval _tm;
  34. struct timeval *tm;
  35. int offset = 0;
  36. int left = n;
  37. DWORD dwLast;
  38. tm = (timeout >= 0) ? &_tm : NULL;
  39. if (tm)
  40. dwLast = GetTickCount();
  41. while (left > 0 && (timeout == -1 || timeout > 0)) {
  42. int t = send(fd, buf+offset, left, 0);
  43. if (t == 0) {
  44. return offset;
  45. } else if (t < 0) {
  46. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  47. int rc;
  48. fd_set wr_fs;
  49. fd_set ex_fs;
  50. FD_ZERO(&wr_fs);
  51. FD_ZERO(&ex_fs);
  52. FD_SET(fd, &wr_fs);
  53. FD_SET(fd, &ex_fs);
  54. if (tm) {
  55. DWORD dwNow = GetTickCount();
  56. long diff = (long)(dwNow - dwLast);
  57. if (timeout >= diff) {
  58. timeout -= diff;
  59. } else {
  60. timeout = 0;
  61. }
  62. tm->tv_sec = timeout/1000;
  63. tm->tv_usec = timeout%1000;
  64. dwLast = dwNow;
  65. }
  66. rc = select(1, NULL, &wr_fs, &ex_fs, tm);
  67. if (rc < 0)
  68. return -1;
  69. if (rc == 0)
  70. return offset;
  71. if (FD_ISSET(fd, &ex_fs))
  72. return -1;
  73. assert(FD_ISSET(fd, &wr_fs));
  74. } else {
  75. return -1;
  76. }
  77. } else { // (t > 0)
  78. offset += t;
  79. left -= t;
  80. }
  81. }
  82. return offset;
  83. }
  84. TOOLKIT_API int trecv_n(int fd, char *buf, size_t n, long timeout/* = -1*/)
  85. {
  86. struct timeval _tm;
  87. struct timeval *tm;
  88. int offset = 0;
  89. int left = n;
  90. DWORD dwLast;
  91. tm = (timeout >= 0) ? &_tm : NULL;
  92. if (tm)
  93. dwLast = GetTickCount();
  94. while (left > 0 && (timeout == -1 || timeout > 0)) {
  95. int t = recv(fd, buf+offset, left, 0);
  96. if (t == 0) {
  97. return offset;
  98. } else if (t < 0) {
  99. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  100. int rc;
  101. fd_set rd_fs;
  102. fd_set ex_fs;
  103. FD_ZERO(&rd_fs);
  104. FD_ZERO(&ex_fs);
  105. FD_SET(fd, &rd_fs);
  106. FD_SET(fd, &ex_fs);
  107. if (tm) {
  108. DWORD dwNow = GetTickCount();
  109. long diff = (long)(dwNow - dwLast);
  110. if (timeout >= diff) {
  111. timeout -= diff;
  112. } else {
  113. timeout = 0;
  114. }
  115. tm->tv_sec = timeout/1000;
  116. tm->tv_usec = timeout%1000;
  117. dwLast = dwNow;
  118. }
  119. rc = select(1, &rd_fs, NULL, &ex_fs, tm);
  120. if (rc < 0)
  121. return -1;
  122. if (rc == 0)
  123. return offset;
  124. if (FD_ISSET(fd, &ex_fs))
  125. return -1;
  126. assert(FD_ISSET(fd, &rd_fs));
  127. } else {
  128. return -1;
  129. }
  130. } else {
  131. offset += t;
  132. left -= t;
  133. }
  134. }
  135. return offset;
  136. }
  137. TOOLKIT_API int trecv_until(int fd, char *buf, int n, const char *delimer, int *header_len, long timeout)
  138. {
  139. struct timeval _tm;
  140. struct timeval *tm;
  141. int offset = 0;
  142. int left = n;
  143. DWORD dwLast;
  144. assert(delimer);
  145. *header_len = 0;
  146. tm = (timeout >= 0) ? &_tm : NULL;
  147. if (tm)
  148. dwLast = GetTickCount();
  149. while (left > 0 && (timeout == -1 || timeout > 0)) {
  150. int t = recv(fd, buf+offset, left, 0);
  151. if (t == 0) {
  152. *header_len = 0;
  153. return offset;
  154. } else if (t < 0) {
  155. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  156. int rc;
  157. fd_set rd_fs;
  158. fd_set ex_fs;
  159. FD_ZERO(&rd_fs);
  160. FD_ZERO(&ex_fs);
  161. FD_SET(fd, &rd_fs);
  162. FD_SET(fd, &ex_fs);
  163. if (tm) {
  164. DWORD dwNow = GetTickCount();
  165. long diff = (long)(dwNow - dwLast);
  166. if (timeout >= diff) {
  167. timeout -= diff;
  168. } else {
  169. timeout = 0;
  170. }
  171. tm->tv_sec = timeout/1000;
  172. tm->tv_usec = timeout%1000;
  173. dwLast = dwNow;
  174. }
  175. rc = select(1, &rd_fs, NULL, &ex_fs, tm);
  176. if (rc < 0)
  177. return -1;
  178. if (rc == 0)
  179. return offset;
  180. if (FD_ISSET(fd, &ex_fs))
  181. return -1;
  182. assert(FD_ISSET(fd, &rd_fs));
  183. } else {
  184. return -1;
  185. }
  186. } else {
  187. const char *p;
  188. offset += t;
  189. left -= t;
  190. p = memstr(buf, offset, delimer);
  191. if (p) {
  192. p += strlen(delimer);
  193. *header_len = p - buf;
  194. return offset;
  195. }
  196. }
  197. }
  198. return offset;
  199. }
  200. TOOLKIT_API int tsend_until(int fd, const char *buf, int n, const char *delimer, long timeout)
  201. {
  202. const char *p;
  203. assert(delimer);
  204. p = memstr(buf, n, delimer);
  205. if (!p)
  206. return -1;
  207. p += strlen(delimer);
  208. return tsend_n(fd, buf, p - buf, timeout);
  209. }
  210. #ifndef SIO_UDP_CONNRESET
  211. #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
  212. #endif
  213. TOOLKIT_API int disable_udp_connreset(SOCKET so)
  214. {
  215. DWORD dwBytesReturned = 0;
  216. BOOL bNewBehavior = FALSE;
  217. return WSAIoctl(so, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior),
  218. NULL, 0, &dwBytesReturned, NULL, NULL);
  219. }
  220. TOOLKIT_API int tsend_n_v(int fd, LPWSABUF lpBuffers, DWORD dwBufferCount, long timeout)
  221. {
  222. struct timeval _tm;
  223. struct timeval *tm;
  224. int sendedbufs = 0;
  225. int leftbufs = (int)dwBufferCount;
  226. int offset = 0;
  227. int sendedbytes = 0;
  228. DWORD dwLast;
  229. tm = (timeout >= 0) ? &_tm : NULL;
  230. if (tm)
  231. dwLast = GetTickCount();
  232. while (leftbufs > 0 && (timeout == -1 || timeout > 0)) {
  233. DWORD dwSent = 0;
  234. int rc = WSASend(fd, lpBuffers+sendedbufs, leftbufs, &dwSent, 0, NULL, NULL);
  235. if (rc < 0) {
  236. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  237. int rc;
  238. fd_set wr_fs;
  239. fd_set ex_fs;
  240. FD_ZERO(&wr_fs);
  241. FD_ZERO(&ex_fs);
  242. FD_SET(fd, &wr_fs);
  243. FD_SET(fd, &ex_fs);
  244. if (tm) {
  245. DWORD dwNow = GetTickCount();
  246. long diff = (long)(dwNow - dwLast);
  247. if (timeout >= diff) {
  248. timeout -= diff;
  249. } else {
  250. timeout = 0;
  251. }
  252. tm->tv_sec = timeout/1000;
  253. tm->tv_usec = timeout%1000;
  254. dwLast = dwNow;
  255. }
  256. rc = select(1, NULL, &wr_fs, &ex_fs, tm);
  257. if (rc < 0)
  258. return -1;
  259. if (rc == 0)
  260. return sendedbytes;
  261. if (FD_ISSET(fd, &ex_fs))
  262. return -1;
  263. assert(FD_ISSET(fd, &wr_fs));
  264. } else {
  265. return -1;
  266. }
  267. } else { // (t > 0)
  268. if (dwSent == 0)
  269. return sendedbytes;
  270. sendedbytes += dwSent;
  271. while (dwSent > 0) {
  272. if (dwSent >= (lpBuffers[sendedbufs].len-offset)) {
  273. dwSent -= lpBuffers[sendedbufs].len-offset;
  274. sendedbufs++;
  275. leftbufs--;
  276. offset = 0;
  277. } else {
  278. lpBuffers[sendedbufs].buf += dwSent;
  279. lpBuffers[sendedbufs].len -= dwSent;
  280. dwSent = 0;
  281. }
  282. }
  283. }
  284. }
  285. return sendedbytes;
  286. }
  287. TOOLKIT_API int trecv_n_v(int fd, LPWSABUF lpBuffers, DWORD dwBufferCount, long timeout)
  288. {
  289. struct timeval _tm;
  290. struct timeval *tm;
  291. int recvedbufs = 0;
  292. int leftbufs = (int)dwBufferCount;
  293. int offset = 0;
  294. int recvedbytes = 0;
  295. DWORD dwLast;
  296. tm = (timeout >= 0) ? &_tm : NULL;
  297. if (tm)
  298. dwLast = GetTickCount();
  299. while (leftbufs > 0 && (timeout == -1 || timeout > 0)) {
  300. DWORD dwRecv = 0;
  301. int rc = WSARecv(fd, lpBuffers+recvedbufs, leftbufs, &dwRecv, 0, NULL, NULL);
  302. if (rc < 0) {
  303. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  304. int rc;
  305. fd_set rd_fs;
  306. fd_set ex_fs;
  307. FD_ZERO(&rd_fs);
  308. FD_ZERO(&ex_fs);
  309. FD_SET(fd, &rd_fs);
  310. FD_SET(fd, &ex_fs);
  311. if (tm) {
  312. DWORD dwNow = GetTickCount();
  313. long diff = (long)(dwNow - dwLast);
  314. if (timeout >= diff) {
  315. timeout -= diff;
  316. } else {
  317. timeout = 0;
  318. }
  319. tm->tv_sec = timeout/1000;
  320. tm->tv_usec = timeout%1000;
  321. dwLast = dwNow;
  322. }
  323. rc = select(1, &rd_fs, NULL, &ex_fs, tm);
  324. if (rc < 0)
  325. return -1;
  326. if (rc == 0)
  327. return recvedbytes;
  328. if (FD_ISSET(fd, &ex_fs))
  329. return -1;
  330. assert(FD_ISSET(fd, &rd_fs));
  331. } else {
  332. return -1;
  333. }
  334. } else { // (t > 0)
  335. if (dwRecv == 0)
  336. return recvedbytes;
  337. recvedbytes += dwRecv;
  338. while (dwRecv > 0) {
  339. if (dwRecv >= (lpBuffers[recvedbufs].len-offset)) {
  340. dwRecv -= lpBuffers[recvedbufs].len-offset;
  341. recvedbufs++;
  342. leftbufs--;
  343. offset = 0;
  344. } else {
  345. lpBuffers[recvedbufs].buf += dwRecv;
  346. lpBuffers[recvedbufs].len -= dwRecv;
  347. dwRecv = 0;
  348. }
  349. }
  350. }
  351. }
  352. return recvedbytes;
  353. }
  354. TOOLKIT_API int tsendto(int fd, const char *buf, int n, const struct sockaddr* to, int tolen, long timeout)
  355. {
  356. struct timeval _tm;
  357. struct timeval *tm;
  358. DWORD dwLast;
  359. tm = (timeout >= 0) ? &_tm : NULL;
  360. if (tm)
  361. dwLast = GetTickCount();
  362. do {
  363. int rc = sendto(fd, buf, n, 0, to, tolen);
  364. if (rc >= 0)
  365. return rc;
  366. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  367. int rc;
  368. fd_set wr_fs;
  369. fd_set ex_fs;
  370. FD_ZERO(&wr_fs);
  371. FD_ZERO(&ex_fs);
  372. FD_SET(fd, &wr_fs);
  373. FD_SET(fd, &ex_fs);
  374. if (tm) {
  375. DWORD dwNow = GetTickCount();
  376. long diff = (long)(dwNow - dwLast);
  377. if (timeout >= diff) {
  378. timeout -= diff;
  379. } else {
  380. timeout = 0;
  381. }
  382. tm->tv_sec = timeout/1000;
  383. tm->tv_usec = timeout%1000;
  384. dwLast = dwNow;
  385. }
  386. rc = select(1, NULL, &wr_fs, &ex_fs, tm);
  387. if (rc <= 0)
  388. break;
  389. if (FD_ISSET(fd, &ex_fs))
  390. break;
  391. assert(FD_ISSET(fd, &wr_fs));
  392. } else {
  393. break;
  394. }
  395. } while (timeout == -1 || timeout > 0);
  396. return -1;
  397. }
  398. TOOLKIT_API int trecvfrom(int fd, char *buf, int n, struct sockaddr* fromaddr, int *fromlen, long timeout)
  399. {
  400. struct timeval _tm;
  401. struct timeval *tm;
  402. DWORD dwLast;
  403. tm = (timeout >= 0) ? &_tm : NULL;
  404. if (tm)
  405. dwLast = GetTickCount();
  406. do {
  407. int rc = recvfrom(fd, buf, n, 0, fromaddr, fromlen);
  408. if (rc >= 0)
  409. return rc;
  410. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  411. int rc;
  412. fd_set rd_fs;
  413. fd_set ex_fs;
  414. FD_ZERO(&rd_fs);
  415. FD_ZERO(&ex_fs);
  416. FD_SET(fd, &rd_fs);
  417. FD_SET(fd, &ex_fs);
  418. if (tm) {
  419. DWORD dwNow = GetTickCount();
  420. long diff = (long)(dwNow - dwLast);
  421. if (timeout >= diff) {
  422. timeout -= diff;
  423. } else {
  424. timeout = 0;
  425. }
  426. tm->tv_sec = timeout/1000;
  427. tm->tv_usec = timeout%1000;
  428. dwLast = dwNow;
  429. }
  430. rc = select(1, &rd_fs, NULL, &ex_fs, tm);
  431. if (rc <= 0)
  432. break;
  433. if (FD_ISSET(fd, &ex_fs))
  434. break;
  435. assert(FD_ISSET(fd, &rd_fs));
  436. } else {
  437. break;
  438. }
  439. } while (timeout == -1 || timeout > 0);
  440. return -1;
  441. }