mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-03 08:05:21 +00:00
common path for sending, too
This commit is contained in:
@@ -177,8 +177,8 @@ struct isc_socketmgr {
|
|||||||
|
|
||||||
static void send_recvdone_event(isc_socket_t *, isc_socketevent_t **,
|
static void send_recvdone_event(isc_socket_t *, isc_socketevent_t **,
|
||||||
isc_result_t);
|
isc_result_t);
|
||||||
static void send_senddone_event(isc_socket_t *, isc_task_t **,
|
static void send_senddone_event(isc_socket_t *, isc_socketevent_t **,
|
||||||
isc_socketevent_t **, isc_result_t, int);
|
isc_result_t);
|
||||||
static void free_socket(isc_socket_t **);
|
static void free_socket(isc_socket_t **);
|
||||||
static isc_result_t allocate_socket(isc_socketmgr_t *, isc_sockettype_t,
|
static isc_result_t allocate_socket(isc_socketmgr_t *, isc_sockettype_t,
|
||||||
isc_socket_t **);
|
isc_socket_t **);
|
||||||
@@ -188,12 +188,12 @@ 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 *);
|
static void process_cmsg(isc_socket_t *, struct msghdr *, isc_socketevent_t *);
|
||||||
static int build_msghdr_send(isc_socket_t *, isc_socketevent_t *,
|
static void build_msghdr_send(isc_socket_t *, isc_socketevent_t *,
|
||||||
struct msghdr *, struct iovec *, unsigned int,
|
struct msghdr *, struct iovec *, unsigned int,
|
||||||
size_t *);
|
size_t *);
|
||||||
static int build_msghdr_recv(isc_socket_t *, isc_socketevent_t *,
|
static void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *,
|
||||||
struct msghdr *, struct iovec *, unsigned int,
|
struct msghdr *, struct iovec *, unsigned int,
|
||||||
size_t *);
|
size_t *);
|
||||||
|
|
||||||
#define SELECT_POKE_SHUTDOWN (-1)
|
#define SELECT_POKE_SHUTDOWN (-1)
|
||||||
#define SELECT_POKE_NOTHING (-2)
|
#define SELECT_POKE_NOTHING (-2)
|
||||||
@@ -307,7 +307,7 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev)
|
|||||||
* If write_countp != NULL, *write_countp will hold the number of bytes
|
* If write_countp != NULL, *write_countp will hold the number of bytes
|
||||||
* this transaction can send.
|
* this transaction can send.
|
||||||
*/
|
*/
|
||||||
static int
|
static void
|
||||||
build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
|
build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
|
||||||
struct msghdr *msg, struct iovec *iov, unsigned int maxiov,
|
struct msghdr *msg, struct iovec *iov, unsigned int maxiov,
|
||||||
size_t *write_countp)
|
size_t *write_countp)
|
||||||
@@ -358,8 +358,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (buffer != NULL) {
|
while (buffer != NULL) {
|
||||||
if (iovcount == maxiov)
|
INSIST(iovcount < maxiov);
|
||||||
return (-1);
|
|
||||||
|
|
||||||
isc_buffer_used(buffer, &used);
|
isc_buffer_used(buffer, &used);
|
||||||
|
|
||||||
@@ -391,8 +390,6 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
|
|||||||
|
|
||||||
if (write_countp != NULL)
|
if (write_countp != NULL)
|
||||||
*write_countp = write_count;
|
*write_countp = write_count;
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -407,7 +404,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
|
|||||||
* If read_countp != NULL, *read_countp will hold the number of bytes
|
* If read_countp != NULL, *read_countp will hold the number of bytes
|
||||||
* this transaction can receive.
|
* this transaction can receive.
|
||||||
*/
|
*/
|
||||||
static int
|
static void
|
||||||
build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
|
build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
|
||||||
struct msghdr *msg, struct iovec *iov, unsigned int maxiov,
|
struct msghdr *msg, struct iovec *iov, unsigned int maxiov,
|
||||||
size_t *read_countp)
|
size_t *read_countp)
|
||||||
@@ -458,8 +455,7 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
|
|||||||
|
|
||||||
iovcount = 0;
|
iovcount = 0;
|
||||||
while (buffer != NULL) {
|
while (buffer != NULL) {
|
||||||
if (iovcount == maxiov)
|
INSIST(iovcount < maxiov);
|
||||||
return (-1);
|
|
||||||
|
|
||||||
isc_buffer_available(buffer, &available);
|
isc_buffer_available(buffer, &available);
|
||||||
|
|
||||||
@@ -487,8 +483,6 @@ build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
|
|||||||
|
|
||||||
if (read_countp != NULL)
|
if (read_countp != NULL)
|
||||||
*read_countp = read_count;
|
*read_countp = read_count;
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -530,11 +524,12 @@ allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype,
|
|||||||
return (ev);
|
return (ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DOIO_SUCCESS 0
|
#define DOIO_SUCCESS 0 /* i/o ok, event sent */
|
||||||
#define DOIO_SOFT 1
|
#define DOIO_SOFT 1 /* i/o ok, soft error, no event sent */
|
||||||
#define DOIO_HARD 2
|
#define DOIO_HARD 2 /* i/o error, event sent */
|
||||||
#define DOIO_EOF 3
|
#define DOIO_EOF 3 /* EOF, no event sent */
|
||||||
#define DOIO_UNEXPECTED (-1)
|
#define DOIO_UNEXPECTED (-1) /* bad stuff, no event sent */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
doio_recv(isc_socket_t *sock, isc_socketevent_t *dev)
|
doio_recv(isc_socket_t *sock, isc_socketevent_t *dev)
|
||||||
{
|
{
|
||||||
@@ -543,10 +538,8 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev)
|
|||||||
size_t read_count;
|
size_t read_count;
|
||||||
struct msghdr msghdr;
|
struct msghdr msghdr;
|
||||||
|
|
||||||
if (build_msghdr_recv(sock, dev, &msghdr, iov,
|
build_msghdr_recv(sock, dev, &msghdr, iov,
|
||||||
ISC_SOCKET_MAXSCATTERGATHER, &read_count)
|
ISC_SOCKET_MAXSCATTERGATHER, &read_count);
|
||||||
!= 0)
|
|
||||||
return (DOIO_UNEXPECTED); /* XXX Need better errors! */
|
|
||||||
|
|
||||||
cc = recvmsg(sock->fd, &msghdr, 0);
|
cc = recvmsg(sock->fd, &msghdr, 0);
|
||||||
if (sock->type == isc_sockettype_udp)
|
if (sock->type == isc_sockettype_udp)
|
||||||
@@ -567,9 +560,9 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev)
|
|||||||
if (sock->type == isc_sockettype_tcp) \
|
if (sock->type == isc_sockettype_tcp) \
|
||||||
sock->recv_result = _isc; \
|
sock->recv_result = _isc; \
|
||||||
send_recvdone_event(sock, &dev, _isc); \
|
send_recvdone_event(sock, &dev, _isc); \
|
||||||
|
return (DOIO_HARD); \
|
||||||
} \
|
} \
|
||||||
select_poke(sock->manager, sock->fd); \
|
return (DOIO_SOFT); \
|
||||||
return (DOIO_HARD); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED);
|
SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED);
|
||||||
@@ -582,7 +575,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev)
|
|||||||
*/
|
*/
|
||||||
if (errno == ENOBUFS) {
|
if (errno == ENOBUFS) {
|
||||||
send_recvdone_event(sock, &dev, ISC_R_UNEXPECTED);
|
send_recvdone_event(sock, &dev, ISC_R_UNEXPECTED);
|
||||||
return (DOIO_SOFT);
|
return (DOIO_HARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
sock->recv_result = ISC_R_UNEXPECTED;
|
sock->recv_result = ISC_R_UNEXPECTED;
|
||||||
@@ -622,7 +615,87 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev)
|
|||||||
* full reads are posted, or partials if partials are ok.
|
* full reads are posted, or partials if partials are ok.
|
||||||
*/
|
*/
|
||||||
send_recvdone_event(sock, &dev, ISC_R_SUCCESS);
|
send_recvdone_event(sock, &dev, ISC_R_SUCCESS);
|
||||||
|
return (DOIO_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
doio_send(isc_socket_t *sock, isc_socketevent_t *dev)
|
||||||
|
{
|
||||||
|
int cc;
|
||||||
|
struct iovec iov[ISC_SOCKET_MAXSCATTERGATHER];
|
||||||
|
size_t write_count;
|
||||||
|
struct msghdr msghdr;
|
||||||
|
|
||||||
|
build_msghdr_send(sock, dev, &msghdr, iov,
|
||||||
|
ISC_SOCKET_MAXSCATTERGATHER, &write_count);
|
||||||
|
|
||||||
|
cc = sendmsg(sock->fd, &msghdr, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check for error or block condition
|
||||||
|
*/
|
||||||
|
if (cc < 0) {
|
||||||
|
if (SOFT_ERROR(errno))
|
||||||
|
return (DOIO_SOFT);
|
||||||
|
|
||||||
|
#define SOFT_OR_HARD(_system, _isc) \
|
||||||
|
if (errno == _system) { \
|
||||||
|
if (sock->connected) { \
|
||||||
|
if (sock->type == isc_sockettype_tcp) \
|
||||||
|
sock->send_result = _isc; \
|
||||||
|
send_senddone_event(sock, &dev, _isc); \
|
||||||
|
return (DOIO_HARD); \
|
||||||
|
} \
|
||||||
|
return (DOIO_SOFT); \
|
||||||
|
}
|
||||||
|
|
||||||
|
SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED);
|
||||||
|
SOFT_OR_HARD(ENETUNREACH, ISC_R_NETUNREACH);
|
||||||
|
SOFT_OR_HARD(EHOSTUNREACH, ISC_R_HOSTUNREACH);
|
||||||
|
#undef SOFT_OR_HARD
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This might not be a permanent error.
|
||||||
|
*/
|
||||||
|
if (errno == ENOBUFS) {
|
||||||
|
send_senddone_event(sock, &dev, ISC_R_NORESOURCES);
|
||||||
|
return (DOIO_HARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The other error types depend on whether or not the
|
||||||
|
* socket is UDP or TCP. If it is UDP, some errors
|
||||||
|
* that we expect to be fatal under TCP are merely
|
||||||
|
* annoying, and are really soft errors.
|
||||||
|
*
|
||||||
|
* However, these soft errors are still returned as
|
||||||
|
* a status.
|
||||||
|
*/
|
||||||
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||||
|
"internal_send: %s",
|
||||||
|
strerror(errno));
|
||||||
|
sock->send_result = ISC_R_UNEXPECTED;
|
||||||
|
send_senddone_event(sock, &dev, ISC_R_UNEXPECTED);
|
||||||
|
return (DOIO_HARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cc == 0)
|
||||||
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||||
|
"internal_send: send() returned 0");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we write less than we expected, update counters,
|
||||||
|
* poke.
|
||||||
|
*/
|
||||||
|
dev->n += cc;
|
||||||
|
if ((size_t)cc != write_count)
|
||||||
|
return (DOIO_SOFT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Exactly what we wanted to write. We're done with this
|
||||||
|
* entry. Post its completion event.
|
||||||
|
*/
|
||||||
|
send_senddone_event(sock, &dev, ISC_R_SUCCESS);
|
||||||
return (DOIO_SUCCESS);
|
return (DOIO_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1047,18 +1120,24 @@ send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev,
|
|||||||
* Caller must have the socket locked.
|
* Caller must have the socket locked.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
send_senddone_event(isc_socket_t *sock, isc_task_t **taskp,
|
send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev,
|
||||||
isc_socketevent_t **dev, isc_result_t resultcode,
|
isc_result_t resultcode)
|
||||||
int detach)
|
|
||||||
{
|
{
|
||||||
|
isc_task_t *task;
|
||||||
|
|
||||||
|
task = (*dev)->sender;
|
||||||
|
|
||||||
(*dev)->result = resultcode;
|
(*dev)->result = resultcode;
|
||||||
(*dev)->sender = sock;
|
(*dev)->sender = sock;
|
||||||
|
|
||||||
if (ISC_LINK_LINKED(*dev, link))
|
if (ISC_LINK_LINKED(*dev, link))
|
||||||
ISC_LIST_DEQUEUE(sock->send_list, *dev, link);
|
ISC_LIST_DEQUEUE(sock->send_list, *dev, link);
|
||||||
if (detach)
|
|
||||||
ISC_TASK_SENDANDDETACH(taskp, (isc_event_t **)dev);
|
if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
|
||||||
|
== ISC_SOCKEVENTATTR_ATTACHED)
|
||||||
|
ISC_TASK_SENDANDDETACH(&task, (isc_event_t **)dev);
|
||||||
else
|
else
|
||||||
ISC_TASK_SEND(*taskp, (isc_event_t **)dev);
|
ISC_TASK_SEND(task, (isc_event_t **)dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1255,9 +1334,13 @@ internal_recv(isc_task_t *me, isc_event_t *ev)
|
|||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sock->recv_result != ISC_R_SUCCESS) {
|
||||||
|
send_recvdone_event(sock, &dev, sock->recv_result);
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
switch (doio_recv(sock, dev)) {
|
switch (doio_recv(sock, dev)) {
|
||||||
case DOIO_SOFT:
|
case DOIO_SOFT:
|
||||||
case DOIO_HARD:
|
|
||||||
goto poke;
|
goto poke;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1278,6 +1361,7 @@ internal_recv(isc_task_t *me, isc_event_t *ev)
|
|||||||
|
|
||||||
case DOIO_UNEXPECTED:
|
case DOIO_UNEXPECTED:
|
||||||
case DOIO_SUCCESS:
|
case DOIO_SUCCESS:
|
||||||
|
case DOIO_HARD:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1298,10 +1382,6 @@ internal_send(isc_task_t *me, isc_event_t *ev)
|
|||||||
isc_socketevent_t *dev;
|
isc_socketevent_t *dev;
|
||||||
isc_socket_t *sock;
|
isc_socket_t *sock;
|
||||||
isc_task_t *task;
|
isc_task_t *task;
|
||||||
int cc;
|
|
||||||
size_t write_count;
|
|
||||||
struct msghdr msghdr;
|
|
||||||
struct iovec iov[ISC_SOCKET_MAXSCATTERGATHER];
|
|
||||||
|
|
||||||
(void)me;
|
(void)me;
|
||||||
|
|
||||||
@@ -1344,91 +1424,24 @@ internal_send(isc_task_t *me, isc_event_t *ev)
|
|||||||
* continue the loop.
|
* continue the loop.
|
||||||
*/
|
*/
|
||||||
if (dev->type == ISC_SOCKEVENT_SENDMARK) {
|
if (dev->type == ISC_SOCKEVENT_SENDMARK) {
|
||||||
send_senddone_event(sock, &task, &dev,
|
send_senddone_event(sock, &dev, sock->send_result);
|
||||||
sock->send_result, 1);
|
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (sock->send_result != ISC_R_SUCCESS) {
|
||||||
* It must be a write request. Try to satisfy it as best
|
send_senddone_event(sock, &dev, sock->send_result);
|
||||||
* we can.
|
|
||||||
*/
|
|
||||||
build_msghdr_send(sock, dev, &msghdr, iov,
|
|
||||||
ISC_SOCKET_MAXSCATTERGATHER, &write_count);
|
|
||||||
|
|
||||||
cc = sendmsg(sock->fd, &msghdr, 0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check for error or block condition
|
|
||||||
*/
|
|
||||||
if (cc < 0) {
|
|
||||||
if (SOFT_ERROR(errno))
|
|
||||||
goto poke;
|
|
||||||
|
|
||||||
#define SOFT_OR_HARD(_system, _isc) \
|
|
||||||
if (errno == _system) { \
|
|
||||||
if (sock->connected) { \
|
|
||||||
if (sock->type == isc_sockettype_tcp) \
|
|
||||||
sock->send_result = _isc; \
|
|
||||||
send_senddone_event(sock, &task, &dev, _isc, 1); \
|
|
||||||
} \
|
|
||||||
goto next; \
|
|
||||||
}
|
|
||||||
|
|
||||||
SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED);
|
|
||||||
SOFT_OR_HARD(ENETUNREACH, ISC_R_NETUNREACH);
|
|
||||||
SOFT_OR_HARD(EHOSTUNREACH, ISC_R_HOSTUNREACH);
|
|
||||||
#undef SOFT_OR_HARD
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This might not be a permanent error.
|
|
||||||
*/
|
|
||||||
if (errno == ENOBUFS) {
|
|
||||||
send_senddone_event(sock, &task, &dev,
|
|
||||||
ISC_R_NORESOURCES, 1);
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The other error types depend on whether or not the
|
|
||||||
* socket is UDP or TCP. If it is UDP, some errors
|
|
||||||
* that we expect to be fatal under TCP are merely
|
|
||||||
* annoying, and are really soft errors.
|
|
||||||
*
|
|
||||||
* However, these soft errors are still returned as
|
|
||||||
* a status.
|
|
||||||
*/
|
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
||||||
"internal_send: %s",
|
|
||||||
strerror(errno));
|
|
||||||
sock->send_result = ISC_R_UNEXPECTED;
|
|
||||||
send_senddone_event(sock, &task, &dev,
|
|
||||||
ISC_R_UNEXPECTED, 1);
|
|
||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cc == 0)
|
switch (doio_send(sock, dev)) {
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
case DOIO_SOFT:
|
||||||
"internal_send: send() returned 0");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if we write less than we expected, update counters,
|
|
||||||
* poke.
|
|
||||||
*/
|
|
||||||
if ((size_t)cc < write_count) {
|
|
||||||
dev->n += cc;
|
|
||||||
goto poke;
|
goto poke;
|
||||||
}
|
break;
|
||||||
|
|
||||||
/*
|
case DOIO_HARD:
|
||||||
* Exactly what we wanted to write. We're done with this
|
case DOIO_UNEXPECTED:
|
||||||
* entry. Post its completion event.
|
case DOIO_SUCCESS:
|
||||||
*/
|
break;
|
||||||
if ((size_t)cc == write_count) {
|
|
||||||
dev->n += write_count;
|
|
||||||
send_senddone_event(sock, &task, &dev,
|
|
||||||
ISC_R_SUCCESS, 1);
|
|
||||||
goto next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next:
|
next:
|
||||||
@@ -1890,21 +1903,24 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
|
|||||||
if (!was_empty)
|
if (!was_empty)
|
||||||
goto queue;
|
goto queue;
|
||||||
|
|
||||||
|
if (sock->recv_result != ISC_R_SUCCESS) {
|
||||||
|
send_recvdone_event(sock, &dev, sock->recv_result);
|
||||||
|
UNLOCK(&sock->lock);
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
switch (doio_recv(sock, dev)) {
|
switch (doio_recv(sock, dev)) {
|
||||||
case DOIO_SOFT:
|
case DOIO_SOFT:
|
||||||
goto queue;
|
goto queue;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DOIO_HARD:
|
|
||||||
goto out;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DOIO_EOF:
|
case DOIO_EOF:
|
||||||
send_recvdone_event(sock, &dev, ISC_R_EOF);
|
send_recvdone_event(sock, &dev, ISC_R_EOF);
|
||||||
UNLOCK(&sock->lock);
|
UNLOCK(&sock->lock);
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DOIO_HARD:
|
||||||
case DOIO_UNEXPECTED:
|
case DOIO_UNEXPECTED:
|
||||||
case DOIO_SUCCESS:
|
case DOIO_SUCCESS:
|
||||||
UNLOCK(&sock->lock);
|
UNLOCK(&sock->lock);
|
||||||
@@ -1920,7 +1936,6 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
|
|||||||
* Attach to socket and to task
|
* Attach to socket and to task
|
||||||
*/
|
*/
|
||||||
isc_task_attach(task, &ntask);
|
isc_task_attach(task, &ntask);
|
||||||
dev->sender = ntask;
|
|
||||||
dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
|
dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1934,7 +1949,6 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
|
|||||||
XTRACE(TRACE_RECV,
|
XTRACE(TRACE_RECV,
|
||||||
("isc_socket_recv: queued event %p, task %p\n", dev, ntask));
|
("isc_socket_recv: queued event %p, task %p\n", dev, ntask));
|
||||||
|
|
||||||
out:
|
|
||||||
UNLOCK(&sock->lock);
|
UNLOCK(&sock->lock);
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
@@ -1957,11 +1971,7 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
|
|||||||
isc_socketevent_t *dev;
|
isc_socketevent_t *dev;
|
||||||
isc_socketmgr_t *manager;
|
isc_socketmgr_t *manager;
|
||||||
isc_task_t *ntask = NULL;
|
isc_task_t *ntask = NULL;
|
||||||
int cc;
|
|
||||||
isc_boolean_t was_empty;
|
isc_boolean_t was_empty;
|
||||||
struct msghdr msghdr;
|
|
||||||
struct iovec iov[ISC_SOCKET_MAXSCATTERGATHER];
|
|
||||||
size_t write_count;
|
|
||||||
|
|
||||||
REQUIRE(VALID_SOCKET(sock));
|
REQUIRE(VALID_SOCKET(sock));
|
||||||
REQUIRE(region != NULL);
|
REQUIRE(region != NULL);
|
||||||
@@ -1982,6 +1992,7 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
|
|||||||
}
|
}
|
||||||
|
|
||||||
dev->region = *region;
|
dev->region = *region;
|
||||||
|
dev->sender = task;
|
||||||
|
|
||||||
set_dev_address(address, sock, dev);
|
set_dev_address(address, sock, dev);
|
||||||
|
|
||||||
@@ -1992,73 +2003,24 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
|
|||||||
if (!was_empty)
|
if (!was_empty)
|
||||||
goto queue;
|
goto queue;
|
||||||
|
|
||||||
build_msghdr_send(sock, dev, &msghdr, iov,
|
if (sock->send_result != ISC_R_SUCCESS) {
|
||||||
ISC_SOCKET_MAXSCATTERGATHER, &write_count);
|
send_senddone_event(sock, &dev, sock->send_result);
|
||||||
|
|
||||||
cc = sendmsg(sock->fd, &msghdr, 0);
|
|
||||||
|
|
||||||
if (cc < 0) {
|
|
||||||
if (SOFT_ERROR(errno))
|
|
||||||
goto queue;
|
|
||||||
|
|
||||||
#define SOFT_OR_HARD(_system, _isc) \
|
|
||||||
if (errno == _system) { \
|
|
||||||
if (sock->connected) { \
|
|
||||||
if (sock->type == isc_sockettype_tcp) \
|
|
||||||
sock->send_result = _isc; \
|
|
||||||
send_senddone_event(sock, &task, &dev, _isc, 0); \
|
|
||||||
} \
|
|
||||||
select_poke(sock->manager, sock->fd); \
|
|
||||||
goto out; \
|
|
||||||
}
|
|
||||||
|
|
||||||
SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED);
|
|
||||||
SOFT_OR_HARD(ENETUNREACH, ISC_R_NETUNREACH);
|
|
||||||
SOFT_OR_HARD(EHOSTUNREACH, ISC_R_HOSTUNREACH);
|
|
||||||
#undef SOFT_OR_HARD
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This might not be a permanent error.
|
|
||||||
*/
|
|
||||||
switch (errno) {
|
|
||||||
case ENOBUFS:
|
|
||||||
send_senddone_event(sock, &task, &dev,
|
|
||||||
ISC_R_NORESOURCES, 0);
|
|
||||||
goto out;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EINVAL:
|
|
||||||
FATAL_ERROR(__FILE__, __LINE__,
|
|
||||||
"isc_socket_sendto: EINVAL");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
|
||||||
"isc_socket_sendto: errno: %s",
|
|
||||||
strerror(errno));
|
|
||||||
sock->send_result = ISC_R_UNEXPECTED;
|
|
||||||
send_senddone_event(sock, &task, &dev,
|
|
||||||
ISC_R_UNEXPECTED, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
UNLOCK(&sock->lock);
|
UNLOCK(&sock->lock);
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->n = cc;
|
switch (doio_send(sock, dev)) {
|
||||||
|
case DOIO_SOFT:
|
||||||
/*
|
|
||||||
* Partial writes need to be queued
|
|
||||||
*/
|
|
||||||
if ((size_t)cc != write_count)
|
|
||||||
goto queue;
|
goto queue;
|
||||||
|
break;
|
||||||
|
|
||||||
/*
|
case DOIO_HARD:
|
||||||
* full writes are posted.
|
case DOIO_UNEXPECTED:
|
||||||
*/
|
case DOIO_SUCCESS:
|
||||||
send_senddone_event(sock, &task, &dev, ISC_R_SUCCESS, 0);
|
UNLOCK(&sock->lock);
|
||||||
|
return (ISC_R_SUCCESS);
|
||||||
UNLOCK(&sock->lock);
|
break;
|
||||||
return (ISC_R_SUCCESS);
|
}
|
||||||
|
|
||||||
queue:
|
queue:
|
||||||
/*
|
/*
|
||||||
@@ -2066,7 +2028,7 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
|
|||||||
* it.
|
* it.
|
||||||
*/
|
*/
|
||||||
isc_task_attach(task, &ntask);
|
isc_task_attach(task, &ntask);
|
||||||
dev->sender = ntask;
|
dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enqueue the request. If the socket was previously not being
|
* Enqueue the request. If the socket was previously not being
|
||||||
@@ -2079,7 +2041,6 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
|
|||||||
XTRACE(TRACE_SEND,
|
XTRACE(TRACE_SEND,
|
||||||
("isc_socket_send: queued event %p, task %p\n", dev, ntask));
|
("isc_socket_send: queued event %p, task %p\n", dev, ntask));
|
||||||
|
|
||||||
out:
|
|
||||||
UNLOCK(&sock->lock);
|
UNLOCK(&sock->lock);
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
@@ -2543,8 +2504,8 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how)
|
|||||||
next = ISC_LIST_NEXT(dev, link);
|
next = ISC_LIST_NEXT(dev, link);
|
||||||
|
|
||||||
if ((task == NULL) || (task == current_task))
|
if ((task == NULL) || (task == current_task))
|
||||||
send_senddone_event(sock, ¤t_task, &dev,
|
send_senddone_event(sock, &dev,
|
||||||
ISC_R_CANCELED, 1);
|
ISC_R_CANCELED);
|
||||||
dev = next;
|
dev = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user