summaryrefslogtreecommitdiffhomepage
path: root/src/event/ngx_event_udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/event/ngx_event_udp.c')
-rw-r--r--src/event/ngx_event_udp.c256
1 files changed, 116 insertions, 140 deletions
diff --git a/src/event/ngx_event_udp.c b/src/event/ngx_event_udp.c
index a524ae04d..64db5c17f 100644
--- a/src/event/ngx_event_udp.c
+++ b/src/event/ngx_event_udp.c
@@ -12,52 +12,37 @@
#if !(NGX_WIN32)
-struct ngx_udp_connection_s {
- ngx_rbtree_node_t node;
- ngx_connection_t *connection;
- ngx_buf_t *buffer;
-};
-
-
static void ngx_close_accepted_udp_connection(ngx_connection_t *c);
static ssize_t ngx_udp_shared_recv(ngx_connection_t *c, u_char *buf,
size_t size);
-static ngx_int_t ngx_insert_udp_connection(ngx_connection_t *c);
+static ngx_int_t ngx_create_udp_connection(ngx_connection_t *c);
static ngx_connection_t *ngx_lookup_udp_connection(ngx_listening_t *ls,
- struct sockaddr *sockaddr, socklen_t socklen,
- struct sockaddr *local_sockaddr, socklen_t local_socklen);
+ ngx_str_t *key, struct sockaddr *local_sockaddr, socklen_t local_socklen);
void
ngx_event_recvmsg(ngx_event_t *ev)
{
+ size_t len;
ssize_t n;
+ ngx_str_t key;
ngx_buf_t buf;
ngx_log_t *log;
ngx_err_t err;
- socklen_t socklen, local_socklen;
+ socklen_t local_socklen;
ngx_event_t *rev, *wev;
struct iovec iov[1];
struct msghdr msg;
ngx_sockaddr_t sa, lsa;
- struct sockaddr *sockaddr, *local_sockaddr;
+ ngx_udp_dgram_t dgram;
+ struct sockaddr *local_sockaddr;
ngx_listening_t *ls;
ngx_event_conf_t *ecf;
ngx_connection_t *c, *lc;
static u_char buffer[65535];
-#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
-
-#if (NGX_HAVE_IP_RECVDSTADDR)
- u_char msg_control[CMSG_SPACE(sizeof(struct in_addr))];
-#elif (NGX_HAVE_IP_PKTINFO)
- u_char msg_control[CMSG_SPACE(sizeof(struct in_pktinfo))];
-#endif
-
-#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
- u_char msg_control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
-#endif
-
+#if (NGX_HAVE_ADDRINFO_CMSG)
+ u_char msg_control[CMSG_SPACE(sizeof(ngx_addrinfo_t))];
#endif
if (ev->timedout) {
@@ -92,25 +77,13 @@ ngx_event_recvmsg(ngx_event_t *ev)
msg.msg_iov = iov;
msg.msg_iovlen = 1;
-#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
-
+#if (NGX_HAVE_ADDRINFO_CMSG)
if (ls->wildcard) {
+ msg.msg_control = &msg_control;
+ msg.msg_controllen = sizeof(msg_control);
-#if (NGX_HAVE_IP_RECVDSTADDR || NGX_HAVE_IP_PKTINFO)
- if (ls->sockaddr->sa_family == AF_INET) {
- msg.msg_control = &msg_control;
- msg.msg_controllen = sizeof(msg_control);
- }
-#endif
-
-#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
- if (ls->sockaddr->sa_family == AF_INET6) {
- msg.msg_control = &msg_control6;
- msg.msg_controllen = sizeof(msg_control6);
- }
-#endif
- }
-
+ ngx_memzero(&msg_control, sizeof(msg_control));
+ }
#endif
n = recvmsg(lc->fd, &msg, 0);
@@ -129,7 +102,7 @@ ngx_event_recvmsg(ngx_event_t *ev)
return;
}
-#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
+#if (NGX_HAVE_ADDRINFO_CMSG)
if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {
ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
"recvmsg() truncated data");
@@ -137,21 +110,21 @@ ngx_event_recvmsg(ngx_event_t *ev)
}
#endif
- sockaddr = msg.msg_name;
- socklen = msg.msg_namelen;
+ dgram.sockaddr = msg.msg_name;
+ dgram.socklen = msg.msg_namelen;
- if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) {
- socklen = sizeof(ngx_sockaddr_t);
+ if (dgram.socklen > (socklen_t) sizeof(ngx_sockaddr_t)) {
+ dgram.socklen = sizeof(ngx_sockaddr_t);
}
- if (socklen == 0) {
+ if (dgram.socklen == 0) {
/*
* on Linux recvmsg() returns zero msg_namelen
* when receiving packets from unbound AF_UNIX sockets
*/
- socklen = sizeof(struct sockaddr);
+ dgram.socklen = sizeof(struct sockaddr);
ngx_memzero(&sa, sizeof(struct sockaddr));
sa.sockaddr.sa_family = ls->sockaddr->sa_family;
}
@@ -159,7 +132,7 @@ ngx_event_recvmsg(ngx_event_t *ev)
local_sockaddr = ls->sockaddr;
local_socklen = ls->socklen;
-#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
+#if (NGX_HAVE_ADDRINFO_CMSG)
if (ls->wildcard) {
struct cmsghdr *cmsg;
@@ -171,66 +144,43 @@ ngx_event_recvmsg(ngx_event_t *ev)
cmsg != NULL;
cmsg = CMSG_NXTHDR(&msg, cmsg))
{
-
-#if (NGX_HAVE_IP_RECVDSTADDR)
-
- if (cmsg->cmsg_level == IPPROTO_IP
- && cmsg->cmsg_type == IP_RECVDSTADDR
- && local_sockaddr->sa_family == AF_INET)
- {
- struct in_addr *addr;
- struct sockaddr_in *sin;
-
- addr = (struct in_addr *) CMSG_DATA(cmsg);
- sin = (struct sockaddr_in *) local_sockaddr;
- sin->sin_addr = *addr;
-
- break;
- }
-
-#elif (NGX_HAVE_IP_PKTINFO)
-
- if (cmsg->cmsg_level == IPPROTO_IP
- && cmsg->cmsg_type == IP_PKTINFO
- && local_sockaddr->sa_family == AF_INET)
- {
- struct in_pktinfo *pkt;
- struct sockaddr_in *sin;
-
- pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
- sin = (struct sockaddr_in *) local_sockaddr;
- sin->sin_addr = pkt->ipi_addr;
-
+ if (ngx_get_srcaddr_cmsg(cmsg, local_sockaddr) == NGX_OK) {
break;
}
+ }
+ }
#endif
-#if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO)
+ key.data = (u_char *) dgram.sockaddr;
+ key.len = dgram.socklen;
- if (cmsg->cmsg_level == IPPROTO_IPV6
- && cmsg->cmsg_type == IPV6_PKTINFO
- && local_sockaddr->sa_family == AF_INET6)
- {
- struct in6_pktinfo *pkt6;
- struct sockaddr_in6 *sin6;
+#if (NGX_HAVE_UNIX_DOMAIN)
- pkt6 = (struct in6_pktinfo *) CMSG_DATA(cmsg);
- sin6 = (struct sockaddr_in6 *) local_sockaddr;
- sin6->sin6_addr = pkt6->ipi6_addr;
+ if (dgram.sockaddr->sa_family == AF_UNIX) {
+ struct sockaddr_un *saun = (struct sockaddr_un *) dgram.sockaddr;
- break;
- }
+ if (dgram.socklen <= (socklen_t) offsetof(struct sockaddr_un,
+ sun_path)
+ || saun->sun_path[0] == '\0')
+ {
+ ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
+ "unbound unix socket");
+ key.len = 0;
+ }
+ }
#endif
+#if (NGX_QUIC)
+ if (ls->quic) {
+ if (ngx_quic_get_packet_dcid(ev->log, buffer, n, &key) != NGX_OK) {
+ goto next;
}
}
-
#endif
- c = ngx_lookup_udp_connection(ls, sockaddr, socklen, local_sockaddr,
- local_socklen);
+ c = ngx_lookup_udp_connection(ls, &key, local_sockaddr, local_socklen);
if (c) {
@@ -252,10 +202,14 @@ ngx_event_recvmsg(ngx_event_t *ev)
buf.pos = buffer;
buf.last = buffer + n;
+ buf.start = buf.pos;
+ buf.end = buffer + sizeof(buffer);
rev = c->read;
- c->udp->buffer = &buf;
+ dgram.buffer = &buf;
+
+ c->udp->dgram = &dgram;
rev->ready = 1;
rev->active = 0;
@@ -263,7 +217,7 @@ ngx_event_recvmsg(ngx_event_t *ev)
rev->handler(rev);
if (c->udp) {
- c->udp->buffer = NULL;
+ c->udp->dgram = NULL;
}
rev->ready = 0;
@@ -286,7 +240,7 @@ ngx_event_recvmsg(ngx_event_t *ev)
c->shared = 1;
c->type = SOCK_DGRAM;
- c->socklen = socklen;
+ c->socklen = dgram.socklen;
#if (NGX_STAT_STUB)
(void) ngx_atomic_fetch_add(ngx_stat_active, 1);
@@ -298,13 +252,21 @@ ngx_event_recvmsg(ngx_event_t *ev)
return;
}
- c->sockaddr = ngx_palloc(c->pool, socklen);
+ len = dgram.socklen;
+
+#if (NGX_QUIC)
+ if (ls->quic) {
+ len = NGX_SOCKADDRLEN;
+ }
+#endif
+
+ c->sockaddr = ngx_palloc(c->pool, len);
if (c->sockaddr == NULL) {
ngx_close_accepted_udp_connection(c);
return;
}
- ngx_memcpy(c->sockaddr, sockaddr, socklen);
+ ngx_memcpy(c->sockaddr, dgram.sockaddr, dgram.socklen);
log = ngx_palloc(c->pool, sizeof(ngx_log_t));
if (log == NULL) {
@@ -405,7 +367,7 @@ ngx_event_recvmsg(ngx_event_t *ev)
}
#endif
- if (ngx_insert_udp_connection(c) != NGX_OK) {
+ if (ngx_create_udp_connection(c) != NGX_OK) {
ngx_close_accepted_udp_connection(c);
return;
}
@@ -448,17 +410,17 @@ ngx_udp_shared_recv(ngx_connection_t *c, u_char *buf, size_t size)
ssize_t n;
ngx_buf_t *b;
- if (c->udp == NULL || c->udp->buffer == NULL) {
+ if (c->udp == NULL || c->udp->dgram == NULL) {
return NGX_AGAIN;
}
- b = c->udp->buffer;
+ b = c->udp->dgram->buffer;
n = ngx_min(b->last - b->pos, (ssize_t) size);
ngx_memcpy(buf, b->pos, n);
- c->udp->buffer = NULL;
+ c->udp->dgram = NULL;
c->read->ready = 0;
c->read->active = 1;
@@ -494,8 +456,8 @@ ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp,
udpt = (ngx_udp_connection_t *) temp;
ct = udpt->connection;
- rc = ngx_cmp_sockaddr(c->sockaddr, c->socklen,
- ct->sockaddr, ct->socklen, 1);
+ rc = ngx_memn2cmp(udp->key.data, udpt->key.data,
+ udp->key.len, udpt->key.len);
if (rc == 0 && c->listening->wildcard) {
rc = ngx_cmp_sockaddr(c->local_sockaddr, c->local_socklen,
@@ -521,12 +483,18 @@ ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp,
static ngx_int_t
-ngx_insert_udp_connection(ngx_connection_t *c)
+ngx_create_udp_connection(ngx_connection_t *c)
{
- uint32_t hash;
+ ngx_str_t key;
ngx_pool_cleanup_t *cln;
ngx_udp_connection_t *udp;
+#if (NGX_QUIC)
+ if (c->listening->quic) {
+ return NGX_OK;
+ }
+#endif
+
if (c->udp) {
return NGX_OK;
}
@@ -536,19 +504,6 @@ ngx_insert_udp_connection(ngx_connection_t *c)
return NGX_ERROR;
}
- udp->connection = c;
-
- ngx_crc32_init(hash);
- ngx_crc32_update(&hash, (u_char *) c->sockaddr, c->socklen);
-
- if (c->listening->wildcard) {
- ngx_crc32_update(&hash, (u_char *) c->local_sockaddr, c->local_socklen);
- }
-
- ngx_crc32_final(hash);
-
- udp->node.key = hash;
-
cln = ngx_pool_cleanup_add(c->pool, 0);
if (cln == NULL) {
return NGX_ERROR;
@@ -557,7 +512,10 @@ ngx_insert_udp_connection(ngx_connection_t *c)
cln->data = c;
cln->handler = ngx_delete_udp_connection;
- ngx_rbtree_insert(&c->listening->rbtree, &udp->node);
+ key.data = (u_char *) c->sockaddr;
+ key.len = c->socklen;
+
+ ngx_insert_udp_connection(c, udp, &key);
c->udp = udp;
@@ -566,6 +524,30 @@ ngx_insert_udp_connection(ngx_connection_t *c)
void
+ngx_insert_udp_connection(ngx_connection_t *c, ngx_udp_connection_t *udp,
+ ngx_str_t *key)
+{
+ uint32_t hash;
+
+ ngx_crc32_init(hash);
+
+ ngx_crc32_update(&hash, key->data, key->len);
+
+ if (c->listening->wildcard) {
+ ngx_crc32_update(&hash, (u_char *) c->local_sockaddr, c->local_socklen);
+ }
+
+ ngx_crc32_final(hash);
+
+ udp->connection = c;
+ udp->key = *key;
+ udp->node.key = hash;
+
+ ngx_rbtree_insert(&c->listening->rbtree, &udp->node);
+}
+
+
+void
ngx_delete_udp_connection(void *data)
{
ngx_connection_t *c = data;
@@ -581,8 +563,8 @@ ngx_delete_udp_connection(void *data)
static ngx_connection_t *
-ngx_lookup_udp_connection(ngx_listening_t *ls, struct sockaddr *sockaddr,
- socklen_t socklen, struct sockaddr *local_sockaddr, socklen_t local_socklen)
+ngx_lookup_udp_connection(ngx_listening_t *ls, ngx_str_t *key,
+ struct sockaddr *local_sockaddr, socklen_t local_socklen)
{
uint32_t hash;
ngx_int_t rc;
@@ -590,27 +572,15 @@ ngx_lookup_udp_connection(ngx_listening_t *ls, struct sockaddr *sockaddr,
ngx_rbtree_node_t *node, *sentinel;
ngx_udp_connection_t *udp;
-#if (NGX_HAVE_UNIX_DOMAIN)
-
- if (sockaddr->sa_family == AF_UNIX) {
- struct sockaddr_un *saun = (struct sockaddr_un *) sockaddr;
-
- if (socklen <= (socklen_t) offsetof(struct sockaddr_un, sun_path)
- || saun->sun_path[0] == '\0')
- {
- ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
- "unbound unix socket");
- return NULL;
- }
+ if (key->len == 0) {
+ return NULL;
}
-#endif
-
node = ls->rbtree.root;
sentinel = ls->rbtree.sentinel;
ngx_crc32_init(hash);
- ngx_crc32_update(&hash, (u_char *) sockaddr, socklen);
+ ngx_crc32_update(&hash, key->data, key->len);
if (ls->wildcard) {
ngx_crc32_update(&hash, (u_char *) local_sockaddr, local_socklen);
@@ -636,8 +606,7 @@ ngx_lookup_udp_connection(ngx_listening_t *ls, struct sockaddr *sockaddr,
c = udp->connection;
- rc = ngx_cmp_sockaddr(sockaddr, socklen,
- c->sockaddr, c->socklen, 1);
+ rc = ngx_memn2cmp(key->data, udp->key.data, key->len, udp->key.len);
if (rc == 0 && ls->wildcard) {
rc = ngx_cmp_sockaddr(local_sockaddr, local_socklen,
@@ -645,6 +614,13 @@ ngx_lookup_udp_connection(ngx_listening_t *ls, struct sockaddr *sockaddr,
}
if (rc == 0) {
+
+#if (NGX_QUIC)
+ if (ls->quic && c->udp != udp) {
+ c->udp = udp;
+ }
+#endif
+
return c;
}