From 47f662861fa3b152bbe9cd25480e41fc133173fa Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 25 Jan 2018 09:56:30 +0000 Subject: [PATCH] Added some socket functions --- qse/configure | 168 ++++++++++++++++++++++++++- qse/configure.ac | 34 +++++- qse/include/qse/config.h.in | 6 + qse/include/qse/si/AppRoot.hpp | 2 +- qse/include/qse/si/Socket.hpp | 27 ++++- qse/include/qse/si/SocketAddress.hpp | 2 - qse/lib/si/Socket.cpp | 112 +++++++++++++++++- qse/lib/si/SocketAddress.cpp | 16 --- qse/lib/si/nwif-cfg.c | 2 +- 9 files changed, 337 insertions(+), 32 deletions(-) diff --git a/qse/configure b/qse/configure index f224fedd..b58e2404 100755 --- a/qse/configure +++ b/qse/configure @@ -22246,6 +22246,84 @@ $as_echo "$ac_res" >&6; } $as_echo "#define QSE_SOCKLEN_T_IS_SIGNED 1" >>confdefs.h + elif eval "test \"\${ax_cv_decl_${typename}_signed}\" = \"no\""; then + $as_echo_n "" + fi + + fi + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of sa_family_t" >&5 +$as_echo_n "checking size of sa_family_t... " >&6; } +if ${ac_cv_sizeof_sa_family_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (sa_family_t))" "ac_cv_sizeof_sa_family_t" " + #include + #include +"; then : + +else + if test "$ac_cv_type_sa_family_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (sa_family_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_sa_family_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_sa_family_t" >&5 +$as_echo "$ac_cv_sizeof_sa_family_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SA_FAMILY_T $ac_cv_sizeof_sa_family_t +_ACEOF + + + if test ${ac_cv_sizeof_sa_family_t} -gt 0 + then + + typename=`echo sa_family_t | sed "s/[^a-zA-Z0-9_]/_/g"` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether sa_family_t is signed" >&5 +$as_echo_n "checking whether sa_family_t is signed... " >&6; } +if eval \${ax_cv_decl_${typename}_signed+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include +int +main () +{ + int foo [ 1 - 2 * !(((sa_family_t) -1) < 0) ] + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "ax_cv_decl_${typename}_signed=\"yes\"" +else + eval "ax_cv_decl_${typename}_signed=\"no\"" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$ax_cv_decl_${typename}_signed + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + symbolname=`echo sa_family_t | sed "s/[^a-zA-Z0-9_]/_/g" | tr "a-z" "A-Z"` + if eval "test \"\${ax_cv_decl_${typename}_signed}\" = \"yes\""; then + +$as_echo "#define QSE_SA_FAMILY_T_IS_SIGNED 1" >>confdefs.h + elif eval "test \"\${ax_cv_decl_${typename}_signed}\" = \"no\""; then $as_echo_n "" fi @@ -22262,6 +22340,7 @@ if ${ac_cv_sizeof_struct_sockaddr_in+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (struct sockaddr_in))" "ac_cv_sizeof_struct_sockaddr_in" " + #include #include #include "; then : @@ -22298,6 +22377,7 @@ if ${ac_cv_sizeof_struct_sockaddr_in6+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (struct sockaddr_in6))" "ac_cv_sizeof_struct_sockaddr_in6" " + #include #include #include "; then : @@ -22334,6 +22414,7 @@ if ${ac_cv_sizeof_struct_sockaddr_un+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (struct sockaddr_un))" "ac_cv_sizeof_struct_sockaddr_un" " + #include #include #include "; then : @@ -22370,6 +22451,7 @@ if ${ac_cv_sizeof_struct_sockaddr_ll+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (struct sockaddr_ll))" "ac_cv_sizeof_struct_sockaddr_ll" " + #include #include #include "; then : @@ -22406,8 +22488,8 @@ if ${ac_cv_sizeof_struct_sockaddr_dl+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (struct sockaddr_dl))" "ac_cv_sizeof_struct_sockaddr_dl" " - #include #include + #include #include "; then : @@ -22433,6 +22515,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF + # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. @@ -22443,6 +22526,7 @@ if ${ac_cv_sizeof_socklen_t+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (socklen_t))" "ac_cv_sizeof_socklen_t" " + #include #include #include "; then : @@ -22469,7 +22553,6 @@ cat >>confdefs.h <<_ACEOF _ACEOF - if test ${ac_cv_sizeof_socklen_t} -gt 0 then @@ -22511,6 +22594,87 @@ $as_echo "#define QSE_SOCKLEN_T_IS_SIGNED 1" >>confdefs.h fi fi + + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of sa_family_t" >&5 +$as_echo_n "checking size of sa_family_t... " >&6; } +if ${ac_cv_sizeof_sa_family_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (sa_family_t))" "ac_cv_sizeof_sa_family_t" " + #include + #include +"; then : + +else + if test "$ac_cv_type_sa_family_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (sa_family_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_sa_family_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_sa_family_t" >&5 +$as_echo "$ac_cv_sizeof_sa_family_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SA_FAMILY_T $ac_cv_sizeof_sa_family_t +_ACEOF + + + if test ${ac_cv_sizeof_sa_family_t} -gt 0 + then + + typename=`echo sa_family_t | sed "s/[^a-zA-Z0-9_]/_/g"` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether sa_family_t is signed" >&5 +$as_echo_n "checking whether sa_family_t is signed... " >&6; } +if eval \${ax_cv_decl_${typename}_signed+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + #include +int +main () +{ + int foo [ 1 - 2 * !(((sa_family_t) -1) < 0) ] + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "ax_cv_decl_${typename}_signed=\"yes\"" +else + eval "ax_cv_decl_${typename}_signed=\"no\"" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$ax_cv_decl_${typename}_signed + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + symbolname=`echo sa_family_t | sed "s/[^a-zA-Z0-9_]/_/g" | tr "a-z" "A-Z"` + if eval "test \"\${ax_cv_decl_${typename}_signed}\" = \"yes\""; then + +$as_echo "#define QSE_SA_FAMILY_T_IS_SIGNED 1" >>confdefs.h + + elif eval "test \"\${ax_cv_decl_${typename}_signed}\" = \"no\""; then + $as_echo_n "" + fi + + fi + fi diff --git a/qse/configure.ac b/qse/configure.ac index 84c24bdf..2a2c6717 100644 --- a/qse/configure.ac +++ b/qse/configure.ac @@ -451,27 +451,43 @@ then [#include #include ]) fi + AC_CHECK_SIZEOF(sa_family_t,, [ + #include + #include ]) + if test ${ac_cv_sizeof_sa_family_t} -gt 0 + then + AX_CHECK_SIGN([sa_family_t], + [ AC_DEFINE(QSE_SA_FAMILY_T_IS_SIGNED, 1, [Define if sa_family_t is signed]) ], + [ AS_ECHO_N("") ], + [#include + #include ]) + fi else AC_CHECK_SIZEOF(struct sockaddr_in,,[ + #include #include #include ]) AC_CHECK_SIZEOF(struct sockaddr_in6,,[ + #include #include #include ]) AC_CHECK_SIZEOF(struct sockaddr_un,,[ + #include #include #include ]) AC_CHECK_SIZEOF(struct sockaddr_ll,,[ + #include #include #include ]) AC_CHECK_SIZEOF(struct sockaddr_dl,,[ - #include #include + #include #include ]) + AC_CHECK_SIZEOF(socklen_t,, [ + #include #include #include ]) - if test ${ac_cv_sizeof_socklen_t} -gt 0 then AX_CHECK_SIGN([socklen_t], @@ -479,6 +495,20 @@ else [ AS_ECHO_N("") ], [#include ]) fi + + AC_CHECK_SIZEOF(sa_family_t,, [ + #include + #include ]) + if test ${ac_cv_sizeof_sa_family_t} -gt 0 + then + AX_CHECK_SIGN([sa_family_t], + [ AC_DEFINE(QSE_SA_FAMILY_T_IS_SIGNED, 1, [Define if sa_family_t is signed]) ], + [ AS_ECHO_N("") ], + [#include + #include + #include ]) + fi + fi diff --git a/qse/include/qse/config.h.in b/qse/include/qse/config.h.in index 5ebb702a..92a2b96a 100644 --- a/qse/include/qse/config.h.in +++ b/qse/include/qse/config.h.in @@ -960,6 +960,9 @@ /* Define if pthread_t is signed */ #undef QSE_PTHREAD_T_IS_SIGNED +/* Define if sa_family_t is signed */ +#undef QSE_SA_FAMILY_T_IS_SIGNED + /* sizeof(char) */ #undef QSE_SIZEOF_CHAR @@ -1104,6 +1107,9 @@ /* The size of `pthread_t', as computed by sizeof. */ #undef SIZEOF_PTHREAD_T +/* The size of `sa_family_t', as computed by sizeof. */ +#undef SIZEOF_SA_FAMILY_T + /* The size of `short', as computed by sizeof. */ #undef SIZEOF_SHORT diff --git a/qse/include/qse/si/AppRoot.hpp b/qse/include/qse/si/AppRoot.hpp index beef3d26..a720a9b4 100644 --- a/qse/include/qse/si/AppRoot.hpp +++ b/qse/include/qse/si/AppRoot.hpp @@ -35,7 +35,7 @@ QSE_BEGIN_NAMESPACE(QSE) ///////////////////////////////// -class AppRoot: Uncopyable, public Types, public Mmged +class AppRoot: public Uncopyable, public Types, public Mmged { public: AppRoot (Mmgr* mmgr): Mmged(mmgr), _root_only(false) {} diff --git a/qse/include/qse/si/Socket.hpp b/qse/include/qse/si/Socket.hpp index 5a9727f6..18c43404 100644 --- a/qse/include/qse/si/Socket.hpp +++ b/qse/include/qse/si/Socket.hpp @@ -27,6 +27,8 @@ #ifndef _QSE_SI_SOCKET_HPP_ #define _QSE_SI_SOCKET_HPP_ +#include +#include #include #include @@ -34,20 +36,41 @@ QSE_BEGIN_NAMESPACE(QSE) ///////////////////////////////// -class Socket +class Socket: public Uncopyable, public Types { public: + enum ErrorCode + { + E_NOERR, + E_NOMEM, + E_INVAL, + E_NOTOPEN, + E_SYSERR + }; + Socket () QSE_CPP_NOEXCEPT; ~Socket () QSE_CPP_NOEXCEPT; + void setError (ErrorCode error_code, const qse_char_t* fmt = QSE_NULL, ...); + + int open (int domain, int type, int protocol) QSE_CPP_NOEXCEPT; void close () QSE_CPP_NOEXCEPT; int connect (const SocketAddress& target) QSE_CPP_NOEXCEPT; - int beginConnect (const SocketAddress& target) QSE_CPP_NOEXCEPT; + int bind (const SocketAddress& target) QSE_CPP_NOEXCEPT; + int accept (Socket* newsck, SocketAddress* newaddr, int flags) QSE_CPP_NOEXCEPT; + + int read () QSE_CPP_NOEXCEPT; + int write () QSE_CPP_NOEXCEPT; protected: qse_sck_hnd_t handle; + + ErrorCode errcode; + qse_char_t errmsg[128]; + + void set_error_with_syserr (int syserr); }; diff --git a/qse/include/qse/si/SocketAddress.hpp b/qse/include/qse/si/SocketAddress.hpp index cd5c00b4..d8026d3d 100644 --- a/qse/include/qse/si/SocketAddress.hpp +++ b/qse/include/qse/si/SocketAddress.hpp @@ -41,7 +41,6 @@ public: SocketAddress (int family); SocketAddress (const qse_skad_t* skad); SocketAddress (const qse_nwad_t* nwad); - SocketAddress (const struct sockaddr* ptr, int len); int getFamily () const; @@ -68,7 +67,6 @@ public: int set (const qse_skad_t* skad); int set (const qse_nwad_t* nwad); - int set (const struct sockaddr* ptr, int len); // treat ptr as a pointer to struct sockaddr protected: qse_skad_t skad; diff --git a/qse/lib/si/Socket.cpp b/qse/lib/si/Socket.cpp index 00c81604..9ca710be 100644 --- a/qse/lib/si/Socket.cpp +++ b/qse/lib/si/Socket.cpp @@ -25,7 +25,13 @@ */ #include +#include + +#include #include +#include +#include +#include ///////////////////////////////// QSE_BEGIN_NAMESPACE(QSE) @@ -47,6 +53,31 @@ int Socket::fdopen (int handle) QSE_CPP_NOEXCEPT } #endif +void Socket::setError (ErrorCode error_code, const qse_char_t* fmt, ...) +{ + static const qse_char_t* errstr[] = + { + QSE_T("no error"), + QSE_T("insufficient memory"), + QSE_T("invalid parameter"), + QSE_T("socket not open"), + QSE_T("system error") + }; + + this->errcode = error_code; + if (fmt) + { + va_list ap; + va_start (ap, fmt); + qse_strxvfmt (this->errmsg, QSE_COUNTOF(errmsg), fmt, ap); + va_end (ap); + } + else + { + qse_strxcpy (this->errmsg, QSE_COUNTOF(errmsg), errstr[error_code]); + } +} + int Socket::open (int domain, int type, int protocol) QSE_CPP_NOEXCEPT { int x; @@ -72,16 +103,85 @@ void Socket::close () QSE_CPP_NOEXCEPT int Socket::connect (const SocketAddress& target) QSE_CPP_NOEXCEPT { - //if (this->handle == QSE_INVALID_SCKHND) - //{ - // - //} + if (this->handle == QSE_INVALID_SCKHND) + { + this->setError (Socket::E_NOTOPEN); + return -1; + } - return -1; + if (::connect(this->handle, (struct sockaddr*)target.getAddrPtr(), target.getAddrSize()) == -1) + { + this->set_error_with_syserr (errno); + return -1; + } + + return 0; } -int Socket::beginConnect (const SocketAddress &target) QSE_CPP_NOEXCEPT +int Socket::bind (const SocketAddress& target) QSE_CPP_NOEXCEPT { + if (this->handle == QSE_INVALID_SCKHND) + { + this->setError (Socket::E_NOTOPEN); + return -1; + } + + if (::bind(this->handle, (struct sockaddr*)target.getAddrPtr(), target.getAddrSize()) == -1) + { + this->set_error_with_syserr (errno); + return -1; + } + + return 0; +} + +int Socket::accept (Socket* newsck, SocketAddress* newaddr, int flags) QSE_CPP_NOEXCEPT +{ + int n; + + if (this->handle == QSE_INVALID_SCKHND) + { + this->setError (Socket::E_NOTOPEN); + return -1; + } +#if 0 + qse_socklen_t len = newaddr->getAddrSize(); + + if ((n = ::accept4 (this->handle, newaddr->getAddrPtr(), &len)) == -1) + { + this->set_error_with_syserr (errno); + return -1; + } + + newsck->handle = n; +#endif + return 0; +} + +void Socket::set_error_with_syserr (int syserr) +{ + qse_mchar_t buf[128]; + ErrorCode errcode; + + switch (errno) + { + case EINVAL: + errcode = this->E_INVAL; + break; + + case ENOMEM: + errcode = this->E_NOMEM; + break; + +// TODO: translate more system error codes + + default: + strerror_r(errno, buf, QSE_COUNTOF(buf)); + this->setError (this->E_SYSERR, QSE_T("%hs"), buf); + return; + } + + this->setError (errcode); } ///////////////////////////////// diff --git a/qse/lib/si/SocketAddress.cpp b/qse/lib/si/SocketAddress.cpp index 350edd6c..9e145143 100644 --- a/qse/lib/si/SocketAddress.cpp +++ b/qse/lib/si/SocketAddress.cpp @@ -111,14 +111,6 @@ SocketAddress::SocketAddress (const qse_nwad_t* nwad) this->set (nwad); } -SocketAddress::SocketAddress (const struct sockaddr* ptr, int len) -{ - if (this->set (ptr, len) <= -1) - { - QSE_MEMSET (&this->skad, 0, QSE_SIZEOF(this->skad)); - } -} - int SocketAddress::getFamily () const { return FAMILY(&this->skad); @@ -206,14 +198,6 @@ int SocketAddress::set (const qse_nwad_t* nwad) return qse_nwadtoskad (nwad, &this->skad); } -int SocketAddress::set (const struct sockaddr* ptr, int len) -{ - int exp_size = qse_skadsize((const qse_skad_t*)ptr); - if (len < exp_size) return -1; - QSE_MEMCPY (&this->skad, ptr, exp_size); - return 0; -} - ///////////////////////////////// QSE_END_NAMESPACE(QSE) diff --git a/qse/lib/si/nwif-cfg.c b/qse/lib/si/nwif-cfg.c index 8d3b588c..b0fff958 100644 --- a/qse/lib/si/nwif-cfg.c +++ b/qse/lib/si/nwif-cfg.c @@ -255,7 +255,7 @@ int qse_getnwifcfg (qse_nwifcfg_t* cfg) head->flags |= QSE_NWIFCFG_PTOP; } - if (ioctl (s, SIOCGLIFINDEX, &ifrbuf) <= -1) goto oops; + if (ioctl (s, SIOCGLIFINDEX, &ifrbuf) <= -1) goto oops; head->index = ifrbuf.lifr_index; if (ioctl (s, SIOCGLIFNETMASK, &ifrbuf) <= -1) goto oops;