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

Add UDP support to libuv.

  • Loading branch information...
bnoordhuis committed Aug 19, 2011
1 parent 5202406 commit 36ce74f2ca9a3a943b342a79837cd3453a2764d8
@@ -55,6 +55,16 @@ typedef struct {
#define UV_CONNECT_PRIVATE_FIELDS \
ngx_queue_t queue;

#define UV_UDP_SEND_PRIVATE_FIELDS \
ngx_queue_t queue; \
struct sockaddr_storage addr; \
socklen_t addrlen; \
uv_buf_t* bufs; \
int bufcnt; \
ssize_t status; \
uv_udp_send_cb send_cb; \
uv_buf_t bufsml[UV_REQ_BUFSML_SIZE]; \

#define UV_PRIVATE_REQ_TYPES /* empty */


@@ -83,6 +93,16 @@ typedef struct {
#define UV_TCP_PRIVATE_FIELDS


/* UV_UDP */
#define UV_UDP_PRIVATE_FIELDS \
uv_alloc_cb alloc_cb; \
uv_udp_recv_cb recv_cb; \
ev_io read_watcher; \
ev_io write_watcher; \
ngx_queue_t write_queue; \
ngx_queue_t write_completed_queue; \


/* UV_NAMED_PIPE */
#define UV_PIPE_PRIVATE_TYPEDEF
#define UV_PIPE_PRIVATE_FIELDS \
@@ -114,6 +114,8 @@ typedef struct uv_buf_t {
struct { uv_tcp_connection_fields }; \
};

#define UV_UDP_PRIVATE_FIELDS

#define uv_pipe_server_fields \
uv_pipe_accept_t accept_reqs[4]; \
uv_pipe_accept_t* pending_accepts;
@@ -45,6 +45,7 @@ typedef struct uv_err_s uv_err_t;
typedef struct uv_handle_s uv_handle_t;
typedef struct uv_stream_s uv_stream_t;
typedef struct uv_tcp_s uv_tcp_t;
typedef struct uv_udp_s uv_udp_t;
typedef struct uv_pipe_s uv_pipe_t;
typedef struct uv_timer_s uv_timer_t;
typedef struct uv_prepare_s uv_prepare_t;
@@ -58,6 +59,7 @@ typedef struct uv_req_s uv_req_t;
typedef struct uv_shutdown_s uv_shutdown_t;
typedef struct uv_write_s uv_write_t;
typedef struct uv_connect_s uv_connect_t;
typedef struct uv_udp_send_s uv_udp_send_t;

#if defined(__unix__) || defined(__POSIX__) || defined(__APPLE__)
# include "uv-unix.h"
@@ -106,8 +108,8 @@ int64_t uv_now();
* In the case of uv_read_cb the uv_buf_t returned should be freed by the
* user.
*/
typedef uv_buf_t (*uv_alloc_cb)(uv_stream_t* tcp, size_t suggested_size);
typedef void (*uv_read_cb)(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf);
typedef uv_buf_t (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size);
typedef void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, uv_buf_t buf);
typedef void (*uv_write_cb)(uv_write_t* req, int status);
typedef void (*uv_connect_cb)(uv_connect_t* req, int status);
typedef void (*uv_shutdown_cb)(uv_shutdown_t* req, int status);
@@ -146,6 +148,7 @@ typedef enum {
UV_EINVAL,
UV_EISCONN,
UV_EMFILE,
UV_EMSGSIZE,
UV_ENETDOWN,
UV_ENETUNREACH,
UV_ENFILE,
@@ -172,6 +175,7 @@ typedef enum {
typedef enum {
UV_UNKNOWN_HANDLE = 0,
UV_TCP,
UV_UDP,
UV_NAMED_PIPE,
UV_TTY,
UV_FILE,
@@ -194,6 +198,7 @@ typedef enum {
UV_WRITE,
UV_SHUTDOWN,
UV_WAKEUP,
UV_UDP_SEND,
UV_REQ_TYPE_PRIVATE
} uv_req_type;

@@ -418,6 +423,188 @@ struct uv_connect_s {
int uv_getsockname(uv_handle_t* handle, struct sockaddr* name, int* namelen);


/*
* UDP support.
*/

/*
* Flag constants. Input flags are meant to be passed to `uv_udp_init()`
* and `uv_udp_init6()`. Output flags are passed to your `uv_udp_recv_cb`
* callback.
*/

/*
* Input flag. Disables dual stack mode. Only valid for `uv_udp_init6()`.
*/
#define UV_UDP_IPV6ONLY (1 << 0)

/*
* Output flag. The message has been truncated because
* the read buffer was too small. The remainder has been
* discarded by the operating system.
*/
#define UV_UDP_PARTIAL (1 << 10)

/*
* Function prototype for the callback that is invoked
* when the UDP datagram has been sent.
*
* Arguments:
* req Request handle.
* status Status indicator. 0 on success, -1 on error.
*/
typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);

/*
* Function prototype for the callback that is invoked when
* a new UDP datagram is received.
*
* Arguments:
* handle UDP handle.
* nread Number of bytes that have been received.
* 0 if there is no more data to read. You may
* discard or repurpose the read buffer.
* -1 if a transmission error was detected.
* buf uv_buf_t with the received data.
* addr struct sockaddr_in or struct sockaddr_in6.
* Valid for the duration of the callback only.
* flags One or more OR'ed UV_UDP_* constants.
* Right now only UV_UDP_PARTIAL is used.
*/
typedef void (*uv_udp_recv_cb)(uv_udp_t* handle,
ssize_t nread,
uv_buf_t buf,
struct sockaddr* addr,
unsigned flags);

/*
* Subclass of uv_handle_t
*/
struct uv_udp_s {
UV_HANDLE_FIELDS
UV_UDP_PRIVATE_FIELDS
};

/*
* Subclass of uv_req_t
*/
struct uv_udp_send_s {
UV_REQ_FIELDS
uv_udp_t* handle;
UV_UDP_SEND_PRIVATE_FIELDS
};

/*
* Initialize a new UDP handle. The actual socket is created lazily.
*
* Arguments:
* handle UDP handle to initialize.
*
* Returns:
* 0 on success, -1 on error.
*/
int uv_udp_init(uv_udp_t* handle);

/*
* Bind to a IPv4 address and port.
*
* Arguments:
* handle UDP handle. Should have been initialized with `uv_udp_init`.
* addr struct sockaddr_in with the address and port to bind to.
* flags Bind flags. One or more OR'ed UV_UDP_* constants.
*
* Returns:
* 0 on success, -1 on error.
*/
int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned flags);

/*
* Bind to a IPv6 address and port.
*
* Arguments:
* handle UDP handle. Should have been initialized with `uv_udp_init`.
* addr struct sockaddr_in with the address and port to bind to.
* flags One or more OR'ed UV_UDP_* constants.
*
* Returns:
* 0 on success, -1 on error.
*/
int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned flags);

/*
* Send data. If the socket has not previously been bound with `uv_udp_bind`
* or `uv_udp_bind6`, it is bound to 0.0.0.0 (the "all interfaces" address)
* and a random port number.
*
* Arguments:
* 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`.
* 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, -1 on error.
*/
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);

/*
* Send data. If the socket has not previously been bound with `uv_udp_bind6`,
* it is bound to :::0 (the "all interfaces" address) and a random port number.
*
* Arguments:
* 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`.
* 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, -1 on error.
*/
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);

/*
* Send data. If the socket has not previously been bound with `uv_udp_bind`
* or `uv_udp_bind6`, it is bound to 0.0.0.0 (the "all interfaces" address)
* and a random port number.
*
* Arguments:
* handle UDP handle. Should have been initialized with `uv_udp_init`.
* alloc_cb Callback to invoke when temporary storage is needed.
* recv_cb Callback to invoke with received data.
*
* Returns:
* 0 on success, -1 on error.
*/
int uv_udp_recv_start(uv_udp_t* handle,
uv_alloc_cb alloc_cb,
uv_udp_recv_cb recv_cb);

/*
* Stop listening for incoming datagrams.
*
* Arguments:
* handle UDP handle. Should have been initialized with `uv_udp_init`.
*
* Returns:
* 0 on success, -1 on error.
*/
int uv_udp_recv_stop(uv_udp_t* handle);


/*
* uv_pipe_t is a subclass of uv_stream_t
*
@@ -699,6 +886,7 @@ typedef struct {
uint64_t handle_init;
uint64_t stream_init;
uint64_t tcp_init;
uint64_t udp_init;
uint64_t pipe_init;
uint64_t prepare_init;
uint64_t check_init;

0 comments on commit 36ce74f

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