diff --git a/qse/configure b/qse/configure index e8e46ed4..10c930ae 100755 --- a/qse/configure +++ b/qse/configure @@ -22999,6 +22999,34 @@ _ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking numeric value of AF_UNSPEC" >&5 +$as_echo_n "checking numeric value of AF_UNSPEC... " >&6; } +if ${ax_cv_numvalof_AF_UNSPEC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(AF_UNSPEC)" "ax_cv_numvalof_AF_UNSPEC" "#include + #include +"; then : + +else + ax_cv_numvalof_AF_UNSPEC=-1 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_numvalof_AF_UNSPEC" >&5 +$as_echo "$ax_cv_numvalof_AF_UNSPEC" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define NUMVALOF_AF_UNSPEC $ax_cv_numvalof_AF_UNSPEC +_ACEOF + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking numeric value of AF_INET" >&5 $as_echo_n "checking numeric value of AF_INET... " >&6; } if ${ax_cv_numvalof_AF_INET+:} false; then : @@ -24504,6 +24532,14 @@ cat >>confdefs.h <<_ACEOF #define QSE_SOCK_RAW ${ax_cv_numvalof_SOCK_RAW} _ACEOF +fi +if test ${ax_cv_numvalof_AF_UNSPEC} -ge 0 +then + +cat >>confdefs.h <<_ACEOF +#define QSE_AF_UNSPEC ${ax_cv_numvalof_AF_UNSPEC} +_ACEOF + fi if test ${ax_cv_numvalof_AF_INET} -ge 0 then diff --git a/qse/configure.ac b/qse/configure.ac index 0ae0da75..8a8e5765 100644 --- a/qse/configure.ac +++ b/qse/configure.ac @@ -539,6 +539,8 @@ AX_CHECK_NUMVALOF(SOCK_RAW, [-1], [#include #include #include ]) +AX_CHECK_NUMVALOF(AF_UNSPEC, [-1], [#include + #include ]) AX_CHECK_NUMVALOF(AF_INET, [-1], [#include #include #include ]) @@ -841,6 +843,10 @@ if test ${ax_cv_numvalof_SOCK_RAW} -ge 0 then AC_DEFINE_UNQUOTED(QSE_SOCK_RAW, ${ax_cv_numvalof_SOCK_RAW}, [SOCK_RAW]) fi +if test ${ax_cv_numvalof_AF_UNSPEC} -ge 0 +then + AC_DEFINE_UNQUOTED(QSE_AF_UNSPEC, ${ax_cv_numvalof_AF_UNSPEC}, [AF_UNSPEC]) +fi if test ${ax_cv_numvalof_AF_INET} -ge 0 then AC_DEFINE_UNQUOTED(QSE_AF_INET, ${ax_cv_numvalof_AF_INET}, [AF_INET]) diff --git a/qse/include/qse/cmn/str.h b/qse/include/qse/cmn/str.h index 2298274c..6782ac6c 100644 --- a/qse/include/qse/cmn/str.h +++ b/qse/include/qse/cmn/str.h @@ -167,7 +167,19 @@ typedef qse_wchar_t* (*qse_wcssubst_t) ( (c>=QSE_T('A') && c<=QSE_T('Z'))? ((c-QSE_T('A')+10=QSE_T('a') && c<=QSE_T('z'))? ((c-QSE_T('a')+10=QSE_MT('0') && c<=QSE_MT('9'))? ((c-QSE_MT('0')=QSE_MT('A') && c<=QSE_MT('Z'))? ((c-QSE_MT('A')+10=QSE_MT('a') && c<=QSE_MT('z'))? ((c-QSE_MT('a')+10=QSE_WT('0') && c<=QSE_WT('9'))? ((c-QSE_WT('0')=QSE_WT('A') && c<=QSE_WT('Z'))? ((c-QSE_WT('A')+10=QSE_WT('a') && c<=QSE_WT('z'))? ((c-QSE_WT('a')+10 0) value *= -1; \ } while(0) -/* qse_strxtonum (const qse_char_t* nptr, qse_size_t len, qse_char_char** endptr, int base) */ +/* qse_strxtonum (const qse_char_t* nptr, qse_size_t len, qse_char_char** endptr, int base, int allowneg) */ #define QSE_STRXTONUM(value,nptr,len,endptr,base,allowneg) do {\ int __ston_f = 0, __ston_v; \ const qse_char_t* __ston_ptr = nptr; \ @@ -223,13 +235,7 @@ typedef qse_wchar_t* (*qse_wcssubst_t) ( if (__ston_f > 0) value *= -1; \ } while(0) -/* int qse_mchartonum (qse_mchar_t c, int base) */ -#define QSE_MCHARTONUM(c,base) \ - ((c>=QSE_MT('0') && c<=QSE_MT('9'))? ((c-QSE_MT('0')=QSE_MT('A') && c<=QSE_MT('Z'))? ((c-QSE_MT('A')+10=QSE_MT('a') && c<=QSE_MT('z'))? ((c-QSE_MT('a')+10 0) value *= -1; \ } while(0) -/* qse_strxtonum (const qse_mchar_t* nptr, qse_size_t len, qse_mchar_t** endptr, int base) */ +/* qse_strxtonum (const qse_mchar_t* nptr, qse_size_t len, qse_mchar_t** endptr, int base, int allowneg) */ #define QSE_MBSXTONUM(value,nptr,len,endptr,base,allowneg) do {\ int __ston_f = 0, __ston_v; \ const qse_mchar_t* __ston_ptr = nptr; \ @@ -285,13 +291,7 @@ typedef qse_wchar_t* (*qse_wcssubst_t) ( if (__ston_f > 0) value *= -1; \ } while(0) -/* int qse_wchartonum (qse_wchar_t c, int base) */ -#define QSE_WCHARTONUM(c,base) \ - ((c>=QSE_WT('0') && c<=QSE_WT('9'))? ((c-QSE_WT('0')=QSE_WT('A') && c<=QSE_WT('Z'))? ((c-QSE_WT('A')+10=QSE_WT('a') && c<=QSE_WT('z'))? ((c-QSE_WT('a')+10 0) value *= -1; \ } while(0) -/* qse_strxtonum (const qse_wchar_t* nptr, qse_size_t len, qse_wchar_t** endptr, int base) */ +/* qse_strxtonum (const qse_wchar_t* nptr, qse_size_t len, qse_wchar_t** endptr, int base, int allowneg) */ #define QSE_WCSXTONUM(value,nptr,len,endptr,base,allowneg) do {\ int __ston_f = 0, __ston_v; \ const qse_wchar_t* __ston_ptr = nptr; \ diff --git a/qse/include/qse/cmn/time.h b/qse/include/qse/cmn/time.h index 2fe9a71c..ba8f6c86 100644 --- a/qse/include/qse/cmn/time.h +++ b/qse/include/qse/cmn/time.h @@ -132,7 +132,7 @@ typedef qse_long_t qse_mtime_t; x->nsec = nsec; } static QSE_INLINE void qse_cleartime(qse_ntime_t* x) { qse_inittime (x, 0, 0); } - /*static QSE_INLINE int qse_cmptime(qse_ntime_t* x, qse_ntime_t* y) + /*static QSE_INLINE int qse_cmptime(const qse_ntime_t* x, const qse_ntime_t* y) { // TODO: fix the type and value range issue and replace the macro below. return (x->sec == y->sec)? (x->nsec - y->nsec): (x->sec - y->sec); diff --git a/qse/include/qse/config.h.in b/qse/include/qse/config.h.in index 6134b4e8..9fb3d11c 100644 --- a/qse/include/qse/config.h.in +++ b/qse/include/qse/config.h.in @@ -810,6 +810,9 @@ /* The size of `AF_UNIX', as computed by valueof. */ #undef NUMVALOF_AF_UNIX +/* The size of `AF_UNSPEC', as computed by valueof. */ +#undef NUMVALOF_AF_UNSPEC + /* The size of `IFNAMSIZ', as computed by valueof. */ #undef NUMVALOF_IFNAMSIZ @@ -871,6 +874,9 @@ /* AF_UNIX */ #undef QSE_AF_UNIX +/* AF_UNSPEC */ +#undef QSE_AF_UNSPEC + /* use the bundled unicode routines */ #undef QSE_ENABLE_BUNDLED_UNICODE diff --git a/qse/include/qse/si/SocketAddress.hpp b/qse/include/qse/si/SocketAddress.hpp index 2e265704..5d3cd87e 100644 --- a/qse/include/qse/si/SocketAddress.hpp +++ b/qse/include/qse/si/SocketAddress.hpp @@ -78,6 +78,7 @@ public: qse_uint32_t getScopeId () const QSE_CPP_NOEXCEPT; // in network-byte order void setScopeId (qse_uint32_t scope_id) QSE_CPP_NOEXCEPT; // in network-byte order + // set address with ip address strings int set (const qse_skad_t* skad) QSE_CPP_NOEXCEPT; int set (const qse_nwad_t* nwad) QSE_CPP_NOEXCEPT; int set (const qse_mchar_t* str) QSE_CPP_NOEXCEPT; @@ -85,6 +86,17 @@ public: int set (const qse_mchar_t* str, qse_size_t len) QSE_CPP_NOEXCEPT; int set (const qse_wchar_t* str, qse_size_t len) QSE_CPP_NOEXCEPT; + // set address with ip address strings or host/service names + int resolve (const qse_mchar_t* service, const qse_mchar_t* host, int family, int type) QSE_CPP_NOEXCEPT; + int resolve (const qse_wchar_t* service, const qse_wchar_t* host, int family, int type) QSE_CPP_NOEXCEPT; + int resolve (const qse_mchar_t* service, const qse_mchar_t* host, int type) QSE_CPP_NOEXCEPT { return this->resolve(service, host, this->getFamily(), type); } + int resolve (const qse_wchar_t* service, const qse_wchar_t* host, int type) QSE_CPP_NOEXCEPT { return this->resolve(service, host, this->getFamily(), type); } + + bool isLoopBack () const QSE_CPP_NOEXCEPT; + // TODO: isLinkLocal() const QSE_CPP_NOEXCEPT + // TODO: isSiteLocal() const QSE_CPP_NOEXCEPT + // TODO: isV4Mapped() const QSE_CPP_NOEXCEPT + qse_mchar_t* toStrBuf (qse_mchar_t* buf, qse_size_t len) const QSE_CPP_NOEXCEPT; qse_wchar_t* toStrBuf (qse_wchar_t* buf, qse_size_t len) const QSE_CPP_NOEXCEPT; diff --git a/qse/lib/cmn/mbwc-str.c b/qse/lib/cmn/mbwc-str.c index c15c6622..970e186c 100644 --- a/qse/lib/cmn/mbwc-str.c +++ b/qse/lib/cmn/mbwc-str.c @@ -145,7 +145,7 @@ static int mbsn_to_wcsn_with_cmgr ( { qse_size_t n; - n = cmgr->mbtowc (p, mlen, &w); + n = cmgr->mbtowc(p, mlen, &w); if (n == 0) { /* invalid sequence */ @@ -301,12 +301,12 @@ static qse_wchar_t* mbs_to_wcs_dup_with_cmgr (const qse_mchar_t* mbs, qse_size_t qse_wchar_t* qse_mbstowcsdupwithcmgr (const qse_mchar_t* mbs, qse_size_t* wcslen, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr) { - return mbs_to_wcs_dup_with_cmgr (mbs, wcslen, mmgr, cmgr, 0); + return mbs_to_wcs_dup_with_cmgr(mbs, wcslen, mmgr, cmgr, 0); } qse_wchar_t* qse_mbstowcsalldupwithcmgr (const qse_mchar_t* mbs, qse_size_t* wcslen, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr) { - return mbs_to_wcs_dup_with_cmgr (mbs, wcslen, mmgr, cmgr, 1); + return mbs_to_wcs_dup_with_cmgr(mbs, wcslen, mmgr, cmgr, 1); } static qse_wchar_t* mbsa_to_wcs_dup_with_cmgr (const qse_mchar_t* mbs[], qse_size_t* wcslen, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr, int all) @@ -344,12 +344,12 @@ static qse_wchar_t* mbsa_to_wcs_dup_with_cmgr (const qse_mchar_t* mbs[], qse_siz qse_wchar_t* qse_mbsatowcsdupwithcmgr (const qse_mchar_t* mbs[], qse_size_t* wcslen, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr) { - return mbsa_to_wcs_dup_with_cmgr (mbs, wcslen, mmgr, cmgr, 0); + return mbsa_to_wcs_dup_with_cmgr(mbs, wcslen, mmgr, cmgr, 0); } qse_wchar_t* qse_mbsatowcsalldupwithcmgr (const qse_mchar_t* mbs[], qse_size_t* wcslen, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr) { - return mbsa_to_wcs_dup_with_cmgr (mbs, wcslen, mmgr, cmgr, 1); + return mbsa_to_wcs_dup_with_cmgr(mbs, wcslen, mmgr, cmgr, 1); } /* ======================================================================== */ diff --git a/qse/lib/cmn/mbwc.c b/qse/lib/cmn/mbwc.c index 4ac75722..eaf22c0e 100644 --- a/qse/lib/cmn/mbwc.c +++ b/qse/lib/cmn/mbwc.c @@ -213,37 +213,37 @@ int qse_wcstombs ( const qse_wchar_t* wcs, qse_size_t* wcslen, qse_mchar_t* mbs, qse_size_t* mbslen) { - return qse_wcstombswithcmgr (wcs, wcslen, mbs, mbslen, dfl_cmgr); + return qse_wcstombswithcmgr(wcs, wcslen, mbs, mbslen, dfl_cmgr); } int qse_wcsntombsn ( const qse_wchar_t* wcs, qse_size_t* wcslen, qse_mchar_t* mbs, qse_size_t* mbslen) { - return qse_wcsntombsnwithcmgr (wcs, wcslen, mbs, mbslen, dfl_cmgr); + return qse_wcsntombsnwithcmgr(wcs, wcslen, mbs, mbslen, dfl_cmgr); } qse_mchar_t* qse_wcstombsdup ( const qse_wchar_t* wcs, qse_size_t* mbslen, qse_mmgr_t* mmgr) { - return qse_wcstombsdupwithcmgr (wcs, mbslen, mmgr, dfl_cmgr); + return qse_wcstombsdupwithcmgr(wcs, mbslen, mmgr, dfl_cmgr); } qse_mchar_t* qse_wcsntombsdup ( const qse_wchar_t* wcs, qse_size_t wcslen, qse_size_t* mbslen, qse_mmgr_t* mmgr) { - return qse_wcsntombsdupwithcmgr (wcs, wcslen, mbslen, mmgr, dfl_cmgr); + return qse_wcsntombsdupwithcmgr(wcs, wcslen, mbslen, mmgr, dfl_cmgr); } qse_mchar_t* qse_wcsatombsdup ( const qse_wchar_t* wcs[], qse_size_t* mbslen, qse_mmgr_t* mmgr) { - return qse_wcsatombsdupwithcmgr (wcs, mbslen, mmgr, dfl_cmgr); + return qse_wcsatombsdupwithcmgr(wcs, mbslen, mmgr, dfl_cmgr); } qse_mchar_t* qse_wcsnatombsdup ( const qse_wcstr_t wcs[], qse_size_t* mbslen, qse_mmgr_t* mmgr) { - return qse_wcsnatombsdupwithcmgr (wcs, mbslen, mmgr, dfl_cmgr); + return qse_wcsnatombsdupwithcmgr(wcs, mbslen, mmgr, dfl_cmgr); } diff --git a/qse/lib/si/SocketAddress.cpp b/qse/lib/si/SocketAddress.cpp index dd5641ac..19017669 100644 --- a/qse/lib/si/SocketAddress.cpp +++ b/qse/lib/si/SocketAddress.cpp @@ -26,6 +26,7 @@ #include +#include #include "../cmn/mem-prv.h" #if defined(_WIN32) @@ -63,6 +64,7 @@ # if defined(HAVE_SYS_UN_H) # include # endif +# include # if defined(QSE_SIZEOF_STRUCT_SOCKADDR_IN6) && (QSE_SIZEOF_STRUCT_SOCKADDR_IN6 <= 0) # undef AF_INET6 @@ -284,6 +286,112 @@ int SocketAddress::set (const qse_wchar_t* str, qse_size_t len) QSE_CPP_NOEXCEPT return qse_nwadtoskad(&nwad, &this->skad); } +/* + * NOTICE: + * When host is "", the address is resolved to localhost. + * When host is XP_NULL, the address is resolved to INADDR_ANY + * or IN6ADDR_ANY_INIT depending on the address family. + */ +int SocketAddress::resolve (const qse_mchar_t* service, const qse_mchar_t* host, int family, int type) QSE_CPP_NOEXCEPT +{ + struct addrinfo hints; + struct addrinfo* info, * p; + int x; + + QSE_ASSERT (family == QSE_AF_UNSPEC || family == QSE_AF_INET || family == QSE_AF_INET6); + + QSE_MEMSET (&hints, 0, QSE_SIZEOF(hints)); + hints.ai_family = family; + hints.ai_socktype = type; + if (!host) hints.ai_flags = AI_PASSIVE; + else if (host[0] == '\0') host = QSE_NULL; + + x = ::getaddrinfo(host, service, &hints, &info); + if (x != 0) return -1; + + for (p = info; p; p = p->ai_next) + { + if (family != QSE_AF_UNSPEC && p->ai_family != family) continue; + if (type != 0 && p->ai_socktype != type) continue; + if (QSE_SIZEOF(this->skad) < p->ai_addrlen) continue; + + QSE_MEMCPY (&this->skad, p->ai_addr, p->ai_addrlen); + break; + } + ::freeaddrinfo (info); + return 0; +} + +int SocketAddress::resolve (const qse_wchar_t* service, const qse_wchar_t* host, int family, int type) QSE_CPP_NOEXCEPT +{ + struct addrinfo hints; + struct addrinfo* info, * p; + int x; + + QSE_ASSERT (family == QSE_AF_UNSPEC || family == QSE_AF_INET || family == QSE_AF_INET6); + + QSE_MEMSET (&hints, 0, QSE_SIZEOF(hints)); + hints.ai_family = family; + hints.ai_socktype = type; + if (!host) hints.ai_flags = AI_PASSIVE; + else if (host[0] == '\0') host = QSE_NULL; + + qse_mchar_t mb_host[NI_MAXHOST + 1]; + qse_mchar_t mb_service[NI_MAXSERV + 1]; + qse_mchar_t* p_host = QSE_NULL; + qse_mchar_t* p_service = QSE_NULL; + + if (host) + { + qse_size_t wcslen, mbslen = QSE_COUNTOF(mb_host); + if (qse_wcstombs(host, &wcslen, mb_host, &mbslen) <= -1) return -1; + p_host = mb_host; + } + if (service) + { + qse_size_t wcslen, mbslen = QSE_COUNTOF(mb_service); + + if (qse_wcstombs(service, &wcslen, mb_service, &mbslen) <= -1) return -1; + p_service = mb_service; + } + x = ::getaddrinfo(p_host, p_service, &hints, &info); + if (x != 0) return -1; + + for (p = info; p; p = p->ai_next) + { + if (family != QSE_AF_UNSPEC && p->ai_family != family) continue; + if (type != 0 && p->ai_socktype != type) continue; + if (QSE_SIZEOF(this->skad) < p->ai_addrlen) continue; + + QSE_MEMCPY (&this->skad, p->ai_addr, p->ai_addrlen); + break; + } + ::freeaddrinfo (info); + return 0; +} + + +bool SocketAddress::isLoopBack () const QSE_CPP_NOEXCEPT +{ + switch (FAMILY(&this->skad)) + { + case AF_INET: + { + struct sockaddr_in* v4 = (struct sockaddr_in*)&this->skad; + return v4->sin_addr.s_addr == QSE_CONST_HTON32(0x7F000001); + } + + case AF_INET6: + { + struct sockaddr_in6* v6 = (struct sockaddr_in6*)&this->skad; + qse_uint32_t* x = (qse_uint32_t*)v6->sin6_addr.s6_addr; // TODO: is this alignment safe? + return x[0] == 0 && x[1] == 0 && x[2] == 0 && x[3] == 1; + } + } + + return false; +} + qse_wchar_t* SocketAddress::toStrBuf (qse_wchar_t* buf, qse_size_t len) const QSE_CPP_NOEXCEPT { qse_nwad_t nwad; @@ -378,70 +486,6 @@ qse_wchar_t* SocketAddress::ip6addrToStrBuf (const qse_ip6ad_t* ipaddr, qse_wcha return buf; } -#if 0 -/* - * NOTICE: - * When host is "", the address is resolved to localhost. - * When host is XP_NULL, the address is resolved to INADDR_ANY - * or IN6ADDR_ANY_INIT depending on the address family. - */ -int SocketAddress::resolve_address (const qse_char_t* service, const qse_char_t* host, int family, int type, int* errnum) -{ - struct addrinfo hints; - struct addrinfo* info, * p; - - QSE_ASSERT (family == QSE_AF_UNSPEC || family == QSE_AF_INET || family == QSE_AF_INET6); - QSE_ASSERT (errnum != QSE_NULL); - - QSE_MEMSET (&hints, 0, QSE_SIZEOF(hints)); - hints.ai_family = family; - hints.ai_socktype = type; - if (host == QSE_NULL) hints.ai_flags = AI_PASSIVE; - else if (host[0] == QSE_T('\0')) host = QSE_NULL; - -#if defined(QSE_CHAR_IS_MCHAR) - *errnum = ::getaddrinfo (host, service, &hints, &info); -#else - qse_mchar_t mb_host[MAX_HOST_LEN + 1]; - qse_mchar_t mb_service[MAX_SERVICE_LEN + 1]; - qse_mchar_t* p_host = QSE_NULL; - qse_mchar_t* p_service = QSE_NULL; - - if (host) { - if (qse_wcstomcs (host, mb_host, QSE_COUNTOF(mb_host)) == 0) - { - *errnum = EAI_NONAME; - return -1; - } - p_host = mb_host; - } - if (service) - { - if (qse_wcstomcs (service, mb_service, QSE_COUNTOF(mb_service)) == 0) - { - *errnum = EAI_NONAME; - return -1; - } - p_service = mb_service; - } - *errnum = ::getaddrinfo(p_host, p_service, &hints, &info); -#endif - if (*errnum != 0) return -1; - - for (p = info; p; p = p->ai_next) - { - if (family != V0 && p->ai_family != family) continue; - if (type != 0 && p->ai_socktype != type) continue; - if (QSE_SIZEOF(this->address_storage) < p->ai_addrlen) continue; - - QSE_MEMCPY (&this->address_storage, p->ai_addr, p->ai_addrlen); - break; - } - ::freeaddrinfo (info); - return 0; -} - -#endif ///////////////////////////////// QSE_END_NAMESPACE(QSE) ///////////////////////////////// diff --git a/qse/samples/si/sck01.cpp b/qse/samples/si/sck01.cpp index f86f2404..803b5bce 100644 --- a/qse/samples/si/sck01.cpp +++ b/qse/samples/si/sck01.cpp @@ -23,6 +23,19 @@ static int test1 () return -1; } + //if (addr.resolve(QSE_T("0"), QSE_T("tango6.miflux.com"), QSE_SOCK_STREAM) >= 0) + if (addr.resolve(QSE_T("0"), QSE_T("code.miflux.com"), QSE_SOCK_STREAM) >= 0) + { + qse_printf (QSE_T("code.miflux.com ===> [%js]\n"), (const qse_char_t*)addr.toString()); + } + + // if 'addr' is set to IPv6 above, this resolve() will fail if the given host doesn't have an IPv6 address + // specifying the family to QSE_AF_INET overrides this behavior. + if (addr.resolve(QSE_T("https"), QSE_T("code.miflux.com"), QSE_AF_INET, QSE_SOCK_STREAM) >= 0) + { + qse_printf (QSE_T("code.miflux.com:https ===> [%js]\n"), (const qse_char_t*)addr.toString()); + } + qse_printf (QSE_T("lo ifindex ===> %d\n"), s.getIfceIndex(QSE_MT("lo"))); if (s.getIfceAddress(QSE_T("lo"), &addr) >= 0) {