-The tsocket_context is like an abstract class and represents
-a socket similar to bsd style sockets. The methods are more
-or less equal to the bsd socket api, while the filedescriptor
-is replaced by tsocket_context and sockaddr, socklen_t pairs
-are replaced by tsocket_address. The 'bind' operation happens
-in the specific constructor as the constructor is typically based
-on tsocket_address of local socket endpoint.
-
-All operations are by design non blocking and can return error
-values like EAGAIN, EINPROGRESS, EWOULDBLOCK or EINTR which
-indicate that the caller should retry the operation later.
-Also read the "The glue to tevent" section.
-
-The socket can of types:
- - TSOCKET_TYPE_STREAM is the equivalent to SOCK_STREAM in the bsd socket api.
- - TSOCKET_TYPE_DGRAM is the equivalent to SOCK_DGRAM in the bsd socket api.
- - TSOCKET_TYPE_MESSAGE operates on a connected socket and is therefore
- like TSOCKET_TYPE_STREAM, but the consumer needs to first read all
- data of a message, which was generated by one message 'write' on the sender,
- before the consumer gets data of the next message. This matches a bit
- like message mode pipes on windows. The concept is to transfer ordered
- messages between to endpoints.
-
-There's a function to connect to a remote endpoint. The behavior
-and error codes match the connect(2) function of the bsd socket api.
-Maybe the specific tsocket_context implementation speficied some
-further details.
-
- int tsocket_connect(struct tsocket_context *sock,
- const struct tsocket_address *remote_addr);
-
-There's a function to listen for incoming connections. The behavior
-and error codes match the listen(2) function of the bsd socket api.
-Maybe the specific tsocket_context implementation speficied some
-further details.
-
- int tsocket_listen(struct tsocket_context *sock,
- int queue_size);
-
-There's a function to accept incoming connections. The behavior
-and error codes match the accept(2) function of the bsd socket api.
-Maybe the specific tsocket_context implementation speficied some
-further details.
-
- int tsocket_accept(struct tsocket_context *sock,
- TALLOC_CTX *mem_ctx,
- struct tsocket_context **new_sock);
-
-There's a function to ask how many bytes are in input buffer
-of the connection. For sockets of type TSOCKET_TYPE_DGRAM or
-TSOCKET_TYPE_MESSAGE the size of the next available dgram/message
-is returned. A return value of -1 indicates a socket error
-and errno will hold the specific error code. If no data
-is available 0 is returned, but retry error codes like
-EINTR can also be returned.
-
- ssize_t tsocket_pending(struct tsocket_context *sock);
-
-There's a function to read data from the socket. The behavior
-and error codes match the readv(3) function, also take a look
-at the recv(2) function of the bsd socket api.
-Maybe the specific tsocket_context implementation speficied some
-further details.
-
- int tsocket_readv(struct tsocket_context *sock,
- const struct iovec *vector, size_t count);
-
-There's a function to write data from the socket. The behavior
-and error codes match the writev(3) function, also take a look
-at the send(2) function of the bsd socket api.
-Maybe the specific tsocket_context implementation speficied some
-further details.
-
- int tsocket_writev(struct tsocket_context *sock,
- const struct iovec *vector, size_t count);
-
-There's a function to read a datagram from a remote endpoint.
-The behavior and error codes match the recvfrom(2) function of
-the bsd socket api. As TSOCKET_TYPE_DGRAM sockets can also be
-used in connected mode src_addr can be NULL, if the caller don't
-want to get the source address. Maybe the specific tsocket_context
-implementation speficied some further details.
-
- ssize_t tsocket_recvfrom(struct tsocket_context *sock,
- uint8_t *data, size_t len,
- TALLOC_CTX *addr_ctx,
- struct tsocket_address **src_addr);
-
-There's a function to send a datagram to a remote endpoint the socket.
-The behavior and error codes match the recvfrom(2) function of the
-bsd socket api. As TSOCKET_TYPE_DGRAM sockets can also be used in
-connected mode dest_addr must be NULL in connected mode and a valid
-tsocket_address otherwise. Maybe the specific tsocket_context
-implementation speficied some further details.
-
- ssize_t tsocket_sendto(struct tsocket_context *sock,
- const uint8_t *data, size_t len,
- const struct tsocket_address *dest_addr);
-
-There's a function to get the current status of the socket.
-The behavior and error codes match the getsockopt(2) function
-of the bsd socket api, with SOL_SOCKET and SO_ERROR as arguments.
-Maybe the specific tsocket_context implementation speficied some
-further details.
-
- int tsocket_get_status(const struct tsocket_context *sock);
-
-There's a function to get tsocket_address of the local endpoint.
-The behavior and error codes match the getsockname(2) function
-of the bsd socket api. Maybe the specific tsocket_context
-implementation speficied some further details.
-
- int tsocket_get_local_address(const struct tsocket_context *sock,
- TALLOC_CTX *mem_ctx,
- struct tsocket_address **local_addr);
-
-There's a function to get tsocket_address of the remote endpoint
-of a connected socket. The behavior and error codes match the
-getpeername(2) function of the bsd socket api. Maybe the specific
-tsocket_context implementation speficied some further details.
-
- int tsocket_get_remote_address(const struct tsocket_context *sock,
- TALLOC_CTX *mem_ctx,
- struct tsocket_address **remote_addr,
- const char *location);
-
-There's a function to ask for specific options of the socket.
-The behavior and error codes match the getsockopt(2) function
-of the bsd socket api. The option and value are represented as string
-values, where the 'value' parameter can be NULL is the caller don't want to
-get the value. The supported options and values are up to the specific
-tsocket_context implementation.
-
- int tsocket_get_option(const struct tsocket_context *sock,
- const char *option,
- TALLOC_CTX *mem_ctx,
- char **value);
-
-There's a function to set specific options of the socket.
-The behavior and error codes match the setsockopt(2) function
-of the bsd socket api. The option and value are represented as string
-values, where the 'value' parameter can be NULL. The supported options
-and values are up to the specific tsocket_context implementation.
-The 'force' parameter specifies whether an error should be returned
-for unsupported options.
-
- int tsocket_set_option(const struct tsocket_context *sock,
- const char *option,
- bool force,
- const char *value);
-
-There's a function to disconnect the socket. The behavior
-and error codes match the close(2) function of the bsd socket api.
-Maybe the specific tsocket_context implementation speficied some
-further details.
-
- void tsocket_disconnect(struct tsocket_context *sock);
-
-The glue to tevent
-==================
-
-As the tsocket library is based on the tevent library,
-there need to be functions to let the caller register
-callback functions, which are triggered when the socket
-is writeable or readable. Typically one would use
-tevent fd events, but in order to hide the filedescriptor
-the tsocket_context abstraction has their own functions.
-
-There's a function to set the currently active tevent_context
-for the socket. It's important there's only one tevent_context
-actively used with the socket. A second call will cancel
-all low level events made on the old tevent_context, it will
-also resets the send and recv handlers to NULL. If the caller
-sets attaches a new event context to the socket, the callback
-function also need to be registered again. It's important
-that the caller keeps the given tevent_context in memory
-and actively calls tsocket_set_event_context(sock, NULL)
-before calling talloc_free(event_context).
-The function returns 0 on success and -1 together with an errno
-on failure.
-
- int tsocket_set_event_context(struct tsocket_context *sock,
- struct tevent_context *ev);
-
-There's a function to register a callback function which is called
-when the socket is readable. If the caller don't want to get notified
-anymore the function should be called with NULL as handler.
-The function returns 0 on success and -1 together with an errno
-on failure.
-
- typedef void (*tsocket_event_handler_t)(struct tsocket_context *, void *);
- int tsocket_set_readable_handler(struct tsocket_context *sock,
- tsocket_event_handler_t handler,
- void *private_data);
-
-There's a function to register a callback function which is called
-when the socket is writeable. If the caller don't want to get notified
-anymore the function should be called with NULL as handler.
-The function returns 0 on success and -1 together with an errno
-on failure.
-
- typedef void (*tsocket_event_handler_t)(struct tsocket_context *, void *);
- int tsocket_set_writeable_handler(struct tsocket_context *sock,
- tsocket_event_handler_t handler,
- void *private_data);
-
-Note: if the socket is readable and writeable, only the writeable
- handler is called, this avoids deadlocks at the application level.
-
-Async helper functions
-======================
-
-To make the life easier for the callers, there're 'tevent_req' based
-helper functions for non-blocking io-operations. For each of this functions
-to work the caller must attach the tevent_context to the tsocket_context
-with tsocket_set_event_context(). Please remember that attching a new
-tevent_context will reset the event state of the socket and should only
-be done, when there's no async request is pending on the socket!
-
-The detailed calling conventions for 'tevent_req' based programming
-will be explained in the 'tevent' documentation.
-
-To receive the next availabe datagram from socket there's a wrapper
-for tsocket_recvfrom(). The caller virtually sends its desire to receive
-the next available datagram by calling the tsocket_recvfrom_send() function
-and attaches a callback function to the returned tevent_req via tevent_req_set_callback().
-The callback function is called when a datagram is available or an error has happened.
-The callback function needs to get the result by calling
-tsocket_recvfrom_recv(). The return value of tsocket_recvfrom_recv()
-matches the return value from tsocket_recvfrom(). A possible errno is delivered
-via the perrno parameter instead of the global errno variable. The datagram
-buffer and optional the source tsocket_address of the datagram are returned as talloc
-childs of the mem_ctx passed to tsocket_recvfrom_recv().
-It's important that the caller garanties that there's only one async
-read request on the socket at a time.
-
- struct tevent_req *tsocket_recvfrom_send(struct tsocket_context *sock,
- TALLOC_CTX *mem_ctx);
- ssize_t tsocket_recvfrom_recv(struct tevent_req *req,
- int *perrno,
- TALLOC_CTX *mem_ctx,
- uint8_t **buf,
- struct tsocket_address **src);
-
-To send a datagram there's a wrapper for tsocket_sendto().
-The caller calls tsocket_sendto_send() instead of tsocket_sendto()
-which returns a tevent_req allocated on the given TALLOC_CTX.
-The caller attaches a callback function to the returned tevent_req via
-tevent_req_set_callback(). The callback function is called when a datagram was
-deliviered into the socket or an error has happened.
-The callback function needs to get the result by calling
-tsocket_sendto_recv(). The return value of tsocket_sendto_recv()
-matches the return value from tsocket_sendto(). A possible errno is delivered
-via the perrno parameter instead of the global errno variable.
-Normal callers should not use this function directly, they should use
-tsocket_sendto_queue_send/recv() instead.
-
- struct tevent_req *tsocket_sendto_send(struct tsocket_context *sock,
- TALLOC_CTX *mem_ctx,
- const uint8_t *buf,
- size_t len,
- const struct tsocket_address *dst);
- ssize_t tsocket_sendto_recv(struct tevent_req *req, int *perrno);
-
-As only one async tsocket_sendto() call should happen at a time,
-there's a 'tevent_queue' is used to serialize the sendto requests.
-
- struct tevent_req *tsocket_sendto_queue_send(TALLOC_CTX *mem_ctx,
- struct tsocket_context *sock,
- struct tevent_queue *queue,
- const uint8_t *buf,
- size_t len,
- struct tsocket_address *dst);
- ssize_t tsocket_sendto_queue_recv(struct tevent_req *req, int *perrno);
-
-Ther's an async helper for tsocket_connect(), which should be used
-to connect TSOCKET_TYPE_STREAM based sockets.
-The caller virtually sends its desire to connect to the destination
-tsocket_address by calling tsocket_connect_send() and gets back a tevent_req.
-The caller sets a callback function via tevent_req_set_callback().
-The callback function is called if the tsocket is connected or an error has happened.
-The callback function needs to get the result by calling
-tsocket_connect_recv(). The return value of tsocket_connect_recv()
-matches the return value from tsocket_connect()/tsocket_get_status().
-A possible errno is delivered via the perrno parameter instead of the global
-errno variable.
-
- struct tevent_req *tsocket_connect_send(struct tsocket_context *sock,
- TALLOC_CTX *mem_ctx,
- const struct tsocket_address *dst);
- int tsocket_connect_recv(struct tevent_req *req, int *perrno);
-
-To send an 'iovec' there's a wrapper for tsocket_writev().
-The caller calls tsocket_writev_send() instead of tsocket_writev()
-which returns a tevent_req allocated on the given TALLOC_CTX.
-The caller attaches a callback function to the returned tevent_req via
-tevent_req_set_callback(). The callback function is called when the whole iovec
-was deliviered into the socket or an error has happened.
-The callback function needs to get the result by calling
-tsocket_writev_recv(). The return value of tsocket_writev_recv()
-matches the return value from tsocket_writev(). A possible errno is delivered
-via the perrno parameter instead of the global errno variable.
-Normal callers should not use this function directly, they should use
-tsocket_writev_queue_send/recv() instead.
-
- struct tevent_req *tsocket_writev_send(struct tsocket_context *sock,
- TALLOC_CTX *mem_ctx,
- const struct iovec *vector,
- size_t count);
- int tsocket_writev_recv(struct tevent_req *req, int *perrno);
-
-As only one async tsocket_writev() call should happen at a time,
-there's a 'tevent_queue' is used to serialize the writev requests.
-
- struct tevent_req *tsocket_writev_queue_send(TALLOC_CTX *mem_ctx,
- struct tsocket_context *sock,
- struct tevent_queue *queue,
- const struct iovec *vector,
- size_t count);
- int tsocket_writev_queue_recv(struct tevent_req *req, int *perrno);
-
-For TSOCKET_TYPE_STREAM sockets, it's typically desired to split the stream
-into PDUs. That's why the helper function for tsocket_readv() is a bit
-different compared to the other helper functions. The general rule
-is still to get a tevent_req, set a callback which gets called when the
-operation is done. The callback function needs to get the result by
-calling tsocket_readv_recv(). The 'next_iovec' callback function
-makes the difference to the other helper function.
-The tsocket_writev_send/recv() logic asks the caller via the
-next_iovec_fn for an iovec array, which will be filled completely
-with bytes from the socket, then the next_iovec_fn is called for
-the next iovec array to fill, untill the next_iovec_fn returns an empty
-iovec array. That next_iovec_fn should allocate the array as child of the
-passed mem_ctx, while the buffers the array referr to belong to the caller.
-The tsocket_writev_send/recv() engine will modify and free the given array!
-The basic idea is that the caller allocates and maintains the real buffers.
-The next_iovec_fn should report error by returning -1 and setting errno to
-the specific error code. The engine will pass the error to the caller
-via tsocket_readv_recv().
-
-typedef int (*tsocket_readv_next_iovec_t)(struct tsocket_context *sock,
- void *private_data,
- TALLOC_CTX *mem_ctx,
- struct iovec **vector,
- size_t *count);
-struct tevent_req *tsocket_readv_send(struct tsocket_context *sock,
- TALLOC_CTX *mem_ctx,
- tsocket_readv_next_iovec_t next_iovec_fn,
- void *private_data);
-int tsocket_readv_recv(struct tevent_req *req, int *perrno);