/test/test-getsockname.c

http://github.com/joyent/libuv · C · 344 lines · 232 code · 86 blank · 26 comment · 40 complexity · 39b5075c5123cdac68cc0e343c0b0e84 MD5 · raw file

  1. /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to
  5. * deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. * sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19. * IN THE SOFTWARE.
  20. */
  21. #include "uv.h"
  22. #include "task.h"
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. static const int server_port = TEST_PORT;
  27. /* Will be updated right after making the uv_connect_call */
  28. static int connect_port = -1;
  29. static int getsocknamecount = 0;
  30. static int getpeernamecount = 0;
  31. static uv_loop_t* loop;
  32. static uv_tcp_t tcp;
  33. static uv_udp_t udp;
  34. static uv_connect_t connect_req;
  35. static uv_tcp_t tcpServer;
  36. static uv_udp_t udpServer;
  37. static uv_udp_send_t send_req;
  38. static uv_buf_t alloc(uv_handle_t* handle, size_t suggested_size) {
  39. uv_buf_t buf;
  40. buf.base = (char*) malloc(suggested_size);
  41. buf.len = suggested_size;
  42. return buf;
  43. }
  44. static void on_close(uv_handle_t* peer) {
  45. free(peer);
  46. uv_close((uv_handle_t*)&tcpServer, NULL);
  47. }
  48. static void after_shutdown(uv_shutdown_t* req, int status) {
  49. uv_close((uv_handle_t*) req->handle, on_close);
  50. free(req);
  51. }
  52. static void after_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
  53. uv_shutdown_t* req;
  54. int r;
  55. if (buf.base) {
  56. free(buf.base);
  57. }
  58. req = (uv_shutdown_t*) malloc(sizeof *req);
  59. r = uv_shutdown(req, handle, after_shutdown);
  60. ASSERT(r == 0);
  61. }
  62. static void check_sockname(struct sockaddr* addr, const char* compare_ip,
  63. int compare_port, const char* context) {
  64. struct sockaddr_in check_addr = *(struct sockaddr_in*) addr;
  65. struct sockaddr_in compare_addr = uv_ip4_addr(compare_ip, compare_port);
  66. char check_ip[17];
  67. int r;
  68. /* Both addresses should be ipv4 */
  69. ASSERT(check_addr.sin_family == AF_INET);
  70. ASSERT(compare_addr.sin_family == AF_INET);
  71. /* Check if the ip matches */
  72. ASSERT(memcmp(&check_addr.sin_addr,
  73. &compare_addr.sin_addr,
  74. sizeof compare_addr.sin_addr) == 0);
  75. /* Check if the port matches. If port == 0 anything goes. */
  76. ASSERT(compare_port == 0 || check_addr.sin_port == compare_addr.sin_port);
  77. r = uv_ip4_name(&check_addr, (char*) check_ip, sizeof check_ip);
  78. ASSERT(r == 0);
  79. printf("%s: %s:%d\n", context, check_ip, ntohs(check_addr.sin_port));
  80. }
  81. static void on_connection(uv_stream_t* server, int status) {
  82. struct sockaddr sockname, peername;
  83. int namelen;
  84. uv_tcp_t* handle;
  85. int r;
  86. if (status != 0) {
  87. fprintf(stderr, "Connect error %d\n",
  88. uv_last_error(loop).code);
  89. }
  90. ASSERT(status == 0);
  91. handle = malloc(sizeof(*handle));
  92. ASSERT(handle != NULL);
  93. r = uv_tcp_init(loop, handle);
  94. ASSERT(r == 0);
  95. /* associate server with stream */
  96. handle->data = server;
  97. r = uv_accept(server, (uv_stream_t*)handle);
  98. ASSERT(r == 0);
  99. namelen = sizeof sockname;
  100. r = uv_tcp_getsockname(handle, &sockname, &namelen);
  101. ASSERT(r == 0);
  102. check_sockname(&sockname, "127.0.0.1", server_port, "accepted socket");
  103. getsocknamecount++;
  104. namelen = sizeof peername;
  105. r = uv_tcp_getpeername(handle, &peername, &namelen);
  106. ASSERT(r == 0);
  107. check_sockname(&peername, "127.0.0.1", connect_port, "accepted socket peer");
  108. getpeernamecount++;
  109. r = uv_read_start((uv_stream_t*)handle, alloc, after_read);
  110. ASSERT(r == 0);
  111. }
  112. static void on_connect(uv_connect_t* req, int status) {
  113. struct sockaddr sockname, peername;
  114. int r, namelen;
  115. ASSERT(status == 0);
  116. namelen = sizeof sockname;
  117. r = uv_tcp_getsockname((uv_tcp_t*) req->handle, &sockname, &namelen);
  118. ASSERT(r == 0);
  119. check_sockname(&sockname, "127.0.0.1", 0, "connected socket");
  120. getsocknamecount++;
  121. namelen = sizeof peername;
  122. r = uv_tcp_getpeername((uv_tcp_t*) req->handle, &peername, &namelen);
  123. ASSERT(r == 0);
  124. check_sockname(&peername, "127.0.0.1", server_port, "connected socket peer");
  125. getpeernamecount++;
  126. uv_close((uv_handle_t*)&tcp, NULL);
  127. }
  128. static int tcp_listener() {
  129. struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", server_port);
  130. struct sockaddr sockname, peername;
  131. int namelen;
  132. int r;
  133. r = uv_tcp_init(loop, &tcpServer);
  134. if (r) {
  135. fprintf(stderr, "Socket creation error\n");
  136. return 1;
  137. }
  138. r = uv_tcp_bind(&tcpServer, addr);
  139. if (r) {
  140. fprintf(stderr, "Bind error\n");
  141. return 1;
  142. }
  143. r = uv_listen((uv_stream_t*)&tcpServer, 128, on_connection);
  144. if (r) {
  145. fprintf(stderr, "Listen error\n");
  146. return 1;
  147. }
  148. memset(&sockname, -1, sizeof sockname);
  149. namelen = sizeof sockname;
  150. r = uv_tcp_getsockname(&tcpServer, &sockname, &namelen);
  151. ASSERT(r == 0);
  152. check_sockname(&sockname, "0.0.0.0", server_port, "server socket");
  153. getsocknamecount++;
  154. namelen = sizeof sockname;
  155. r = uv_tcp_getpeername(&tcpServer, &peername, &namelen);
  156. ASSERT(r == -1);
  157. ASSERT(uv_last_error(loop).code == UV_ENOTCONN);
  158. getpeernamecount++;
  159. return 0;
  160. }
  161. static void tcp_connector() {
  162. struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", server_port);
  163. struct sockaddr sockname;
  164. int r, namelen;
  165. r = uv_tcp_init(loop, &tcp);
  166. tcp.data = &connect_req;
  167. ASSERT(!r);
  168. r = uv_tcp_connect(&connect_req, &tcp, server_addr, on_connect);
  169. ASSERT(!r);
  170. /* Fetch the actual port used by the connecting socket. */
  171. namelen = sizeof sockname;
  172. r = uv_tcp_getsockname(&tcp, &sockname, &namelen);
  173. ASSERT(!r);
  174. ASSERT(sockname.sa_family == AF_INET);
  175. connect_port = ntohs(((struct sockaddr_in*) &sockname)->sin_port);
  176. ASSERT(connect_port > 0);
  177. }
  178. static void udp_recv(uv_udp_t* handle,
  179. ssize_t nread,
  180. uv_buf_t buf,
  181. struct sockaddr* addr,
  182. unsigned flags) {
  183. struct sockaddr sockname;
  184. int namelen;
  185. int r;
  186. ASSERT(nread >= 0);
  187. free(buf.base);
  188. if (nread == 0) {
  189. return;
  190. }
  191. memset(&sockname, -1, sizeof sockname);
  192. namelen = sizeof(sockname);
  193. r = uv_udp_getsockname(&udp, &sockname, &namelen);
  194. ASSERT(r == 0);
  195. check_sockname(&sockname, "0.0.0.0", 0, "udp receiving socket");
  196. getsocknamecount++;
  197. uv_close((uv_handle_t*) &udp, NULL);
  198. uv_close((uv_handle_t*) handle, NULL);
  199. }
  200. static void udp_send(uv_udp_send_t* req, int status) {
  201. }
  202. static int udp_listener() {
  203. struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", server_port);
  204. struct sockaddr sockname;
  205. int namelen;
  206. int r;
  207. r = uv_udp_init(loop, &udpServer);
  208. if (r) {
  209. fprintf(stderr, "Socket creation error\n");
  210. return 1;
  211. }
  212. r = uv_udp_bind(&udpServer, addr, 0);
  213. if (r) {
  214. fprintf(stderr, "Bind error\n");
  215. return 1;
  216. }
  217. memset(&sockname, -1, sizeof sockname);
  218. namelen = sizeof sockname;
  219. r = uv_udp_getsockname(&udpServer, &sockname, &namelen);
  220. ASSERT(r == 0);
  221. check_sockname(&sockname, "0.0.0.0", server_port, "udp listener socket");
  222. getsocknamecount++;
  223. r = uv_udp_recv_start(&udpServer, alloc, udp_recv);
  224. ASSERT(r == 0);
  225. return 0;
  226. }
  227. static void udp_sender(void) {
  228. struct sockaddr_in server_addr;
  229. uv_buf_t buf;
  230. int r;
  231. r = uv_udp_init(loop, &udp);
  232. ASSERT(!r);
  233. buf = uv_buf_init("PING", 4);
  234. server_addr = uv_ip4_addr("127.0.0.1", server_port);
  235. r = uv_udp_send(&send_req, &udp, &buf, 1, server_addr, udp_send);
  236. ASSERT(!r);
  237. }
  238. TEST_IMPL(getsockname_tcp) {
  239. loop = uv_default_loop();
  240. if (tcp_listener())
  241. return 1;
  242. tcp_connector();
  243. uv_run(loop);
  244. ASSERT(getsocknamecount == 3);
  245. ASSERT(getpeernamecount == 3);
  246. MAKE_VALGRIND_HAPPY();
  247. return 0;
  248. }
  249. TEST_IMPL(getsockname_udp) {
  250. loop = uv_default_loop();
  251. if (udp_listener())
  252. return 1;
  253. udp_sender();
  254. uv_run(loop);
  255. ASSERT(getsocknamecount == 2);
  256. MAKE_VALGRIND_HAPPY();
  257. return 0;
  258. }