Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

test: add udp4_echo_server helper

  • Loading branch information...
bnoordhuis committed Jan 13, 2012
1 parent a13584b commit dc3b80a50f53c7c69ebeeb685c1371bc5589807e
Showing with 66 additions and 0 deletions.
  1. +64 −0 test/echo-server.c
  2. +1 −0 test/task.h
  3. +1 −0 test/test-list.h
@@ -34,6 +34,7 @@ static uv_loop_t* loop;
static int server_closed;
static stream_type serverType;
static uv_tcp_t tcpServer;
static uv_udp_t udpServer;
static uv_pipe_t pipeServer;
static uv_handle_t* server;

@@ -176,6 +177,34 @@ static void on_server_close(uv_handle_t* handle) {
}


static void on_send(uv_udp_send_t* req, int status);


static void on_recv(uv_udp_t* handle,
ssize_t nread,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags) {
uv_udp_send_t* req;
int r;

ASSERT(nread > 0);
ASSERT(addr->sa_family == AF_INET);

req = malloc(sizeof(*req));
ASSERT(req != NULL);

r = uv_udp_send(req, handle, &buf, 1, *(struct sockaddr_in*)addr, on_send);
ASSERT(r == 0);
}


static void on_send(uv_udp_send_t* req, int status) {
ASSERT(status == 0);
free(req);
}


static int tcp4_echo_start(int port) {
struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", port);
int r;
@@ -242,6 +271,30 @@ static int tcp6_echo_start(int port) {
}


static int udp4_echo_start(int port) {
int r;

server = (uv_handle_t*)&udpServer;
serverType = UDP;

r = uv_udp_init(loop, &udpServer);
if (r) {
fprintf(stderr, "uv_udp_init: %s\n",
uv_strerror(uv_last_error(loop)));
return 1;
}

r = uv_udp_recv_start(&udpServer, echo_alloc, on_recv);
if (r) {
fprintf(stderr, "uv_udp_recv_start: %s\n",
uv_strerror(uv_last_error(loop)));
return 1;
}

return 0;
}


static int pipe_echo_start(char* pipeName) {
int r;

@@ -304,3 +357,14 @@ HELPER_IMPL(pipe_echo_server) {
uv_run(loop);
return 0;
}


HELPER_IMPL(udp4_echo_server) {
loop = uv_default_loop();

if (udp4_echo_start(TEST_PORT))
return 1;

uv_run(loop);
return 0;
}
@@ -42,6 +42,7 @@

typedef enum {
TCP = 0,
UDP,
PIPE
} stream_type;

@@ -128,6 +128,7 @@ TEST_DECLARE (listen_no_simultaneous_accepts)
#endif
HELPER_DECLARE (tcp4_echo_server)
HELPER_DECLARE (tcp6_echo_server)
HELPER_DECLARE (udp4_echo_server)
HELPER_DECLARE (pipe_echo_server)


7 comments on commit dc3b80a

@DavidJFelix

This comment has been minimized.

Copy link

replied Nov 7, 2013

Not sure if this will be seen, but it's worth a question.

Isn't the process:

  • uv_udp_init
  • uv_udp_open / uv_udp_bind
  • uv_udp_recv_start / uv_udp_send

??

In this test the recv_start happens immediately after init without an open or bind. So then what's the point of open and bind?

@bnoordhuis

This comment has been minimized.

Copy link
Contributor Author

replied Nov 7, 2013

@DavidJFelix uv_udp_open() is for using a file descriptor you control, uv_udp_bind() for binding to a specific address and port. If you don't call uv_udp_bind() first, the operating system will do an implicit bind to the 'any address' with a random port. You can also do an explicit bind to a random port by specifying 0 as the port number, by the way.

@DavidJFelix

This comment has been minimized.

Copy link

replied Nov 8, 2013

Thanks for the quick response. This makes some sense, but I'm still not clear on why the bind is unneeded in this test. Doesn't the implied client need to know which port to send it's message to on the server? I'm not trying to imply that the test is incorrect in anyway, I'm just using it and the libuv tutorials as models and this was an inconsistency I noted between the two.

@bnoordhuis

This comment has been minimized.

Copy link
Contributor Author

replied Nov 8, 2013

The server's recv callback gets a struct sockaddr that contains the address and the port of the sender. If you look at line 197, you can see how the server basically bounces back the message to the sender.

@DavidJFelix

This comment has been minimized.

Copy link

replied Nov 8, 2013

I understand how the server gets the client's port, but how does the client get the server's port:

  • Client sends message to server addr:port
  • Server receives message and client addr:port
  • Sever echos message to client addr:port

So in theory, an echo server should always bind (or at least check what it's port is so that clients can be told which port it is operating on). Is this a correct assumption on my part?

@bnoordhuis

This comment has been minimized.

Copy link
Contributor Author

replied Nov 8, 2013

So in theory, an echo server should always bind

If you want to be reachable at a well-known address/port (e.g. 0.0.0.0:53 for a DNS server), then yes: you must call uv_udp_bind().

@DavidJFelix

This comment has been minimized.

Copy link

replied Nov 8, 2013

Awesome! Thanks for your help and writing this in the first place. I wouldn't be nearly as far into my project without it.

Please sign in to comment.
You can’t perform that action at this time.