| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756 |
- /**
- * @file BDatagram_win.c
- * @author Ambroz Bizjak <ambrop7@gmail.com>
- *
- * @section LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the author nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <stdlib.h>
- #include <base/BLog.h>
- #include "BDatagram.h"
- #include <generated/blog_channel_BDatagram.h>
- static int family_socket_to_sys (int family);
- static void addr_socket_to_sys (struct BDatagram_sys_addr *out, BAddr addr);
- static void addr_sys_to_socket (BAddr *out, struct BDatagram_sys_addr addr);
- static void set_pktinfo (SOCKET sock, int family);
- static void report_error (BDatagram *o);
- static void datagram_abort (BDatagram *o);
- static void start_send (BDatagram *o);
- static void start_recv (BDatagram *o);
- static void send_job_handler (BDatagram *o);
- static void recv_job_handler (BDatagram *o);
- static void send_if_handler_send (BDatagram *o, uint8_t *data, int data_len);
- static void recv_if_handler_recv (BDatagram *o, uint8_t *data);
- static void send_olap_handler (BDatagram *o, int event, DWORD bytes);
- static void recv_olap_handler (BDatagram *o, int event, DWORD bytes);
- static int family_socket_to_sys (int family)
- {
- switch (family) {
- case BADDR_TYPE_IPV4:
- return AF_INET;
- case BADDR_TYPE_IPV6:
- return AF_INET6;
- }
-
- ASSERT(0);
- return 0;
- }
- static void addr_socket_to_sys (struct BDatagram_sys_addr *out, BAddr addr)
- {
- switch (addr.type) {
- case BADDR_TYPE_IPV4: {
- out->len = sizeof(out->addr.ipv4);
- memset(&out->addr.ipv4, 0, sizeof(out->addr.ipv4));
- out->addr.ipv4.sin_family = AF_INET;
- out->addr.ipv4.sin_port = addr.ipv4.port;
- out->addr.ipv4.sin_addr.s_addr = addr.ipv4.ip;
- } break;
-
- case BADDR_TYPE_IPV6: {
- out->len = sizeof(out->addr.ipv6);
- memset(&out->addr.ipv6, 0, sizeof(out->addr.ipv6));
- out->addr.ipv6.sin6_family = AF_INET6;
- out->addr.ipv6.sin6_port = addr.ipv6.port;
- out->addr.ipv6.sin6_flowinfo = 0;
- memcpy(out->addr.ipv6.sin6_addr.s6_addr, addr.ipv6.ip, 16);
- out->addr.ipv6.sin6_scope_id = 0;
- } break;
-
- default: ASSERT(0);
- }
- }
- static void addr_sys_to_socket (BAddr *out, struct BDatagram_sys_addr addr)
- {
- switch (addr.addr.generic.sa_family) {
- case AF_INET: {
- ASSERT(addr.len == sizeof(struct sockaddr_in))
- BAddr_InitIPv4(out, addr.addr.ipv4.sin_addr.s_addr, addr.addr.ipv4.sin_port);
- } break;
-
- case AF_INET6: {
- ASSERT(addr.len == sizeof(struct sockaddr_in6))
- BAddr_InitIPv6(out, addr.addr.ipv6.sin6_addr.s6_addr, addr.addr.ipv6.sin6_port);
- } break;
-
- default: {
- BAddr_InitNone(out);
- } break;
- }
- }
- static void set_pktinfo (SOCKET sock, int family)
- {
- DWORD opt = 1;
-
- switch (family) {
- case BADDR_TYPE_IPV4: {
- if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, (char *)&opt, sizeof(opt)) < 0) {
- BLog(BLOG_ERROR, "setsockopt(IP_PKTINFO) failed");
- }
- } break;
-
- case BADDR_TYPE_IPV6: {
- if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, (char *)&opt, sizeof(opt)) < 0) {
- BLog(BLOG_ERROR, "setsockopt(IPV6_PKTINFO) failed");
- }
- } break;
- }
- }
- static void report_error (BDatagram *o)
- {
- DebugError_AssertNoError(&o->d_err);
-
- // report error
- DEBUGERROR(&o->d_err, o->handler(o->user, BDATAGRAM_EVENT_ERROR));
- return;
- }
- static void datagram_abort (BDatagram *o)
- {
- ASSERT(!o->aborted)
-
- // cancel I/O
- if ((o->recv.inited && o->recv.data_have && o->recv.data_busy) || (o->send.inited && o->send.data_len >= 0 && o->send.data_busy)) {
- if (!CancelIo((HANDLE)o->sock)) {
- BLog(BLOG_ERROR, "CancelIo failed");
- }
- }
-
- // close socket
- if (closesocket(o->sock) == SOCKET_ERROR) {
- BLog(BLOG_ERROR, "closesocket failed");
- }
-
- // wait for receiving to complete
- if (o->recv.inited && o->recv.data_have && o->recv.data_busy) {
- BReactorIOCPOverlapped_Wait(&o->recv.olap, NULL, NULL);
- }
-
- // wait for sending to complete
- if (o->send.inited && o->send.data_len >= 0 && o->send.data_busy) {
- BReactorIOCPOverlapped_Wait(&o->send.olap, NULL, NULL);
- }
-
- // free recv olap
- BReactorIOCPOverlapped_Free(&o->recv.olap);
-
- // free send olap
- BReactorIOCPOverlapped_Free(&o->send.olap);
-
- // set aborted
- o->aborted = 1;
- }
- static void start_send (BDatagram *o)
- {
- DebugError_AssertNoError(&o->d_err);
- ASSERT(!o->aborted)
- ASSERT(o->send.inited)
- ASSERT(o->send.data_len >= 0)
- ASSERT(!o->send.data_busy)
- ASSERT(o->send.have_addrs)
-
- // convert destination address
- addr_socket_to_sys(&o->send.sysaddr, o->send.remote_addr);
-
- WSABUF buf;
- buf.buf = o->send.data;
- buf.len = (o->send.data_len > ULONG_MAX ? ULONG_MAX : o->send.data_len);
-
- memset(&o->send.olap.olap, 0, sizeof(o->send.olap.olap));
-
- if (o->fnWSASendMsg) {
- o->send.msg.name = &o->send.sysaddr.addr.generic;
- o->send.msg.namelen = o->send.sysaddr.len;
- o->send.msg.lpBuffers = &buf;
- o->send.msg.dwBufferCount = 1;
- o->send.msg.Control.buf = (char *)&o->send.cdata;
- o->send.msg.Control.len = sizeof(o->send.cdata);
- o->send.msg.dwFlags = 0;
-
- int sum = 0;
-
- WSACMSGHDR *cmsg = WSA_CMSG_FIRSTHDR(&o->send.msg);
-
- switch (o->send.local_addr.type) {
- case BADDR_TYPE_IPV4: {
- memset(cmsg, 0, WSA_CMSG_SPACE(sizeof(struct in_pktinfo)));
- cmsg->cmsg_level = IPPROTO_IP;
- cmsg->cmsg_type = IP_PKTINFO;
- cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(struct in_pktinfo));
- struct in_pktinfo *pktinfo = (struct in_pktinfo *)WSA_CMSG_DATA(cmsg);
- pktinfo->ipi_addr.s_addr = o->send.local_addr.ipv4;
- sum += WSA_CMSG_SPACE(sizeof(struct in_pktinfo));
- } break;
- case BADDR_TYPE_IPV6: {
- memset(cmsg, 0, WSA_CMSG_SPACE(sizeof(struct in6_pktinfo)));
- cmsg->cmsg_level = IPPROTO_IPV6;
- cmsg->cmsg_type = IPV6_PKTINFO;
- cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(struct in6_pktinfo));
- struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)WSA_CMSG_DATA(cmsg);
- memcpy(pktinfo->ipi6_addr.s6_addr, o->send.local_addr.ipv6, 16);
- sum += WSA_CMSG_SPACE(sizeof(struct in6_pktinfo));
- } break;
- }
-
- o->send.msg.Control.len = sum;
-
- if (o->send.msg.Control.len == 0) {
- o->send.msg.Control.buf = NULL;
- }
-
- // send
- int res = o->fnWSASendMsg(o->sock, &o->send.msg, 0, NULL, &o->send.olap.olap, NULL);
- if (res == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
- BLog(BLOG_ERROR, "WSASendMsg failed (%d)", WSAGetLastError());
- report_error(o);
- return;
- }
- } else {
- // send
- int res = WSASendTo(o->sock, &buf, 1, NULL, 0, &o->send.sysaddr.addr.generic, o->send.sysaddr.len, &o->send.olap.olap, NULL);
- if (res == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
- BLog(BLOG_ERROR, "WSASendTo failed (%d)", WSAGetLastError());
- report_error(o);
- return;
- }
- }
-
- // set busy
- o->send.data_busy = 1;
- }
- static void start_recv (BDatagram *o)
- {
- DebugError_AssertNoError(&o->d_err);
- ASSERT(!o->aborted)
- ASSERT(o->recv.inited)
- ASSERT(o->recv.data_have)
- ASSERT(!o->recv.data_busy)
- ASSERT(o->recv.started)
-
- WSABUF buf;
- buf.buf = o->recv.data;
- buf.len = (o->recv.mtu > ULONG_MAX ? ULONG_MAX : o->recv.mtu);
-
- memset(&o->recv.olap.olap, 0, sizeof(o->recv.olap.olap));
-
- if (o->fnWSARecvMsg) {
- o->recv.msg.name = &o->recv.sysaddr.addr.generic;
- o->recv.msg.namelen = sizeof(o->recv.sysaddr.addr);
- o->recv.msg.lpBuffers = &buf;
- o->recv.msg.dwBufferCount = 1;
- o->recv.msg.Control.buf = (char *)&o->recv.cdata;
- o->recv.msg.Control.len = sizeof(o->recv.cdata);
- o->recv.msg.dwFlags = 0;
-
- // recv
- int res = o->fnWSARecvMsg(o->sock, &o->recv.msg, NULL, &o->recv.olap.olap, NULL);
- if (res == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
- BLog(BLOG_ERROR, "WSARecvMsg failed (%d)", WSAGetLastError());
- report_error(o);
- return;
- }
- } else {
- o->recv.sysaddr.len = sizeof(o->recv.sysaddr.addr);
-
- // recv
- DWORD flags = 0;
- int res = WSARecvFrom(o->sock, &buf, 1, NULL, &flags, &o->recv.sysaddr.addr.generic, &o->recv.sysaddr.len, &o->recv.olap.olap, NULL);
- if (res == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) {
- BLog(BLOG_ERROR, "WSARecvFrom failed (%d)", WSAGetLastError());
- report_error(o);
- return;
- }
- }
-
- // set busy
- o->recv.data_busy = 1;
- }
- static void send_job_handler (BDatagram *o)
- {
- DebugObject_Access(&o->d_obj);
- DebugError_AssertNoError(&o->d_err);
- ASSERT(!o->aborted)
- ASSERT(o->send.inited)
- ASSERT(o->send.data_len >= 0)
- ASSERT(!o->send.data_busy)
- ASSERT(o->send.have_addrs)
-
- // send
- start_send(o);
- return;
- }
- static void recv_job_handler (BDatagram *o)
- {
- DebugObject_Access(&o->d_obj);
- DebugError_AssertNoError(&o->d_err);
- ASSERT(!o->aborted)
- ASSERT(o->recv.inited)
- ASSERT(o->recv.data_have)
- ASSERT(!o->recv.data_busy)
- ASSERT(o->recv.started)
-
- // recv
- start_recv(o);
- return;
- }
- static void send_if_handler_send (BDatagram *o, uint8_t *data, int data_len)
- {
- DebugObject_Access(&o->d_obj);
- DebugError_AssertNoError(&o->d_err);
- ASSERT(!o->aborted)
- ASSERT(o->send.inited)
- ASSERT(o->send.data_len == -1)
- ASSERT(data_len >= 0)
- ASSERT(data_len <= o->send.mtu)
-
- // remember data
- o->send.data = data;
- o->send.data_len = data_len;
- o->send.data_busy = 0;
-
- // if have no addresses, wait
- if (!o->send.have_addrs) {
- return;
- }
-
- // send
- start_send(o);
- return;
- }
- static void recv_if_handler_recv (BDatagram *o, uint8_t *data)
- {
- DebugObject_Access(&o->d_obj);
- DebugError_AssertNoError(&o->d_err);
- ASSERT(!o->aborted)
- ASSERT(o->recv.inited)
- ASSERT(!o->recv.data_have)
-
- // remember data
- o->recv.data = data;
- o->recv.data_have = 1;
- o->recv.data_busy = 0;
-
- // if recv not started yet, wait
- if (!o->recv.started) {
- return;
- }
-
- // recv
- start_recv(o);
- return;
- }
- static void send_olap_handler (BDatagram *o, int event, DWORD bytes)
- {
- DebugObject_Access(&o->d_obj);
- DebugError_AssertNoError(&o->d_err);
- ASSERT(!o->aborted)
- ASSERT(o->send.inited)
- ASSERT(o->send.data_len >= 0)
- ASSERT(o->send.data_busy)
- ASSERT(event == BREACTOR_IOCP_EVENT_SUCCEEDED || event == BREACTOR_IOCP_EVENT_FAILED)
-
- // set not busy
- o->send.data_busy = 0;
-
- if (event == BREACTOR_IOCP_EVENT_FAILED) {
- BLog(BLOG_ERROR, "sending failed");
- report_error(o);
- return;
- }
-
- ASSERT(bytes >= 0)
- ASSERT(bytes <= o->send.data_len)
-
- if (bytes < o->send.data_len) {
- BLog(BLOG_ERROR, "sent too little");
- }
-
- // if recv wasn't started yet, start it
- if (!o->recv.started) {
- // set recv started
- o->recv.started = 1;
-
- // continue receiving
- if (o->recv.inited && o->recv.data_have) {
- ASSERT(!o->recv.data_busy)
-
- BPending_Set(&o->recv.job);
- }
- }
-
- // set no data
- o->send.data_len = -1;
-
- // done
- PacketPassInterface_Done(&o->send.iface);
- }
- static void recv_olap_handler (BDatagram *o, int event, DWORD bytes)
- {
- DebugObject_Access(&o->d_obj);
- DebugError_AssertNoError(&o->d_err);
- ASSERT(!o->aborted)
- ASSERT(o->recv.inited)
- ASSERT(o->recv.data_have)
- ASSERT(o->recv.data_busy)
- ASSERT(event == BREACTOR_IOCP_EVENT_SUCCEEDED || event == BREACTOR_IOCP_EVENT_FAILED)
-
- // set not busy
- o->recv.data_busy = 0;
-
- if (event == BREACTOR_IOCP_EVENT_FAILED) {
- BLog(BLOG_ERROR, "receiving failed");
- report_error(o);
- return;
- }
-
- ASSERT(bytes >= 0)
- ASSERT(bytes <= o->recv.mtu)
-
- if (o->fnWSARecvMsg) {
- o->recv.sysaddr.len = o->recv.msg.namelen;
- }
-
- // read remote address
- addr_sys_to_socket(&o->recv.remote_addr, o->recv.sysaddr);
-
- // read local address
- BIPAddr_InitInvalid(&o->recv.local_addr);
- if (o->fnWSARecvMsg) {
- for (WSACMSGHDR *cmsg = WSA_CMSG_FIRSTHDR(&o->recv.msg); cmsg; cmsg = WSA_CMSG_NXTHDR(&o->recv.msg, cmsg)) {
- if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
- struct in_pktinfo *pktinfo = (struct in_pktinfo *)WSA_CMSG_DATA(cmsg);
- BIPAddr_InitIPv4(&o->recv.local_addr, pktinfo->ipi_addr.s_addr);
- }
- else if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
- struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)WSA_CMSG_DATA(cmsg);
- BIPAddr_InitIPv6(&o->recv.local_addr, pktinfo->ipi6_addr.s6_addr);
- }
- }
- }
-
- // set have addresses
- o->recv.have_addrs = 1;
-
- // set no data
- o->recv.data_have = 0;
-
- // done
- PacketRecvInterface_Done(&o->recv.iface, bytes);
- }
- int BDatagram_AddressFamilySupported (int family)
- {
- return (family == BADDR_TYPE_IPV4 || family == BADDR_TYPE_IPV6);
- }
- int BDatagram_Init (BDatagram *o, int family, BReactor *reactor, void *user,
- BDatagram_handler handler)
- {
- ASSERT(BDatagram_AddressFamilySupported(family))
- ASSERT(handler)
- BNetwork_Assert();
-
- // init arguments
- o->reactor = reactor;
- o->user = user;
- o->handler = handler;
-
- // init socket
- if ((o->sock = WSASocket(family_socket_to_sys(family), SOCK_DGRAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) {
- BLog(BLOG_ERROR, "WSASocket failed");
- goto fail0;
- }
-
- GUID guid;
- DWORD out_bytes;
-
- // obtain WSASendMsg
- guid = (GUID)WSAID_WSASENDMSG;
- if (WSAIoctl(o->sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &o->fnWSASendMsg, sizeof(o->fnWSASendMsg), &out_bytes, NULL, NULL) != 0) {
- o->fnWSASendMsg = NULL;
- }
-
- // obtain WSARecvMsg
- guid = (GUID)WSAID_WSARECVMSG;
- if (WSAIoctl(o->sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &o->fnWSARecvMsg, sizeof(o->fnWSARecvMsg), &out_bytes, NULL, NULL) != 0) {
- BLog(BLOG_ERROR, "failed to obtain WSARecvMsg");
- o->fnWSARecvMsg = NULL;
- }
-
- // associate with IOCP
- if (!CreateIoCompletionPort((HANDLE)o->sock, BReactor_GetIOCPHandle(o->reactor), 0, 0)) {
- BLog(BLOG_ERROR, "CreateIoCompletionPort failed");
- goto fail1;
- }
-
- // enable receiving pktinfo
- set_pktinfo(o->sock, family);
-
- // set not aborted
- o->aborted = 0;
-
- // init send olap
- BReactorIOCPOverlapped_Init(&o->send.olap, o->reactor, o, (BReactorIOCPOverlapped_handler)send_olap_handler);
-
- // set have no send addrs
- o->send.have_addrs = 0;
-
- // set send not inited
- o->send.inited = 0;
-
- // init recv olap
- BReactorIOCPOverlapped_Init(&o->recv.olap, o->reactor, o, (BReactorIOCPOverlapped_handler)recv_olap_handler);
-
- // set recv not started
- o->recv.started = 0;
-
- // set have no recv addrs
- o->recv.have_addrs = 0;
-
- // set recv not inited
- o->recv.inited = 0;
-
- DebugError_Init(&o->d_err, BReactor_PendingGroup(o->reactor));
- DebugObject_Init(&o->d_obj);
- return 1;
-
- fail1:
- if (closesocket(o->sock) == SOCKET_ERROR) {
- BLog(BLOG_ERROR, "closesocket failed");
- }
- fail0:
- return 0;
- }
- void BDatagram_Free (BDatagram *o)
- {
- DebugObject_Free(&o->d_obj);
- DebugError_Free(&o->d_err);
- ASSERT(!o->recv.inited)
- ASSERT(!o->send.inited)
-
- if (!o->aborted) {
- datagram_abort(o);
- }
- }
- int BDatagram_Bind (BDatagram *o, BAddr addr)
- {
- DebugObject_Access(&o->d_obj);
- DebugError_AssertNoError(&o->d_err);
- ASSERT(!o->aborted)
- ASSERT(BDatagram_AddressFamilySupported(addr.type))
-
- // translate address
- struct BDatagram_sys_addr sysaddr;
- addr_socket_to_sys(&sysaddr, addr);
-
- // bind
- if (bind(o->sock, &sysaddr.addr.generic, sysaddr.len) < 0) {
- BLog(BLOG_ERROR, "bind failed");
- return 0;
- }
-
- // if recv wasn't started yet, start it
- if (!o->recv.started) {
- // set recv started
- o->recv.started = 1;
-
- // continue receiving
- if (o->recv.inited && o->recv.data_have) {
- ASSERT(!o->recv.data_busy)
-
- BPending_Set(&o->recv.job);
- }
- }
-
- return 1;
- }
- void BDatagram_SetSendAddrs (BDatagram *o, BAddr remote_addr, BIPAddr local_addr)
- {
- DebugObject_Access(&o->d_obj);
- DebugError_AssertNoError(&o->d_err);
- ASSERT(!o->aborted)
- ASSERT(BDatagram_AddressFamilySupported(remote_addr.type))
- ASSERT(local_addr.type == BADDR_TYPE_NONE || BDatagram_AddressFamilySupported(local_addr.type))
-
- // set addresses
- o->send.remote_addr = remote_addr;
- o->send.local_addr = local_addr;
-
- // set have addresses
- o->send.have_addrs = 1;
-
- // start sending
- if (o->send.inited && o->send.data_len >= 0 && !o->send.data_busy) {
- BPending_Set(&o->send.job);
- }
- }
- int BDatagram_GetLastReceiveAddrs (BDatagram *o, BAddr *remote_addr, BIPAddr *local_addr)
- {
- DebugObject_Access(&o->d_obj);
-
- if (!o->recv.have_addrs) {
- return 0;
- }
-
- *remote_addr = o->recv.remote_addr;
- *local_addr = o->recv.local_addr;
- return 1;
- }
- int BDatagram_SetReuseAddr (BDatagram *o, int reuse)
- {
- DebugObject_Access(&o->d_obj);
- ASSERT(reuse == 0 || reuse == 1)
-
- if (setsockopt(o->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) {
- return 0;
- }
-
- return 1;
- }
- void BDatagram_SendAsync_Init (BDatagram *o, int mtu)
- {
- DebugObject_Access(&o->d_obj);
- DebugError_AssertNoError(&o->d_err);
- ASSERT(!o->aborted)
- ASSERT(!o->send.inited)
- ASSERT(mtu >= 0)
-
- // init arguments
- o->send.mtu = mtu;
-
- // init interface
- PacketPassInterface_Init(&o->send.iface, o->send.mtu, (PacketPassInterface_handler_send)send_if_handler_send, o, BReactor_PendingGroup(o->reactor));
-
- // init job
- BPending_Init(&o->send.job, BReactor_PendingGroup(o->reactor), (BPending_handler)send_job_handler, o);
-
- // set have no data
- o->send.data_len = -1;
-
- // set inited
- o->send.inited = 1;
- }
- void BDatagram_SendAsync_Free (BDatagram *o)
- {
- DebugObject_Access(&o->d_obj);
- ASSERT(o->send.inited)
-
- // abort if busy
- if (o->send.data_len >= 0 && o->send.data_busy && !o->aborted) {
- datagram_abort(o);
- }
-
- // free job
- BPending_Free(&o->send.job);
-
- // free interface
- PacketPassInterface_Free(&o->send.iface);
-
- // set not inited
- o->send.inited = 0;
- }
- PacketPassInterface * BDatagram_SendAsync_GetIf (BDatagram *o)
- {
- DebugObject_Access(&o->d_obj);
- ASSERT(o->send.inited)
-
- return &o->send.iface;
- }
- void BDatagram_RecvAsync_Init (BDatagram *o, int mtu)
- {
- DebugObject_Access(&o->d_obj);
- DebugError_AssertNoError(&o->d_err);
- ASSERT(!o->aborted)
- ASSERT(!o->recv.inited)
- ASSERT(mtu >= 0)
-
- // init arguments
- o->recv.mtu = mtu;
-
- // init interface
- PacketRecvInterface_Init(&o->recv.iface, o->recv.mtu, (PacketRecvInterface_handler_recv)recv_if_handler_recv, o, BReactor_PendingGroup(o->reactor));
-
- // init job
- BPending_Init(&o->recv.job, BReactor_PendingGroup(o->reactor), (BPending_handler)recv_job_handler, o);
-
- // set have no data
- o->recv.data_have = 0;
-
- // set inited
- o->recv.inited = 1;
- }
- void BDatagram_RecvAsync_Free (BDatagram *o)
- {
- DebugObject_Access(&o->d_obj);
- ASSERT(o->recv.inited)
-
- // abort if busy
- if (o->recv.data_have && o->recv.data_busy && !o->aborted) {
- datagram_abort(o);
- }
-
- // free job
- BPending_Free(&o->recv.job);
-
- // free interface
- PacketRecvInterface_Free(&o->recv.iface);
-
- // set not inited
- o->recv.inited = 0;
- }
- PacketRecvInterface * BDatagram_RecvAsync_GetIf (BDatagram *o)
- {
- DebugObject_Access(&o->d_obj);
- ASSERT(o->recv.inited)
-
- return &o->recv.iface;
- }
|