hsocket.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #ifndef HV_SOCKET_H_
  2. #define HV_SOCKET_H_
  3. #include "hplatform.h"
  4. #include "hdef.h"
  5. #ifdef _MSC_VER
  6. #pragma comment(lib, "ws2_32.lib")
  7. #endif
  8. #define LOCALHOST "127.0.0.1"
  9. #define ANYADDR "0.0.0.0"
  10. BEGIN_EXTERN_C
  11. static inline int socket_errno() {
  12. #ifdef OS_WIN
  13. return WSAGetLastError();
  14. #else
  15. return errno;
  16. #endif
  17. }
  18. const char* socket_strerror(int err);
  19. #ifdef OS_WIN
  20. typedef int socklen_t;
  21. static inline int blocking(int sockfd) {
  22. unsigned long nb = 0;
  23. return ioctlsocket(sockfd, FIONBIO, &nb);
  24. }
  25. static inline int nonblocking(int sockfd) {
  26. unsigned long nb = 1;
  27. return ioctlsocket(sockfd, FIONBIO, &nb);
  28. }
  29. #define poll WSAPoll
  30. #undef EAGAIN
  31. #define EAGAIN WSAEWOULDBLOCK
  32. #undef EINPROGRESS
  33. #define EINPROGRESS WSAEINPROGRESS
  34. #undef ENOTSOCK
  35. #define ENOTSOCK WSAENOTSOCK
  36. #else
  37. #define blocking(s) fcntl(s, F_SETFL, fcntl(s, F_GETFL) & ~O_NONBLOCK)
  38. #define nonblocking(s) fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK)
  39. typedef int SOCKET;
  40. #define INVALID_SOCKET -1
  41. #define closesocket close
  42. #endif
  43. typedef union {
  44. struct sockaddr sa;
  45. struct sockaddr_in sin;
  46. struct sockaddr_in6 sin6;
  47. } sockaddr_un;
  48. // @param host: domain or ip
  49. // @retval 0:succeed
  50. int Resolver(const char* host, sockaddr_un* addr);
  51. static inline socklen_t sockaddrlen(sockaddr_un* addr) {
  52. if (addr->sa.sa_family == AF_INET) {
  53. return sizeof(struct sockaddr_in);
  54. }
  55. else if (addr->sa.sa_family == AF_INET6) {
  56. return sizeof(struct sockaddr_in6);
  57. }
  58. return sizeof(sockaddr_un);
  59. }
  60. static inline const char* sockaddr_ip(sockaddr_un* addr, char *ip, int len) {
  61. if (addr->sa.sa_family == AF_INET) {
  62. return inet_ntop(AF_INET, &addr->sin.sin_addr, ip, len);
  63. }
  64. else if (addr->sa.sa_family == AF_INET6) {
  65. return inet_ntop(AF_INET6, &addr->sin6.sin6_addr, ip, len);
  66. }
  67. return ip;
  68. }
  69. static inline uint16_t sockaddr_port(sockaddr_un* addr) {
  70. uint16_t port = 0;
  71. if (addr->sa.sa_family == AF_INET) {
  72. port = htons(addr->sin.sin_port);
  73. }
  74. else if (addr->sa.sa_family == AF_INET6) {
  75. port = htons(addr->sin6.sin6_port);
  76. }
  77. return port;
  78. }
  79. static inline void sockaddr_set_port(sockaddr_un* addr, int port) {
  80. if (addr->sa.sa_family == AF_INET) {
  81. addr->sin.sin_port = ntohs(port);
  82. }
  83. else if (addr->sa.sa_family == AF_INET6) {
  84. addr->sin6.sin6_port = ntohs(port);
  85. }
  86. }
  87. //#define INET_ADDRSTRLEN 16
  88. //#define INET6_ADDRSTRLEN 46
  89. #define SOCKADDR_STRLEN 64 // ipv4:port | [ipv6]:port
  90. #define SOCKADDR_STR(addr, buf) sockaddr_str((sockaddr_un*)addr, buf, sizeof(buf))
  91. // NOTE: typeof(addr)=[sockaddr*, sockaddr_in*, sockaddr_in6*, sockaddr_un*]
  92. // char buf[SOCKADDR_STRLEN] = {0};
  93. // SOCKADDR_STR(addr, buf);
  94. static inline const char* sockaddr_str(sockaddr_un* addr, char* buf, int len) {
  95. char ip[SOCKADDR_STRLEN] = {0};
  96. uint16_t port = 0;
  97. if (addr->sa.sa_family == AF_INET) {
  98. inet_ntop(AF_INET, &addr->sin.sin_addr, ip, len);
  99. port = htons(addr->sin.sin_port);
  100. snprintf(buf, len, "%s:%d", ip, port);
  101. }
  102. else if (addr->sa.sa_family == AF_INET6) {
  103. inet_ntop(AF_INET6, &addr->sin6.sin6_addr, ip, len);
  104. port = htons(addr->sin6.sin6_port);
  105. snprintf(buf, len, "[%s]:%d", ip, port);
  106. }
  107. return buf;
  108. }
  109. static inline void sockaddr_print(sockaddr_un* addr) {
  110. char buf[SOCKADDR_STRLEN] = {0};
  111. sockaddr_str(addr, buf, sizeof(buf));
  112. puts(buf);
  113. }
  114. static inline int sockaddr_assign(sockaddr_un* addr, const char* host, int port) {
  115. if (host) {
  116. int ret = Resolver(host, addr);
  117. if (ret != 0) return ret;
  118. }
  119. else {
  120. addr->sin.sin_family = AF_INET;
  121. addr->sin.sin_addr.s_addr = htonl(INADDR_ANY);
  122. }
  123. sockaddr_set_port(addr, port);
  124. return 0;
  125. }
  126. // socket -> setsockopt -> bind
  127. // @param type: SOCK_STREAM(tcp) SOCK_DGRAM(udp)
  128. // @return sockfd
  129. int Bind(int port, const char* host DEFAULT(ANYADDR), int type DEFAULT(SOCK_STREAM));
  130. // Bind -> listen
  131. // @return sockfd
  132. int Listen(int port, const char* host DEFAULT(ANYADDR));
  133. // @return sockfd
  134. // Resolver -> socket -> nonblocking -> connect
  135. int Connect(const char* host, int port, int nonblock DEFAULT(0));
  136. // Connect(host, port, 1)
  137. int ConnectNonblock(const char* host, int port);
  138. // Connect(host, port, 1) -> select -> blocking
  139. #define DEFAULT_CONNECT_TIMEOUT 5000 // ms
  140. int ConnectTimeout(const char* host, int port, int ms DEFAULT(DEFAULT_CONNECT_TIMEOUT));
  141. // Just implement Socketpair(AF_INET, SOCK_STREAM, 0, sv);
  142. int Socketpair(int family, int type, int protocol, int sv[2]);
  143. static inline int tcp_nodelay(int sockfd, int on DEFAULT(1)) {
  144. return setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(int));
  145. }
  146. static inline int tcp_nopush(int sockfd, int on DEFAULT(1)) {
  147. #ifdef TCP_NOPUSH
  148. return setsockopt(sockfd, IPPROTO_TCP, TCP_NOPUSH, (const char*)&on, sizeof(int));
  149. #elif defined(TCP_CORK)
  150. return setsockopt(sockfd, IPPROTO_TCP, TCP_CORK, (const char*)&on, sizeof(int));
  151. #else
  152. return -10;
  153. #endif
  154. }
  155. static inline int tcp_keepalive(int sockfd, int on DEFAULT(1), int delay DEFAULT(60)) {
  156. if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (const char*)&on, sizeof(int)) != 0) {
  157. return socket_errno();
  158. }
  159. #ifdef TCP_KEEPALIVE
  160. return setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE, (const char*)&delay, sizeof(int));
  161. #elif defined(TCP_KEEPIDLE)
  162. // TCP_KEEPIDLE => tcp_keepalive_time
  163. // TCP_KEEPCNT => tcp_keepalive_probes
  164. // TCP_KEEPINTVL => tcp_keepalive_intvl
  165. return setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (const char*)&delay, sizeof(int));
  166. #else
  167. return 0;
  168. #endif
  169. }
  170. static inline int udp_broadcast(int sockfd, int on DEFAULT(1)) {
  171. return setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const char*)&on, sizeof(int));
  172. }
  173. // send timeout
  174. static inline int so_sndtimeo(int sockfd, int timeout) {
  175. #ifdef OS_WIN
  176. return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(int));
  177. #else
  178. struct timeval tv = {timeout/1000, (timeout%1000)*1000};
  179. return setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
  180. #endif
  181. }
  182. // recv timeout
  183. static inline int so_rcvtimeo(int sockfd, int timeout) {
  184. #ifdef OS_WIN
  185. return setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(int));
  186. #else
  187. struct timeval tv = {timeout/1000, (timeout%1000)*1000};
  188. return setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
  189. #endif
  190. }
  191. END_EXTERN_C
  192. #endif // HV_SOCKET_H_