hsocket.h 6.6 KB

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