From 9b391741d6671ee48d3a18a928acc65da2c3011d Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Wed, 23 Jan 2019 09:37:23 +0000 Subject: [PATCH] added sck-addr.c for socket address conversion work --- mio/lib/mio-pro.c | 12 +- mio/lib/mio-sck.c | 28 ++-- mio/lib/mio-tim.c | 2 +- mio/lib/sck-addr.c | 400 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 421 insertions(+), 21 deletions(-) create mode 100644 mio/lib/sck-addr.c diff --git a/mio/lib/mio-pro.c b/mio/lib/mio-pro.c index fc79759..a8b737e 100644 --- a/mio/lib/mio-pro.c +++ b/mio/lib/mio-pro.c @@ -545,7 +545,7 @@ static int dev_pro_read_slave (mio_dev_t* dev, void* buf, mio_iolen_t* len, mio_ mio_dev_pro_slave_t* pro = (mio_dev_pro_slave_t*)dev; ssize_t x; - x = read (pro->pfd, buf, *len); + x = read(pro->pfd, buf, *len); if (x <= -1) { if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data available */ @@ -757,17 +757,17 @@ static mio_dev_pro_slave_t* make_slave (mio_t* mio, slave_info_t* si) switch (si->id) { case MIO_DEV_PRO_IN: - return (mio_dev_pro_slave_t*)mio_makedev ( + return (mio_dev_pro_slave_t*)mio_makedev( mio, MIO_SIZEOF(mio_dev_pro_t), &dev_pro_methods_slave, &dev_pro_event_callbacks_slave_in, si); case MIO_DEV_PRO_OUT: - return (mio_dev_pro_slave_t*)mio_makedev ( + return (mio_dev_pro_slave_t*)mio_makedev( mio, MIO_SIZEOF(mio_dev_pro_t), &dev_pro_methods_slave, &dev_pro_event_callbacks_slave_out, si); case MIO_DEV_PRO_ERR: - return (mio_dev_pro_slave_t*)mio_makedev ( + return (mio_dev_pro_slave_t*)mio_makedev( mio, MIO_SIZEOF(mio_dev_pro_t), &dev_pro_methods_slave, &dev_pro_event_callbacks_slave_err, si); @@ -779,7 +779,7 @@ static mio_dev_pro_slave_t* make_slave (mio_t* mio, slave_info_t* si) mio_dev_pro_t* mio_dev_pro_make (mio_t* mio, mio_oow_t xtnsize, const mio_dev_pro_make_t* info) { - return (mio_dev_pro_t*)mio_makedev ( + return (mio_dev_pro_t*)mio_makedev( mio, MIO_SIZEOF(mio_dev_pro_t) + xtnsize, &dev_pro_methods, &dev_pro_event_callbacks, (void*)info); } @@ -793,7 +793,7 @@ int mio_dev_pro_write (mio_dev_pro_t* dev, const void* data, mio_iolen_t dlen, v { if (dev->slave[0]) { - return mio_dev_write ((mio_dev_t*)dev->slave[0], data, dlen, wrctx, MIO_NULL); + return mio_dev_write((mio_dev_t*)dev->slave[0], data, dlen, wrctx, MIO_NULL); } else { diff --git a/mio/lib/mio-sck.c b/mio/lib/mio-sck.c index 1d724de..0959cd6 100644 --- a/mio/lib/mio-sck.c +++ b/mio/lib/mio-sck.c @@ -211,7 +211,7 @@ int mio_equalsckaddrs (mio_t* mio, const mio_sckaddr_t* addr1, const mio_sckaddr mio_getsckaddrinfo (mio, addr1, &len1, &fam1); mio_getsckaddrinfo (mio, addr2, &len2, &fam2); - return fam1 == fam2 && len1 == len2 && MIO_MEMCMP (addr1, addr2, len1) == 0; + return fam1 == fam2 && len1 == len2 && MIO_MEMCMP(addr1, addr2, len1) == 0; } /* ========================================================================= */ @@ -544,7 +544,7 @@ static int dev_sck_read_stateful (mio_dev_t* dev, void* buf, mio_iolen_t* len, m x = SSL_read ((SSL*)rdev->ssl, buf, *len); if (x <= -1) { - int err = SSL_get_error ((SSL*)rdev->ssl, x); + int err = SSL_get_error((SSL*)rdev->ssl, x); if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) return 0; rdev->mio->errnum = MIO_ESYSERR; return -1; @@ -640,7 +640,7 @@ static int dev_sck_write_stateful (mio_dev_t* dev, const void* data, mio_iolen_t { /* it's a writing finish indicator. close the writing end of * the socket, probably leaving it in the half-closed state */ - if (shutdown (rdev->sck, SHUT_WR) == -1) + if (shutdown(rdev->sck, SHUT_WR) == -1) { rdev->mio->errnum = mio_syserrtoerrnum(errno); return -1; @@ -653,7 +653,7 @@ static int dev_sck_write_stateful (mio_dev_t* dev, const void* data, mio_iolen_t #if defined(MSG_NOSIGNAL) flags |= MSG_NOSIGNAL; #endif - x = send (rdev->sck, data, *len, flags); + x = send(rdev->sck, data, *len, flags); if (x == -1) { if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */ @@ -674,7 +674,7 @@ static int dev_sck_write_stateless (mio_dev_t* dev, const void* data, mio_iolen_ mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev; ssize_t x; - x = sendto (rdev->sck, data, *len, 0, dstaddr->ptr, dstaddr->len); + x = sendto(rdev->sck, data, *len, 0, dstaddr->ptr, dstaddr->len); if (x <= -1) { if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */ @@ -836,7 +836,7 @@ static int dev_sck_ioctl (mio_dev_t* dev, int cmd, void* arg) { #if defined(IP_TRANSPARENT) int v = 1; - if (setsockopt (rdev->sck, SOL_IP, IP_TRANSPARENT, &v, MIO_SIZEOF(v)) == -1) + if (setsockopt(rdev->sck, SOL_IP, IP_TRANSPARENT, &v, MIO_SIZEOF(v)) == -1) { rdev->mio->errnum = mio_syserrtoerrnum(errno); return -1; @@ -868,16 +868,16 @@ static int dev_sck_ioctl (mio_dev_t* dev, int cmd, void* arg) return -1; } - ssl_ctx = SSL_CTX_new (SSLv23_server_method()); + ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if (!ssl_ctx) { rdev->mio->errnum = MIO_ESYSERR; return -1; } - if (SSL_CTX_use_certificate_file (ssl_ctx, bnd->ssl_certfile, SSL_FILETYPE_PEM) == 0 || - SSL_CTX_use_PrivateKey_file (ssl_ctx, bnd->ssl_keyfile, SSL_FILETYPE_PEM) == 0 || - SSL_CTX_check_private_key (ssl_ctx) == 0 /*|| + if (SSL_CTX_use_certificate_file(ssl_ctx, bnd->ssl_certfile, SSL_FILETYPE_PEM) == 0 || + SSL_CTX_use_PrivateKey_file(ssl_ctx, bnd->ssl_keyfile, SSL_FILETYPE_PEM) == 0 || + SSL_CTX_check_private_key(ssl_ctx) == 0 /*|| SSL_CTX_use_certificate_chain_file (ssl_ctx, bnd->chainfile) == 0*/) { SSL_CTX_free (ssl_ctx); @@ -899,9 +899,9 @@ static int dev_sck_ioctl (mio_dev_t* dev, int cmd, void* arg) #endif } - if (mio_getsckaddrinfo (dev->mio, &bnd->localaddr, &sl, &fam) <= -1) return -1; + if (mio_getsckaddrinfo(dev->mio, &bnd->localaddr, &sl, &fam) <= -1) return -1; - x = bind (rdev->sck, sa, sl); + x = bind(rdev->sck, sa, sl); if (x == -1) { rdev->mio->errnum = mio_syserrtoerrnum(errno); @@ -1007,7 +1007,7 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK); if (mio_ispostime(&conn->connect_tmout)) { - if (schedule_timer_job_after (rdev, &conn->connect_tmout, connect_timedout) <= -1) + if (schedule_timer_job_after(rdev, &conn->connect_tmout, connect_timedout) <= -1) { goto oops_connect; } @@ -1189,7 +1189,7 @@ static int harvest_outgoing_connection (mio_dev_sck_t* rdev) MIO_ASSERT (!(rdev->state & MIO_DEV_SCK_CONNECTED)); len = MIO_SIZEOF(errcode); - if (getsockopt (rdev->sck, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1) + if (getsockopt(rdev->sck, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len) == -1) { rdev->mio->errnum = mio_syserrtoerrnum(errno); return -1; diff --git a/mio/lib/mio-tim.c b/mio/lib/mio-tim.c index acaf66f..46e4b83 100644 --- a/mio/lib/mio-tim.c +++ b/mio/lib/mio-tim.c @@ -169,7 +169,7 @@ void mio_gettime (mio_ntime_t* t) t->nsec = MIO_USEC_TO_NSEC(tv.tv_usec); #else - t->sec = time (MIO_NULL); + t->sec = time(MIO_NULL); t->nsec = 0; #endif } diff --git a/mio/lib/sck-addr.c b/mio/lib/sck-addr.c new file mode 100644 index 0000000..4dbf27d --- /dev/null +++ b/mio/lib/sck-addr.c @@ -0,0 +1,400 @@ +union sockaddr_t +{ + struct sockaddr sa; +#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN > 0) + struct sockaddr_in in4; +#endif +#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) + struct sockaddr_in6 in6; +#endif +#if (MIO_SIZEOF_STRUCT_SOCKADDR_LL > 0) + struct sockaddr_ll ll; +#endif +#if (MIO_SIZEOF_STRUCT_SOCKADDR_UN > 0) + struct sockaddr_un un; +#endif +}; +typedef union sockaddr_t sockaddr_t; + + +static int str_to_ipv4 (const mio_ooch_t* str, mio_oow_t len, struct in_addr* inaddr) +{ + const mio_ooch_t* end; + int dots = 0, digits = 0; + mio_uint32_t acc = 0, addr = 0; + mio_ooch_t c; + + end = str + len; + + do + { + if (str >= end) + { + if (dots < 3 || digits == 0) return -1; + addr = (addr << 8) | acc; + break; + } + + c = *str++; + + if (c >= '0' && c <= '9') + { + if (digits > 0 && acc == 0) return -1; + acc = acc * 10 + (c - '0'); + if (acc > 255) return -1; + digits++; + } + else if (c == '.') + { + if (dots >= 3 || digits == 0) return -1; + addr = (addr << 8) | acc; + dots++; acc = 0; digits = 0; + } + else return -1; + } + while (1); + + inaddr->s_addr = mio_hton32(addr); + return 0; + +} + +#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) +static int str_to_ipv6 (const mio_ooch_t* src, mio_oow_t len, struct in6_addr* inaddr) +{ + mio_uint8_t* tp, * endp, * colonp; + const mio_ooch_t* curtok; + mio_ooch_t ch; + int saw_xdigit; + unsigned int val; + const mio_ooch_t* src_end; + + src_end = src + len; + + MIO_MEMSET (inaddr, 0, MIO_SIZEOF(*inaddr)); + tp = &inaddr->s6_addr[0]; + endp = &inaddr->s6_addr[MIO_COUNTOF(inaddr->s6_addr)]; + colonp = MIO_NULL; + + /* Leading :: requires some special handling. */ + if (src < src_end && *src == ':') + { + src++; + if (src >= src_end || *src != ':') return -1; + } + + curtok = src; + saw_xdigit = 0; + val = 0; + + while (src < src_end) + { + int v1; + + ch = *src++; + + if (ch >= '0' && ch <= '9') + v1 = ch - '0'; + else if (ch >= 'A' && ch <= 'F') + v1 = ch - 'A' + 10; + else if (ch >= 'a' && ch <= 'f') + v1 = ch - 'a' + 10; + else v1 = -1; + if (v1 >= 0) + { + val <<= 4; + val |= v1; + if (val > 0xffff) return -1; + saw_xdigit = 1; + continue; + } + + if (ch == ':') + { + curtok = src; + if (!saw_xdigit) + { + if (colonp) return -1; + colonp = tp; + continue; + } + else if (src >= src_end) + { + /* a colon can't be the last character */ + return -1; + } + + *tp++ = (mio_uint8_t)(val >> 8) & 0xff; + *tp++ = (mio_uint8_t)val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + + if (ch == '.' && ((tp + MIO_SIZEOF(struct in_addr)) <= endp) && + str_to_ipv4(curtok, src_end - curtok, (struct in_addr*)tp) == 0) + { + tp += MIO_SIZEOF(struct in_addr*); + saw_xdigit = 0; + break; + } + + return -1; + } + + if (saw_xdigit) + { + if (tp + MIO_SIZEOF(mio_uint16_t) > endp) return -1; + *tp++ = (mio_uint8_t)(val >> 8) & 0xff; + *tp++ = (mio_uint8_t)val & 0xff; + } + if (colonp != MIO_NULL) + { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + mio_oow_t n = tp - colonp; + mio_oow_t i; + + for (i = 1; i <= n; i++) + { + endp[-i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + + if (tp != endp) return -1; + + return 0; +} +#endif + + +static int str_to_sockaddr (mio_t* mio, const mio_ooch_t* str, mio_oow_t len, sockaddr_t* nwad) +{ + const mio_ooch_t* p; + const mio_ooch_t* end; + mio_oocs_t tmp; + + p = str; + end = str + len; + + if (p >= end) + { + mio_seterrbfmt (mio, MIO_EINVAL, "blank address"); + return -1; + } + + MIO_MEMSET (nwad, 0, MIO_SIZEOF(*nwad)); + +#if defined(AF_UNIX) + if (*p == '/' && len >= 2) + { + #if defined(MIO_OOCH_IS_BCH) + mio_copybcstr (nwad->un.sun_path, MIO_COUNTOF(nwad->un.sun_path), str); + #else + mio_oow_t dstlen; + + dstlen = MIO_COUNTOF(nwad->un.sun_path) - 1; + if (mio_convutobchars (mio, p, &len, nwad->un.sun_path, &dstlen) <= -1) + { + mio_seterrbfmt (mio, MIO_EINVAL, "unable to convert encoding"); + return -1; + } + nwad->un.sun_path[dstlen] = '\0'; + #endif + nwad->un.sun_family = AF_UNIX; + return 0; + } +#endif + +#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) + if (*p == '[') + { + /* IPv6 address */ + tmp.ptr = (mio_ooch_t*)++p; /* skip [ and remember the position */ + while (p < end && *p != '%' && *p != ']') p++; + + if (p >= end) goto no_rbrack; + + tmp.len = p - tmp.ptr; + if (*p == '%') + { + /* handle scope id */ + mio_uint32_t x; + + p++; /* skip % */ + + if (p >= end) + { + /* premature end */ + mio_seterrbfmt (mio, MIO_EINVAL, "scope id blank"); + return -1; + } + + if (*p >= '0' && *p <= '9') + { + /* numeric scope id */ + nwad->in6.sin6_scope_id = 0; + do + { + x = nwad->in6.sin6_scope_id * 10 + (*p - '0'); + if (x < nwad->in6.sin6_scope_id) + { + mio_seterrbfmt (mio, MIO_EINVAL, "scope id too large"); + return -1; /* overflow */ + } + nwad->in6.sin6_scope_id = x; + p++; + } + while (p < end && *p >= '0' && *p <= '9'); + } + else + { +#if 0 +TODO: + /* interface name as a scope id? */ + const mio_ooch_t* stmp = p; + unsigned int index; + do p++; while (p < end && *p != ']'); + if (mio_nwifwcsntoindex (stmp, p - stmp, &index) <= -1) return -1; + tmpad.u.in6.scope = index; +#endif + } + + if (p >= end || *p != ']') goto no_rbrack; + } + p++; /* skip ] */ + + if (str_to_ipv6(tmp.ptr, tmp.len, &nwad->in6.sin6_addr) <= -1) goto unrecog; + nwad->in6.sin6_family = AF_INET6; + } + else + { +#endif + /* IPv4 address */ + tmp.ptr = (mio_ooch_t*)p; + while (p < end && *p != ':') p++; + tmp.len = p - tmp.ptr; + + if (str_to_ipv4(tmp.ptr, tmp.len, &nwad->in4.sin_addr) <= -1) + { + #if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) + /* check if it is an IPv6 address not enclosed in []. + * the port number can't be specified in this format. */ + if (p >= end || *p != ':') + { + /* without :, it can't be an ipv6 address */ + goto unrecog; + } + + + while (p < end && *p != '%') p++; + tmp.len = p - tmp.ptr; + + if (str_to_ipv6(tmp.ptr, tmp.len, &nwad->in6.sin6_addr) <= -1) goto unrecog; + + if (p < end && *p == '%') + { + /* handle scope id */ + mio_uint32_t x; + + p++; /* skip % */ + + if (p >= end) + { + /* premature end */ + mio_seterrbfmt (mio, MIO_EINVAL, "scope id blank"); + return -1; + } + + if (*p >= '0' && *p <= '9') + { + /* numeric scope id */ + nwad->in6.sin6_scope_id = 0; + do + { + x = nwad->in6.sin6_scope_id * 10 + (*p - '0'); + if (x < nwad->in6.sin6_scope_id) + { + mio_seterrbfmt (mio, MIO_EINVAL, "scope id too large"); + return -1; /* overflow */ + } + nwad->in6.sin6_scope_id = x; + p++; + } + while (p < end && *p >= '0' && *p <= '9'); + } + else + { +#if 0 +TODO + /* interface name as a scope id? */ + const mio_ooch_t* stmp = p; + unsigned int index; + do p++; while (p < end); + if (mio_nwifwcsntoindex (stmp, p - stmp, &index) <= -1) return -1; + nwad->in6.sin6_scope_id = index; +#endif + } + } + + if (p < end) goto unrecog; /* some gargage after the end? */ + + nwad->in6.sin6_family = AF_INET6; + return 0; + #else + goto unrecog; + #endif + } + + nwad->in4.sin_family = AF_INET; +#if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) + } +#endif + + if (p < end && *p == ':') + { + /* port number */ + mio_uint32_t port = 0; + + p++; /* skip : */ + + tmp.ptr = (mio_ooch_t*)p; + while (p < end && *p >= '0' && *p <= '9') + { + port = port * 10 + (*p - '0'); + p++; + } + + tmp.len = p - tmp.ptr; + if (tmp.len <= 0 || tmp.len >= 6 || + port > MIO_TYPE_MAX(mio_uint16_t)) + { + mio_seterrbfmt (mio, MIO_EINVAL, "port number blank or too large"); + return -1; + } + + #if (MIO_SIZEOF_STRUCT_SOCKADDR_IN6 > 0) + if (nwad->in4.sin_family == AF_INET) + nwad->in4.sin_port = mio_hton16(port); + else + nwad->in6.sin6_port = mio_hton16(port); + #else + nwad->in4.sin_port = mio_hton16(port); + #endif + } + + return 0; + + +unrecog: + mio_seterrbfmt (mio, MIO_EINVAL, "unrecognized address"); + return -1; + +no_rbrack: + mio_seterrbfmt (mio, MIO_EINVAL, "missing right bracket"); + return -1; +}