2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 13:38:26 +00:00

Add isc_socket_sendto2() and isc_socket_recv2(). These versions take

a partially constructed event and flags.  The flags can include
ISC_SOCKFLAG_IMMEDIATE, which means that if the operation completes, the
event is filled in and not sent.
This commit is contained in:
Brian Wellington 2001-02-12 21:43:17 +00:00
parent 2ba06bbf5a
commit 1f7f8d5c07
2 changed files with 144 additions and 61 deletions

View File

@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: socket.h,v 1.52 2001/01/26 23:17:25 bwelling Exp $ */
/* $Id: socket.h,v 1.53 2001/02/12 21:43:17 bwelling Exp $ */
#ifndef ISC_SOCKET_H
#define ISC_SOCKET_H 1
@ -163,6 +163,11 @@ typedef enum {
#define ISC_SOCKCANCEL_CONNECT 0x00000008 /* cancel connect */
#define ISC_SOCKCANCEL_ALL 0x0000000f /* cancel everything */
/*
* Flags for isc_socket_send() and isc_socket_recv() calls.
*/
#define ISC_SOCKFLAG_IMMEDIATE 0x00000001 /* send event only if needed */
/***
*** Socket and Socket Manager Functions
***
@ -441,6 +446,12 @@ isc_result_t
isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
unsigned int minimum,
isc_task_t *task, isc_taskaction_t action, const void *arg);
isc_result_t
isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
unsigned int minimum, isc_task_t *task,
isc_socketevent_t *event, unsigned int flags);
/*
* Receive from 'socket', storing the results in region.
*
@ -469,6 +480,18 @@ isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
* all buffers will be returned in the done event's 'bufferlist'
* member. On error return, '*buflist' will be unchanged.
*
* For isc_socket_recv2():
* 'event' is not NULL, and the non-socket specific fields are
* expected to be initialized.
*
* For isc_socket_recv2():
* The only defined value for 'flags' is ISC_SOCKFLAG_IMMEDIATE. If
* set and the operation completes, the return value will be
* ISC_R_SUCCESS and the event will be filled in and not sent. If the
* operation does not complete, the return value will be
* ISC_R_INPROGRESS and the event will be sent when the operation
* completes.
*
* Requires:
*
* 'socket' is a valid, bound socket.
@ -481,11 +504,16 @@ isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
*
* 'task' is a valid task
*
* For isc_socket_recv() and isc_socket_recvv():
* action != NULL and is a valid action
*
* For isc_socket_recv2():
* event != NULL
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_INPROGRESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*
@ -510,6 +538,12 @@ isc_result_t
isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
isc_task_t *task, isc_taskaction_t action, const void *arg,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo);
isc_result_t
isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
isc_socketevent_t *event, unsigned int flags);
/*
* Send the contents of 'region' to the socket's peer.
*
@ -530,6 +564,18 @@ isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
* all buffers will be returned in the done event's 'bufferlist'
* member. On error return, '*buflist' will be unchanged.
*
* For isc_socket_sendto2():
* 'event' is not NULL, and the non-socket specific fields are
* expected to be initialized.
*
* For isc_socket_sendto2():
* The only defined value for 'flags' is ISC_SOCKFLAG_IMMEDIATE. If
* set and the operation completes, the return value will be
* ISC_R_SUCCESS and the event will be filled in and not sent. If the
* operation does not complete, the return value will be
* ISC_R_INPROGRESS and the event will be sent when the operation
* completes.
*
* Requires:
*
* 'socket' is a valid, bound socket.
@ -542,11 +588,17 @@ isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
*
* 'task' is a valid task
*
* For isc_socket_sendv(), isc_socket_sendtov(), isc_socket_send(), and
* isc_socket_sendto():
* action == NULL or is a valid action
*
* For isc_socket_sendto2():
* event != NULL
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_INPROGRESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*

View File

@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: socket.c,v 1.191 2001/02/08 00:04:11 bwelling Exp $ */
/* $Id: socket.c,v 1.192 2001/02/12 21:43:15 bwelling Exp $ */
#include <config.h>
@ -234,10 +234,8 @@ static isc_socketmgr_t *socketmgr = NULL;
# define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
#endif
static void send_recvdone_event(isc_socket_t *, isc_socketevent_t **,
isc_result_t);
static void send_senddone_event(isc_socket_t *, isc_socketevent_t **,
isc_result_t);
static void send_recvdone_event(isc_socket_t *, isc_socketevent_t **);
static void send_senddone_event(isc_socket_t *, isc_socketevent_t **);
static void free_socket(isc_socket_t **);
static isc_result_t allocate_socket(isc_socketmgr_t *, isc_sockettype_t,
isc_socket_t **);
@ -885,14 +883,14 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
#define SOFT_OR_HARD(_system, _isc) \
if (errno == _system) { \
if (sock->connected) { \
send_recvdone_event(sock, &dev, _isc); \
dev->result = _isc; \
return (DOIO_HARD); \
} \
return (DOIO_SOFT); \
}
#define ALWAYS_HARD(_system, _isc) \
if (errno == _system) { \
send_recvdone_event(sock, &dev, _isc); \
dev->result = _isc; \
return (DOIO_HARD); \
}
@ -904,8 +902,8 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
#undef SOFT_OR_HARD
#undef ALWAYS_HARD
send_recvdone_event(sock, &dev, ISC_R_UNEXPECTED);
return (DOIO_SUCCESS);
dev->result = ISC_R_UNEXPECTED;
return (DOIO_HARD);
}
/*
@ -975,17 +973,17 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
/*
* Full reads are posted, or partials if partials are ok.
*/
send_recvdone_event(sock, &dev, ISC_R_SUCCESS);
dev->result = ISC_R_SUCCESS;
return (DOIO_SUCCESS);
}
/*
* Returns:
* DOIO_SUCCESS The operation succeeded. The senddone event
* was sent.
* DOIO_SUCCESS The operation succeeded. dev->result contains
* ISC_R_SUCCESS.
*
* DOIO_HARD A hard or unexpected I/O error was encountered.
* The senddone event was sent.
* dev->result contains the appropriate error.
*
* DOIO_SOFT A soft I/O error was encountered. No senddone
* event was sent. The operation should be retried.
@ -1019,14 +1017,14 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
#define SOFT_OR_HARD(_system, _isc) \
if (errno == _system) { \
if (sock->connected) { \
send_senddone_event(sock, &dev, _isc); \
dev->result = _isc; \
return (DOIO_HARD); \
} \
return (DOIO_SOFT); \
}
#define ALWAYS_HARD(_system, _isc) \
if (errno == _system) { \
send_senddone_event(sock, &dev, _isc); \
dev->result = _isc; \
return (DOIO_HARD); \
}
@ -1059,7 +1057,7 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"internal_send: %s: %s",
addrbuf, strerror(errno));
send_senddone_event(sock, &dev, ISC_R_UNEXPECTED);
dev->result = ISC_R_UNEXPECTED;
return (DOIO_HARD);
}
@ -1080,7 +1078,7 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
* Exactly what we wanted to write. We're done with this
* entry. Post its completion event.
*/
send_senddone_event(sock, &dev, ISC_R_SUCCESS);
dev->result = ISC_R_SUCCESS;
return (DOIO_SUCCESS);
}
@ -1558,14 +1556,11 @@ dispatch_connect(isc_socket_t *sock) {
* Caller must have the socket locked if the event is attached to the socket.
*/
static void
send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev,
isc_result_t resultcode)
{
send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
isc_task_t *task;
task = (*dev)->ev_sender;
(*dev)->result = resultcode;
(*dev)->ev_sender = sock;
if (ISC_LINK_LINKED(*dev, ev_link))
@ -1584,15 +1579,12 @@ send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev,
* Caller must have the socket locked if the event is attached to the socket.
*/
static void
send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev,
isc_result_t resultcode)
{
send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
isc_task_t *task;
INSIST(dev != NULL && *dev != NULL);
task = (*dev)->ev_sender;
(*dev)->result = resultcode;
(*dev)->ev_sender = sock;
if (ISC_LINK_LINKED(*dev, ev_link))
@ -1816,13 +1808,15 @@ internal_recv(isc_task_t *me, isc_event_t *ev) {
* the events with an EOF result code.
*/
do {
send_recvdone_event(sock, &dev, ISC_R_EOF);
dev->result = ISC_R_EOF;
send_recvdone_event(sock, &dev);
dev = ISC_LIST_HEAD(sock->recv_list);
} while (dev != NULL);
goto poke;
case DOIO_SUCCESS:
case DOIO_HARD:
send_recvdone_event(sock, &dev);
break;
}
@ -1877,6 +1871,7 @@ internal_send(isc_task_t *me, isc_event_t *ev) {
case DOIO_HARD:
case DOIO_SUCCESS:
send_senddone_event(sock, &dev);
break;
}
@ -2261,11 +2256,14 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
*managerp = NULL;
}
static void
socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task) {
static isc_result_t
socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
unsigned int flags)
{
int io_state;
isc_boolean_t have_lock = ISC_FALSE;
isc_task_t *ntask = NULL;
isc_result_t result = ISC_R_SUCCESS;
dev->ev_sender = task;
@ -2309,21 +2307,25 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task) {
"socket_recv: event %p -> task %p",
dev, ntask);
if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
result = ISC_R_INPROGRESS;
break;
case DOIO_EOF:
send_recvdone_event(sock, &dev, ISC_R_EOF);
break;
dev->result = ISC_R_EOF;
/* fallthrough */
case DOIO_HARD:
case DOIO_SUCCESS:
if ((flags & ISC_SOCKFLAG_IMMEDIATE) == 0)
send_recvdone_event(sock, &dev);
break;
}
if (have_lock)
UNLOCK(&sock->lock);
return (result);
}
isc_result_t
@ -2377,9 +2379,7 @@ isc_socket_recvv(isc_socket_t *sock, isc_bufferlist_t *buflist,
buffer = ISC_LIST_HEAD(*buflist);
}
socket_recv(sock, dev, task);
return (ISC_R_SUCCESS);
return (socket_recv(sock, dev, task, 0));
}
isc_result_t
@ -2390,9 +2390,6 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
isc_socketmgr_t *manager;
REQUIRE(VALID_SOCKET(sock));
REQUIRE(region != NULL);
REQUIRE(region->length >= minimum);
REQUIRE(task != NULL);
REQUIRE(action != NULL);
manager = sock->manager;
@ -2401,36 +2398,49 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
INSIST(sock->bound);
dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
if (dev == NULL) {
if (dev == NULL)
return (ISC_R_NOMEMORY);
}
return (isc_socket_recv2(sock, region, minimum, task, dev, 0));
}
isc_result_t
isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
unsigned int minimum, isc_task_t *task,
isc_socketevent_t *event, unsigned int flags)
{
event->ev_sender = sock;
event->result = ISC_R_UNEXPECTED;
ISC_LIST_INIT(event->bufferlist);
event->region = *region;
event->n = 0;
event->offset = 0;
event->attributes = 0;
/*
* UDP sockets are always partial read.
*/
if (sock->type == isc_sockettype_udp)
dev->minimum = 1;
event->minimum = 1;
else {
if (minimum == 0)
dev->minimum = region->length;
event->minimum = region->length;
else
dev->minimum = minimum;
event->minimum = minimum;
}
dev->region = *region;
socket_recv(sock, dev, task);
return (ISC_R_SUCCESS);
return (socket_recv(sock, event, task, flags));
}
static void
static isc_result_t
socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo)
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
unsigned int flags)
{
int io_state;
isc_boolean_t have_lock = ISC_FALSE;
isc_task_t *ntask = NULL;
isc_result_t result = ISC_R_SUCCESS;
dev->ev_sender = task;
@ -2489,15 +2499,21 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
"socket_send: event %p -> task %p",
dev, ntask);
if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
result = ISC_R_INPROGRESS;
break;
case DOIO_HARD:
case DOIO_SUCCESS:
if ((flags & ISC_SOCKFLAG_IMMEDIATE) == 0)
send_senddone_event(sock, &dev);
break;
}
if (have_lock)
UNLOCK(&sock->lock);
return (result);
}
isc_result_t
@ -2536,9 +2552,7 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
dev->region = *region;
socket_send(sock, dev, task, address, pktinfo);
return (ISC_R_SUCCESS);
return (socket_send(sock, dev, task, address, pktinfo, 0));
}
isc_result_t
@ -2586,9 +2600,24 @@ isc_socket_sendtov(isc_socket_t *sock, isc_bufferlist_t *buflist,
buffer = ISC_LIST_HEAD(*buflist);
}
socket_send(sock, dev, task, address, pktinfo);
return (socket_send(sock, dev, task, address, pktinfo, 0));
}
return (ISC_R_SUCCESS);
isc_result_t
isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task,
isc_sockaddr_t *address, struct in6_pktinfo *pktinfo,
isc_socketevent_t *event, unsigned int flags)
{
event->ev_sender = sock;
event->result = ISC_R_UNEXPECTED;
ISC_LIST_INIT(event->bufferlist);
event->region = *region;
event->n = 0;
event->offset = 0;
event->attributes = 0;
return (socket_send(sock, event, task, address, pktinfo, flags));
}
isc_result_t
@ -3061,9 +3090,10 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
current_task = dev->ev_sender;
next = ISC_LIST_NEXT(dev, ev_link);
if ((task == NULL) || (task == current_task))
send_recvdone_event(sock, &dev,
ISC_R_CANCELED);
if ((task == NULL) || (task == current_task)) {
dev->result = ISC_R_CANCELED;
send_recvdone_event(sock, &dev);
}
dev = next;
}
}
@ -3080,9 +3110,10 @@ isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
current_task = dev->ev_sender;
next = ISC_LIST_NEXT(dev, ev_link);
if ((task == NULL) || (task == current_task))
send_senddone_event(sock, &dev,
ISC_R_CANCELED);
if ((task == NULL) || (task == current_task)) {
dev->result = ISC_R_CANCELED;
send_senddone_event(sock, &dev);
}
dev = next;
}
}