2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

Merge the common parts between udp, tcpdns and tlsdns protocol

The udp, tcpdns and tlsdns contained lot of cut&paste code or code that
was very similar making the stack harder to maintain as any change to
one would have to be copied to the the other protocols.

In this commit, we merge the common parts into the common functions
under isc__nm_<foo> namespace and just keep the little differences based
on the socket type.
This commit is contained in:
Ondřej Surý
2021-03-18 09:27:38 +01:00
parent caa5b6548a
commit 1ef232f93d
5 changed files with 238 additions and 737 deletions

View File

@@ -50,33 +50,11 @@ timer_close_cb(uv_handle_t *handle);
static void
udp_close_direct(isc_nmsocket_t *sock);
static void
failed_read_cb(isc_nmsocket_t *sock, isc_result_t result);
static void
failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
isc_result_t eresult);
static void
stop_udp_parent(isc_nmsocket_t *sock);
static void
stop_udp_child(isc_nmsocket_t *sock);
static void
start_reading(isc_nmsocket_t *sock);
static void
stop_reading(isc_nmsocket_t *sock);
static isc__nm_uvreq_t *
get_read_req(isc_nmsocket_t *sock, isc_sockaddr_t *sockaddr);
static bool
inactive(isc_nmsocket_t *sock) {
return (!isc__nmsocket_active(sock) ||
atomic_load(&sock->mgr->closing) ||
(sock->server != NULL && !isc__nmsocket_active(sock->server)));
}
static uv_os_sock_t
isc__nm_udp_lb_socket(sa_family_t sa_family) {
isc_result_t result;
@@ -192,32 +170,6 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
return (result);
}
/*%<
* Allocator for UDP recv operations. Limited to size 20 * (2^16 + 2),
* which allows enough space for recvmmsg() to get multiple messages at
* a time.
*
* Note this doesn't actually allocate anything, it just assigns the
* worker's receive buffer to a socket, and marks it as "in use".
*/
static void
udp_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
isc_nmsocket_t *sock = uv_handle_get_data(handle);
isc__networker_t *worker = NULL;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->type == isc_nm_udpsocket);
REQUIRE(isc__nm_in_netthread());
REQUIRE(size <= ISC_NETMGR_RECVBUF_SIZE);
worker = &sock->mgr->workers[sock->tid];
INSIST(!worker->recvbuf_inuse);
buf->base = worker->recvbuf;
buf->len = ISC_NETMGR_RECVBUF_SIZE;
worker->recvbuf_inuse = true;
}
/*
* Asynchronous 'udplisten' call handler: start listening on a UDP socket.
*/
@@ -306,7 +258,8 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
uv_send_buffer_size(&sock->uv_handle.handle,
&(int){ ISC_SEND_BUFFER_SIZE });
#endif
r = uv_udp_recv_start(&sock->uv_handle.udp, udp_alloc_cb, udp_recv_cb);
r = uv_udp_recv_start(&sock->uv_handle.udp, isc__nm_alloc_cb,
udp_recv_cb);
if (r != 0) {
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_BINDFAIL]);
goto done;
@@ -430,7 +383,7 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
* we can free the buffer and bail.
*/
if (addr == NULL) {
failed_read_cb(sock, ISC_R_EOF);
isc__nm_failed_read_cb(sock, ISC_R_EOF);
goto free;
}
@@ -438,19 +391,19 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
* - If the socket is no longer active.
*/
if (!isc__nmsocket_active(sock)) {
failed_read_cb(sock, ISC_R_CANCELED);
isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
goto free;
}
if (nrecv < 0) {
failed_read_cb(sock, isc__nm_uverr2result(nrecv));
isc__nm_failed_read_cb(sock, isc__nm_uverr2result(nrecv));
goto free;
}
result = isc_sockaddr_fromsockaddr(&sockaddr, addr);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
req = get_read_req(sock, &sockaddr);
req = isc__nm_get_read_req(sock, &sockaddr);
/*
* The callback will be called synchronously, because result is
@@ -570,15 +523,15 @@ isc__nm_async_udpsend(isc__networker_t *worker, isc__netievent_t *ev0) {
REQUIRE(sock->tid == isc_nm_tid());
UNUSED(worker);
if (inactive(sock)) {
failed_send_cb(sock, uvreq, ISC_R_CANCELED);
if (isc__nm_inactive(sock)) {
isc__nm_failed_send_cb(sock, uvreq, ISC_R_CANCELED);
return;
}
result = udp_send_direct(sock, uvreq, &ievent->peer);
if (result != ISC_R_SUCCESS) {
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_SENDFAIL]);
failed_send_cb(sock, uvreq, result);
isc__nm_failed_send_cb(sock, uvreq, result);
}
}
@@ -614,7 +567,7 @@ udp_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(sock->type == isc_nm_udpsocket);
if (inactive(sock)) {
if (isc__nm_inactive(sock)) {
return (ISC_R_CANCELED);
}
@@ -839,9 +792,9 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
return (result);
}
static void
udp_read_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
const struct sockaddr *addr, unsigned flags) {
void
isc__nm_udp_read_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
const struct sockaddr *addr, unsigned flags) {
isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)handle);
REQUIRE(VALID_NMSOCK(sock));
@@ -854,17 +807,17 @@ udp_read_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf,
* does not.
*/
if (!sock->parent) {
stop_reading(sock);
isc__nm_stop_reading(sock);
}
}
static void
failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
void
isc__nm_udp_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(result != ISC_R_SUCCESS);
if (atomic_load(&sock->client)) {
stop_reading(sock);
isc__nm_stop_reading(sock);
if (!sock->recv_read) {
goto destroy;
@@ -872,7 +825,7 @@ failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
sock->recv_read = false;
if (sock->recv_cb != NULL) {
isc__nm_uvreq_t *req = get_read_req(sock, NULL);
isc__nm_uvreq_t *req = isc__nm_get_read_req(sock, NULL);
isc__nmsocket_clearcb(sock);
isc__nm_readcb(sock, req, result);
}
@@ -895,46 +848,11 @@ failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
sock->recv_read = false;
if (sock->recv_cb != NULL) {
isc__nm_uvreq_t *req = get_read_req(sock, NULL);
isc__nm_uvreq_t *req = isc__nm_get_read_req(sock, NULL);
isc__nm_readcb(sock, req, result);
}
}
void
isc__nm_udp_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result) {
failed_read_cb(sock, result);
}
static void
failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
isc_result_t eresult) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(VALID_UVREQ(req));
if (req->cb.send != NULL) {
isc__nm_sendcb(sock, req, eresult, true);
} else {
isc__nm_uvreq_put(&req, sock);
}
}
static isc__nm_uvreq_t *
get_read_req(isc_nmsocket_t *sock, isc_sockaddr_t *sockaddr) {
isc__nm_uvreq_t *req = NULL;
req = isc__nm_uvreq_get(sock->mgr, sock);
req->cb.recv = sock->recv_cb;
req->cbarg = sock->recv_cbarg;
if (atomic_load(&sock->client)) {
isc_nmhandle_attach(sock->statichandle, &req->handle);
} else {
req->handle = isc__nmhandle_get(sock, sockaddr, NULL);
}
return req;
}
/*
* Asynchronous 'udpread' call handler: start or resume reading on a
* socket; pause reading and call the 'recv' callback after each
@@ -950,41 +868,16 @@ isc__nm_async_udpread(isc__networker_t *worker, isc__netievent_t *ev0) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
if (inactive(sock)) {
if (isc__nm_inactive(sock)) {
sock->reading = true;
failed_read_cb(sock, ISC_R_CANCELED);
isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
return;
}
start_reading(sock);
isc__nm_start_reading(sock);
isc__nmsocket_timer_start(sock);
}
static void
start_reading(isc_nmsocket_t *sock) {
if (sock->reading) {
return;
}
int r = uv_udp_recv_start(&sock->uv_handle.udp, udp_alloc_cb,
udp_read_cb);
REQUIRE(r == 0);
sock->reading = true;
}
static void
stop_reading(isc_nmsocket_t *sock) {
if (!sock->reading) {
return;
}
int r = uv_udp_recv_stop(&sock->uv_handle.udp);
REQUIRE(r == 0);
sock->reading = false;
isc__nmsocket_timer_stop(sock);
}
void
isc__nm_udp_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
REQUIRE(VALID_NMHANDLE(handle));
@@ -1192,7 +1085,7 @@ isc__nm_udp_shutdown(isc_nmsocket_t *sock) {
* interested in the callback.
*/
if (sock->statichandle) {
failed_read_cb(sock, ISC_R_CANCELED);
isc__nm_failed_read_cb(sock, ISC_R_CANCELED);
return;
}
@@ -1236,5 +1129,5 @@ isc__nm_async_udpcancel(isc__networker_t *worker, isc__netievent_t *ev0) {
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(atomic_load(&sock->client));
failed_read_cb(sock, ISC_R_EOF);
isc__nm_failed_read_cb(sock, ISC_R_EOF);
}