BDatagram_win.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  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. report_error(o);
  199. return;
  200. }
  201. } else {
  202. // send
  203. int res = WSASendTo(o->sock, &buf, 1, NULL, 0, &o->send.sysaddr.addr.generic, o->send.sysaddr.len, &o->send.olap.olap, NULL);
  204. if (res == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
  205. report_error(o);
  206. return;
  207. }
  208. }
  209. // set busy
  210. o->send.data_busy = 1;
  211. }
  212. static void start_recv (BDatagram *o)
  213. {
  214. DebugError_AssertNoError(&o->d_err);
  215. ASSERT(!o->aborted)
  216. ASSERT(o->recv.inited)
  217. ASSERT(o->recv.data_have)
  218. ASSERT(!o->recv.data_busy)
  219. ASSERT(o->recv.started)
  220. WSABUF buf;
  221. buf.buf = (char *)o->recv.data;
  222. buf.len = (o->recv.mtu > ULONG_MAX ? ULONG_MAX : o->recv.mtu);
  223. memset(&o->recv.olap.olap, 0, sizeof(o->recv.olap.olap));
  224. if (o->fnWSARecvMsg) {
  225. o->recv.msg.name = &o->recv.sysaddr.addr.generic;
  226. o->recv.msg.namelen = sizeof(o->recv.sysaddr.addr);
  227. o->recv.msg.lpBuffers = &buf;
  228. o->recv.msg.dwBufferCount = 1;
  229. o->recv.msg.Control.buf = (char *)&o->recv.cdata;
  230. o->recv.msg.Control.len = sizeof(o->recv.cdata);
  231. o->recv.msg.dwFlags = 0;
  232. // recv
  233. int res = o->fnWSARecvMsg(o->sock, &o->recv.msg, NULL, &o->recv.olap.olap, NULL);
  234. if (res == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
  235. BLog(BLOG_ERROR, "WSARecvMsg failed (%d)", WSAGetLastError());
  236. report_error(o);
  237. return;
  238. }
  239. } else {
  240. o->recv.sysaddr.len = sizeof(o->recv.sysaddr.addr);
  241. // recv
  242. DWORD flags = 0;
  243. int res = WSARecvFrom(o->sock, &buf, 1, NULL, &flags, &o->recv.sysaddr.addr.generic, &o->recv.sysaddr.len, &o->recv.olap.olap, NULL);
  244. if (res == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
  245. BLog(BLOG_ERROR, "WSARecvFrom failed (%d)", WSAGetLastError());
  246. report_error(o);
  247. return;
  248. }
  249. }
  250. // set busy
  251. o->recv.data_busy = 1;
  252. }
  253. static void send_job_handler (BDatagram *o)
  254. {
  255. DebugObject_Access(&o->d_obj);
  256. DebugError_AssertNoError(&o->d_err);
  257. ASSERT(!o->aborted)
  258. ASSERT(o->send.inited)
  259. ASSERT(o->send.data_len >= 0)
  260. ASSERT(!o->send.data_busy)
  261. ASSERT(o->send.have_addrs)
  262. // send
  263. start_send(o);
  264. return;
  265. }
  266. static void recv_job_handler (BDatagram *o)
  267. {
  268. DebugObject_Access(&o->d_obj);
  269. DebugError_AssertNoError(&o->d_err);
  270. ASSERT(!o->aborted)
  271. ASSERT(o->recv.inited)
  272. ASSERT(o->recv.data_have)
  273. ASSERT(!o->recv.data_busy)
  274. ASSERT(o->recv.started)
  275. // recv
  276. start_recv(o);
  277. return;
  278. }
  279. static void send_if_handler_send (BDatagram *o, uint8_t *data, int data_len)
  280. {
  281. DebugObject_Access(&o->d_obj);
  282. DebugError_AssertNoError(&o->d_err);
  283. ASSERT(!o->aborted)
  284. ASSERT(o->send.inited)
  285. ASSERT(o->send.data_len == -1)
  286. ASSERT(data_len >= 0)
  287. ASSERT(data_len <= o->send.mtu)
  288. // remember data
  289. o->send.data = data;
  290. o->send.data_len = data_len;
  291. o->send.data_busy = 0;
  292. // if have no addresses, wait
  293. if (!o->send.have_addrs) {
  294. return;
  295. }
  296. // send
  297. start_send(o);
  298. return;
  299. }
  300. static void recv_if_handler_recv (BDatagram *o, uint8_t *data)
  301. {
  302. DebugObject_Access(&o->d_obj);
  303. DebugError_AssertNoError(&o->d_err);
  304. ASSERT(!o->aborted)
  305. ASSERT(o->recv.inited)
  306. ASSERT(!o->recv.data_have)
  307. // remember data
  308. o->recv.data = data;
  309. o->recv.data_have = 1;
  310. o->recv.data_busy = 0;
  311. // if recv not started yet, wait
  312. if (!o->recv.started) {
  313. return;
  314. }
  315. // recv
  316. start_recv(o);
  317. return;
  318. }
  319. static void send_olap_handler (BDatagram *o, int event, DWORD bytes)
  320. {
  321. DebugObject_Access(&o->d_obj);
  322. DebugError_AssertNoError(&o->d_err);
  323. ASSERT(!o->aborted)
  324. ASSERT(o->send.inited)
  325. ASSERT(o->send.data_len >= 0)
  326. ASSERT(o->send.data_busy)
  327. ASSERT(event == BREACTOR_IOCP_EVENT_SUCCEEDED || event == BREACTOR_IOCP_EVENT_FAILED)
  328. // set not busy
  329. o->send.data_busy = 0;
  330. if (event == BREACTOR_IOCP_EVENT_FAILED) {
  331. report_error(o);
  332. return;
  333. }
  334. ASSERT(bytes >= 0)
  335. ASSERT(bytes <= o->send.data_len)
  336. if (bytes < o->send.data_len) {
  337. BLog(BLOG_ERROR, "sent too little");
  338. }
  339. // if recv wasn't started yet, start it
  340. if (!o->recv.started) {
  341. // set recv started
  342. o->recv.started = 1;
  343. // continue receiving
  344. if (o->recv.inited && o->recv.data_have) {
  345. ASSERT(!o->recv.data_busy)
  346. BPending_Set(&o->recv.job);
  347. }
  348. }
  349. // set no data
  350. o->send.data_len = -1;
  351. // done
  352. PacketPassInterface_Done(&o->send.iface);
  353. }
  354. static void recv_olap_handler (BDatagram *o, int event, DWORD bytes)
  355. {
  356. DebugObject_Access(&o->d_obj);
  357. DebugError_AssertNoError(&o->d_err);
  358. ASSERT(!o->aborted)
  359. ASSERT(o->recv.inited)
  360. ASSERT(o->recv.data_have)
  361. ASSERT(o->recv.data_busy)
  362. ASSERT(event == BREACTOR_IOCP_EVENT_SUCCEEDED || event == BREACTOR_IOCP_EVENT_FAILED)
  363. // set not busy
  364. o->recv.data_busy = 0;
  365. if (event == BREACTOR_IOCP_EVENT_FAILED) {
  366. BLog(BLOG_ERROR, "receiving failed");
  367. report_error(o);
  368. return;
  369. }
  370. ASSERT(bytes >= 0)
  371. ASSERT(bytes <= o->recv.mtu)
  372. if (o->fnWSARecvMsg) {
  373. o->recv.sysaddr.len = o->recv.msg.namelen;
  374. }
  375. // read remote address
  376. addr_sys_to_socket(&o->recv.remote_addr, o->recv.sysaddr);
  377. // read local address
  378. BIPAddr_InitInvalid(&o->recv.local_addr);
  379. if (o->fnWSARecvMsg) {
  380. for (WSACMSGHDR *cmsg = WSA_CMSG_FIRSTHDR(&o->recv.msg); cmsg; cmsg = WSA_CMSG_NXTHDR(&o->recv.msg, cmsg)) {
  381. if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
  382. struct in_pktinfo *pktinfo = (struct in_pktinfo *)WSA_CMSG_DATA(cmsg);
  383. BIPAddr_InitIPv4(&o->recv.local_addr, pktinfo->ipi_addr.s_addr);
  384. }
  385. else if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
  386. struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)WSA_CMSG_DATA(cmsg);
  387. BIPAddr_InitIPv6(&o->recv.local_addr, pktinfo->ipi6_addr.s6_addr);
  388. }
  389. }
  390. }
  391. // set have addresses
  392. o->recv.have_addrs = 1;
  393. // set no data
  394. o->recv.data_have = 0;
  395. // done
  396. PacketRecvInterface_Done(&o->recv.iface, bytes);
  397. }
  398. int BDatagram_AddressFamilySupported (int family)
  399. {
  400. return (family == BADDR_TYPE_IPV4 || family == BADDR_TYPE_IPV6);
  401. }
  402. int BDatagram_Init (BDatagram *o, int family, BReactor *reactor, void *user,
  403. BDatagram_handler handler)
  404. {
  405. ASSERT(BDatagram_AddressFamilySupported(family))
  406. ASSERT(handler)
  407. BNetwork_Assert();
  408. // init arguments
  409. o->reactor = reactor;
  410. o->user = user;
  411. o->handler = handler;
  412. // init socket
  413. if ((o->sock = WSASocket(family_socket_to_sys(family), SOCK_DGRAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) {
  414. BLog(BLOG_ERROR, "WSASocket failed");
  415. goto fail0;
  416. }
  417. DWORD out_bytes;
  418. // obtain WSASendMsg
  419. GUID guid1 = WSAID_WSASENDMSG;
  420. if (WSAIoctl(o->sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid1, sizeof(guid1), &o->fnWSASendMsg, sizeof(o->fnWSASendMsg), &out_bytes, NULL, NULL) != 0) {
  421. o->fnWSASendMsg = NULL;
  422. }
  423. // obtain WSARecvMsg
  424. GUID guid2 = WSAID_WSARECVMSG;
  425. if (WSAIoctl(o->sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid2, sizeof(guid2), &o->fnWSARecvMsg, sizeof(o->fnWSARecvMsg), &out_bytes, NULL, NULL) != 0) {
  426. BLog(BLOG_ERROR, "failed to obtain WSARecvMsg");
  427. o->fnWSARecvMsg = NULL;
  428. }
  429. // associate with IOCP
  430. if (!CreateIoCompletionPort((HANDLE)o->sock, BReactor_GetIOCPHandle(o->reactor), 0, 0)) {
  431. BLog(BLOG_ERROR, "CreateIoCompletionPort failed");
  432. goto fail1;
  433. }
  434. // enable receiving pktinfo
  435. set_pktinfo(o->sock, family);
  436. // set not aborted
  437. o->aborted = 0;
  438. // init send olap
  439. BReactorIOCPOverlapped_Init(&o->send.olap, o->reactor, o, (BReactorIOCPOverlapped_handler)send_olap_handler);
  440. // set have no send addrs
  441. o->send.have_addrs = 0;
  442. // set send not inited
  443. o->send.inited = 0;
  444. // init recv olap
  445. BReactorIOCPOverlapped_Init(&o->recv.olap, o->reactor, o, (BReactorIOCPOverlapped_handler)recv_olap_handler);
  446. // set recv not started
  447. o->recv.started = 0;
  448. // set have no recv addrs
  449. o->recv.have_addrs = 0;
  450. // set recv not inited
  451. o->recv.inited = 0;
  452. DebugError_Init(&o->d_err, BReactor_PendingGroup(o->reactor));
  453. DebugObject_Init(&o->d_obj);
  454. return 1;
  455. fail1:
  456. if (closesocket(o->sock) == SOCKET_ERROR) {
  457. BLog(BLOG_ERROR, "closesocket failed");
  458. }
  459. fail0:
  460. return 0;
  461. }
  462. void BDatagram_Free (BDatagram *o)
  463. {
  464. DebugObject_Free(&o->d_obj);
  465. DebugError_Free(&o->d_err);
  466. ASSERT(!o->recv.inited)
  467. ASSERT(!o->send.inited)
  468. if (!o->aborted) {
  469. datagram_abort(o);
  470. }
  471. }
  472. int BDatagram_Bind (BDatagram *o, BAddr addr)
  473. {
  474. DebugObject_Access(&o->d_obj);
  475. DebugError_AssertNoError(&o->d_err);
  476. ASSERT(!o->aborted)
  477. ASSERT(BDatagram_AddressFamilySupported(addr.type))
  478. // translate address
  479. struct BDatagram_sys_addr sysaddr;
  480. addr_socket_to_sys(&sysaddr, addr);
  481. // bind
  482. if (bind(o->sock, &sysaddr.addr.generic, sysaddr.len) < 0) {
  483. BLog(BLOG_ERROR, "bind failed");
  484. return 0;
  485. }
  486. // if recv wasn't started yet, start it
  487. if (!o->recv.started) {
  488. // set recv started
  489. o->recv.started = 1;
  490. // continue receiving
  491. if (o->recv.inited && o->recv.data_have) {
  492. ASSERT(!o->recv.data_busy)
  493. BPending_Set(&o->recv.job);
  494. }
  495. }
  496. return 1;
  497. }
  498. void BDatagram_SetSendAddrs (BDatagram *o, BAddr remote_addr, BIPAddr local_addr)
  499. {
  500. DebugObject_Access(&o->d_obj);
  501. DebugError_AssertNoError(&o->d_err);
  502. ASSERT(!o->aborted)
  503. ASSERT(BDatagram_AddressFamilySupported(remote_addr.type))
  504. ASSERT(local_addr.type == BADDR_TYPE_NONE || BDatagram_AddressFamilySupported(local_addr.type))
  505. // set addresses
  506. o->send.remote_addr = remote_addr;
  507. o->send.local_addr = local_addr;
  508. // set have addresses
  509. o->send.have_addrs = 1;
  510. // start sending
  511. if (o->send.inited && o->send.data_len >= 0 && !o->send.data_busy) {
  512. BPending_Set(&o->send.job);
  513. }
  514. }
  515. int BDatagram_GetLastReceiveAddrs (BDatagram *o, BAddr *remote_addr, BIPAddr *local_addr)
  516. {
  517. DebugObject_Access(&o->d_obj);
  518. if (!o->recv.have_addrs) {
  519. return 0;
  520. }
  521. *remote_addr = o->recv.remote_addr;
  522. *local_addr = o->recv.local_addr;
  523. return 1;
  524. }
  525. int BDatagram_GetLocalPort (BDatagram *o, uint16_t *local_port)
  526. {
  527. DebugObject_Access(&o->d_obj);
  528. struct BDatagram_sys_addr sysaddr;
  529. BAddr addr;
  530. socklen_t addr_size = sizeof(sysaddr.addr.generic);
  531. if (getsockname(o->sock, &sysaddr.addr.generic, &addr_size) != 0) {
  532. BLog(BLOG_ERROR, "getsockname failed");
  533. return 0;
  534. }
  535. addr_sys_to_socket(&addr, sysaddr);
  536. if (addr.type == BADDR_TYPE_IPV4) {
  537. *local_port = addr.ipv4.port;
  538. return 1;
  539. }
  540. if (addr.type == BADDR_TYPE_IPV6) {
  541. *local_port = addr.ipv6.port;
  542. return 1;
  543. }
  544. BLog(BLOG_ERROR, "Unknown address type from getsockname: %d", addr.type);
  545. return 0;
  546. }
  547. int BDatagram_SetReuseAddr (BDatagram *o, int reuse)
  548. {
  549. DebugObject_Access(&o->d_obj);
  550. ASSERT(reuse == 0 || reuse == 1)
  551. if (setsockopt(o->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) {
  552. return 0;
  553. }
  554. return 1;
  555. }
  556. void BDatagram_SendAsync_Init (BDatagram *o, int mtu)
  557. {
  558. DebugObject_Access(&o->d_obj);
  559. DebugError_AssertNoError(&o->d_err);
  560. ASSERT(!o->aborted)
  561. ASSERT(!o->send.inited)
  562. ASSERT(mtu >= 0)
  563. // init arguments
  564. o->send.mtu = mtu;
  565. // init interface
  566. PacketPassInterface_Init(&o->send.iface, o->send.mtu, (PacketPassInterface_handler_send)send_if_handler_send, o, BReactor_PendingGroup(o->reactor));
  567. // init job
  568. BPending_Init(&o->send.job, BReactor_PendingGroup(o->reactor), (BPending_handler)send_job_handler, o);
  569. // set have no data
  570. o->send.data_len = -1;
  571. // set inited
  572. o->send.inited = 1;
  573. }
  574. void BDatagram_SendAsync_Free (BDatagram *o)
  575. {
  576. DebugObject_Access(&o->d_obj);
  577. ASSERT(o->send.inited)
  578. // abort if busy
  579. if (o->send.data_len >= 0 && o->send.data_busy && !o->aborted) {
  580. datagram_abort(o);
  581. }
  582. // free job
  583. BPending_Free(&o->send.job);
  584. // free interface
  585. PacketPassInterface_Free(&o->send.iface);
  586. // set not inited
  587. o->send.inited = 0;
  588. }
  589. PacketPassInterface * BDatagram_SendAsync_GetIf (BDatagram *o)
  590. {
  591. DebugObject_Access(&o->d_obj);
  592. ASSERT(o->send.inited)
  593. return &o->send.iface;
  594. }
  595. void BDatagram_RecvAsync_Init (BDatagram *o, int mtu)
  596. {
  597. DebugObject_Access(&o->d_obj);
  598. DebugError_AssertNoError(&o->d_err);
  599. ASSERT(!o->aborted)
  600. ASSERT(!o->recv.inited)
  601. ASSERT(mtu >= 0)
  602. // init arguments
  603. o->recv.mtu = mtu;
  604. // init interface
  605. PacketRecvInterface_Init(&o->recv.iface, o->recv.mtu, (PacketRecvInterface_handler_recv)recv_if_handler_recv, o, BReactor_PendingGroup(o->reactor));
  606. // init job
  607. BPending_Init(&o->recv.job, BReactor_PendingGroup(o->reactor), (BPending_handler)recv_job_handler, o);
  608. // set have no data
  609. o->recv.data_have = 0;
  610. // set inited
  611. o->recv.inited = 1;
  612. }
  613. void BDatagram_RecvAsync_Free (BDatagram *o)
  614. {
  615. DebugObject_Access(&o->d_obj);
  616. ASSERT(o->recv.inited)
  617. // abort if busy
  618. if (o->recv.data_have && o->recv.data_busy && !o->aborted) {
  619. datagram_abort(o);
  620. }
  621. // free job
  622. BPending_Free(&o->recv.job);
  623. // free interface
  624. PacketRecvInterface_Free(&o->recv.iface);
  625. // set not inited
  626. o->recv.inited = 0;
  627. }
  628. PacketRecvInterface * BDatagram_RecvAsync_GetIf (BDatagram *o)
  629. {
  630. DebugObject_Access(&o->d_obj);
  631. ASSERT(o->recv.inited)
  632. return &o->recv.iface;
  633. }