mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 14:07:59 +00:00
use sendmsg() rather than send() or sendto() now, and start on control message
processing
This commit is contained in:
@@ -151,6 +151,10 @@ struct isc_socket {
|
|||||||
listener : 1, /* listener socket */
|
listener : 1, /* listener socket */
|
||||||
connected : 1,
|
connected : 1,
|
||||||
connecting : 1; /* connect pending */
|
connecting : 1; /* connect pending */
|
||||||
|
|
||||||
|
#ifdef notyet
|
||||||
|
unsigned char cmsg[1024]; /* XXX size? */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SOCKET_MANAGER_MAGIC 0x494f6d67U /* IOmg */
|
#define SOCKET_MANAGER_MAGIC 0x494f6d67U /* IOmg */
|
||||||
@@ -189,6 +193,7 @@ static void internal_accept(isc_task_t *, isc_event_t *);
|
|||||||
static void internal_connect(isc_task_t *, isc_event_t *);
|
static void internal_connect(isc_task_t *, isc_event_t *);
|
||||||
static void internal_recv(isc_task_t *, isc_event_t *);
|
static void internal_recv(isc_task_t *, isc_event_t *);
|
||||||
static void internal_send(isc_task_t *, isc_event_t *);
|
static void internal_send(isc_task_t *, isc_event_t *);
|
||||||
|
static void process_cmsg(isc_socket_t *, struct msghdr *, isc_socketevent_t *);
|
||||||
|
|
||||||
#define SELECT_POKE_SHUTDOWN (-1)
|
#define SELECT_POKE_SHUTDOWN (-1)
|
||||||
#define SELECT_POKE_NOTHING (-2)
|
#define SELECT_POKE_NOTHING (-2)
|
||||||
@@ -264,6 +269,29 @@ make_nonblock(int fd)
|
|||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process control messages received on a socket.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev)
|
||||||
|
{
|
||||||
|
struct cmsghdr *cm;
|
||||||
|
|
||||||
|
if ((msg->msg_flags & MSG_TRUNC) == MSG_TRUNC)
|
||||||
|
dev->attributes |= ISC_SOCKEVENTATTR_TRUNC;
|
||||||
|
|
||||||
|
if ((msg->msg_flags & MSG_CTRUNC) == MSG_CTRUNC)
|
||||||
|
dev->attributes |= ISC_SOCKEVENTATTR_CTRUNC;
|
||||||
|
|
||||||
|
if (msg->msg_controllen == 0 || msg->msg_control == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pull off the options
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kill.
|
* Kill.
|
||||||
*
|
*
|
||||||
@@ -421,6 +449,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
|||||||
{
|
{
|
||||||
isc_socket_t *sock = NULL;
|
isc_socket_t *sock = NULL;
|
||||||
isc_result_t ret;
|
isc_result_t ret;
|
||||||
|
int on = 1;
|
||||||
|
|
||||||
REQUIRE(VALID_MANAGER(manager));
|
REQUIRE(VALID_MANAGER(manager));
|
||||||
REQUIRE(socketp != NULL && *socketp == NULL);
|
REQUIRE(socketp != NULL && *socketp == NULL);
|
||||||
@@ -464,6 +493,16 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
|
|||||||
return (ISC_R_UNEXPECTED);
|
return (ISC_R_UNEXPECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SO_TIMESTAMP
|
||||||
|
if (type == isc_sockettype_udp
|
||||||
|
&& setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP,
|
||||||
|
ISC_SOCKDATA_CAST(&on), sizeof on) < 0) {
|
||||||
|
UNEXPECTED_ERROR(__FILE__, __LINE__, "setsockopt(%d) failed",
|
||||||
|
sock->fd);
|
||||||
|
/* Press on... */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
sock->references = 1;
|
sock->references = 1;
|
||||||
*socketp = sock;
|
*socketp = sock;
|
||||||
|
|
||||||
@@ -885,7 +924,7 @@ internal_recv(isc_task_t *me, isc_event_t *ev)
|
|||||||
* we can.
|
* we can.
|
||||||
*/
|
*/
|
||||||
read_count = dev->region.length - dev->n;
|
read_count = dev->region.length - dev->n;
|
||||||
iov.iov_base = dev->region.base + dev->n;
|
iov.iov_base = (void *)(dev->region.base + dev->n);
|
||||||
iov.iov_len = read_count;
|
iov.iov_len = read_count;
|
||||||
|
|
||||||
memset(&msghdr, 0, sizeof (msghdr));
|
memset(&msghdr, 0, sizeof (msghdr));
|
||||||
@@ -900,11 +939,17 @@ internal_recv(isc_task_t *me, isc_event_t *ev)
|
|||||||
}
|
}
|
||||||
msghdr.msg_iov = &iov;
|
msghdr.msg_iov = &iov;
|
||||||
msghdr.msg_iovlen = 1;
|
msghdr.msg_iovlen = 1;
|
||||||
|
#ifdef notyet
|
||||||
|
msghdr.msg_control = (void *)sock->cmsg;
|
||||||
|
msghdr.msg_controllen = sizeof (sock->cmsg);
|
||||||
|
#else
|
||||||
msghdr.msg_control = NULL;
|
msghdr.msg_control = NULL;
|
||||||
msghdr.msg_controllen = 0;
|
msghdr.msg_controllen = 0;
|
||||||
|
#endif
|
||||||
msghdr.msg_flags = 0;
|
msghdr.msg_flags = 0;
|
||||||
|
|
||||||
cc = recvmsg(sock->fd, &msghdr, 0);
|
cc = recvmsg(sock->fd, &msghdr, 0);
|
||||||
|
|
||||||
if (sock->type == isc_sockettype_udp)
|
if (sock->type == isc_sockettype_udp)
|
||||||
dev->address.length = msghdr.msg_namelen;
|
dev->address.length = msghdr.msg_namelen;
|
||||||
|
|
||||||
@@ -976,6 +1021,8 @@ internal_recv(isc_task_t *me, isc_event_t *ev)
|
|||||||
if ((size_t)cc < read_count) {
|
if ((size_t)cc < read_count) {
|
||||||
dev->n += cc;
|
dev->n += cc;
|
||||||
|
|
||||||
|
process_cmsg(sock, &msghdr, dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If partial reads are allowed, we return whatever
|
* If partial reads are allowed, we return whatever
|
||||||
* was read with a success result, and continue
|
* was read with a success result, and continue
|
||||||
@@ -1023,6 +1070,8 @@ internal_send(isc_task_t *me, isc_event_t *ev)
|
|||||||
isc_task_t *task;
|
isc_task_t *task;
|
||||||
int cc;
|
int cc;
|
||||||
size_t write_count;
|
size_t write_count;
|
||||||
|
struct msghdr msghdr;
|
||||||
|
struct iovec iov;
|
||||||
|
|
||||||
(void)me;
|
(void)me;
|
||||||
|
|
||||||
@@ -1075,20 +1124,23 @@ internal_send(isc_task_t *me, isc_event_t *ev)
|
|||||||
* we can.
|
* we can.
|
||||||
*/
|
*/
|
||||||
write_count = dev->region.length - dev->n;
|
write_count = dev->region.length - dev->n;
|
||||||
if (sock->type == isc_sockettype_udp) {
|
iov.iov_base = (void *)(dev->region.base + dev->n);
|
||||||
cc = sendto(sock->fd,
|
iov.iov_len = write_count;
|
||||||
ISC_SOCKDATA_CAST(dev->region.base
|
|
||||||
+ dev->n),
|
|
||||||
write_count, 0,
|
|
||||||
&dev->address.type.sa,
|
|
||||||
(int)dev->address.length);
|
|
||||||
|
|
||||||
} else {
|
memset(&msghdr, 0, sizeof (msghdr));
|
||||||
cc = send(sock->fd,
|
if (sock->type == isc_sockettype_udp) {
|
||||||
ISC_SOCKDATA_CAST(dev->region.base + dev->n),
|
msghdr.msg_name = (void *)&dev->address.type.sa;
|
||||||
write_count, 0);
|
msghdr.msg_namelen = dev->address.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msghdr.msg_iov = &iov;
|
||||||
|
msghdr.msg_iovlen = 1;
|
||||||
|
msghdr.msg_control = NULL;
|
||||||
|
msghdr.msg_controllen = 0;
|
||||||
|
msghdr.msg_flags = 0;
|
||||||
|
|
||||||
|
cc = sendmsg(sock->fd, &msghdr, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check for error or block condition
|
* check for error or block condition
|
||||||
*/
|
*/
|
||||||
@@ -1608,9 +1660,9 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
|
|||||||
dev->minimum = minimum;
|
dev->minimum = minimum;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->region = *region;
|
|
||||||
dev->n = 0;
|
|
||||||
dev->result = ISC_R_SUCCESS;
|
dev->result = ISC_R_SUCCESS;
|
||||||
|
dev->n = 0;
|
||||||
|
dev->region = *region;
|
||||||
|
|
||||||
was_empty = ISC_LIST_EMPTY(sock->recv_list);
|
was_empty = ISC_LIST_EMPTY(sock->recv_list);
|
||||||
|
|
||||||
@@ -1620,7 +1672,7 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
|
|||||||
if (!was_empty)
|
if (!was_empty)
|
||||||
goto queue;
|
goto queue;
|
||||||
|
|
||||||
iov.iov_base = dev->region.base;
|
iov.iov_base = (void *)dev->region.base;
|
||||||
iov.iov_len = dev->region.length;
|
iov.iov_len = dev->region.length;
|
||||||
|
|
||||||
memset(&msghdr, 0, sizeof(msghdr));
|
memset(&msghdr, 0, sizeof(msghdr));
|
||||||
@@ -1635,8 +1687,13 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
|
|||||||
}
|
}
|
||||||
msghdr.msg_iov = &iov;
|
msghdr.msg_iov = &iov;
|
||||||
msghdr.msg_iovlen = 1;
|
msghdr.msg_iovlen = 1;
|
||||||
|
#ifdef notyet
|
||||||
|
msghdr.msg_control = (void *)sock->cmsg;
|
||||||
|
msghdr.msg_controllen = sizeof (sock->cmsg);
|
||||||
|
#else
|
||||||
msghdr.msg_control = NULL;
|
msghdr.msg_control = NULL;
|
||||||
msghdr.msg_controllen = 0;
|
msghdr.msg_controllen = 0;
|
||||||
|
#endif
|
||||||
msghdr.msg_flags = 0;
|
msghdr.msg_flags = 0;
|
||||||
|
|
||||||
cc = recvmsg(sock->fd, &msghdr, 0);
|
cc = recvmsg(sock->fd, &msghdr, 0);
|
||||||
@@ -1700,6 +1757,16 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
|
|||||||
|
|
||||||
dev->n = cc;
|
dev->n = cc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there are control messages attached, run through them and pull
|
||||||
|
* out the interesting bits.
|
||||||
|
*
|
||||||
|
* Note that for multi-read TCP this isn't as interesting in that
|
||||||
|
* only the last packet will set some of these, but that is better
|
||||||
|
* than nothing.
|
||||||
|
*/
|
||||||
|
process_cmsg(sock, &msghdr, dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Partial reads need to be queued
|
* Partial reads need to be queued
|
||||||
*/
|
*/
|
||||||
@@ -1760,6 +1827,8 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
|
|||||||
isc_task_t *ntask = NULL;
|
isc_task_t *ntask = NULL;
|
||||||
int cc;
|
int cc;
|
||||||
isc_boolean_t was_empty;
|
isc_boolean_t was_empty;
|
||||||
|
struct msghdr msghdr;
|
||||||
|
struct iovec iov;
|
||||||
|
|
||||||
REQUIRE(VALID_SOCKET(sock));
|
REQUIRE(VALID_SOCKET(sock));
|
||||||
REQUIRE(region != NULL);
|
REQUIRE(region != NULL);
|
||||||
@@ -1783,10 +1852,10 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
|
|||||||
}
|
}
|
||||||
ISC_LINK_INIT(dev, link);
|
ISC_LINK_INIT(dev, link);
|
||||||
|
|
||||||
dev->region = *region;
|
|
||||||
dev->n = 0;
|
|
||||||
dev->result = ISC_R_SUCCESS;
|
dev->result = ISC_R_SUCCESS;
|
||||||
dev->minimum = region->length;
|
dev->minimum = region->length;
|
||||||
|
dev->n = 0;
|
||||||
|
dev->region = *region;
|
||||||
|
|
||||||
was_empty = ISC_LIST_EMPTY(sock->send_list);
|
was_empty = ISC_LIST_EMPTY(sock->send_list);
|
||||||
|
|
||||||
@@ -1806,23 +1875,23 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
|
|||||||
if (!was_empty)
|
if (!was_empty)
|
||||||
goto queue;
|
goto queue;
|
||||||
|
|
||||||
if (sock->type == isc_sockettype_udp)
|
iov.iov_base = (void *)(dev->region.base);
|
||||||
cc = sendto(sock->fd,
|
iov.iov_len = dev->n;
|
||||||
ISC_SOCKDATA_CAST(dev->region.base),
|
|
||||||
dev->region.length, 0,
|
memset(&msghdr, 0, sizeof (msghdr));
|
||||||
&dev->address.type.sa,
|
if (sock->type == isc_sockettype_udp) {
|
||||||
(int)dev->address.length);
|
msghdr.msg_name = (void *)&dev->address.type.sa;
|
||||||
else if (sock->type == isc_sockettype_tcp)
|
msghdr.msg_namelen = dev->address.length;
|
||||||
cc = send(sock->fd,
|
|
||||||
ISC_SOCKDATA_CAST(dev->region.base),
|
|
||||||
dev->region.length, 0);
|
|
||||||
else {
|
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
||||||
"isc_socket_send: unknown socket type");
|
|
||||||
UNLOCK(&sock->lock);
|
|
||||||
return (ISC_R_UNEXPECTED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msghdr.msg_iov = &iov;
|
||||||
|
msghdr.msg_iovlen = 1;
|
||||||
|
msghdr.msg_control = NULL;
|
||||||
|
msghdr.msg_controllen = 0;
|
||||||
|
msghdr.msg_flags = 0;
|
||||||
|
|
||||||
|
cc = sendmsg(sock->fd, &msghdr, 0);
|
||||||
|
|
||||||
if (cc < 0) {
|
if (cc < 0) {
|
||||||
if (SOFT_ERROR(errno))
|
if (SOFT_ERROR(errno))
|
||||||
goto queue;
|
goto queue;
|
||||||
@@ -2452,6 +2521,11 @@ isc_socket_recvmark(isc_socket_t *sock,
|
|||||||
}
|
}
|
||||||
ISC_LINK_INIT(dev, link);
|
ISC_LINK_INIT(dev, link);
|
||||||
|
|
||||||
|
dev->result = ISC_R_SUCCESS;
|
||||||
|
dev->attributes = 0;
|
||||||
|
dev->minimum = 0;
|
||||||
|
dev->n = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the queue is empty, simply return the last error we got on
|
* If the queue is empty, simply return the last error we got on
|
||||||
* this socket as the result code, and send off the done event.
|
* this socket as the result code, and send off the done event.
|
||||||
@@ -2471,8 +2545,6 @@ isc_socket_recvmark(isc_socket_t *sock,
|
|||||||
*/
|
*/
|
||||||
isc_task_attach(task, &ntask);
|
isc_task_attach(task, &ntask);
|
||||||
|
|
||||||
dev->result = ISC_R_SUCCESS;
|
|
||||||
dev->minimum = 0;
|
|
||||||
dev->sender = ntask;
|
dev->sender = ntask;
|
||||||
|
|
||||||
ISC_LIST_ENQUEUE(sock->recv_list, dev, link);
|
ISC_LIST_ENQUEUE(sock->recv_list, dev, link);
|
||||||
@@ -2512,6 +2584,11 @@ isc_socket_sendmark(isc_socket_t *sock,
|
|||||||
}
|
}
|
||||||
ISC_LINK_INIT(dev, link);
|
ISC_LINK_INIT(dev, link);
|
||||||
|
|
||||||
|
dev->result = ISC_R_SUCCESS;
|
||||||
|
dev->attributes = 0;
|
||||||
|
dev->minimum = 0;
|
||||||
|
dev->n = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the queue is empty, simply return the last error we got on
|
* If the queue is empty, simply return the last error we got on
|
||||||
* this socket as the result code, and send off the done event.
|
* this socket as the result code, and send off the done event.
|
||||||
@@ -2531,8 +2608,6 @@ isc_socket_sendmark(isc_socket_t *sock,
|
|||||||
*/
|
*/
|
||||||
isc_task_attach(task, &ntask);
|
isc_task_attach(task, &ntask);
|
||||||
|
|
||||||
dev->result = ISC_R_SUCCESS;
|
|
||||||
dev->minimum = 0;
|
|
||||||
dev->sender = ntask;
|
dev->sender = ntask;
|
||||||
|
|
||||||
ISC_LIST_ENQUEUE(sock->send_list, dev, link);
|
ISC_LIST_ENQUEUE(sock->send_list, dev, link);
|
||||||
|
Reference in New Issue
Block a user