BDatagram_unix.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. /**
  2. * @file BDatagram_unix.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. #ifndef _GNU_SOURCE
  23. #define _GNU_SOURCE
  24. #endif
  25. #include <string.h>
  26. #include <unistd.h>
  27. #include <errno.h>
  28. #include <sys/types.h>
  29. #include <sys/socket.h>
  30. #ifdef BADVPN_LINUX
  31. # include <netpacket/packet.h>
  32. # include <net/ethernet.h>
  33. #endif
  34. #include <misc/nonblocking.h>
  35. #include <base/BLog.h>
  36. #include "BDatagram.h"
  37. #include <generated/blog_channel_BDatagram.h>
  38. struct sys_addr {
  39. socklen_t len;
  40. union {
  41. struct sockaddr generic;
  42. struct sockaddr_in ipv4;
  43. struct sockaddr_in6 ipv6;
  44. #ifdef BADVPN_LINUX
  45. struct sockaddr_ll packet;
  46. #endif
  47. } addr;
  48. };
  49. static int family_socket_to_sys (int family);
  50. static void addr_socket_to_sys (struct sys_addr *out, BAddr addr);
  51. static void addr_sys_to_socket (BAddr *out, struct sys_addr addr);
  52. static void set_pktinfo (int fd, int family);
  53. static void report_error (BDatagram *o);
  54. static void do_send (BDatagram *o);
  55. static void do_recv (BDatagram *o);
  56. static void fd_handler (BDatagram *o, int events);
  57. static void send_job_handler (BDatagram *o);
  58. static void recv_job_handler (BDatagram *o);
  59. static void send_if_handler_send (BDatagram *o, uint8_t *data, int data_len);
  60. static void recv_if_handler_recv (BDatagram *o, uint8_t *data);
  61. static int family_socket_to_sys (int family)
  62. {
  63. switch (family) {
  64. case BADDR_TYPE_IPV4:
  65. return AF_INET;
  66. case BADDR_TYPE_IPV6:
  67. return AF_INET6;
  68. #ifdef BADVPN_LINUX
  69. case BADDR_TYPE_PACKET:
  70. return AF_PACKET;
  71. #endif
  72. }
  73. ASSERT(0);
  74. return 0;
  75. }
  76. static void addr_socket_to_sys (struct sys_addr *out, BAddr addr)
  77. {
  78. switch (addr.type) {
  79. case BADDR_TYPE_IPV4: {
  80. out->len = sizeof(out->addr.ipv4);
  81. memset(&out->addr.ipv4, 0, sizeof(out->addr.ipv4));
  82. out->addr.ipv4.sin_family = AF_INET;
  83. out->addr.ipv4.sin_port = addr.ipv4.port;
  84. out->addr.ipv4.sin_addr.s_addr = addr.ipv4.ip;
  85. } break;
  86. case BADDR_TYPE_IPV6: {
  87. out->len = sizeof(out->addr.ipv6);
  88. memset(&out->addr.ipv6, 0, sizeof(out->addr.ipv6));
  89. out->addr.ipv6.sin6_family = AF_INET6;
  90. out->addr.ipv6.sin6_port = addr.ipv6.port;
  91. out->addr.ipv6.sin6_flowinfo = 0;
  92. memcpy(out->addr.ipv6.sin6_addr.s6_addr, addr.ipv6.ip, 16);
  93. out->addr.ipv6.sin6_scope_id = 0;
  94. } break;
  95. #ifdef BADVPN_LINUX
  96. case BADDR_TYPE_PACKET: {
  97. ASSERT(addr.packet.header_type == BADDR_PACKET_HEADER_TYPE_ETHERNET)
  98. memset(&out->addr.packet, 0, sizeof(out->addr.packet));
  99. out->len = sizeof(out->addr.packet);
  100. out->addr.packet.sll_family = AF_PACKET;
  101. out->addr.packet.sll_protocol = addr.packet.phys_proto;
  102. out->addr.packet.sll_ifindex = addr.packet.interface_index;
  103. out->addr.packet.sll_hatype = 1; // linux/if_arp.h: #define ARPHRD_ETHER 1
  104. switch (addr.packet.packet_type) {
  105. case BADDR_PACKET_PACKET_TYPE_HOST:
  106. out->addr.packet.sll_pkttype = PACKET_HOST;
  107. break;
  108. case BADDR_PACKET_PACKET_TYPE_BROADCAST:
  109. out->addr.packet.sll_pkttype = PACKET_BROADCAST;
  110. break;
  111. case BADDR_PACKET_PACKET_TYPE_MULTICAST:
  112. out->addr.packet.sll_pkttype = PACKET_MULTICAST;
  113. break;
  114. case BADDR_PACKET_PACKET_TYPE_OTHERHOST:
  115. out->addr.packet.sll_pkttype = PACKET_OTHERHOST;
  116. break;
  117. case BADDR_PACKET_PACKET_TYPE_OUTGOING:
  118. out->addr.packet.sll_pkttype = PACKET_OUTGOING;
  119. break;
  120. default:
  121. ASSERT(0);
  122. }
  123. out->addr.packet.sll_halen = 6;
  124. memcpy(out->addr.packet.sll_addr, addr.packet.phys_addr, 6);
  125. } break;
  126. #endif
  127. default: ASSERT(0);
  128. }
  129. }
  130. static void addr_sys_to_socket (BAddr *out, struct sys_addr addr)
  131. {
  132. switch (addr.addr.generic.sa_family) {
  133. case AF_INET: {
  134. ASSERT(addr.len == sizeof(struct sockaddr_in))
  135. BAddr_InitIPv4(out, addr.addr.ipv4.sin_addr.s_addr, addr.addr.ipv4.sin_port);
  136. } break;
  137. case AF_INET6: {
  138. ASSERT(addr.len == sizeof(struct sockaddr_in6))
  139. BAddr_InitIPv6(out, addr.addr.ipv6.sin6_addr.s6_addr, addr.addr.ipv6.sin6_port);
  140. } break;
  141. default: {
  142. BAddr_InitNone(out);
  143. } break;
  144. }
  145. }
  146. static void set_pktinfo (int fd, int family)
  147. {
  148. int opt = 1;
  149. switch (family) {
  150. case BADDR_TYPE_IPV4: {
  151. #ifdef BADVPN_FREEBSD
  152. if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) < 0) {
  153. BLog(BLOG_ERROR, "setsockopt(IP_RECVDSTADDR) failed");
  154. }
  155. #else
  156. if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) < 0) {
  157. BLog(BLOG_ERROR, "setsockopt(IP_PKTINFO) failed");
  158. }
  159. #endif
  160. } break;
  161. #ifdef IPV6_RECVPKTINFO
  162. case BADDR_TYPE_IPV6: {
  163. if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt)) < 0) {
  164. BLog(BLOG_ERROR, "setsockopt(IPV6_RECVPKTINFO) failed");
  165. }
  166. } break;
  167. #endif
  168. }
  169. }
  170. static void report_error (BDatagram *o)
  171. {
  172. DebugError_AssertNoError(&o->d_err);
  173. // report error
  174. DEBUGERROR(&o->d_err, o->handler(o->user, BDATAGRAM_EVENT_ERROR));
  175. return;
  176. }
  177. static void do_send (BDatagram *o)
  178. {
  179. DebugError_AssertNoError(&o->d_err);
  180. ASSERT(o->send.inited)
  181. ASSERT(o->send.busy)
  182. ASSERT(o->send.have_addrs)
  183. // limit
  184. if (!BReactorLimit_Increment(&o->send.limit)) {
  185. // wait for fd
  186. o->wait_events |= BREACTOR_WRITE;
  187. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  188. return;
  189. }
  190. // convert destination address
  191. struct sys_addr sysaddr;
  192. addr_socket_to_sys(&sysaddr, o->send.remote_addr);
  193. struct iovec iov;
  194. iov.iov_base = (uint8_t *)o->send.busy_data;
  195. iov.iov_len = o->send.busy_data_len;
  196. union {
  197. #ifdef BADVPN_FREEBSD
  198. char in[CMSG_SPACE(sizeof(struct in_addr))];
  199. #else
  200. char in[CMSG_SPACE(sizeof(struct in_pktinfo))];
  201. #endif
  202. char in6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
  203. } cdata;
  204. struct msghdr msg;
  205. memset(&msg, 0, sizeof(msg));
  206. msg.msg_name = &sysaddr.addr.generic;
  207. msg.msg_namelen = sysaddr.len;
  208. msg.msg_iov = &iov;
  209. msg.msg_iovlen = 1;
  210. msg.msg_control = &cdata;
  211. msg.msg_controllen = sizeof(cdata);
  212. struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
  213. size_t controllen = 0;
  214. switch (o->send.local_addr.type) {
  215. case BADDR_TYPE_IPV4: {
  216. #ifdef BADVPN_FREEBSD
  217. memset(cmsg, 0, CMSG_SPACE(sizeof(struct in_addr)));
  218. cmsg->cmsg_level = IPPROTO_IP;
  219. cmsg->cmsg_type = IP_SENDSRCADDR;
  220. cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
  221. struct in_addr *addrinfo = (struct in_addr *)CMSG_DATA(cmsg);
  222. addrinfo->s_addr = o->send.local_addr.ipv4;
  223. controllen += CMSG_SPACE(sizeof(struct in_addr));
  224. #else
  225. memset(cmsg, 0, CMSG_SPACE(sizeof(struct in_pktinfo)));
  226. cmsg->cmsg_level = IPPROTO_IP;
  227. cmsg->cmsg_type = IP_PKTINFO;
  228. cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
  229. struct in_pktinfo *pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
  230. pktinfo->ipi_spec_dst.s_addr = o->send.local_addr.ipv4;
  231. controllen += CMSG_SPACE(sizeof(struct in_pktinfo));
  232. #endif
  233. } break;
  234. case BADDR_TYPE_IPV6: {
  235. memset(cmsg, 0, CMSG_SPACE(sizeof(struct in6_pktinfo)));
  236. cmsg->cmsg_level = IPPROTO_IPV6;
  237. cmsg->cmsg_type = IPV6_PKTINFO;
  238. cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
  239. struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
  240. memcpy(pktinfo->ipi6_addr.s6_addr, o->send.local_addr.ipv6, 16);
  241. controllen += CMSG_SPACE(sizeof(struct in6_pktinfo));
  242. } break;
  243. }
  244. msg.msg_controllen = controllen;
  245. if (msg.msg_controllen == 0) {
  246. msg.msg_control = NULL;
  247. }
  248. // send
  249. int bytes = sendmsg(o->fd, &msg, 0);
  250. if (bytes < 0) {
  251. if (errno == EAGAIN || errno == EWOULDBLOCK) {
  252. // wait for fd
  253. o->wait_events |= BREACTOR_WRITE;
  254. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  255. return;
  256. }
  257. BLog(BLOG_ERROR, "send failed");
  258. report_error(o);
  259. return;
  260. }
  261. ASSERT(bytes >= 0)
  262. ASSERT(bytes <= o->send.busy_data_len)
  263. if (bytes < o->send.busy_data_len) {
  264. BLog(BLOG_ERROR, "send sent too little");
  265. }
  266. // if recv wasn't started yet, start it
  267. if (!o->recv.started) {
  268. // set recv started
  269. o->recv.started = 1;
  270. // continue receiving
  271. if (o->recv.inited && o->recv.busy) {
  272. BPending_Set(&o->recv.job);
  273. }
  274. }
  275. // set not busy
  276. o->send.busy = 0;
  277. // done
  278. PacketPassInterface_Done(&o->send.iface);
  279. }
  280. static void do_recv (BDatagram *o)
  281. {
  282. DebugError_AssertNoError(&o->d_err);
  283. ASSERT(o->recv.inited)
  284. ASSERT(o->recv.busy)
  285. ASSERT(o->recv.started)
  286. // limit
  287. if (!BReactorLimit_Increment(&o->recv.limit)) {
  288. // wait for fd
  289. o->wait_events |= BREACTOR_READ;
  290. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  291. return;
  292. }
  293. struct sys_addr sysaddr;
  294. struct iovec iov;
  295. iov.iov_base = o->recv.busy_data;
  296. iov.iov_len = o->recv.mtu;
  297. union {
  298. #ifdef BADVPN_FREEBSD
  299. char in[CMSG_SPACE(sizeof(struct in_addr))];
  300. #else
  301. char in[CMSG_SPACE(sizeof(struct in_pktinfo))];
  302. #endif
  303. char in6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
  304. } cdata;
  305. struct msghdr msg;
  306. memset(&msg, 0, sizeof(msg));
  307. msg.msg_name = &sysaddr.addr.generic;
  308. msg.msg_namelen = sizeof(sysaddr.addr);
  309. msg.msg_iov = &iov;
  310. msg.msg_iovlen = 1;
  311. msg.msg_control = &cdata;
  312. msg.msg_controllen = sizeof(cdata);
  313. // recv
  314. int bytes = recvmsg(o->fd, &msg, 0);
  315. if (bytes < 0) {
  316. if (errno == EAGAIN || errno == EWOULDBLOCK) {
  317. // wait for fd
  318. o->wait_events |= BREACTOR_READ;
  319. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  320. return;
  321. }
  322. BLog(BLOG_ERROR, "recv failed");
  323. report_error(o);
  324. return;
  325. }
  326. ASSERT(bytes >= 0)
  327. ASSERT(bytes <= o->recv.mtu)
  328. // read returned address
  329. sysaddr.len = msg.msg_namelen;
  330. addr_sys_to_socket(&o->recv.remote_addr, sysaddr);
  331. // read returned local address
  332. BIPAddr_InitInvalid(&o->recv.local_addr);
  333. for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
  334. #ifdef BADVPN_FREEBSD
  335. if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
  336. struct in_addr *addrinfo = (struct in_addr *)CMSG_DATA(cmsg);
  337. BIPAddr_InitIPv4(&o->recv.local_addr, addrinfo->s_addr);
  338. }
  339. #else
  340. if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
  341. struct in_pktinfo *pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
  342. BIPAddr_InitIPv4(&o->recv.local_addr, pktinfo->ipi_addr.s_addr);
  343. }
  344. #endif
  345. else if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
  346. struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
  347. BIPAddr_InitIPv6(&o->recv.local_addr, pktinfo->ipi6_addr.s6_addr);
  348. }
  349. }
  350. // set have addresses
  351. o->recv.have_addrs = 1;
  352. // set not busy
  353. o->recv.busy = 0;
  354. // done
  355. PacketRecvInterface_Done(&o->recv.iface, bytes);
  356. }
  357. static void fd_handler (BDatagram *o, int events)
  358. {
  359. DebugObject_Access(&o->d_obj);
  360. DebugError_AssertNoError(&o->d_err);
  361. // clear handled events
  362. o->wait_events &= ~events;
  363. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  364. int have_send = 0;
  365. int have_recv = 0;
  366. if ((events & BREACTOR_WRITE) || ((events & BREACTOR_ERROR) && o->send.inited && o->send.busy && o->send.have_addrs)) {
  367. ASSERT(o->send.inited)
  368. ASSERT(o->send.busy)
  369. ASSERT(o->send.have_addrs)
  370. have_send = 1;
  371. }
  372. if ((events & BREACTOR_READ) || ((events & BREACTOR_ERROR) && o->recv.inited && o->recv.busy && o->recv.started)) {
  373. ASSERT(o->recv.inited)
  374. ASSERT(o->recv.busy)
  375. ASSERT(o->recv.started)
  376. have_recv = 1;
  377. }
  378. if (have_send) {
  379. if (have_recv) {
  380. BPending_Set(&o->recv.job);
  381. }
  382. do_send(o);
  383. return;
  384. }
  385. if (have_recv) {
  386. do_recv(o);
  387. return;
  388. }
  389. BLog(BLOG_ERROR, "fd error event");
  390. report_error(o);
  391. return;
  392. }
  393. static void send_job_handler (BDatagram *o)
  394. {
  395. DebugObject_Access(&o->d_obj);
  396. DebugError_AssertNoError(&o->d_err);
  397. ASSERT(o->send.inited)
  398. ASSERT(o->send.busy)
  399. ASSERT(o->send.have_addrs)
  400. do_send(o);
  401. return;
  402. }
  403. static void recv_job_handler (BDatagram *o)
  404. {
  405. DebugObject_Access(&o->d_obj);
  406. DebugError_AssertNoError(&o->d_err);
  407. ASSERT(o->recv.inited)
  408. ASSERT(o->recv.busy)
  409. ASSERT(o->recv.started)
  410. do_recv(o);
  411. return;
  412. }
  413. static void send_if_handler_send (BDatagram *o, uint8_t *data, int data_len)
  414. {
  415. DebugObject_Access(&o->d_obj);
  416. DebugError_AssertNoError(&o->d_err);
  417. ASSERT(o->send.inited)
  418. ASSERT(!o->send.busy)
  419. ASSERT(data_len >= 0)
  420. ASSERT(data_len <= o->send.mtu)
  421. // remember data
  422. o->send.busy_data = data;
  423. o->send.busy_data_len = data_len;
  424. // set busy
  425. o->send.busy = 1;
  426. // if have no addresses, wait
  427. if (!o->send.have_addrs) {
  428. return;
  429. }
  430. // set job
  431. BPending_Set(&o->send.job);
  432. }
  433. static void recv_if_handler_recv (BDatagram *o, uint8_t *data)
  434. {
  435. DebugObject_Access(&o->d_obj);
  436. DebugError_AssertNoError(&o->d_err);
  437. ASSERT(o->recv.inited)
  438. ASSERT(!o->recv.busy)
  439. // remember data
  440. o->recv.busy_data = data;
  441. // set busy
  442. o->recv.busy = 1;
  443. // if recv not started yet, wait
  444. if (!o->recv.started) {
  445. return;
  446. }
  447. // set job
  448. BPending_Set(&o->recv.job);
  449. }
  450. int BDatagram_AddressFamilySupported (int family)
  451. {
  452. switch (family) {
  453. case BADDR_TYPE_IPV4:
  454. case BADDR_TYPE_IPV6:
  455. #ifdef BADVPN_LINUX
  456. case BADDR_TYPE_PACKET:
  457. #endif
  458. return 1;
  459. }
  460. return 0;
  461. }
  462. int BDatagram_Init (BDatagram *o, int family, BReactor *reactor, void *user,
  463. BDatagram_handler handler)
  464. {
  465. ASSERT(BDatagram_AddressFamilySupported(family))
  466. ASSERT(handler)
  467. BNetwork_Assert();
  468. // init arguments
  469. o->reactor = reactor;
  470. o->user = user;
  471. o->handler = handler;
  472. // init fd
  473. if ((o->fd = socket(family_socket_to_sys(family), SOCK_DGRAM, 0)) < 0) {
  474. BLog(BLOG_ERROR, "socket failed");
  475. goto fail0;
  476. }
  477. // set fd non-blocking
  478. if (!badvpn_set_nonblocking(o->fd)) {
  479. BLog(BLOG_ERROR, "badvpn_set_nonblocking failed");
  480. goto fail1;
  481. }
  482. // enable receiving pktinfo
  483. set_pktinfo(o->fd, family);
  484. // init BFileDescriptor
  485. BFileDescriptor_Init(&o->bfd, o->fd, (BFileDescriptor_handler)fd_handler, o);
  486. if (!BReactor_AddFileDescriptor(o->reactor, &o->bfd)) {
  487. BLog(BLOG_ERROR, "BReactor_AddFileDescriptor failed");
  488. goto fail1;
  489. }
  490. // set no wait events
  491. o->wait_events = 0;
  492. // init limits
  493. BReactorLimit_Init(&o->send.limit, o->reactor, BDATAGRAM_SEND_LIMIT);
  494. BReactorLimit_Init(&o->recv.limit, o->reactor, BDATAGRAM_RECV_LIMIT);
  495. // set have no send and recv addresses
  496. o->send.have_addrs = 0;
  497. o->recv.have_addrs = 0;
  498. // set recv not started
  499. o->recv.started = 0;
  500. // set send and recv not inited
  501. o->send.inited = 0;
  502. o->recv.inited = 0;
  503. DebugError_Init(&o->d_err, BReactor_PendingGroup(o->reactor));
  504. DebugObject_Init(&o->d_obj);
  505. return 1;
  506. fail1:
  507. if (close(o->fd) < 0) {
  508. BLog(BLOG_ERROR, "close failed");
  509. }
  510. fail0:
  511. return 0;
  512. }
  513. void BDatagram_Free (BDatagram *o)
  514. {
  515. DebugObject_Free(&o->d_obj);
  516. DebugError_Free(&o->d_err);
  517. ASSERT(!o->recv.inited)
  518. ASSERT(!o->send.inited)
  519. // free limits
  520. BReactorLimit_Free(&o->recv.limit);
  521. BReactorLimit_Free(&o->send.limit);
  522. // free BFileDescriptor
  523. BReactor_RemoveFileDescriptor(o->reactor, &o->bfd);
  524. // free fd
  525. if (close(o->fd) < 0) {
  526. BLog(BLOG_ERROR, "close failed");
  527. }
  528. }
  529. int BDatagram_Bind (BDatagram *o, BAddr addr)
  530. {
  531. DebugObject_Access(&o->d_obj);
  532. DebugError_AssertNoError(&o->d_err);
  533. ASSERT(BDatagram_AddressFamilySupported(addr.type))
  534. // translate address
  535. struct sys_addr sysaddr;
  536. addr_socket_to_sys(&sysaddr, addr);
  537. // bind
  538. if (bind(o->fd, &sysaddr.addr.generic, sysaddr.len) < 0) {
  539. BLog(BLOG_ERROR, "bind failed");
  540. return 0;
  541. }
  542. // if recv wasn't started yet, start it
  543. if (!o->recv.started) {
  544. // set recv started
  545. o->recv.started = 1;
  546. // continue receiving
  547. if (o->recv.inited && o->recv.busy) {
  548. BPending_Set(&o->recv.job);
  549. }
  550. }
  551. return 1;
  552. }
  553. void BDatagram_SetSendAddrs (BDatagram *o, BAddr remote_addr, BIPAddr local_addr)
  554. {
  555. DebugObject_Access(&o->d_obj);
  556. DebugError_AssertNoError(&o->d_err);
  557. ASSERT(BDatagram_AddressFamilySupported(remote_addr.type))
  558. ASSERT(local_addr.type == BADDR_TYPE_NONE || BDatagram_AddressFamilySupported(local_addr.type))
  559. // set addresses
  560. o->send.remote_addr = remote_addr;
  561. o->send.local_addr = local_addr;
  562. if (!o->send.have_addrs) {
  563. // set have addresses
  564. o->send.have_addrs = 1;
  565. // start sending
  566. if (o->send.inited && o->send.busy) {
  567. BPending_Set(&o->send.job);
  568. }
  569. }
  570. }
  571. int BDatagram_GetLastReceiveAddrs (BDatagram *o, BAddr *remote_addr, BIPAddr *local_addr)
  572. {
  573. DebugObject_Access(&o->d_obj);
  574. if (!o->recv.have_addrs) {
  575. return 0;
  576. }
  577. *remote_addr = o->recv.remote_addr;
  578. *local_addr = o->recv.local_addr;
  579. return 1;
  580. }
  581. int BDatagram_GetFd (BDatagram *o)
  582. {
  583. DebugObject_Access(&o->d_obj);
  584. return o->fd;
  585. }
  586. void BDatagram_SendAsync_Init (BDatagram *o, int mtu)
  587. {
  588. DebugObject_Access(&o->d_obj);
  589. DebugError_AssertNoError(&o->d_err);
  590. ASSERT(!o->send.inited)
  591. ASSERT(mtu >= 0)
  592. // init arguments
  593. o->send.mtu = mtu;
  594. // init interface
  595. PacketPassInterface_Init(&o->send.iface, o->send.mtu, (PacketPassInterface_handler_send)send_if_handler_send, o, BReactor_PendingGroup(o->reactor));
  596. // init job
  597. BPending_Init(&o->send.job, BReactor_PendingGroup(o->reactor), (BPending_handler)send_job_handler, o);
  598. // set not busy
  599. o->send.busy = 0;
  600. // set inited
  601. o->send.inited = 1;
  602. }
  603. void BDatagram_SendAsync_Free (BDatagram *o)
  604. {
  605. DebugObject_Access(&o->d_obj);
  606. ASSERT(o->send.inited)
  607. // update events
  608. o->wait_events &= ~BREACTOR_WRITE;
  609. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  610. // free job
  611. BPending_Free(&o->send.job);
  612. // free interface
  613. PacketPassInterface_Free(&o->send.iface);
  614. // set not inited
  615. o->send.inited = 0;
  616. }
  617. PacketPassInterface * BDatagram_SendAsync_GetIf (BDatagram *o)
  618. {
  619. DebugObject_Access(&o->d_obj);
  620. ASSERT(o->send.inited)
  621. return &o->send.iface;
  622. }
  623. void BDatagram_RecvAsync_Init (BDatagram *o, int mtu)
  624. {
  625. DebugObject_Access(&o->d_obj);
  626. DebugError_AssertNoError(&o->d_err);
  627. ASSERT(!o->recv.inited)
  628. ASSERT(mtu >= 0)
  629. // init arguments
  630. o->recv.mtu = mtu;
  631. // init interface
  632. PacketRecvInterface_Init(&o->recv.iface, o->recv.mtu, (PacketRecvInterface_handler_recv)recv_if_handler_recv, o, BReactor_PendingGroup(o->reactor));
  633. // init job
  634. BPending_Init(&o->recv.job, BReactor_PendingGroup(o->reactor), (BPending_handler)recv_job_handler, o);
  635. // set not busy
  636. o->recv.busy = 0;
  637. // set inited
  638. o->recv.inited = 1;
  639. }
  640. void BDatagram_RecvAsync_Free (BDatagram *o)
  641. {
  642. DebugObject_Access(&o->d_obj);
  643. ASSERT(o->recv.inited)
  644. // update events
  645. o->wait_events &= ~BREACTOR_READ;
  646. BReactor_SetFileDescriptorEvents(o->reactor, &o->bfd, o->wait_events);
  647. // free job
  648. BPending_Free(&o->recv.job);
  649. // free interface
  650. PacketRecvInterface_Free(&o->recv.iface);
  651. // set not inited
  652. o->recv.inited = 0;
  653. }
  654. PacketRecvInterface * BDatagram_RecvAsync_GetIf (BDatagram *o)
  655. {
  656. DebugObject_Access(&o->d_obj);
  657. ASSERT(o->recv.inited)
  658. return &o->recv.iface;
  659. }