From 71ffd4ce1775c1bac244a49dce578b1baa9a2226 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Tue, 25 Feb 2020 07:09:20 +0000 Subject: [PATCH] changed mio_dev_sck_connect() to not fire on_connect() callback inside itself upon immediate successful connect. fixed some issues in dns related code --- mio/bin/t01.c | 10 +- mio/bin/t02.c | 259 +++++++++++++++++++++++++++++++++++++++++++++ mio/lib/dns-cli.c | 91 +++++++++------- mio/lib/dns.c | 78 +++++++------- mio/lib/mio-skad.h | 12 +-- mio/lib/sck.c | 81 +++----------- mio/lib/skad.c | 30 +++--- 7 files changed, 395 insertions(+), 166 deletions(-) create mode 100644 mio/bin/t02.c diff --git a/mio/bin/t01.c b/mio/bin/t01.c index 369edf6..7785dc4 100644 --- a/mio/bin/t01.c +++ b/mio/bin/t01.c @@ -952,7 +952,6 @@ for (i = 0; i < 5; i++) reply_tmout.sec = 1; reply_tmout.nsec = 0; - mio_bcstrtoskad (mio, "8.8.8.8:53", &servaddr); //mio_bcstrtoskad (mio, "[fe80::c7e2:bd6e:1209:ac1b]:1153", &servaddr); //mio_bcstrtoskad (mio, "[fe80::c7e2:bd6e:1209:ac1b%eno1]:1153", &servaddr); @@ -968,10 +967,14 @@ for (i = 0; i < 5; i++) { "code6.abiyo.net", MIO_DNS_RRT_AAAA, MIO_DNS_RRC_IN }, { "abiyo.net", MIO_DNS_RRT_MX, MIO_DNS_RRC_IN } }; + + mio_ip4ad_t rrdata_a = { { 4, 3, 2, 1 } }; + mio_ip6ad_t rrdata_aaaa = { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, }}; + mio_dns_brr_t rrs[] = { - { MIO_DNS_RR_PART_ANSWER, "code.miflux.com", MIO_DNS_RRT_A, MIO_DNS_RRC_IN, 86400, 0, MIO_NULL }, - { MIO_DNS_RR_PART_ANSWER, "code.miflux.com", MIO_DNS_RRT_AAAA, MIO_DNS_RRC_IN, 86400, 0, MIO_NULL }, + { MIO_DNS_RR_PART_ANSWER, "code.miflux.com", MIO_DNS_RRT_A, MIO_DNS_RRC_IN, 86400, MIO_SIZEOF(rrdata_a), &rrdata_a }, + { MIO_DNS_RR_PART_ANSWER, "code.miflux.com", MIO_DNS_RRT_AAAA, MIO_DNS_RRC_IN, 86400, MIO_SIZEOF(rrdata_aaaa), &rrdata_aaaa }, { MIO_DNS_RR_PART_ANSWER, "miflux.com", MIO_DNS_RRT_NS, MIO_DNS_RRC_IN, 86400, 0, "ns1.miflux.com" }, { MIO_DNS_RR_PART_ANSWER, "miflux.com", MIO_DNS_RRT_NS, MIO_DNS_RRC_IN, 86400, 0, "ns2.miflux.com" }, //, //{ MIO_DNS_RR_PART_AUTHORITY, "miflux.com", MIO_DNS_RRT_SOA, MIO_DNS_RRC_IN, 86400, 0, "ns2.miflux.com" }, //, @@ -1029,6 +1032,7 @@ for (i = 0; i < 5; i++) } #endif + if (!mio_svc_dnc_resolve(dnc, "a.wild.com", MIO_DNS_RRT_A, 0, on_dnc_resolve, 0)) { printf ("resolve attempt failure ---> a.wild.com\n"); diff --git a/mio/bin/t02.c b/mio/bin/t02.c new file mode 100644 index 0000000..ed29507 --- /dev/null +++ b/mio/bin/t02.c @@ -0,0 +1,259 @@ + + +#include +#include +#include +#include +#include +#include + +struct mmgr_stat_t +{ + mio_oow_t total_count; +}; + +typedef struct mmgr_stat_t mmgr_stat_t; + +static mmgr_stat_t mmgr_stat; + +static void* mmgr_alloc (mio_mmgr_t* mmgr, mio_oow_t size) +{ + void* x; + + if (((mmgr_stat_t*)mmgr->ctx)->total_count > 3000) + { +printf ("CRITICAL ERROR ---> too many heap chunks...\n"); + return MIO_NULL; + } + + x = malloc (size); + if (x) ((mmgr_stat_t*)mmgr->ctx)->total_count++; + return x; +} + +static void* mmgr_realloc (mio_mmgr_t* mmgr, void* ptr, mio_oow_t size) +{ + return realloc (ptr, size); +} + +static void mmgr_free (mio_mmgr_t* mmgr, void* ptr) +{ + ((mmgr_stat_t*)mmgr->ctx)->total_count--; + return free (ptr); +} + + +static mio_mmgr_t mmgr = +{ + mmgr_alloc, + mmgr_realloc, + mmgr_free, + &mmgr_stat +}; + + +struct tcp_xtn_t +{ + int tally; +}; +typedef struct tcp_xtn_t tcp_xtn_t; + + +static void tcp_sck_on_disconnect (mio_dev_sck_t* tcp) +{ + switch (MIO_DEV_SCK_GET_PROGRESS(tcp)) + { + case MIO_DEV_SCK_CONNECTING: + MIO_INFO1 (tcp->mio, "OUTGOING SESSION DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck); + break; + + case MIO_DEV_SCK_CONNECTING_SSL: + MIO_INFO1 (tcp->mio, "OUTGOING SESSION DISCONNECTED - FAILED TO SSL-CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck); + break; + + case MIO_DEV_SCK_LISTENING: + MIO_INFO1 (tcp->mio, "SHUTTING DOWN THE SERVER SOCKET(%d)...\n", (int)tcp->sck); + break; + + case MIO_DEV_SCK_CONNECTED: + MIO_INFO1 (tcp->mio, "OUTGOING CLIENT CONNECTION GOT TORN DOWN(%d).......\n", (int)tcp->sck); + break; + + case MIO_DEV_SCK_ACCEPTING_SSL: + MIO_INFO1 (tcp->mio, "INCOMING SSL-ACCEPT GOT DISCONNECTED(%d) ....\n", (int)tcp->sck); + break; + + case MIO_DEV_SCK_ACCEPTED: + MIO_INFO1 (tcp->mio, "INCOMING CLIENT BEING SERVED GOT DISCONNECTED(%d).......\n", (int)tcp->sck); + break; + + default: + MIO_INFO2 (tcp->mio, "SOCKET DEVICE DISCONNECTED (%d - %x)\n", (int)tcp->sck, (unsigned int)tcp->state); + break; + } +} + +static void tcp_sck_on_connect (mio_dev_sck_t* tcp) +{ + mio_bch_t buf1[128], buf2[128]; + + mio_skadtobcstr (tcp->mio, &tcp->localaddr, buf1, MIO_COUNTOF(buf1), MIO_SKAD_TO_BCSTR_ADDR | MIO_SKAD_TO_BCSTR_PORT); + mio_skadtobcstr (tcp->mio, &tcp->remoteaddr, buf2, MIO_COUNTOF(buf2), MIO_SKAD_TO_BCSTR_ADDR | MIO_SKAD_TO_BCSTR_PORT); + + if (tcp->state & MIO_DEV_SCK_CONNECTED) + { + MIO_INFO3 (tcp->mio, "DEVICE connected to a remote server... LOCAL %hs REMOTE %hs SCK: %d\n", buf1, buf2, tcp->sck); + } + else if (tcp->state & MIO_DEV_SCK_ACCEPTED) + { + MIO_INFO3 (tcp->mio, "DEVICE accepted client device... .LOCAL %hs REMOTE %hs SCK: %d\n", buf1, buf2, tcp->sck); + } + + if (mio_dev_sck_write(tcp, "hello", 5, MIO_NULL, MIO_NULL) <= -1) + { + mio_dev_sck_halt (tcp); + } +} + +static int tcp_sck_on_write (mio_dev_sck_t* tcp, mio_iolen_t wrlen, void* wrctx, const mio_skad_t* dstaddr) +{ + tcp_xtn_t* ts; + mio_ntime_t tmout; + + if (wrlen <= -1) + { + MIO_INFO1 (tcp->mio, "TCP_SCK_ON_WRITE(%d) >>> SEDING TIMED OUT...........\n", (int)tcp->sck); + mio_dev_sck_halt (tcp); + } + else + { + ts = (tcp_xtn_t*)(tcp + 1); + if (wrlen == 0) + { + MIO_INFO1 (tcp->mio, "TCP_SCK_ON_WRITE(%d) >>> CLOSED WRITING END\n", (int)tcp->sck); + } + else + { + MIO_INFO3 (tcp->mio, "TCP_SCK_ON_WRITE(%d) >>> SENT MESSAGE %d of length %ld\n", (int)tcp->sck, ts->tally, (long int)wrlen); + } + + ts->tally++; + // if (ts->tally >= 2) mio_dev_sck_halt (tcp); + + + MIO_INIT_NTIME (&tmout, 5, 0); + //mio_dev_sck_read (tcp, 1); + + MIO_INFO3 (tcp->mio, "TCP_SCK_ON_WRITE(%d) >>> REQUESTING to READ with timeout of %ld.%08ld\n", (int)tcp->sck, (long int)tmout.sec, (long int)tmout.nsec); + mio_dev_sck_timedread (tcp, 1, &tmout); + } + return 0; +} + +static int tcp_sck_on_read (mio_dev_sck_t* tcp, const void* buf, mio_iolen_t len, const mio_skad_t* srcaddr) +{ + int n; + + if (len <= -1) + { + MIO_INFO1 (tcp->mio, "TCP_SCK_ON_READ(%d) STREAM DEVICE: TIMED OUT...\n", (int)tcp->sck); + mio_dev_sck_halt (tcp); + return 0; + } + else if (len <= 0) + { + MIO_INFO1 (tcp->mio, "TCP_SCK_ON_READ(%d) STREAM DEVICE: EOF RECEIVED...\n", (int)tcp->sck); + /* no outstanding request. but EOF */ + mio_dev_sck_halt (tcp); + return 0; + } + + MIO_INFO2 (tcp->mio, "TCP_SCK_ON_READ(%d) - received %d bytes\n", (int)tcp->sck, (int)len); + + { + mio_ntime_t tmout; + + static char a ='A'; + static char xxx[1000000]; + memset (xxx, a++ , MIO_SIZEOF(xxx)); + + MIO_INFO2 (tcp->mio, "TCP_SCK_ON_READ(%d) >>> REQUESTING to write data of %d bytes\n", (int)tcp->sck, MIO_SIZEOF(xxx)); + //return mio_dev_sck_write (tcp, "HELLO", 5, MIO_NULL); + MIO_INIT_NTIME (&tmout, 5, 0); + n = mio_dev_sck_timedwrite(tcp, xxx, MIO_SIZEOF(xxx), &tmout, MIO_NULL, MIO_NULL); + + if (n <= -1) return -1; + } + + MIO_INFO1 (tcp->mio, "TCP_SCK_ON_READ(%d) - REQUESTING TO STOP READ\n", (int)tcp->sck); + mio_dev_sck_read (tcp, 0); + +#if 0 + MIO_INFO1 (tcp->mio, "TCP_SCK_ON_READ(%d) - REQUESTING TO CLOSE WRITING END\n", (int)tcp->sck); + /* post the write finisher - close the writing end */ + n = mio_dev_sck_write(tcp, MIO_NULL, 0, MIO_NULL, MIO_NULL); + if (n <= -1) return -1; +#endif + + return 0; + +/* return 1; let the main loop to read more greedily without consulting the multiplexer */ +} + + +int main (int argc, char* argv[]) +{ + + mio_t* mio = MIO_NULL; + mio_dev_sck_t* tcpsvr; + mio_dev_sck_make_t tcp_make; + mio_dev_sck_connect_t tcp_conn; + tcp_xtn_t* ts; + + if (argc != 2) + { + fprintf (stderr, "Usage: %s ipaddr:port\n", argv[0]); + return -1; + } + mio = mio_open(&mmgr, 0, MIO_NULL, 512, MIO_NULL); + if (!mio) + { + printf ("Cannot open mio\n"); + goto oops; + } + + memset (&tcp_conn, 0, MIO_SIZEOF(tcp_conn)); + mio_bcstrtoskad(mio, argv[1], &tcp_conn.remoteaddr); + MIO_INIT_NTIME (&tcp_conn.connect_tmout, 5, 0); + tcp_conn.options = 0; + + memset (&tcp_make, 0, MIO_SIZEOF(tcp_make)); + tcp_make.type = mio_skad_family(&tcp_conn.remoteaddr) == MIO_AF_INET? MIO_DEV_SCK_TCP4: MIO_DEV_SCK_TCP6; + tcp_make.on_write = tcp_sck_on_write; + tcp_make.on_read = tcp_sck_on_read; + tcp_make.on_connect = tcp_sck_on_connect; + tcp_make.on_disconnect = tcp_sck_on_disconnect; + tcpsvr = mio_dev_sck_make(mio, MIO_SIZEOF(tcp_xtn_t), &tcp_make); + if (!tcpsvr) + { + printf ("Cannot make a tcp server\n"); + goto oops; + } + + ts = (tcp_xtn_t*)(tcpsvr + 1); + ts->tally = 0; + + + if (mio_dev_sck_connect(tcpsvr, &tcp_conn) <= -1) + { + } + + mio_loop (mio); + +oops: + if (mio) mio_close (mio); + return 0; + + return 0; +} + diff --git a/mio/lib/dns-cli.c b/mio/lib/dns-cli.c index 943bb16..151a611 100644 --- a/mio/lib/dns-cli.c +++ b/mio/lib/dns-cli.c @@ -83,29 +83,6 @@ typedef struct dnc_dns_msg_xtn_t dnc_dns_msg_xtn_t; # define dnc_dns_msg_getxtn(msg) ((dnc_dns_msg_xtn_t*)((mio_uint8_t*)mio_dns_msg_to_pkt(msg) + msg->pktalilen)) #endif -static mio_dns_msg_t* build_dns_msg (mio_svc_dnc_t* dnc, mio_dns_bhdr_t* bdns, mio_dns_bqr_t* qr, mio_oow_t qr_count, mio_dns_brr_t* rr, mio_oow_t rr_count, mio_dns_bedns_t* edns, mio_oow_t xtnsize) -{ - mio_dns_msg_t* msg; - dnc_dns_msg_xtn_t* msgxtn; - - msg = mio_dns_make_msg(dnc->mio, bdns, qr, qr_count, rr, rr_count, edns, MIO_SIZEOF(*msgxtn) + xtnsize); - if (msg) - { - if (bdns->id < 0) - { - mio_dns_pkt_t* pkt = mio_dns_msg_to_pkt(msg); - pkt->id = mio_hton16(dnc->seq); - dnc->seq++; - } - - msgxtn = dnc_dns_msg_getxtn(msg); - msgxtn->dev = (mio_dev_t*)dnc->udp_sck; - msgxtn->rtmridx = MIO_TMRIDX_INVALID; - } - - return msg; -} - static MIO_INLINE void chain_pending_dns_reqmsg (mio_svc_dnc_t* dnc, mio_dns_msg_t* msg) { if (dnc->pending_req) @@ -137,27 +114,39 @@ MIO_DEBUG1 (mio, "releasing dns msg %d\n", (int)mio_ntoh16(mio_dns_msg_to_pkt(ms unchain_pending_dns_reqmsg (dnc, msg); } -/* TODO: add it to the free msg list instead of just freeing it. */ if (msgxtn->rtmridx != MIO_TMRIDX_INVALID) { mio_deltmrjob (mio, msgxtn->rtmridx); MIO_ASSERT (mio, msgxtn->rtmridx == MIO_TMRIDX_INVALID); } +/* TODO: add it to the free msg list instead of just freeing it. */ mio_dns_free_msg (dnc->mio, msg); } - /* ----------------------------------------------------------------------- */ static int on_tcp_read (mio_dev_sck_t* dev, const void* data, mio_iolen_t dlen, const mio_skad_t* srcaddr) { + if (MIO_UNLIKELY(dlen <= -1)) + { +printf ("ON TCP READ ERROR>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %d\n", dlen); + } + else if (dlen == 0) + { +printf ("ON TCP READ EOF>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %d\n", dlen); + } + else + { +printf ("ON TCP READ DATA>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %d\n", dlen); + } return 0; } static int on_tcp_write (mio_dev_sck_t* dev, mio_iolen_t wrlen, void* wrctx, const mio_skad_t* dstaddr) { -printf ("ON WRITE >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); +printf ("ON TCP WRITE >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); + return 0; } @@ -169,14 +158,18 @@ static void on_tcp_connect (mio_dev_sck_t* dev) mio_dns_msg_t* reqmsg = ((dnc_sck_xtn_t*)mio_dev_sck_getxtn(dev))->reqmsg; dnc_dns_msg_xtn_t* reqmsgxtn = dnc_dns_msg_getxtn(reqmsg); mio_uint16_t pktlen; + mio_iovec_t iov[2]; MIO_ASSERT (mio, dev == dnc->tcp_sck); pktlen = mio_hton16(reqmsg->pktlen); -/* TODO: create writev... which triggered on_write_once */ - mio_dev_sck_timedwrite(dev, &pktlen, MIO_SIZEOF(pktlen), &reqmsgxtn->rtmout, reqmsg, MIO_NULL); - if (mio_dev_sck_timedwrite(dev, mio_dns_msg_to_pkt(reqmsg), reqmsg->pktlen, &reqmsgxtn->rtmout, reqmsg, MIO_NULL) <= -1) +/* TODO: Is it better to create 2 byte space when sending UDP and use it here instead of iov? */ + iov[0].iov_ptr = &pktlen; + iov[0].iov_len = MIO_SIZEOF(pktlen); + iov[1].iov_ptr = mio_dns_msg_to_pkt(reqmsg); + iov[1].iov_len = reqmsg->pktlen; + if (mio_dev_sck_timedwritev(dev, iov, MIO_COUNTOF(iov), &reqmsgxtn->rtmout, reqmsg, MIO_NULL) <= -1) { if (MIO_LIKELY(reqmsgxtn->on_reply)) reqmsgxtn->on_reply (dnc, reqmsg, mio_geterrnum(mio), MIO_NULL, 0); @@ -206,7 +199,6 @@ MIO_DEBUG2 (mio, "TCP UNABLED TO CONNECT .. OR DISCONNECTED ... ---> %d -> %js\n if (MIO_LIKELY(reqmsgxtn->on_reply)) reqmsgxtn->on_reply (dnc, reqmsg, status, MIO_NULL, 0); - release_dns_msg (dnc, reqmsg); } @@ -243,6 +235,7 @@ static int switch_reqmsg_transport_to_tcp (mio_svc_dnc_t* dnc, mio_dns_msg_t* re mkinfo.on_connect = on_tcp_connect; mkinfo.on_disconnect = on_tcp_disconnect; dnc->tcp_sck = mio_dev_sck_make(mio, MIO_SIZEOF(*sckxtn), &mkinfo); + if (!dnc->tcp_sck) return -1; } sckxtn = (dnc_sck_xtn_t*)mio_dev_sck_getxtn(dnc->tcp_sck); @@ -253,8 +246,19 @@ static int switch_reqmsg_transport_to_tcp (mio_svc_dnc_t* dnc, mio_dns_msg_t* re cinfo.remoteaddr = reqmsgxtn->servaddr; cinfo.connect_tmout = reqmsgxtn->rtmout; /* TOOD: create a separate connect timeout or treate rtmout as a whole transaction time and calculate the remaining time from the transaction start, and use it */ - reqmsgxtn->rtries = 0; /* reset the number of tries back to 0 which means it's never sent over tcp */ - return mio_dev_sck_connect(dnc->tcp_sck, &cinfo); + if (mio_dev_sck_connect(dnc->tcp_sck, &cinfo) <= -1) return -1; /* the connect request hasn't been honored. */ + + /* switch the belonging device to the tcp socket since the connect request has been acknowledged. */ + reqmsgxtn->dev = (mio_dev_t*)dnc->tcp_sck; + reqmsgxtn->rtries = 0; + if (reqmsgxtn->rtmridx != MIO_TMRIDX_INVALID) + { + /* unschedule a timer job added for udp transport if any */ + mio_deltmrjob (mio, reqmsgxtn->rtmridx); + MIO_ASSERT (mio, reqmsgxtn->rtmridx == MIO_TMRIDX_INVALID); + } + + return 0; } /* ----------------------------------------------------------------------- */ @@ -295,12 +299,11 @@ static int on_udp_read (mio_dev_sck_t* dev, const void* data, mio_iolen_t dlen, //////////////////////// pkt->tc = 1; //////////////////////// - if (pkt->tc) /* truncated */ + if (MIO_UNLIKELY(pkt->tc)) { /* TODO: add an option for this behavior */ - /* TODO: switch to tc ... send the same request over tcp... */ - switch_reqmsg_transport_to_tcp (dnc, reqmsg); - return 0; + if (switch_reqmsg_transport_to_tcp(dnc, reqmsg) >= 0) return 0; + /* TODO: add an option to call an error callback with TRUNCATION error code instead of fallback to received UDP truncated message */ } MIO_DEBUG1 (mio, "received dns response...id %d\n", id); @@ -489,13 +492,14 @@ oops: void mio_svc_dnc_stop (mio_svc_dnc_t* dnc) { mio_t* mio = dnc->mio; + if (dnc->udp_sck) mio_dev_sck_kill (dnc->udp_sck); - MIO_SVC_UNREGISTER (mio, dnc); + if (dnc->tcp_sck) mio_dev_sck_kill (dnc->tcp_sck); while (dnc->pending_req) release_dns_msg (dnc, dnc->pending_req); + MIO_SVC_UNREGISTER (mio, dnc); mio_freemem (mio, dnc); } - mio_dns_msg_t* mio_svc_dnc_sendmsg (mio_svc_dnc_t* dnc, mio_dns_bhdr_t* bdns, mio_dns_bqr_t* qr, mio_oow_t qr_count, mio_dns_brr_t* rr, mio_oow_t rr_count, mio_dns_bedns_t* edns, mio_svc_dnc_on_reply_t on_reply, mio_oow_t xtnsize) { /* send a request or a response */ @@ -503,10 +507,19 @@ mio_dns_msg_t* mio_svc_dnc_sendmsg (mio_svc_dnc_t* dnc, mio_dns_bhdr_t* bdns, mi dnc_dns_msg_xtn_t* msgxtn; mio_ntime_t* tmout; - msg = build_dns_msg(dnc, bdns, qr, qr_count, rr, rr_count, edns, MIO_SIZEOF(*msgxtn) + xtnsize); + msg = mio_dns_make_msg(dnc->mio, bdns, qr, qr_count, rr, rr_count, edns, MIO_SIZEOF(*msgxtn) + xtnsize); if (!msg) return MIO_NULL; + if (bdns->id < 0) + { + mio_dns_pkt_t* pkt = mio_dns_msg_to_pkt(msg); + pkt->id = mio_hton16(dnc->seq); + dnc->seq++; + } + msgxtn = dnc_dns_msg_getxtn(msg); + msgxtn->dev = (mio_dev_t*)dnc->udp_sck; + msgxtn->rtmridx = MIO_TMRIDX_INVALID; msgxtn->on_reply = on_reply; msgxtn->wtmout = dnc->send_tmout; msgxtn->rtmout = dnc->reply_tmout; diff --git a/mio/lib/dns.c b/mio/lib/dns.c index 74275ae..934d8f4 100644 --- a/mio/lib/dns.c +++ b/mio/lib/dns.c @@ -285,11 +285,11 @@ static int parse_answer_rr (mio_t* mio, mio_dns_rr_part_t rr_part, mio_oow_t pos } case MIO_DNS_RRT_A: - if (MIO_UNLIKELY(dlen != 4)) goto oops; + if (MIO_UNLIKELY(dlen != MIO_SIZEOF(mio_ip4ad_t))) goto oops; goto verbatim; case MIO_DNS_RRT_AAAA: - if (MIO_UNLIKELY(dlen != 16)) goto oops; + if (MIO_UNLIKELY(dlen != MIO_SIZEOF(mio_ip6ad_t))) goto oops; goto verbatim; case MIO_DNS_RRT_CNAME: @@ -465,22 +465,19 @@ void mio_dns_free_packet_info (mio_t* mio, mio_dns_pkt_info_t* pi) /* ----------------------------------------------------------------------- */ -static mio_oow_t encode_rrdata_in_dns_msg (mio_t* mio, const mio_dns_brr_t* rr, void* dptr) +static int encode_rrdata_in_dns_msg (mio_t* mio, const mio_dns_brr_t* rr, mio_uint16_t* dxlen, void* dptr) { mio_oow_t xlen; switch (rr->rrtype) { case MIO_DNS_RRT_A: - xlen = rr->dlen; - break; - case MIO_DNS_RRT_AAAA: - xlen = rr->dlen; - break; + if (rr->dlen != MIO_SIZEOF(mio_ip4ad_t)) goto inval; + goto verbatim; - /* - case MIO_DNS_RRT_WKS: - break; */ + case MIO_DNS_RRT_AAAA: + if (rr->dlen != MIO_SIZEOF(mio_ip6ad_t)) goto inval; + goto verbatim; case MIO_DNS_RRT_CNAME: /*case MIO_DNS_RRT_MB: @@ -496,7 +493,7 @@ static mio_oow_t encode_rrdata_in_dns_msg (mio_t* mio, const mio_dns_brr_t* rr, xlen = to_dn(rr->dptr, dptr); else xlen = to_dn_capa(rr->dptr); - if (xlen <= 0) + if (xlen <= 0) goto inval; break; #if 0 @@ -520,14 +517,21 @@ static mio_oow_t encode_rrdata_in_dns_msg (mio_t* mio, const mio_dns_brr_t* rr, case MIO_DNS_RRT_TXT: case MIO_DNS_RRT_NULL: default: + verbatim: /* TODO: custom transformator? */ - if (rr->dlen > 0) MIO_MEMCPY (dptr, rr->dptr, rr->dlen); + if (dptr) MIO_MEMCPY (dptr, rr->dptr, rr->dlen); xlen = rr->dlen; break; } - if (MIO_UNLIKELY(xlen > MIO_TYPE_MAX(mio_uint16_t))) return 0; - return xlen; + if (MIO_UNLIKELY(xlen > MIO_TYPE_MAX(mio_uint16_t))) goto inval; + *dxlen = (mio_uint16_t)xlen; + return 0; + + +inval: + mio_seterrnum (mio, MIO_EINVAL); + return -1; } mio_dns_msg_t* mio_dns_make_msg (mio_t* mio, mio_dns_bhdr_t* bhdr, mio_dns_bqr_t* qr, mio_oow_t qr_count, mio_dns_brr_t* rr, mio_oow_t rr_count, mio_dns_bedns_t* edns, mio_oow_t xtnsize) @@ -545,20 +549,26 @@ mio_dns_msg_t* mio_dns_make_msg (mio_t* mio, mio_dns_bhdr_t* bhdr, mio_dns_bqr_t for (i = 0; i < qr_count; i++) { - pktlen += to_dn_capa(qr[i].qname) + MIO_SIZEOF(*qrtr); + dnlen = to_dn_capa(qr[i].qname); + if (MIO_UNLIKELY(dnlen <= 0)) + { + mio_seterrnum (mio, MIO_EINVAL); + return MIO_NULL; + } + pktlen += dnlen + MIO_SIZEOF(*qrtr); } for (i = 0; i < rr_count; i++) { - mio_oow_t rrdata_len; - rrdata_len = encode_rrdata_in_dns_msg(mio, &rr[i], MIO_NULL); - if (MIO_UNLIKELY(rrdata_len <= 0)) + mio_uint16_t rrdata_len; + dnlen = to_dn_capa(rr[i].rrname); + if (MIO_UNLIKELY(dnlen <= 0)) { - /* invalid rrdata */ mio_seterrnum (mio, MIO_EINVAL); return MIO_NULL; } - pktlen += to_dn_capa(rr[i].rrname) + MIO_SIZEOF(*rrtr) + rrdata_len; + if (MIO_UNLIKELY(encode_rrdata_in_dns_msg(mio, &rr[i], &rrdata_len, MIO_NULL) <= -1)) return MIO_NULL; + pktlen += dnlen + MIO_SIZEOF(*rrtr) + rrdata_len; } edns_dlen = 0; @@ -572,7 +582,7 @@ mio_dns_msg_t* mio_dns_make_msg (mio_t* mio, mio_dns_bhdr_t* bhdr, mio_dns_bqr_t for (i = 0; i < edns->beonum; i++) { edns_dlen += MIO_SIZEOF(mio_dns_eopt_t) + beopt->dlen; - if (edns_dlen > MIO_TYPE_MAX(mio_uint16_t)) + if (MIO_UNLIKELY(edns_dlen > MIO_TYPE_MAX(mio_uint16_t))) { mio_seterrbfmt (mio, MIO_EINVAL, "edns options too large"); return MIO_NULL; @@ -584,7 +594,7 @@ mio_dns_msg_t* mio_dns_make_msg (mio_t* mio, mio_dns_bhdr_t* bhdr, mio_dns_bqr_t } else { - if (bhdr->rcode > 0x0F) + if (MIO_UNLIKELY(bhdr->rcode > 0x0F)) { /* rcode is larger than 4 bits. but edns info is not provided */ mio_seterrbfmt (mio, MIO_EINVAL, "rcode too large without edns - %d", bhdr->rcode); @@ -608,12 +618,8 @@ mio_dns_msg_t* mio_dns_make_msg (mio_t* mio, mio_dns_bhdr_t* bhdr, mio_dns_bqr_t { /* dnlen includes the ending */ dnlen = to_dn(qr[i].qname, dn); - if (dnlen <= 0) - { - mio_dns_free_msg (mio, msg); - mio_seterrbfmt (mio, MIO_EINVAL, "invalid domain name - %hs", qr[i].qname); - return MIO_NULL; - } + MIO_ASSERT (mio, dnlen > 0); + qrtr = (mio_dns_qrtr_t*)(dn + dnlen); qrtr->qtype = mio_hton16(qr[i].qtype); qrtr->qclass = mio_hton16(qr[i].qclass); @@ -628,23 +634,17 @@ mio_dns_msg_t* mio_dns_make_msg (mio_t* mio, mio_dns_bhdr_t* bhdr, mio_dns_bqr_t { if (rr[i].part == rr_sect) { - mio_oow_t rrdata_len; + mio_uint16_t rrdata_len; dnlen = to_dn(rr[i].rrname, dn); - if (dnlen <= 0) - { - mio_dns_free_msg (mio, msg); - mio_seterrbfmt (mio, MIO_EINVAL, "invalid domain name - %hs", rr[i].rrname); - return MIO_NULL; - } - + MIO_ASSERT (mio, dnlen > 0); + rrtr = (mio_dns_rrtr_t*)(dn + dnlen); rrtr->rrtype = mio_hton16(rr[i].rrtype); rrtr->rrclass = mio_hton16(rr[i].rrclass); rrtr->ttl = mio_hton32(rr[i].ttl); - rrdata_len = encode_rrdata_in_dns_msg(mio, &rr[i], rrtr + 1); - MIO_ASSERT (mio, rrdata_len > 0); + encode_rrdata_in_dns_msg(mio, &rr[i], &rrdata_len, rrtr + 1); /* this must succeed */ rrtr->dlen = mio_hton16(rrdata_len); dn = (mio_uint8_t*)(rrtr + 1) + rrdata_len; diff --git a/mio/lib/mio-skad.h b/mio/lib/mio-skad.h index dd2652f..13f1da6 100644 --- a/mio/lib/mio-skad.h +++ b/mio/lib/mio-skad.h @@ -75,17 +75,17 @@ struct MIO_PACKED mio_ethaddr_t }; typedef struct mio_ethaddr_t mio_ethaddr_t; -struct MIO_PACKED mio_ip4addr_t +struct MIO_PACKED mio_ip4ad_t { mio_uint8_t v[MIO_IP4ADDR_LEN]; }; -typedef struct mio_ip4addr_t mio_ip4addr_t; +typedef struct mio_ip4ad_t mio_ip4ad_t; -struct MIO_PACKED mio_ip6addr_t +struct MIO_PACKED mio_ip6ad_t { mio_uint8_t v[MIO_IP6ADDR_LEN]; }; -typedef struct mio_ip6addr_t mio_ip6addr_t; +typedef struct mio_ip6ad_t mio_ip6ad_t; #include #if defined(__cplusplus) @@ -137,13 +137,13 @@ MIO_EXPORT mio_oow_t mio_skadtobcstr ( MIO_EXPORT void mio_skad_init_for_ip4 ( mio_skad_t* skad, mio_uint16_t port, - mio_ip4addr_t* ip4addr + mio_ip4ad_t* ip4ad ); MIO_EXPORT void mio_skad_init_for_ip6 ( mio_skad_t* skad, mio_uint16_t port, - mio_ip6addr_t* ip6addr, + mio_ip6ad_t* ip6ad, int scope_id ); diff --git a/mio/lib/sck.c b/mio/lib/sck.c index 4ee0538..7a62fe7 100644 --- a/mio/lib/sck.c +++ b/mio/lib/sck.c @@ -986,18 +986,17 @@ static int dev_sck_ioctl (mio_dev_t* dev, int cmd, void* arg) SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); } #endif + /* the socket is already non-blocking */ /*{ int flags = fcntl (rdev->sck, F_GETFL); fcntl (rdev->sck, F_SETFL, flags & ~O_NONBLOCK); }*/ - - /* the socket is already non-blocking */ x = connect(rdev->sck, sa, sl); /*{ int flags = fcntl (rdev->sck, F_GETFL); fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK); }*/ - if (x == -1) + if (x <= -1) { if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) { @@ -1051,70 +1050,24 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK); else { /* connected immediately */ + + /* don't call on_connect() callback even though the connection has been established. + * i don't want on_connect() to be called within the this function. */ + if (mio_dev_watch((mio_dev_t*)rdev, MIO_DEV_WATCH_UPDATE, MIO_DEV_EVENT_IN | MIO_DEV_EVENT_OUT) <= -1) + { + /* watcher update failure. it's critical */ + mio_stop (mio, MIO_STOPREQ_WATCHER_ERROR); + goto oops_connect; + } + + /* as i know it's connected already, + * i don't schedule a connection timeout job */ + rdev->remoteaddr = conn->remoteaddr; - - sl = MIO_SIZEOF(localaddr); - if (getsockname(rdev->sck, (struct sockaddr*)&localaddr, &sl) == 0) rdev->localaddr = localaddr; - #if defined(USE_SSL) - if (ssl_ctx) - { - int x; - rdev->ssl_ctx = ssl_ctx; - - x = connect_ssl(rdev); - if (x <= -1) - { - SSL_CTX_free (rdev->ssl_ctx); - rdev->ssl_ctx = MIO_NULL; - - MIO_ASSERT (mio, rdev->ssl == MIO_NULL); - return -1; - } - if (x == 0) - { - MIO_ASSERT (mio, rdev->tmrjob_index == MIO_TMRIDX_INVALID); - MIO_INIT_NTIME (&rdev->tmout, 0, 0); /* just in case */ - - /* it's ok to use conn->connect_tmout for ssl-connect as - * the underlying socket connection has been established immediately */ - if (MIO_IS_POS_NTIME(&conn->connect_tmout)) - { - if (schedule_timer_job_after(rdev, &conn->connect_tmout, ssl_connect_timedout) <= -1) - { - /* no device halting in spite of failure. - * let the caller handle this after having - * checked the return code as it is an IOCTL call. */ - SSL_CTX_free (rdev->ssl_ctx); - rdev->ssl_ctx = MIO_NULL; - - MIO_ASSERT (mio, rdev->ssl == MIO_NULL); - return -1; - } - else - { - /* update rdev->tmout to the deadline of the connect timeout job */ - MIO_ASSERT (mio, rdev->tmrjob_index != MIO_TMRIDX_INVALID); - mio_gettmrjobdeadline (mio, rdev->tmrjob_index, &rdev->tmout); - } - } - - MIO_DEV_SCK_SET_PROGRESS (rdev, MIO_DEV_SCK_CONNECTING_SSL); - } - else - { - goto ssl_connected; - } - } - else - { - ssl_connected: - #endif - MIO_DEV_SCK_SET_PROGRESS (rdev, MIO_DEV_SCK_CONNECTED); - if (rdev->on_connect) rdev->on_connect (rdev); - #if defined(USE_SSL) - } + rdev->ssl_ctx = ssl_ctx; #endif + MIO_DEV_SCK_SET_PROGRESS (rdev, MIO_DEV_SCK_CONNECTING); return 0; } } diff --git a/mio/lib/skad.c b/mio/lib/skad.c index 0f291dd..5b7c9e4 100644 --- a/mio/lib/skad.c +++ b/mio/lib/skad.c @@ -790,7 +790,7 @@ int mio_bcharstoskad (mio_t* mio, const mio_bch_t* str, mio_oow_t len, mio_skad_ unrecog: mio_seterrbfmt (mio, MIO_EINVAL, "unrecognized address"); return -1; - + no_rbrack: mio_seterrbfmt (mio, MIO_EINVAL, "missing right bracket"); return -1; @@ -827,7 +827,7 @@ no_rbrack: /* ---------------------------------------------------------- */ -static mio_oow_t ip4addr_to_ucstr (const struct in_addr* ipad, mio_uch_t* buf, mio_oow_t size) +static mio_oow_t ip4ad_to_ucstr (const struct in_addr* ipad, mio_uch_t* buf, mio_oow_t size) { mio_uint8_t b; mio_uch_t* p, * end; @@ -859,7 +859,7 @@ static mio_oow_t ip4addr_to_ucstr (const struct in_addr* ipad, mio_uch_t* buf, m } -static mio_oow_t ip6addr_to_ucstr (const struct in6_addr* ipad, mio_uch_t* buf, mio_oow_t size) +static mio_oow_t ip6ad_to_ucstr (const struct in6_addr* ipad, mio_uch_t* buf, mio_oow_t size) { /* * Note that int32_t and int16_t need only be "at least" large enough @@ -942,7 +942,7 @@ static mio_oow_t ip6addr_to_ucstr (const struct in6_addr* ipad, mio_uch_t* buf, { struct in_addr ip4ad; MIO_MEMCPY (&ip4ad.s_addr, ipad->s6_addr + 12, MIO_SIZEOF(ip4ad.s_addr)); - tp += ip4addr_to_ucstr(&ip4ad, tp, MIO_COUNTOF(tmp) - (tp - tmp)); + tp += ip4ad_to_ucstr(&ip4ad, tp, MIO_COUNTOF(tmp) - (tp - tmp)); break; } @@ -972,7 +972,7 @@ mio_oow_t mio_skadtoucstr (mio_t* mio, const mio_skad_t* _skad, mio_uch_t* buf, if (flags & MIO_SKAD_TO_BCSTR_ADDR) { if (xlen + 1 >= len) goto done; - xlen += ip4addr_to_ucstr(&skad->in4.sin_addr, buf, len); + xlen += ip4ad_to_ucstr(&skad->in4.sin_addr, buf, len); } if (flags & MIO_SKAD_TO_BCSTR_PORT) @@ -1007,7 +1007,7 @@ mio_oow_t mio_skadtoucstr (mio_t* mio, const mio_skad_t* _skad, mio_uch_t* buf, if (flags & MIO_SKAD_TO_BCSTR_ADDR) { if (xlen + 1 >= len) goto done; - xlen += ip6addr_to_ucstr(&skad->in6.sin6_addr, &buf[xlen], len - xlen); + xlen += ip6ad_to_ucstr(&skad->in6.sin6_addr, &buf[xlen], len - xlen); if (skad->in6.sin6_scope_id != 0) { @@ -1073,7 +1073,7 @@ done: /* ---------------------------------------------------------- */ -static mio_oow_t ip4addr_to_bcstr (const struct in_addr* ipad, mio_bch_t* buf, mio_oow_t size) +static mio_oow_t ip4ad_to_bcstr (const struct in_addr* ipad, mio_bch_t* buf, mio_oow_t size) { mio_uint8_t b; mio_bch_t* p, * end; @@ -1105,7 +1105,7 @@ static mio_oow_t ip4addr_to_bcstr (const struct in_addr* ipad, mio_bch_t* buf, m } -static mio_oow_t ip6addr_to_bcstr (const struct in6_addr* ipad, mio_bch_t* buf, mio_oow_t size) +static mio_oow_t ip6ad_to_bcstr (const struct in6_addr* ipad, mio_bch_t* buf, mio_oow_t size) { /* * Note that int32_t and int16_t need only be "at least" large enough @@ -1188,7 +1188,7 @@ static mio_oow_t ip6addr_to_bcstr (const struct in6_addr* ipad, mio_bch_t* buf, { struct in_addr ip4ad; MIO_MEMCPY (&ip4ad.s_addr, ipad->s6_addr + 12, MIO_SIZEOF(ip4ad.s_addr)); - tp += ip4addr_to_bcstr(&ip4ad, tp, MIO_COUNTOF(tmp) - (tp - tmp)); + tp += ip4ad_to_bcstr(&ip4ad, tp, MIO_COUNTOF(tmp) - (tp - tmp)); break; } @@ -1218,7 +1218,7 @@ mio_oow_t mio_skadtobcstr (mio_t* mio, const mio_skad_t* _skad, mio_bch_t* buf, if (flags & MIO_SKAD_TO_BCSTR_ADDR) { if (xlen + 1 >= len) goto done; - xlen += ip4addr_to_bcstr(&skad->in4.sin_addr, buf, len); + xlen += ip4ad_to_bcstr(&skad->in4.sin_addr, buf, len); } if (flags & MIO_SKAD_TO_BCSTR_PORT) @@ -1254,7 +1254,7 @@ mio_oow_t mio_skadtobcstr (mio_t* mio, const mio_skad_t* _skad, mio_bch_t* buf, { if (xlen + 1 >= len) goto done; - xlen += ip6addr_to_bcstr(&skad->in6.sin6_addr, &buf[xlen], len - xlen); + xlen += ip6ad_to_bcstr(&skad->in6.sin6_addr, &buf[xlen], len - xlen); if (skad->in6.sin6_scope_id != 0) { @@ -1381,7 +1381,7 @@ int mio_skad_ifindex (const mio_skad_t* _skad) } -void mio_skad_init_for_ip4 (mio_skad_t* skad, mio_uint16_t port, mio_ip4addr_t* ip4addr) +void mio_skad_init_for_ip4 (mio_skad_t* skad, mio_uint16_t port, mio_ip4ad_t* ip4ad) { #if (MIO_SIZEOF_STRUCT_SOCKADDR_IN > 0) struct sockaddr_in* sin = (struct sockaddr_in*)skad; @@ -1389,11 +1389,11 @@ void mio_skad_init_for_ip4 (mio_skad_t* skad, mio_uint16_t port, mio_ip4addr_t* MIO_MEMSET (sin, 0, MIO_SIZEOF(*sin)); sin->sin_family = AF_INET; sin->sin_port = htons(port); - if (ip4addr) MIO_MEMCPY (&sin->sin_addr, ip4addr, MIO_IP4ADDR_LEN); + if (ip4ad) MIO_MEMCPY (&sin->sin_addr, ip4ad, MIO_IP4ADDR_LEN); #endif } -void mio_skad_init_for_ip6 (mio_skad_t* skad, mio_uint16_t port, mio_ip6addr_t* ip6addr, int scope_id) +void mio_skad_init_for_ip6 (mio_skad_t* skad, mio_uint16_t port, mio_ip6ad_t* ip6ad, int scope_id) { #if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) struct sockaddr_in6* sin = (struct sockaddr_in6*)skad; @@ -1402,7 +1402,7 @@ void mio_skad_init_for_ip6 (mio_skad_t* skad, mio_uint16_t port, mio_ip6addr_t* sin->sin6_family = AF_INET; sin->sin6_port = htons(port); sin->sin6_scope_id = scope_id; - if (ip6addr) MIO_MEMCPY (&sin->sin6_addr, ip6addr, MIO_IP6ADDR_LEN); + if (ip6ad) MIO_MEMCPY (&sin->sin6_addr, ip6ad, MIO_IP6ADDR_LEN); #endif }