BDatagram_win.c 21 KB

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