Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Commit

Permalink
include: uv_udp_send{6} now takes sockaddr_in*
Browse files Browse the repository at this point in the history
Passing or returning structs as values makes life hard for people that
work with libuv through a foreign function interface. Switch to a
pointer-based approach.

Fixes #684.
  • Loading branch information
bnoordhuis committed Sep 1, 2013
1 parent 525dbb5 commit 263da51
Show file tree
Hide file tree
Showing 16 changed files with 116 additions and 164 deletions.
2 changes: 1 addition & 1 deletion include/uv-unix.h
Expand Up @@ -213,7 +213,7 @@ typedef struct {
#define UV_UDP_SEND_PRIVATE_FIELDS \
void* queue[2]; \
struct sockaddr_in6 addr; \
int bufcnt; \
unsigned int nbufs; \
uv_buf_t* bufs; \
ssize_t status; \
uv_udp_send_cb send_cb; \
Expand Down
22 changes: 14 additions & 8 deletions include/uv.h
Expand Up @@ -991,16 +991,19 @@ UV_EXTERN int uv_udp_set_ttl(uv_udp_t* handle, int ttl);
* req UDP request handle. Need not be initialized.
* handle UDP handle. Should have been initialized with `uv_udp_init`.
* bufs List of buffers to send.
* bufcnt Number of buffers in `bufs`.
* nbufs Number of buffers in `bufs`.
* addr Address of the remote peer. See `uv_ip4_addr`.
* send_cb Callback to invoke when the data has been sent out.
*
* Returns:
* 0 on success, or an error code < 0 on failure.
*/
UV_EXTERN int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle,
uv_buf_t bufs[], int bufcnt, struct sockaddr_in addr,
uv_udp_send_cb send_cb);
UV_EXTERN int uv_udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
const struct sockaddr_in* addr,
uv_udp_send_cb send_cb);

/*
* Send data. If the socket has not previously been bound with `uv_udp_bind6`,
Expand All @@ -1010,16 +1013,19 @@ UV_EXTERN int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle,
* req UDP request handle. Need not be initialized.
* handle UDP handle. Should have been initialized with `uv_udp_init`.
* bufs List of buffers to send.
* bufcnt Number of buffers in `bufs`.
* nbufs Number of buffers in `bufs`.
* addr Address of the remote peer. See `uv_ip6_addr`.
* send_cb Callback to invoke when the data has been sent out.
*
* Returns:
* 0 on success, or an error code < 0 on failure.
*/
UV_EXTERN int uv_udp_send6(uv_udp_send_t* req, uv_udp_t* handle,
uv_buf_t bufs[], int bufcnt, struct sockaddr_in6 addr,
uv_udp_send_cb send_cb);
UV_EXTERN int uv_udp_send6(uv_udp_send_t* req,
uv_udp_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
const struct sockaddr_in6* addr,
uv_udp_send_cb send_cb);

/*
* Receive data. If the socket has not previously been bound with `uv_udp_bind`
Expand Down
83 changes: 15 additions & 68 deletions src/unix/udp.c
Expand Up @@ -35,13 +35,6 @@ static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents);
static void uv__udp_recvmsg(uv_loop_t* loop, uv__io_t* w, unsigned int revents);
static void uv__udp_sendmsg(uv_loop_t* loop, uv__io_t* w, unsigned int revents);
static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain);
static int uv__send(uv_udp_send_t* req,
uv_udp_t* handle,
uv_buf_t bufs[],
int bufcnt,
struct sockaddr* addr,
socklen_t addrlen,
uv_udp_send_cb send_cb);


void uv__udp_close(uv_udp_t* handle) {
Expand Down Expand Up @@ -100,8 +93,8 @@ static void uv__udp_run_pending(uv_udp_t* handle) {
h.msg_name = &req->addr;
h.msg_namelen = (req->addr.sin6_family == AF_INET6 ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
h.msg_iov = (struct iovec*)req->bufs;
h.msg_iovlen = req->bufcnt;
h.msg_iov = (struct iovec*) req->bufs;
h.msg_iovlen = req->nbufs;

do {
size = sendmsg(handle->io_watcher.fd, &h, 0);
Expand All @@ -116,19 +109,6 @@ static void uv__udp_run_pending(uv_udp_t* handle) {

req->status = (size == -1 ? -errno : size);

#ifndef NDEBUG
/* Sanity check. */
if (size != -1) {
ssize_t nbytes;
int i;

for (nbytes = i = 0; i < req->bufcnt; i++)
nbytes += req->bufs[i].len;

assert(size == nbytes);
}
#endif

/* Sending a datagram is an atomic operation: either all data
* is written or nothing is (and EMSGSIZE is raised). That is
* why we don't handle partial writes. Just pop the request
Expand Down Expand Up @@ -400,16 +380,16 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain) {
}


static int uv__send(uv_udp_send_t* req,
uv_udp_t* handle,
uv_buf_t bufs[],
int bufcnt,
struct sockaddr* addr,
socklen_t addrlen,
uv_udp_send_cb send_cb) {
int uv__udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
const struct sockaddr* addr,
unsigned int addrlen,
uv_udp_send_cb send_cb) {
int err;

assert(bufcnt > 0);
assert(nbufs > 0);

err = uv__udp_maybe_deferred_bind(handle, addr->sa_family);
if (err)
Expand All @@ -421,17 +401,16 @@ static int uv__send(uv_udp_send_t* req,
memcpy(&req->addr, addr, addrlen);
req->send_cb = send_cb;
req->handle = handle;
req->bufcnt = bufcnt;
req->nbufs = nbufs;

if (bufcnt <= (int) ARRAY_SIZE(req->bufsml))
req->bufs = req->bufsml;
else
req->bufs = malloc(bufcnt * sizeof(*bufs));
req->bufs = req->bufsml;
if (nbufs > ARRAY_SIZE(req->bufsml))
req->bufs = malloc(nbufs * sizeof(bufs[0]));

if (req->bufs == NULL)
return -ENOMEM;

memcpy(req->bufs, bufs, bufcnt * sizeof(bufs[0]));
memcpy(req->bufs, bufs, nbufs * sizeof(bufs[0]));
QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue);
uv__io_start(handle->loop, &handle->io_watcher, UV__POLLOUT);
uv__handle_start(handle);
Expand Down Expand Up @@ -575,38 +554,6 @@ int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen) {
}


int uv__udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
uv_buf_t bufs[],
int bufcnt,
struct sockaddr_in addr,
uv_udp_send_cb send_cb) {
return uv__send(req,
handle,
bufs,
bufcnt,
(struct sockaddr*)&addr,
sizeof addr,
send_cb);
}


int uv__udp_send6(uv_udp_send_t* req,
uv_udp_t* handle,
uv_buf_t bufs[],
int bufcnt,
struct sockaddr_in6 addr,
uv_udp_send_cb send_cb) {
return uv__send(req,
handle,
bufs,
bufcnt,
(struct sockaddr*)&addr,
sizeof addr,
send_cb);
}


int uv__udp_recv_start(uv_udp_t* handle,
uv_alloc_cb alloc_cb,
uv_udp_recv_cb recv_cb) {
Expand Down
40 changes: 26 additions & 14 deletions src/uv-common.c
Expand Up @@ -258,27 +258,39 @@ int uv_tcp_connect6(uv_connect_t* req,

int uv_udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
uv_buf_t bufs[],
int bufcnt,
struct sockaddr_in addr,
const uv_buf_t bufs[],
unsigned int nbufs,
const struct sockaddr_in* addr,
uv_udp_send_cb send_cb) {
if (handle->type != UV_UDP || addr.sin_family != AF_INET)
return UV_EINVAL;
else
return uv__udp_send(req, handle, bufs, bufcnt, addr, send_cb);
if (handle->type == UV_UDP && addr->sin_family == AF_INET) {
return uv__udp_send(req,
handle,
bufs,
nbufs,
(const struct sockaddr*) addr,
sizeof(*addr),
send_cb);
}
return UV_EINVAL;
}


int uv_udp_send6(uv_udp_send_t* req,
uv_udp_t* handle,
uv_buf_t bufs[],
int bufcnt,
struct sockaddr_in6 addr,
const uv_buf_t bufs[],
unsigned int nbufs,
const struct sockaddr_in6* addr,
uv_udp_send_cb send_cb) {
if (handle->type != UV_UDP || addr.sin6_family != AF_INET6)
return UV_EINVAL;
else
return uv__udp_send6(req, handle, bufs, bufcnt, addr, send_cb);
if (handle->type == UV_UDP && addr->sin6_family == AF_INET6) {
return uv__udp_send(req,
handle,
bufs,
nbufs,
(const struct sockaddr*) addr,
sizeof(*addr),
send_cb);
}
return UV_EINVAL;
}


Expand Down
14 changes: 4 additions & 10 deletions src/uv-common.h
Expand Up @@ -76,18 +76,12 @@ int uv__udp_bind(uv_udp_t* handle,

int uv__udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
uv_buf_t bufs[],
int bufcnt,
struct sockaddr_in addr,
const uv_buf_t bufs[],
unsigned int nbufs,
const struct sockaddr* addr,
unsigned int addrlen,
uv_udp_send_cb send_cb);

int uv__udp_send6(uv_udp_send_t* req,
uv_udp_t* handle,
uv_buf_t bufs[],
int bufcnt,
struct sockaddr_in6 addr,
uv_udp_send_cb send_cb);

int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloccb,
uv_udp_recv_cb recv_cb);

Expand Down
95 changes: 44 additions & 51 deletions src/win/udp.c
Expand Up @@ -359,8 +359,13 @@ int uv__udp_recv_stop(uv_udp_t* handle) {
}


static int uv__send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],
int bufcnt, struct sockaddr* addr, int addr_len, uv_udp_send_cb cb) {
static int uv__send(uv_udp_send_t* req,
uv_udp_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
const struct sockaddr* addr,
unsigned int addrlen,
uv_udp_send_cb cb) {
uv_loop_t* loop = handle->loop;
DWORD result, bytes;

Expand All @@ -372,11 +377,11 @@ static int uv__send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],

result = WSASendTo(handle->socket,
(WSABUF*)bufs,
bufcnt,
nbufs,
&bytes,
0,
addr,
addr_len,
addrlen,
&req->overlapped,
NULL);

Expand All @@ -388,7 +393,7 @@ static int uv__send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],
uv_insert_pending_req(loop, (uv_req_t*)req);
} else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) {
/* Request queued by the kernel. */
req->queued_bytes = uv_count_bufs(bufs, bufcnt);
req->queued_bytes = uv_count_bufs(bufs, nbufs);
handle->reqs_pending++;
REGISTER_HANDLE_REQ(loop, handle, req);
} else {
Expand All @@ -400,52 +405,6 @@ static int uv__send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],
}


int uv__udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],
int bufcnt, struct sockaddr_in addr, uv_udp_send_cb cb) {
int err;

if (!(handle->flags & UV_HANDLE_BOUND)) {
err = uv_udp_try_bind(handle,
(const struct sockaddr*) &uv_addr_ip4_any_,
sizeof(uv_addr_ip4_any_),
0);
if (err)
return err;
}

return uv__send(req,
handle,
bufs,
bufcnt,
(struct sockaddr*) &addr,
sizeof addr,
cb);
}


int uv__udp_send6(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[],
int bufcnt, struct sockaddr_in6 addr, uv_udp_send_cb cb) {
int err;

if (!(handle->flags & UV_HANDLE_BOUND)) {
err = uv_udp_try_bind(handle,
(const struct sockaddr*) &uv_addr_ip6_any_,
sizeof(uv_addr_ip6_any_),
0);
if (err)
return err;
}

return uv__send(req,
handle,
bufs,
bufcnt,
(struct sockaddr*) &addr,
sizeof addr,
cb);
}


void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle,
uv_req_t* req) {
uv_buf_t buf;
Expand Down Expand Up @@ -753,3 +712,37 @@ int uv__udp_bind(uv_udp_t* handle,

return 0;
}


/* This function is an egress point, i.e. it returns libuv errors rather than
* system errors.
*/
int uv__udp_send(uv_udp_send_t* req,
uv_udp_t* handle,
const uv_buf_t bufs[],
unsigned int nbufs,
const struct sockaddr* addr,
unsigned int addrlen,
uv_udp_send_cb send_cb) {
const struct sockaddr* bind_addr;
int err;

if (!(handle->flags & UV_HANDLE_BOUND)) {
if (addrlen == sizeof(uv_addr_ip4_any_)) {
bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_;
} else if (addrlen == sizeof(uv_addr_ip6_any_)) {
bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_;
} else {
abort();
}
err = uv_udp_try_bind(handle, bind_addr, addrlen, 0);
if (err)
return uv_translate_sys_error(err);
}

err = uv__send(req, handle, bufs, nbufs, addr, addrlen, send_cb);
if (err)
return uv_translate_sys_error(err);

return 0;
}

0 comments on commit 263da51

Please sign in to comment.