endpoint.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. // Copyright (c) 2011 Baidu.com, Inc. All Rights Reserved
  2. //
  3. // Implement base/endpoint.h
  4. //
  5. // Author: Ge,Jun (gejun@baidu.com)
  6. // Date: Mon. Nov 7 14:47:36 CST 2011
  7. #include <arpa/inet.h> // inet_pton, inet_ntop
  8. #include <netdb.h> // gethostbyname_r
  9. #include <unistd.h> // gethostname
  10. #include <errno.h> // errno
  11. #include <string.h> // strcpy
  12. #include <stdio.h> // snprintf
  13. #include <stdlib.h> // strtol
  14. #include "base/fd_guard.h" // fd_guard
  15. #include "base/endpoint.h" // ip_t
  16. #include "base/logging.h"
  17. #include "base/memory/singleton_on_pthread_once.h"
  18. __BEGIN_DECLS
  19. int BAIDU_WEAK bthread_connect(
  20. int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) {
  21. return connect(sockfd, serv_addr, addrlen);
  22. }
  23. __END_DECLS
  24. namespace base {
  25. int str2ip(const char* ip_str, ip_t* ip) {
  26. // ip_str can be NULL when called by EndPoint(0, ...)
  27. if (ip_str != NULL) {
  28. for (; isspace(*ip_str); ++ip_str);
  29. int rc = inet_pton(AF_INET, ip_str, ip);
  30. if (rc > 0) {
  31. return 0;
  32. }
  33. }
  34. return -1;
  35. }
  36. IPStr ip2str(ip_t ip) {
  37. IPStr str;
  38. if (inet_ntop(AF_INET, &ip, str._buf, INET_ADDRSTRLEN) == NULL) {
  39. return ip2str(IP_NONE);
  40. }
  41. return str;
  42. }
  43. int ip2hostname(ip_t ip, char* host, size_t host_len) {
  44. if (host == NULL || host_len == 0) {
  45. errno = EINVAL;
  46. return -1;
  47. }
  48. sockaddr_in sa;
  49. bzero((char*)&sa, sizeof(sa));
  50. sa.sin_family = AF_INET;
  51. sa.sin_port = 0; // useless since we don't need server_name
  52. sa.sin_addr = ip;
  53. if (getnameinfo((const sockaddr*)&sa, sizeof(sa),
  54. host, host_len, NULL, 0, NI_NAMEREQD) != 0) {
  55. return -1;
  56. }
  57. // remove baidu-specific domain name (that every name has)
  58. base::StringPiece str(host);
  59. if (str.ends_with(".baidu.com")) {
  60. host[str.size() - 10] = '\0';
  61. }
  62. return 0;
  63. }
  64. int ip2hostname(ip_t ip, std::string* host) {
  65. char buf[128];
  66. if (ip2hostname(ip, buf, sizeof(buf)) == 0) {
  67. host->assign(buf);
  68. return 0;
  69. }
  70. return -1;
  71. }
  72. EndPointStr endpoint2str(const EndPoint& point) {
  73. EndPointStr str;
  74. if (inet_ntop(AF_INET, &point.ip, str._buf, INET_ADDRSTRLEN) == NULL) {
  75. return endpoint2str(EndPoint(IP_NONE, 0));
  76. }
  77. char* buf = str._buf + strlen(str._buf);
  78. *buf++ = ':';
  79. snprintf(buf, 16, "%d", point.port);
  80. return str;
  81. }
  82. int hostname2ip(const char* hostname, ip_t* ip) {
  83. char buf[256];
  84. if (NULL == hostname) {
  85. if (gethostname(buf, sizeof(buf)) < 0) {
  86. return -1;
  87. }
  88. hostname = buf;
  89. } else {
  90. // skip heading space
  91. for (; isspace(*hostname); ++hostname);
  92. }
  93. char aux_buf[1024];
  94. int error = 0;
  95. struct hostent ent;
  96. struct hostent* result = NULL;
  97. if (gethostbyname_r(hostname, &ent, aux_buf, sizeof(aux_buf),
  98. &result, &error) != 0 || result == NULL) {
  99. return -1;
  100. }
  101. // Only fetch the first address here
  102. bcopy((char*)result->h_addr, (char*)ip, result->h_length);
  103. return 0;
  104. }
  105. struct MyAddressInfo {
  106. char my_hostname[256];
  107. ip_t my_ip;
  108. IPStr my_ip_str;
  109. MyAddressInfo() {
  110. my_ip = IP_ANY;
  111. if (gethostname(my_hostname, sizeof(my_hostname)) < 0) {
  112. my_hostname[0] = '\0';
  113. } else if (hostname2ip(my_hostname, &my_ip) != 0) {
  114. my_ip = IP_ANY;
  115. }
  116. my_ip_str = ip2str(my_ip);
  117. }
  118. };
  119. ip_t my_ip() {
  120. return get_leaky_singleton<MyAddressInfo>()->my_ip;
  121. }
  122. const char* my_ip_cstr() {
  123. return get_leaky_singleton<MyAddressInfo>()->my_ip_str.c_str();
  124. }
  125. const char* my_hostname() {
  126. return get_leaky_singleton<MyAddressInfo>()->my_hostname;
  127. }
  128. int str2endpoint(const char* str, EndPoint* point) {
  129. // Should be enough to hold ip address
  130. char buf[64];
  131. size_t i = 0;
  132. for (; i < sizeof(buf) && str[i] != '\0' && str[i] != ':'; ++i) {
  133. buf[i] = str[i];
  134. }
  135. if (i >= sizeof(buf) || str[i] != ':') {
  136. return -1;
  137. }
  138. buf[i] = '\0';
  139. if (str2ip(buf, &point->ip) != 0) {
  140. return -1;
  141. }
  142. ++i;
  143. char* end = NULL;
  144. point->port = strtol(str + i, &end, 10);
  145. if (end == str + i) {
  146. return -1;
  147. } else if (*end) {
  148. for (++end; isspace(*end); ++end);
  149. if (*end) {
  150. return -1;
  151. }
  152. }
  153. if (point->port < 0 || point->port > 65535) {
  154. return -1;
  155. }
  156. return 0;
  157. }
  158. int str2endpoint(const char* ip_str, int port, EndPoint* point) {
  159. if (str2ip(ip_str, &point->ip) != 0) {
  160. return -1;
  161. }
  162. if (port < 0 || port > 65535) {
  163. return -1;
  164. }
  165. point->port = port;
  166. return 0;
  167. }
  168. int hostname2endpoint(const char* str, EndPoint* point) {
  169. // Should be enough to hold ip address
  170. char buf[64];
  171. size_t i = 0;
  172. for (; i < sizeof(buf) - 1 && str[i] != '\0' && str[i] != ':'; ++i) {
  173. buf[i] = str[i];
  174. }
  175. if (i == sizeof(buf) - 1) {
  176. return -1;
  177. }
  178. buf[i] = '\0';
  179. if (hostname2ip(buf, &point->ip) != 0) {
  180. return -1;
  181. }
  182. if (str[i] == ':') {
  183. ++i;
  184. }
  185. char* end = NULL;
  186. point->port = strtol(str + i, &end, 10);
  187. if (end == str + i) {
  188. return -1;
  189. } else if (*end) {
  190. for (; isspace(*end); ++end);
  191. if (*end) {
  192. return -1;
  193. }
  194. }
  195. if (point->port < 0 || point->port > 65535) {
  196. return -1;
  197. }
  198. return 0;
  199. }
  200. int hostname2endpoint(const char* name_str, int port, EndPoint* point) {
  201. if (hostname2ip(name_str, &point->ip) != 0) {
  202. return -1;
  203. }
  204. if (port < 0 || port > 65535) {
  205. return -1;
  206. }
  207. point->port = port;
  208. return 0;
  209. }
  210. int endpoint2hostname(const EndPoint& point, char* host, size_t host_len) {
  211. if (ip2hostname(point.ip, host, host_len) == 0) {
  212. size_t len = strlen(host);
  213. if (len + 1 < host_len) {
  214. snprintf(host + len, host_len - len, ":%d", point.port);
  215. }
  216. return 0;
  217. }
  218. return -1;
  219. }
  220. int endpoint2hostname(const EndPoint& point, std::string* host) {
  221. char buf[128];
  222. if (endpoint2hostname(point, buf, sizeof(buf)) == 0) {
  223. host->assign(buf);
  224. return 0;
  225. }
  226. return -1;
  227. }
  228. int tcp_connect(EndPoint point, int* self_port) {
  229. fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
  230. if (sockfd < 0) {
  231. return -1;
  232. }
  233. struct sockaddr_in serv_addr;
  234. bzero((char*)&serv_addr, sizeof(serv_addr));
  235. serv_addr.sin_family = AF_INET;
  236. serv_addr.sin_addr = point.ip;
  237. serv_addr.sin_port = htons(point.port);
  238. int rc = 0;
  239. if (bthread_connect != NULL) {
  240. rc = bthread_connect(sockfd, (struct sockaddr*)&serv_addr,
  241. sizeof(serv_addr));
  242. } else {
  243. rc = ::connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
  244. }
  245. if (rc < 0) {
  246. return -1;
  247. }
  248. if (self_port != NULL) {
  249. EndPoint pt;
  250. if (get_local_side(sockfd, &pt) == 0) {
  251. *self_port = pt.port;
  252. } else {
  253. CHECK(false) << "Fail to get the local port of sockfd=" << sockfd;
  254. }
  255. }
  256. return sockfd.release();
  257. }
  258. int tcp_listen(EndPoint point, bool reuse_addr) {
  259. fd_guard sockfd(socket(AF_INET, SOCK_STREAM, 0));
  260. if (sockfd < 0) {
  261. return -1;
  262. }
  263. if (reuse_addr) {
  264. const int on = 1;
  265. if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
  266. &on, sizeof(on)) != 0) {
  267. return -1;
  268. }
  269. }
  270. struct sockaddr_in serv_addr;
  271. bzero((char*)&serv_addr, sizeof(serv_addr));
  272. serv_addr.sin_family = AF_INET;
  273. serv_addr.sin_addr = point.ip;
  274. serv_addr.sin_port = htons(point.port);
  275. if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) != 0) {
  276. return -1;
  277. }
  278. if (listen(sockfd, INT_MAX) != 0) {
  279. // ^^^ kernel would silently truncate backlog to the value
  280. // defined in /proc/sys/net/core/somaxconn
  281. return -1;
  282. }
  283. return sockfd.release();
  284. }
  285. int get_local_side(int fd, EndPoint *out) {
  286. struct sockaddr addr;
  287. socklen_t socklen = sizeof(addr);
  288. const int rc = getsockname(fd, &addr, &socklen);
  289. if (rc != 0) {
  290. return rc;
  291. }
  292. if (out) {
  293. *out = base::EndPoint(*(sockaddr_in*)&addr);
  294. }
  295. return 0;
  296. }
  297. int get_remote_side(int fd, EndPoint *out) {
  298. struct sockaddr addr;
  299. socklen_t socklen = sizeof(addr);
  300. const int rc = getpeername(fd, &addr, &socklen);
  301. if (rc != 0) {
  302. return rc;
  303. }
  304. if (out) {
  305. *out = base::EndPoint(*(sockaddr_in*)&addr);
  306. }
  307. return 0;
  308. }
  309. } // namespace base