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 22 #include "uv.h" 23 #include "task.h" 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 29 static const int server_port = TEST_PORT; 30 /* Will be updated right after making the uv_connect_call */ 31 static int connect_port = -1; 32 33 static int getsocknamecount = 0; 34 static int getpeernamecount = 0; 35 36 static uv_loop_t* loop; 37 static uv_tcp_t tcp; 38 static uv_udp_t udp; 39 static uv_connect_t connect_req; 40 static uv_tcp_t tcpServer; 41 static uv_udp_t udpServer; 42 static uv_udp_send_t send_req; 43 44 45 static void alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { 46 buf->base = malloc(suggested_size); 47 buf->len = suggested_size; 48 } 49 50 51 static void on_close(uv_handle_t* peer) { 52 free(peer); 53 uv_close((uv_handle_t*)&tcpServer, NULL); 54 } 55 56 57 static void after_shutdown(uv_shutdown_t* req, int status) { 58 uv_close((uv_handle_t*) req->handle, on_close); 59 free(req); 60 } 61 62 63 static void after_read(uv_stream_t* handle, 64 ssize_t nread, 65 const uv_buf_t* buf) { 66 uv_shutdown_t* req; 67 int r; 68 69 if (buf->base) { 70 free(buf->base); 71 } 72 73 req = (uv_shutdown_t*) malloc(sizeof *req); 74 r = uv_shutdown(req, handle, after_shutdown); 75 ASSERT(r == 0); 76 } 77 78 79 static void check_sockname(struct sockaddr* addr, const char* compare_ip, 80 int compare_port, const char* context) { 81 struct sockaddr_in check_addr = *(struct sockaddr_in*) addr; 82 struct sockaddr_in compare_addr; 83 char check_ip[17]; 84 int r; 85 86 ASSERT(0 == uv_ip4_addr(compare_ip, compare_port, &compare_addr)); 87 88 /* Both addresses should be ipv4 */ 89 ASSERT(check_addr.sin_family == AF_INET); 90 ASSERT(compare_addr.sin_family == AF_INET); 91 92 /* Check if the ip matches */ 93 ASSERT(memcmp(&check_addr.sin_addr, 94 &compare_addr.sin_addr, 95 sizeof compare_addr.sin_addr) == 0); 96 97 /* Check if the port matches. If port == 0 anything goes. */ 98 ASSERT(compare_port == 0 || check_addr.sin_port == compare_addr.sin_port); 99 100 r = uv_ip4_name(&check_addr, (char*) check_ip, sizeof check_ip); 101 ASSERT(r == 0); 102 103 printf("%s: %s:%d\n", context, check_ip, ntohs(check_addr.sin_port)); 104 } 105 106 107 static void on_connection(uv_stream_t* server, int status) { 108 struct sockaddr sockname, peername; 109 int namelen; 110 uv_tcp_t* handle; 111 int r; 112 113 if (status != 0) { 114 fprintf(stderr, "Connect error %s\n", uv_err_name(status)); 115 } 116 ASSERT(status == 0); 117 118 handle = malloc(sizeof(*handle)); 119 ASSERT(handle != NULL); 120 121 r = uv_tcp_init(loop, handle); 122 ASSERT(r == 0); 123 124 /* associate server with stream */ 125 handle->data = server; 126 127 r = uv_accept(server, (uv_stream_t*)handle); 128 ASSERT(r == 0); 129 130 namelen = sizeof sockname; 131 r = uv_tcp_getsockname(handle, &sockname, &namelen); 132 ASSERT(r == 0); 133 check_sockname(&sockname, "127.0.0.1", server_port, "accepted socket"); 134 getsocknamecount++; 135 136 namelen = sizeof peername; 137 r = uv_tcp_getpeername(handle, &peername, &namelen); 138 ASSERT(r == 0); 139 check_sockname(&peername, "127.0.0.1", connect_port, "accepted socket peer"); 140 getpeernamecount++; 141 142 r = uv_read_start((uv_stream_t*)handle, alloc, after_read); 143 ASSERT(r == 0); 144 } 145 146 147 static void on_connect(uv_connect_t* req, int status) { 148 struct sockaddr sockname, peername; 149 int r, namelen; 150 151 ASSERT(status == 0); 152 153 namelen = sizeof sockname; 154 r = uv_tcp_getsockname((uv_tcp_t*) req->handle, &sockname, &namelen); 155 ASSERT(r == 0); 156 check_sockname(&sockname, "127.0.0.1", 0, "connected socket"); 157 getsocknamecount++; 158 159 namelen = sizeof peername; 160 r = uv_tcp_getpeername((uv_tcp_t*) req->handle, &peername, &namelen); 161 ASSERT(r == 0); 162 check_sockname(&peername, "127.0.0.1", server_port, "connected socket peer"); 163 getpeernamecount++; 164 165 uv_close((uv_handle_t*)&tcp, NULL); 166 } 167 168 169 static int tcp_listener(void) { 170 struct sockaddr_in addr; 171 struct sockaddr sockname, peername; 172 int namelen; 173 int r; 174 175 ASSERT(0 == uv_ip4_addr("0.0.0.0", server_port, &addr)); 176 177 r = uv_tcp_init(loop, &tcpServer); 178 if (r) { 179 fprintf(stderr, "Socket creation error\n"); 180 return 1; 181 } 182 183 r = uv_tcp_bind(&tcpServer, (const struct sockaddr*) &addr, 0); 184 if (r) { 185 fprintf(stderr, "Bind error\n"); 186 return 1; 187 } 188 189 r = uv_listen((uv_stream_t*)&tcpServer, 128, on_connection); 190 if (r) { 191 fprintf(stderr, "Listen error\n"); 192 return 1; 193 } 194 195 memset(&sockname, -1, sizeof sockname); 196 namelen = sizeof sockname; 197 r = uv_tcp_getsockname(&tcpServer, &sockname, &namelen); 198 ASSERT(r == 0); 199 check_sockname(&sockname, "0.0.0.0", server_port, "server socket"); 200 getsocknamecount++; 201 202 namelen = sizeof sockname; 203 r = uv_tcp_getpeername(&tcpServer, &peername, &namelen); 204 ASSERT(r == UV_ENOTCONN); 205 getpeernamecount++; 206 207 return 0; 208 } 209 210 211 static void tcp_connector(void) { 212 struct sockaddr_in server_addr; 213 struct sockaddr sockname; 214 int r, namelen; 215 216 ASSERT(0 == uv_ip4_addr("127.0.0.1", server_port, &server_addr)); 217 218 r = uv_tcp_init(loop, &tcp); 219 tcp.data = &connect_req; 220 ASSERT(!r); 221 222 r = uv_tcp_connect(&connect_req, 223 &tcp, 224 (const struct sockaddr*) &server_addr, 225 on_connect); 226 ASSERT(!r); 227 228 /* Fetch the actual port used by the connecting socket. */ 229 namelen = sizeof sockname; 230 r = uv_tcp_getsockname(&tcp, &sockname, &namelen); 231 ASSERT(!r); 232 ASSERT(sockname.sa_family == AF_INET); 233 connect_port = ntohs(((struct sockaddr_in*) &sockname)->sin_port); 234 ASSERT(connect_port > 0); 235 } 236 237 238 static void udp_recv(uv_udp_t* handle, 239 ssize_t nread, 240 const uv_buf_t* buf, 241 const struct sockaddr* addr, 242 unsigned flags) { 243 struct sockaddr sockname; 244 int namelen; 245 int r; 246 247 ASSERT(nread >= 0); 248 free(buf->base); 249 250 if (nread == 0) { 251 return; 252 } 253 254 memset(&sockname, -1, sizeof sockname); 255 namelen = sizeof(sockname); 256 r = uv_udp_getsockname(&udp, &sockname, &namelen); 257 ASSERT(r == 0); 258 check_sockname(&sockname, "0.0.0.0", 0, "udp receiving socket"); 259 getsocknamecount++; 260 261 uv_close((uv_handle_t*) &udp, NULL); 262 uv_close((uv_handle_t*) handle, NULL); 263 } 264 265 266 static void udp_send(uv_udp_send_t* req, int status) { 267 268 } 269 270 271 static int udp_listener(void) { 272 struct sockaddr_in addr; 273 struct sockaddr sockname; 274 int namelen; 275 int r; 276 277 ASSERT(0 == uv_ip4_addr("0.0.0.0", server_port, &addr)); 278 279 r = uv_udp_init(loop, &udpServer); 280 if (r) { 281 fprintf(stderr, "Socket creation error\n"); 282 return 1; 283 } 284 285 r = uv_udp_bind(&udpServer, (const struct sockaddr*) &addr, 0); 286 if (r) { 287 fprintf(stderr, "Bind error\n"); 288 return 1; 289 } 290 291 memset(&sockname, -1, sizeof sockname); 292 namelen = sizeof sockname; 293 r = uv_udp_getsockname(&udpServer, &sockname, &namelen); 294 ASSERT(r == 0); 295 check_sockname(&sockname, "0.0.0.0", server_port, "udp listener socket"); 296 getsocknamecount++; 297 298 r = uv_udp_recv_start(&udpServer, alloc, udp_recv); 299 ASSERT(r == 0); 300 301 return 0; 302 } 303 304 305 static void udp_sender(void) { 306 struct sockaddr_in server_addr; 307 uv_buf_t buf; 308 int r; 309 310 r = uv_udp_init(loop, &udp); 311 ASSERT(!r); 312 313 buf = uv_buf_init("PING", 4); 314 ASSERT(0 == uv_ip4_addr("127.0.0.1", server_port, &server_addr)); 315 316 r = uv_udp_send(&send_req, 317 &udp, 318 &buf, 319 1, 320 (const struct sockaddr*) &server_addr, 321 udp_send); 322 ASSERT(!r); 323 } 324 325 326 TEST_IMPL(getsockname_tcp) { 327 loop = uv_default_loop(); 328 329 if (tcp_listener()) 330 return 1; 331 332 tcp_connector(); 333 334 uv_run(loop, UV_RUN_DEFAULT); 335 336 ASSERT(getsocknamecount == 3); 337 ASSERT(getpeernamecount == 3); 338 339 MAKE_VALGRIND_HAPPY(); 340 return 0; 341 } 342 343 344 TEST_IMPL(getsockname_udp) { 345 loop = uv_default_loop(); 346 347 if (udp_listener()) 348 return 1; 349 350 udp_sender(); 351 352 uv_run(loop, UV_RUN_DEFAULT); 353 354 ASSERT(getsocknamecount == 2); 355 356 ASSERT(udp.send_queue_size == 0); 357 ASSERT(udpServer.send_queue_size == 0); 358 359 MAKE_VALGRIND_HAPPY(); 360 return 0; 361 } 362