PageRenderTime 36ms CodeModel.GetById 15ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

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