BDatagram_win.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. /**
  2. * @file BDatagram_win.c
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the author nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include <stdlib.h>
  30. #include <base/BLog.h>
  31. #include "BDatagram.h"
  32. #include <generated/blog_channel_BDatagram.h>
  33. static int family_socket_to_sys (int family);
  34. static void addr_socket_to_sys (struct BDatagram_sys_addr *out, BAddr addr);
  35. static void addr_sys_to_socket (BAddr *out, struct BDatagram_sys_addr addr);
  36. static void set_pktinfo (SOCKET sock, int family);
  37. static void report_error (BDatagram *o);
  38. static void datagram_abort (BDatagram *o);
  39. static void start_send (BDatagram *o);
  40. static void start_recv (BDatagram *o);
  41. static void send_job_handler (BDatagram *o);
  42. static void recv_job_handler (BDatagram *o);
  43. static void send_if_handler_send (BDatagram *o, uint8_t *data, int data_len);
  44. static void recv_if_handler_recv (BDatagram *o, uint8_t *data);
  45. static void send_olap_handler (BDatagram *o, int event, DWORD bytes);
  46. static void recv_olap_handler (BDatagram *o, int event, DWORD bytes);
  47. static int family_socket_to_sys (int family)
  48. {
  49. switch (family) {
  50. case BADDR_TYPE_IPV4:
  51. return AF_INET;
  52. case BADDR_TYPE_IPV6:
  53. return AF_INET6;
  54. }
  55. ASSERT(0);
  56. return 0;
  57. }
  58. static void addr_socket_to_sys (struct BDatagram_sys_addr *out, BAddr addr)
  59. {
  60. switch (addr.type) {
  61. case BADDR_TYPE_IPV4: {
  62. out->len = sizeof(out->addr.ipv4);
  63. memset(&out->addr.ipv4, 0, sizeof(out->addr.ipv4));
  64. out->addr.ipv4.sin_family = AF_INET;
  65. out->addr.ipv4.sin_port = addr.ipv4.port;
  66. out->addr.ipv4.sin_addr.s_addr = addr.ipv4.ip;
  67. } break;
  68. case BADDR_TYPE_IPV6: {
  69. out->len = sizeof(out->addr.ipv6);
  70. memset(&out->addr.ipv6, 0, sizeof(out->addr.ipv6));
  71. out->addr.ipv6.sin6_family = AF_INET6;
  72. out->addr.ipv6.sin6_port = addr.ipv6.port;
  73. out->addr.ipv6.sin6_flowinfo = 0;
  74. memcpy(out->addr.ipv6.sin6_addr.s6_addr, addr.ipv6.ip, 16);
  75. out->addr.ipv6.sin6_scope_id = 0;
  76. } break;
  77. default: ASSERT(0);
  78. }
  79. }
  80. static void addr_sys_to_socket (BAddr *out, struct BDatagram_sys_addr addr)
  81. {
  82. switch (addr.addr.generic.sa_family) {
  83. case AF_INET: {
  84. ASSERT(addr.len == sizeof(struct sockaddr_in))
  85. BAddr_InitIPv4(out, addr.addr.ipv4.sin_addr.s_addr, addr.addr.ipv4.sin_port);
  86. } break;
  87. case AF_INET6: {
  88. ASSERT(addr.len == sizeof(struct sockaddr_in6))
  89. BAddr_InitIPv6(out, addr.addr.ipv6.sin6_addr.s6_addr, addr.addr.ipv6.sin6_port);
  90. } break;
  91. default: {
  92. BAddr_InitNone(out);
  93. } break;
  94. }
  95. }
  96. static void set_pktinfo (SOCKET sock, int family)
  97. {
  98. DWORD opt = 1;
  99. switch (family) {
  100. case BADDR_TYPE_IPV4: {
  101. if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, (char *)&opt, sizeof(opt)) < 0) {
  102. BLog(BLOG_ERROR, "setsockopt(IP_PKTINFO) failed");
  103. }
  104. } break;
  105. case BADDR_TYPE_IPV6: {
  106. if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, (char *)&opt, sizeof(opt)) < 0) {
  107. BLog(BLOG_ERROR, "setsockopt(IPV6_PKTINFO) failed");
  108. }
  109. } break;
  110. }
  111. }
  112. static void report_error (BDatagram *o)
  113. {
  114. DebugError_AssertNoError(&o->d_err);
  115. // report error
  116. DEBUGERROR(&o->d_err, o->handler(o->user, BDATAGRAM_EVENT_ERROR));
  117. return;
  118. }
  119. static void datagram_abort (BDatagram *o)
  120. {
  121. ASSERT(!o->aborted)
  122. // cancel I/O
  123. if ((o->recv.inited && o->recv.data_have && o->recv.data_busy) || (o->send.inited && o->send.data_len >= 0 && o->send.data_busy)) {
  124. if (!CancelIo((HANDLE)o->sock)) {
  125. BLog(BLOG_ERROR, "CancelIo failed");
  126. }
  127. }
  128. // close socket
  129. if (closesocket(o->sock) == SOCKET_ERROR) {
  130. BLog(BLOG_ERROR, "closesocket failed");
  131. }
  132. // wait for receiving to complete
  133. if (o->recv.inited && o->recv.data_have && o->recv.data_busy) {
  134. BReactorIOCPOverlapped_Wait(&o->recv.olap, NULL, NULL);
  135. }
  136. // wait for sending to complete
  137. if (o->send.inited && o->send.data_len >= 0 && o->send.data_busy) {
  138. BReactorIOCPOverlapped_Wait(&o->send.olap, NULL, NULL);
  139. }
  140. // free recv olap
  141. BReactorIOCPOverlapped_Free(&o->recv.olap);
  142. // free send olap
  143. BReactorIOCPOverlapped_Free(&o->send.olap);
  144. // set aborted
  145. o->aborted = 1;
  146. }
  147. static void start_send (BDatagram *o)
  148. {
  149. DebugError_AssertNoError(&o->d_err);
  150. ASSERT(!o->aborted)
  151. ASSERT(o->send.inited)
  152. ASSERT(o->send.data_len >= 0)
  153. ASSERT(!o->send.data_busy)
  154. ASSERT(o->send.have_addrs)
  155. // convert destination address
  156. addr_socket_to_sys(&o->send.sysaddr, o->send.remote_addr);
  157. WSABUF buf;
  158. buf.buf = (char *)o->send.data;
  159. buf.len = (o->send.data_len > ULONG_MAX ? ULONG_MAX : o->send.data_len);
  160. memset(&o->send.olap.olap, 0, sizeof(o->send.olap.olap));
  161. if (o->fnWSASendMsg) {
  162. o->send.msg.name = &o->send.sysaddr.addr.generic;
  163. o->send.msg.namelen = o->send.sysaddr.len;
  164. o->send.msg.lpBuffers = &buf;
  165. o->send.msg.dwBufferCount = 1;
  166. o->send.msg.Control.buf = (char *)&o->send.cdata;
  167. o->send.msg.Control.len = sizeof(o->send.cdata);
  168. o->send.msg.dwFlags = 0;
  169. int sum = 0;
  170. WSACMSGHDR *cmsg = WSA_CMSG_FIRSTHDR(&o->send.msg);
  171. switch (o->send.local_addr.type) {
  172. case BADDR_TYPE_IPV4: {
  173. memset(cmsg, 0, WSA_CMSG_SPACE(sizeof(struct in_pktinfo)));
  174. cmsg->cmsg_level = IPPROTO_IP;
  175. cmsg->cmsg_type = IP_PKTINFO;
  176. cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(struct in_pktinfo));
  177. struct in_pktinfo *pktinfo = (struct in_pktinfo *)WSA_CMSG_DATA(cmsg);
  178. pktinfo->ipi_addr.s_addr = o->send.local_addr.ipv4;
  179. sum += WSA_CMSG_SPACE(sizeof(struct in_pktinfo));
  180. } break;
  181. case BADDR_TYPE_IPV6: {
  182. memset(cmsg, 0, WSA_CMSG_SPACE(sizeof(struct in6_pktinfo)));
  183. cmsg->cmsg_level = IPPROTO_IPV6;
  184. cmsg->cmsg_type = IPV6_PKTINFO;
  185. cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(struct in6_pktinfo));
  186. struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)WSA_CMSG_DATA(cmsg);
  187. memcpy(pktinfo->ipi6_addr.s6_addr, o->send.local_addr.ipv6, 16);
  188. sum += WSA_CMSG_SPACE(sizeof(struct in6_pktinfo));
  189. } break;
  190. }
  191. o->send.msg.Control.len = sum;
  192. if (o->send.msg.Control.len == 0) {
  193. o->send.msg.Control.buf = NULL;
  194. }
  195. // send
  196. int res = o->fnWSASendMsg(o->sock, &o->send.msg, 0, NULL, &o->send.olap.olap, NULL);
  197. if (res == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
  198. BLog(BLOG_ERROR, "WSASendMsg failed (%d)", WSAGetLastError());
  199. report_error(o);
  200. return;
  201. }
  202. } else {
  203. // send
  204. int res = WSASendTo(o->sock, &buf, 1, NULL, 0, &o->send.sysaddr.addr.generic, o->send.sysaddr.len, &o->send.olap.olap, NULL);
  205. if (res == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
  206. BLog(BLOG_ERROR, "WSASendTo failed (%d)", WSAGetLastError());
  207. report_error(o);
  208. return;
  209. }
  210. }
  211. // set busy
  212. o->send.data_busy = 1;
  213. }
  214. static void start_recv (BDatagram *o)
  215. {
  216. DebugError_AssertNoError(&o->d_err);
  217. ASSERT(!o->aborted)
  218. ASSERT(o->recv.inited)
  219. ASSERT(o->recv.data_have)
  220. ASSERT(!o->recv.data_busy)
  221. ASSERT(o->recv.started)
  222. WSABUF buf;
  223. buf.buf = (char *)o->recv.data;
  224. buf.len = (o->recv.mtu > ULONG_MAX ? ULONG_MAX : o->recv.mtu);
  225. memset(&o->recv.olap.olap, 0, sizeof(o->recv.olap.olap));
  226. if (o->fnWSARecvMsg) {
  227. o->recv.msg.name = &o->recv.sysaddr.addr.generic;
  228. o->recv.msg.namelen = sizeof(o->recv.sysaddr.addr);
  229. o->recv.msg.lpBuffers = &buf;
  230. o->recv.msg.dwBufferCount = 1;
  231. o->recv.msg.Control.buf = (char *)&o->recv.cdata;
  232. o->recv.msg.Control.len = sizeof(o->recv.cdata);
  233. o->recv.msg.dwFlags = 0;
  234. // recv
  235. int res = o->fnWSARecvMsg(o->sock, &o->recv.msg, NULL, &o->recv.olap.olap, NULL);
  236. if (res == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
  237. BLog(BLOG_ERROR, "WSARecvMsg failed (%d)", WSAGetLastError());
  238. report_error(o);
  239. return;
  240. }
  241. } else {
  242. o->recv.sysaddr.len = sizeof(o->recv.sysaddr.addr);
  243. // recv
  244. DWORD flags = 0;
  245. int res = WSARecvFrom(o->sock, &buf, 1, NULL, &flags, &o->recv.sysaddr.addr.generic, &o->recv.sysaddr.len, &o->recv.olap.olap, NULL);
  246. if (res == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
  247. BLog(BLOG_ERROR, "WSARecvFrom failed (%d)", WSAGetLastError());
  248. report_error(o);
  249. return;
  250. }
  251. }
  252. // set busy
  253. o->recv.data_busy = 1;
  254. }
  255. static void send_job_handler (BDatagram *o)
  256. {
  257. DebugObject_Access(&o->d_obj);
  258. DebugError_AssertNoError(&o->d_err);
  259. ASSERT(!o->aborted)
  260. ASSERT(o->send.inited)
  261. ASSERT(o->send.data_len >= 0)
  262. ASSERT(!o->send.data_busy)
  263. ASSERT(o->send.have_addrs)
  264. // send
  265. start_send(o);
  266. return;
  267. }
  268. static void recv_job_handler (BDatagram *o)
  269. {
  270. DebugObject_Access(&o->d_obj);
  271. DebugError_AssertNoError(&o->d_err);
  272. ASSERT(!o->aborted)
  273. ASSERT(o->recv.inited)
  274. ASSERT(o->recv.data_have)
  275. ASSERT(!o->recv.data_busy)
  276. ASSERT(o->recv.started)
  277. // recv
  278. start_recv(o);
  279. return;
  280. }
  281. static void send_if_handler_send (BDatagram *o, uint8_t *data, int data_len)
  282. {
  283. DebugObject_Access(&o->d_obj);
  284. DebugError_AssertNoError(&o->d_err);
  285. ASSERT(!o->aborted)
  286. ASSERT(o->send.inited)
  287. ASSERT(o->send.data_len == -1)
  288. ASSERT(data_len >= 0)
  289. ASSERT(data_len <= o->send.mtu)
  290. // remember data
  291. o->send.data = data;
  292. o->send.data_len = data_len;
  293. o->send.data_busy = 0;
  294. // if have no addresses, wait
  295. if (!o->send.have_addrs) {
  296. return;
  297. }
  298. // send
  299. start_send(o);
  300. return;
  301. }
  302. static void recv_if_handler_recv (BDatagram *o, uint8_t *data)
  303. {
  304. DebugObject_Access(&o->d_obj);
  305. DebugError_AssertNoError(&o->d_err);
  306. ASSERT(!o->aborted)
  307. ASSERT(o->recv.inited)
  308. ASSERT(!o->recv.data_have)
  309. // remember data
  310. o->recv.data = data;
  311. o->recv.data_have = 1;
  312. o->recv.data_busy = 0;
  313. // if recv not started yet, wait
  314. if (!o->recv.started) {
  315. return;
  316. }
  317. // recv
  318. start_recv(o);
  319. return;
  320. }
  321. static void send_olap_handler (BDatagram *o, int event, DWORD bytes)
  322. {
  323. DebugObject_Access(&o->d_obj);
  324. DebugError_AssertNoError(&o->d_err);
  325. ASSERT(!o->aborted)
  326. ASSERT(o->send.inited)
  327. ASSERT(o->send.data_len >= 0)
  328. ASSERT(o->send.data_busy)
  329. ASSERT(event == BREACTOR_IOCP_EVENT_SUCCEEDED || event == BREACTOR_IOCP_EVENT_FAILED)
  330. // set not busy
  331. o->send.data_busy = 0;
  332. if (event == BREACTOR_IOCP_EVENT_FAILED) {
  333. BLog(BLOG_ERROR, "sending failed");
  334. report_error(o);
  335. return;
  336. }
  337. ASSERT(bytes >= 0)
  338. ASSERT(bytes <= o->send.data_len)
  339. if (bytes < o->send.data_len) {
  340. BLog(BLOG_ERROR, "sent too little");
  341. }
  342. // if recv wasn't started yet, start it
  343. if (!o->recv.started) {
  344. // set recv started
  345. o->recv.started = 1;
  346. // continue receiving
  347. if (o->recv.inited && o->recv.data_have) {
  348. ASSERT(!o->recv.data_busy)
  349. BPending_Set(&o->recv.job);
  350. }
  351. }
  352. // set no data
  353. o->send.data_len = -1;
  354. // done
  355. PacketPassInterface_Done(&o->send.iface);
  356. }
  357. static void recv_olap_handler (BDatagram *o, int event, DWORD bytes)
  358. {
  359. DebugObject_Access(&o->d_obj);
  360. DebugError_AssertNoError(&o->d_err);
  361. ASSERT(!o->aborted)
  362. ASSERT(o->recv.inited)
  363. ASSERT(o->recv.data_have)
  364. ASSERT(o->recv.data_busy)
  365. ASSERT(event == BREACTOR_IOCP_EVENT_SUCCEEDED || event == BREACTOR_IOCP_EVENT_FAILED)
  366. // set not busy
  367. o->recv.data_busy = 0;
  368. if (event == BREACTOR_IOCP_EVENT_FAILED) {
  369. BLog(BLOG_ERROR, "receiving failed");
  370. report_error(o);
  371. return;
  372. }
  373. ASSERT(bytes >= 0)
  374. ASSERT(bytes <= o->recv.mtu)
  375. if (o->fnWSARecvMsg) {
  376. o->recv.sysaddr.len = o->recv.msg.namelen;
  377. }
  378. // read remote address
  379. addr_sys_to_socket(&o->recv.remote_addr, o->recv.sysaddr);
  380. // read local address
  381. BIPAddr_InitInvalid(&o->recv.local_addr);
  382. if (o->fnWSARecvMsg) {
  383. for (WSACMSGHDR *cmsg = WSA_CMSG_FIRSTHDR(&o->recv.msg); cmsg; cmsg = WSA_CMSG_NXTHDR(&o->recv.msg, cmsg)) {
  384. if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
  385. struct in_pktinfo *pktinfo = (struct in_pktinfo *)WSA_CMSG_DATA(cmsg);
  386. BIPAddr_InitIPv4(&o->recv.local_addr, pktinfo->ipi_addr.s_addr);
  387. }
  388. else if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
  389. struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)WSA_CMSG_DATA(cmsg);
  390. BIPAddr_InitIPv6(&o->recv.local_addr, pktinfo->ipi6_addr.s6_addr);
  391. }
  392. }
  393. }
  394. // set have addresses
  395. o->recv.have_addrs = 1;
  396. // set no data
  397. o->recv.data_have = 0;
  398. // done
  399. PacketRecvInterface_Done(&o->recv.iface, bytes);
  400. }
  401. int BDatagram_AddressFamilySupported (int family)
  402. {
  403. return (family == BADDR_TYPE_IPV4 || family == BADDR_TYPE_IPV6);
  404. }
  405. int BDatagram_Init (BDatagram *o, int family, BReactor *reactor, void *user,
  406. BDatagram_handler handler)
  407. {
  408. ASSERT(BDatagram_AddressFamilySupported(family))
  409. ASSERT(handler)
  410. BNetwork_Assert();
  411. // init arguments
  412. o->reactor = reactor;
  413. o->user = user;
  414. o->handler = handler;
  415. // init socket
  416. if ((o->sock = WSASocket(family_socket_to_sys(family), SOCK_DGRAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) {
  417. BLog(BLOG_ERROR, "WSASocket failed");
  418. goto fail0;
  419. }
  420. DWORD out_bytes;
  421. // obtain WSASendMsg
  422. GUID guid1 = WSAID_WSASENDMSG;
  423. if (WSAIoctl(o->sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid1, sizeof(guid1), &o->fnWSASendMsg, sizeof(o->fnWSASendMsg), &out_bytes, NULL, NULL) != 0) {
  424. o->fnWSASendMsg = NULL;
  425. }
  426. // obtain WSARecvMsg
  427. GUID guid2 = WSAID_WSARECVMSG;
  428. if (WSAIoctl(o->sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid2, sizeof(guid2), &o->fnWSARecvMsg, sizeof(o->fnWSARecvMsg), &out_bytes, NULL, NULL) != 0) {
  429. BLog(BLOG_ERROR, "failed to obtain WSARecvMsg");
  430. o->fnWSARecvMsg = NULL;
  431. }
  432. // associate with IOCP
  433. if (!CreateIoCompletionPort((HANDLE)o->sock, BReactor_GetIOCPHandle(o->reactor), 0, 0)) {
  434. BLog(BLOG_ERROR, "CreateIoCompletionPort failed");
  435. goto fail1;
  436. }
  437. // enable receiving pktinfo
  438. set_pktinfo(o->sock, family);
  439. // set not aborted
  440. o->aborted = 0;
  441. // init send olap
  442. BReactorIOCPOverlapped_Init(&o->send.olap, o->reactor, o, (BReactorIOCPOverlapped_handler)send_olap_handler);
  443. // set have no send addrs
  444. o->send.have_addrs = 0;
  445. // set send not inited
  446. o->send.inited = 0;
  447. // init recv olap
  448. BReactorIOCPOverlapped_Init(&o->recv.olap, o->reactor, o, (BReactorIOCPOverlapped_handler)recv_olap_handler);
  449. // set recv not started
  450. o->recv.started = 0;
  451. // set have no recv addrs
  452. o->recv.have_addrs = 0;
  453. // set recv not inited
  454. o->recv.inited = 0;
  455. DebugError_Init(&o->d_err, BReactor_PendingGroup(o->reactor));
  456. DebugObject_Init(&o->d_obj);
  457. return 1;
  458. fail1:
  459. if (closesocket(o->sock) == SOCKET_ERROR) {
  460. BLog(BLOG_ERROR, "closesocket failed");
  461. }
  462. fail0:
  463. return 0;
  464. }
  465. void BDatagram_Free (BDatagram *o)
  466. {
  467. DebugObject_Free(&o->d_obj);
  468. DebugError_Free(&o->d_err);
  469. ASSERT(!o->recv.inited)
  470. ASSERT(!o->send.inited)
  471. if (!o->aborted) {
  472. datagram_abort(o);
  473. }
  474. }
  475. int BDatagram_Bind (BDatagram *o, BAddr addr)
  476. {
  477. DebugObject_Access(&o->d_obj);
  478. DebugError_AssertNoError(&o->d_err);
  479. ASSERT(!o->aborted)
  480. ASSERT(BDatagram_AddressFamilySupported(addr.type))
  481. // translate address
  482. struct BDatagram_sys_addr sysaddr;
  483. addr_socket_to_sys(&sysaddr, addr);
  484. // bind
  485. if (bind(o->sock, &sysaddr.addr.generic, sysaddr.len) < 0) {
  486. BLog(BLOG_ERROR, "bind failed");
  487. return 0;
  488. }
  489. // if recv wasn't started yet, start it
  490. if (!o->recv.started) {
  491. // set recv started
  492. o->recv.started = 1;
  493. // continue receiving
  494. if (o->recv.inited && o->recv.data_have) {
  495. ASSERT(!o->recv.data_busy)
  496. BPending_Set(&o->recv.job);
  497. }
  498. }
  499. return 1;
  500. }
  501. void BDatagram_SetSendAddrs (BDatagram *o, BAddr remote_addr, BIPAddr local_addr)
  502. {
  503. DebugObject_Access(&o->d_obj);
  504. DebugError_AssertNoError(&o->d_err);
  505. ASSERT(!o->aborted)
  506. ASSERT(BDatagram_AddressFamilySupported(remote_addr.type))
  507. ASSERT(local_addr.type == BADDR_TYPE_NONE || BDatagram_AddressFamilySupported(local_addr.type))
  508. // set addresses
  509. o->send.remote_addr = remote_addr;
  510. o->send.local_addr = local_addr;
  511. // set have addresses
  512. o->send.have_addrs = 1;
  513. // start sending
  514. if (o->send.inited && o->send.data_len >= 0 && !o->send.data_busy) {
  515. BPending_Set(&o->send.job);
  516. }
  517. }
  518. int BDatagram_GetLastReceiveAddrs (BDatagram *o, BAddr *remote_addr, BIPAddr *local_addr)
  519. {
  520. DebugObject_Access(&o->d_obj);
  521. if (!o->recv.have_addrs) {
  522. return 0;
  523. }
  524. *remote_addr = o->recv.remote_addr;
  525. *local_addr = o->recv.local_addr;
  526. return 1;
  527. }
  528. int BDatagram_SetReuseAddr (BDatagram *o, int reuse)
  529. {
  530. DebugObject_Access(&o->d_obj);
  531. ASSERT(reuse == 0 || reuse == 1)
  532. if (setsockopt(o->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) {
  533. return 0;
  534. }
  535. return 1;
  536. }
  537. void BDatagram_SendAsync_Init (BDatagram *o, int mtu)
  538. {
  539. DebugObject_Access(&o->d_obj);
  540. DebugError_AssertNoError(&o->d_err);
  541. ASSERT(!o->aborted)
  542. ASSERT(!o->send.inited)
  543. ASSERT(mtu >= 0)
  544. // init arguments
  545. o->send.mtu = mtu;
  546. // init interface
  547. PacketPassInterface_Init(&o->send.iface, o->send.mtu, (PacketPassInterface_handler_send)send_if_handler_send, o, BReactor_PendingGroup(o->reactor));
  548. // init job
  549. BPending_Init(&o->send.job, BReactor_PendingGroup(o->reactor), (BPending_handler)send_job_handler, o);
  550. // set have no data
  551. o->send.data_len = -1;
  552. // set inited
  553. o->send.inited = 1;
  554. }
  555. void BDatagram_SendAsync_Free (BDatagram *o)
  556. {
  557. DebugObject_Access(&o->d_obj);
  558. ASSERT(o->send.inited)
  559. // abort if busy
  560. if (o->send.data_len >= 0 && o->send.data_busy && !o->aborted) {
  561. datagram_abort(o);
  562. }
  563. // free job
  564. BPending_Free(&o->send.job);
  565. // free interface
  566. PacketPassInterface_Free(&o->send.iface);
  567. // set not inited
  568. o->send.inited = 0;
  569. }
  570. PacketPassInterface * BDatagram_SendAsync_GetIf (BDatagram *o)
  571. {
  572. DebugObject_Access(&o->d_obj);
  573. ASSERT(o->send.inited)
  574. return &o->send.iface;
  575. }
  576. void BDatagram_RecvAsync_Init (BDatagram *o, int mtu)
  577. {
  578. DebugObject_Access(&o->d_obj);
  579. DebugError_AssertNoError(&o->d_err);
  580. ASSERT(!o->aborted)
  581. ASSERT(!o->recv.inited)
  582. ASSERT(mtu >= 0)
  583. // init arguments
  584. o->recv.mtu = mtu;
  585. // init interface
  586. PacketRecvInterface_Init(&o->recv.iface, o->recv.mtu, (PacketRecvInterface_handler_recv)recv_if_handler_recv, o, BReactor_PendingGroup(o->reactor));
  587. // init job
  588. BPending_Init(&o->recv.job, BReactor_PendingGroup(o->reactor), (BPending_handler)recv_job_handler, o);
  589. // set have no data
  590. o->recv.data_have = 0;
  591. // set inited
  592. o->recv.inited = 1;
  593. }
  594. void BDatagram_RecvAsync_Free (BDatagram *o)
  595. {
  596. DebugObject_Access(&o->d_obj);
  597. ASSERT(o->recv.inited)
  598. // abort if busy
  599. if (o->recv.data_have && o->recv.data_busy && !o->aborted) {
  600. datagram_abort(o);
  601. }
  602. // free job
  603. BPending_Free(&o->recv.job);
  604. // free interface
  605. PacketRecvInterface_Free(&o->recv.iface);
  606. // set not inited
  607. o->recv.inited = 0;
  608. }
  609. PacketRecvInterface * BDatagram_RecvAsync_GetIf (BDatagram *o)
  610. {
  611. DebugObject_Access(&o->d_obj);
  612. ASSERT(o->recv.inited)
  613. return &o->recv.iface;
  614. }