diff --git a/sys/sio.hpp b/sys/sio.hpp index 0f48c97cc4ed440735d6c04f17ef51b1dc674cb1..bd49b58cbe879de6ed30d37c6260c2e494862ac8 100644 --- a/sys/sio.hpp +++ b/sys/sio.hpp @@ -91,7 +91,7 @@ namespace rlib { #if RLIB_OS_ID == OS_WINDOWS template <bool doNotWSAStartup = false> - static inline sockfd_t quick_listen(const std::string &addr, uint16_t port) { + static inline sockfd_t quick_listen(const std::string &addr, uint16_t port, bool use_udp = false) { WSADATA wsaData; sockfd_t listenfd = INVALID_SOCKET; if(!doNotWSAStartup) { @@ -102,9 +102,15 @@ namespace rlib { addrinfo *psaddr; addrinfo hints { 0 }; hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; + if(use_udp) { + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + } hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ - hints.ai_protocol = IPPROTO_TCP; auto _ = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &psaddr); if(_ != 0) { WSACleanup(); @@ -126,14 +132,17 @@ namespace rlib { } if(!success) throw std::runtime_error("Failed to bind to any of these addr."); - if(SOCKET_ERROR == ::listen(listenfd, 16)) throw std::runtime_error("listen failed. {}"_format(strerror(errno))); + if(!use_udp) { + // UDP don't need to listen. + if(SOCKET_ERROR == ::listen(listenfd, 16)) throw std::runtime_error("listen failed. {}"_format(strerror(errno))); + } freeaddrinfo(psaddr); return listenfd; } template <bool doNotWSAStartup = false> - static inline sockfd_t quick_connect(const std::string &addr, uint16_t port) { + static inline sockfd_t quick_connect(const std::string &addr, uint16_t port, bool use_udp = false) { WSADATA wsaData; sockfd_t sockfd = INVALID_SOCKET; if(!doNotWSAStartup) { @@ -145,8 +154,15 @@ namespace rlib { addrinfo hints { 0 }; hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; + if(use_udp) { + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + } + auto _ = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &paddr); if(_ != 0) { WSACleanup(); @@ -175,13 +191,20 @@ namespace rlib { #else // POSIX version - static inline fd_t quick_listen(const std::string &addr, uint16_t port) { + static inline fd_t quick_listen(const std::string &addr, uint16_t port, bool use_udp = false) { addrinfo *psaddr; addrinfo hints{0}; fd_t listenfd; hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; + if(use_udp) { + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + } hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ auto _ = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &psaddr); if (_ != 0) throw std::runtime_error("Failed to getaddrinfo. returnval={}, check `man getaddrinfo`'s return value."_format(_)); @@ -204,19 +227,30 @@ namespace rlib { } if (!success) throw std::runtime_error("Failed to bind {}:{}."_format(addr, port)); - if (-1 == ::listen(listenfd, 16)) throw std::runtime_error("listen failed. {}"_format(strerror(errno))); + if(!use_udp) { + // UDP don't need to listen. + if (-1 == ::listen(listenfd, 16)) throw std::runtime_error("listen failed. {}"_format(strerror(errno))); + } rlib_defer([psaddr] { freeaddrinfo(psaddr); }); return listenfd; } - static inline fd_t quick_connect(const std::string &addr, uint16_t port) { + static inline fd_t quick_connect(const std::string &addr, uint16_t port, bool use_udp = false) { addrinfo *paddr; addrinfo hints{0}; fd_t sockfd; hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; + if(use_udp) { + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + } + auto _ = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &paddr); if (_ != 0) throw std::runtime_error("getaddrinfo failed. Check network connection to {}:{}; returnval={}, check `man getaddrinfo`'s return value."_format( diff --git a/sys/unix_handy.hpp b/sys/unix_handy.hpp index 9d212d71db109edda013f61f04634a3e97eaf17e..ffc63bc792447fb7f7140dfc0b315367cf8cae9c 100644 --- a/sys/unix_handy.hpp +++ b/sys/unix_handy.hpp @@ -13,17 +13,26 @@ #error rlib/sys/unix_handy.hpp is not for Windows. #endif +// Deprecated. Use sys/sio.hpp +#if 1+1 == 4 namespace rlib { namespace impl { using rlib::literals::operator""_format; - static inline fd unix_quick_listen(const std::string &addr, uint16_t port) { + static inline fd unix_quick_listen(const std::string &addr, uint16_t port, bool use_udp = false) { addrinfo *psaddr; addrinfo hints{0}; fd listenfd; hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ + if(use_udp) { + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + } + hints.ai_flags = AI_PASSIVE; /* For listen */ auto _ = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &psaddr); if (_ != 0) throw std::runtime_error("Failed to getaddrinfo. returnval={}, check `man getaddrinfo`'s return value."_format(_)); @@ -51,13 +60,20 @@ namespace rlib { return listenfd; } - static inline fd unix_quick_connect(const std::string &addr, uint16_t port) { + static inline fd unix_quick_connect(const std::string &addr, uint16_t port, bool use_udp = false) { addrinfo *paddr; addrinfo hints{0}; fd sockfd; hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; + if(use_udp) { + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + } auto _ = getaddrinfo(addr.c_str(), std::to_string(port).c_str(), &hints, &paddr); if (_ != 0) throw std::runtime_error("getaddrinfo failed. Check network connection to {}:{}; returnval={}, check `man getaddrinfo`'s return value."_format( @@ -88,6 +104,7 @@ namespace rlib { using impl::unix_quick_connect; using impl::unix_quick_listen; } +#endif // Unfinished. I'm not sure if I must implement it.