2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-05 09:05:40 +00:00
Files
bind/lib/isc/include/isc/socket.h
1999-05-10 22:52:55 +00:00

599 lines
14 KiB
C

/*
* Copyright (C) 1998, 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifndef ISC_SOCKET_H
#define ISC_SOCKET_H 1
/*****
***** Module Info
*****/
/*
* Sockets
*
* Provides TCP and UDP sockets for network I/O. The sockets are event
* sources in the task system.
*
* When I/O completes, a completion event for the socket is posted to the
* event queue of the task which requested the I/O.
*
* MP:
* The module ensures appropriate synchronization of data structures it
* creates and manipulates.
*
* Clients of this module must not be holding a socket's task's lock when
* making a call that affects that socket. Failure to follow this rule
* can result in deadlock.
*
* The caller must ensure that isc_socketmgr_destroy() is called only
* once for a given manager.
*
* Reliability:
* No anticipated impact.
*
* Resources:
* <TBS>
*
* Security:
* No anticipated impact.
*
* Standards:
* None.
*/
/***
*** Imports
***/
#include <isc/lang.h>
#include <isc/boolean.h>
#include <isc/result.h>
#include <isc/event.h>
#include <isc/eventclass.h>
#include <isc/task.h>
#include <isc/region.h>
#include <isc/mem.h>
#include <isc/sockaddr.h>
ISC_LANG_BEGINDECLS
/***
*** Types
***/
typedef struct isc_socket isc_socket_t;
typedef struct isc_socketmgr isc_socketmgr_t;
typedef struct isc_socketevent {
isc_event_t common; /* Sender is the socket. */
isc_result_t result; /* OK, EOF, whatever else */
unsigned int n; /* bytes read or written */
isc_region_t region; /* the region info */
isc_sockaddr_t address; /* source address */
unsigned int addrlength; /* length of address */
} isc_socketevent_t;
typedef struct isc_socket_newconnev {
isc_event_t common;
isc_socket_t * newsocket;
isc_result_t result; /* OK, EOF, whatever else */
isc_sockaddr_t address; /* source address */
unsigned int addrlength; /* length of address */
} isc_socket_newconnev_t;
typedef struct isc_socket_connev {
isc_event_t common;
isc_result_t result; /* OK, EOF, whatever else */
} isc_socket_connev_t;
#define ISC_SOCKEVENT_ANYEVENT (0)
#define ISC_SOCKEVENT_RECVDONE (ISC_EVENTCLASS_SOCKET + 1)
#define ISC_SOCKEVENT_SENDDONE (ISC_EVENTCLASS_SOCKET + 2)
#define ISC_SOCKEVENT_NEWCONN (ISC_EVENTCLASS_SOCKET + 3)
#define ISC_SOCKEVENT_CONNECT (ISC_EVENTCLASS_SOCKET + 4)
#define ISC_SOCKEVENT_RECVMARK (ISC_EVENTCLASS_SOCKET + 5)
#define ISC_SOCKEVENT_SENDMARK (ISC_EVENTCLASS_SOCKET + 6)
/*
* Internal events.
*/
#define ISC_SOCKEVENT_INTRECV (ISC_EVENTCLASS_SOCKET + 257)
#define ISC_SOCKEVENT_INTSEND (ISC_EVENTCLASS_SOCKET + 258)
#define ISC_SOCKEVENT_INTACCEPT (ISC_EVENTCLASS_SOCKET + 259)
#define ISC_SOCKEVENT_INTCONN (ISC_EVENTCLASS_SOCKET + 260)
typedef enum {
isc_socket_udp,
isc_socket_tcp
} isc_sockettype_t;
/*
* How a socket should be shutdown in isc_socket_shutdown() calls.
*/
#define ISC_SOCKSHUT_RECV 0x00000001 /* close read side */
#define ISC_SOCKSHUT_SEND 0x00000002 /* close write side */
#define ISC_SOCKSHUT_ALL 0x00000003 /* close them all */
/*
* What I/O events to cancel in isc_socket_cancel() calls.
*/
#define ISC_SOCKCANCEL_RECV 0x00000001 /* cancel recv */
#define ISC_SOCKCANCEL_SEND 0x00000002 /* cancel send */
#define ISC_SOCKCANCEL_ACCEPT 0x00000004 /* cancel accept */
#define ISC_SOCKCANCEL_CONNECT 0x00000008 /* cancel connect */
#define ISC_SOCKCANCEL_ALL 0x0000000f /* cancel everything */
/***
*** Socket and Socket Manager Functions
***
*** Note: all Ensures conditions apply only if the result is success for
*** those functions which return an isc_result.
***/
isc_result_t
isc_socket_create(isc_socketmgr_t *manager,
isc_sockettype_t type,
isc_socket_t **socketp);
/*
* Create a new 'type' socket managed by 'manager'.
*
* Requires:
*
* 'manager' is a valid manager
*
* 'socketp' is a valid pointer, and *socketp == NULL
*
* Ensures:
*
* '*socketp' is attached to the newly created socket
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_NORESOURCES
* ISC_R_UNEXPECTED
*/
void
isc_socket_cancel(isc_socket_t *sock, isc_task_t *task,
unsigned int how);
/*
* Cancel pending I/O of the type specified by "how".
*
* Note: if "task" is NULL, then the cancel applies to all tasks using the
* socket.
*
* Requires:
*
* "socket" is a valid socket
*
* "task" is NULL or a valid task
*
* "how" is a bitmask describing the type of cancelation to perform.
* The type ISC_SOCKCANCEL_ALL will cancel all pending I/O on this
* socket.
*
* ISC_SOCKCANCEL_RECV:
* Cancel pending isc_socket_recv() calls.
*
* ISC_SOCKCANCEL_SEND:
* Cancel pending isc_socket_send() and isc_socket_sendto() calls.
*
* ISC_SOCKCANCEL_ACCEPT:
* Cancel pending isc_socket_accept() calls.
*
* ISC_SOCKCANCEL_CONNECT:
* Cancel pending isc_socket_connect() call.
*/
void
isc_socket_shutdown(isc_socket_t *sock, unsigned int how);
/*
* Shutdown 'socket' according to 'how'.
*
* Requires:
*
* 'socket' is a valid socket.
*
* 'task' is NULL or is a valid task.
*
* If 'how' is 'ISC_SOCKSHUT_RECV' or 'ISC_SOCKSHUT_ALL' then
*
* The read queue must be empty.
*
* No further read requests may be made.
*
* If 'how' is 'ISC_SOCKSHUT_SEND' or 'ISC_SOCKSHUT_ALL' then
*
* The write queue must be empty.
*
* No further write requests may be made.
*/
void
isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp);
/*
* Attach *socketp to socket.
*
* Requires:
*
* 'socket' is a valid socket.
*
* 'socketp' points to a NULL socket.
*
* Ensures:
*
* *socketp is attached to socket.
*/
void
isc_socket_detach(isc_socket_t **socketp);
/*
* Detach *socketp from its socket.
*
* Notes:
*
* Detaching the last reference may cause any still-pending I/O to be
* cancelled.
*
* Requires:
*
* 'socketp' points to a valid socket.
*
* Ensures:
*
* *socketp is NULL.
*
* If '*socketp' is the last reference to the socket,
* then:
*
* The socket will be shutdown (both reading and writing)
* for all tasks.
*
* All resources used by the socket have been freed
*/
isc_result_t
isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *addressp,
int length);
/*
* Bind 'socket' to '*addressp'.
*
* Requires:
*
* 'socket' is a valid socket
*
* 'addressp' points to a valid isc_sockaddr.
*
* 'length' is approprate for the isc_sockaddr type.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOPERM
* ISC_R_ADDRNOTAVAIL
* ISC_R_ADDRINUSE
* ISC_R_BOUND
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socket_listen(isc_socket_t *sock, unsigned int backlog);
/*
* Set listen mode on the socket. After this call, the only function that
* can be used (other than attach and detach) is isc_socket_accept().
*
* Notes:
*
* 'backlog' is as in the UNIX system call listen() and may be
* ignored by non-UNIX implementations.
*
* If 'backlog' is zero, a reasonable system default is used, usually
* SOMAXCONN.
*
* Requires:
*
* 'socket' is a valid TCP socket.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socket_accept(isc_socket_t *sock,
isc_task_t *task, isc_taskaction_t action, void *arg);
/*
* Queue accept event. When a new connection is received, the task will
* get an ISC_SOCKEVENT_NEWCONN event with the sender set to the listen
* socket. The new socket structure is sent inside the isc_socket_newconnev_t
* event type, and is attached to the task 'task'.
*
* REQUIRES:
* 'socket' is a valid TCP socket that isc_socket_listen() has been
* called on
*
* 'task' is a valid task
*
* 'action' is a valid action
*
* RETURNS:
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addressp,
int length, isc_task_t *task, isc_taskaction_t action,
void *arg);
/*
* Connect 'socket' to peer with address *saddr. When the connection
* succeeds, or when an error occurs, a CONNECT event with action 'action'
* and arg 'arg' will be posted to the event queue for 'task'.
*
* Requires:
*
* 'socket' is a valid TCP socket
*
* 'addressp' points to a valid isc_sockaddr
*
* 'length' is approprate for the isc_sockaddr type
*
* 'task' is a valid task
*
* 'action' is a valid action
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*
* Posted event's result code:
*
* ISC_R_SUCCESS
* ISC_R_TIMEDOUT
* ISC_R_CONNREFUSED
* ISC_R_NETUNREACH
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp,
int *lengthp);
/*
* Get the name of the peer connected to 'socket'.
*
* Requires:
*
* 'socket' is a valid TCP socket.
*
* 'addressp' points to '*lengthp' bytes.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_TOOSMALL
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp,
int *lengthp);
/*
* Get the name of 'socket'.
*
* Requires:
*
* 'socket' is a valid socket.
*
* 'addressp' points to '*lengthp' bytes.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_TOOSMALL
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socket_recv(isc_socket_t *sock, isc_region_t *region,
isc_boolean_t partial,
isc_task_t *task, isc_taskaction_t action, void *arg);
/*
* Receive from 'socket', storing the results in region.
*
* Notes:
*
* Let 'length' refer to the length of 'region'.
*
* If 'partial' is true, then at most 'length' bytes will be read.
* Otherwise the read will not complete until exactly 'length' bytes
* have been read.
*
* The read will complete when the desired number of bytes have been
* read, if end-of-input occurs, or if an error occurs. A read done
* event with the given 'action' and 'arg' will be posted to the
* event queue of 'task'.
*
* Partial reads are always turned on for UDP.
*
* The caller may neither read from nor write to 'region' until it
* has received the read completion event.
*
* Requires:
*
* 'socket' is a valid socket
*
* 'region' is a valid region
*
* 'task' is a valid task
*
* action != NULL and is a valid action
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*
* Event results:
*
* ISC_R_SUCCESS
* ISC_R_UNEXPECTED
* XXX needs other net-type errors
*/
isc_result_t
isc_socket_send(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task, isc_taskaction_t action, void *arg);
isc_result_t
isc_socket_sendto(isc_socket_t *sock, isc_region_t *region,
isc_task_t *task, isc_taskaction_t action, void *arg,
isc_sockaddr_t *address, unsigned int addrlength);
/*
* Send the contents of 'region' to the socket's peer.
*
* Notes:
*
* Shutting down the requestor's task *may* result in any
* still pending writes being dropped.
*
* If 'action' is NULL, then no completion event will be posted.
*
* The caller may neither read from nor write to 'region' until it
* has received the write completion event, or all references to the
* socket have been detached.
*
* Requires:
*
* 'socket' is a valid socket
*
* 'region' is a valid region
*
* 'task' is a valid task
*
* action == NULL or is a valid action
*
* Returns:
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*
* Event results:
*
* ISC_R_SUCCESS
* ISC_R_UNEXPECTED
* XXX needs other net-type errors
*/
isc_result_t
isc_socket_recvmark(isc_socket_t *sock,
isc_task_t *task, isc_taskaction_t action, void *arg);
isc_result_t
isc_socket_sendmark(isc_socket_t *sock,
isc_task_t *task, isc_taskaction_t action, void *arg);
/*
* Insert a recv/send marker for the socket.
*
* This marker is processed when all I/O requests in the proper queue
* have been processed.
*
* Requires:
*
* 'sock' to be a valid socket.
*
* 'task' is a valid task, 'action' is a valid action.
*
* Notes:
*
* If the queue is empty, the event will be posted immediately to the
* task.
*
* On return, the event's 'result' member will sometimes contain useful
* information. If the mark was processed after a fatal error, it will
* contain the same error that the last isc_socket_recv(), _send(),
* or sendto() returned, depending on the mark type.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*/
isc_result_t
isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
/*
* Create a socket manager.
*
* Notes:
*
* All memory will be allocated in memory context 'mctx'.
*
* Requires:
*
* 'mctx' is a valid memory context.
*
* 'managerp' points to a NULL isc_socketmgr_t.
*
* Ensures:
*
* '*managerp' is a valid isc_socketmgr_t.
*
* Returns:
*
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
* ISC_R_UNEXPECTED
*/
void
isc_socketmgr_destroy(isc_socketmgr_t **managerp);
/*
* Destroy a socket manager.
*
* Notes:
*
* This routine blocks until there are no sockets left in the manager,
* so if the caller holds any socket references using the manager, it
* must detach them before calling isc_socketmgr_destroy() or it will
* block forever.
*
* Requires:
*
* '*managerp' is a valid isc_socketmgr_t.
*
* All sockets managed by this manager are fully detached.
*
* Ensures:
*
* *managerp == NULL
*
* All resources used by the manager have been freed.
*/
ISC_LANG_ENDDECLS
#endif /* ISC_SOCKET_H */