. \" Copyright (C) Daniel Stenberg
. \" SPDX-License-Identifier: MIT
.TH ARES_SET_SOCKET_FUNCTIONS 3 "13 Dec 2016"
.SH NAME
ares_set_socket_functions \- Set socket io callbacks
.SH SYNOPSIS
.nf
#include <ares.h>
struct ares_socket_functions {
ares_socket_t (*\fI asocket\fP )(int, int, int, void *);
int (*\fI aclose\fP )(ares_socket_t, void *);
int (*\fI aconnect\fP )(ares_socket_t, const struct sockaddr *, ares_socklen_t, void *);
ares_ssize_t (*\fI arecvfrom\fP )(ares_socket_t, void *, size_t, int,
struct sockaddr *, ares_socklen_t *, void *);
ares_ssize_t (*\fI asendv\fP )(ares_socket_t, const struct iovec *, int, void *);
};
`ares_channel` -> `ares_channel_t *`: don't bury the pointer (#595)
`ares_channel` is defined as `typedef struct ares_channeldata *ares_channel;`. The problem with this, is it embeds the pointer into the typedef, which means an `ares_channel` can never be declared as `const` as if you write `const ares_channel channel`, that expands to `struct ares_channeldata * const ares_channel` and not `const struct ares_channeldata *channel`.
We will now typedef `ares_channel_t` as `typedef struct ares_channeldata ares_channel_t;`, so if you write `const ares_channel_t *channel`, it properly expands to `const struct ares_channeldata *channel`.
We are maintaining the old typedef for API compatibility with existing integrations, and due to typedef expansion this should not even cause any compiler warnings for existing code. There are no ABI implications with this change. I could be convinced to keep existing public functions as `ares_channel` if a sufficient argument exists, but internally we really need make this change for modern best practices.
This change will allow us to internally use `const ares_channel_t *` where appropriate. Whether or not we decide to change any public interfaces to use `const` may require further discussion on if there might be ABI implications (I don't think so, but I'm also not 100% sure what a compiler internally does with `const` when emitting machine code ... I think more likely ABI implications would occur going the opposite direction).
FYI, This PR was done via a combination of sed and clang-format, the only manual code change was the addition of the new typedef, and a couple doc fixes :)
Fix By: Brad House (@bradh352)
1 year ago
void ares_set_socket_functions(ares_channel_t *\fI channel\fP ,
const struct ares_socket_functions * \fI functions\fP ,
void *\fI user_data\fP );
.fi
.SH DESCRIPTION
.PP
This function sets a set of callback \fI functions\fP in the given ares channel handle.
Cannot be used when \fB ARES_OPT_EVENT_THREAD\fP is passed to \fI ares_init_options(3)\fP .
These callback functions will be invoked to create/destroy socket objects and perform
io, instead of the normal system calls. A client application can override normal network
operation fully through this functionality, and provide its own transport layer. You
can choose to only implement some of the socket functions, and provide NULL to any
others and c-ares will use its built-in system functions in that case.
.PP
All callback functions are expected to operate like their system equivalents, and to
set
.BR errno(3)
to an appropriate error code on failure. C-ares also expects all io functions to behave
asynchronously, i.e. as if the socket object has been set to non-blocking mode. Thus
read/write calls (for TCP connections) are expected to often generate
.BR EAGAIN
or
.BR EWOULDBLOCK.
.PP
The \fI user_data\fP value is provided to each callback function invocation to serve as
context.
.PP
The
.B ares_socket_functions
must provide the following callbacks:
.TP 18
.B \fI asocket\fP
.B ares_socket_t(*)(int \fI domain\fP, int \fI type\fP, int \fI protocol\fP, void * \fI user_data\fP)
.br
Creates an endpoint for communication and returns a descriptor. \fI domain\fP , \fI type\fP , and \fI protocol\fP
each correspond to the parameters of
.BR socket(2).
Returns ahandle to the newly created socket, or -1 on error.
.TP 18
.B \fI aclose\fP
.B int(*)(ares_socket_t \fI fd\fP, void * \fI user_data\fP)
.br
Closes the socket endpoint indicated by \fI fd\fP . See
.BR close(2)
.TP 18
.B \fI aconnect\fP
.B int(*)(ares_socket_t \fI fd\fP, const struct sockaddr * \fI addr\fP, ares_socklen_t \fI addr_len\fP, void * \fI user_data\fP)
.br
Initiate a connection to the address indicated by \fI addr\fP on a socket. See
.BR connect(2)
.TP 18
.B \fI arecvfrom\fP
.B ares_ssize_t(*)(ares_socket_t \fI fd\fP, void * \fI buffer\fP, size_t \fI buf_size\fP, int \fI flags\fP, struct sockaddr * \fI addr\fP, ares_socklen_t * \fI addr_len\fP, void * \fI user_data\fP)
.br
Receives data from remote socket endpoint, if available. If the \fI addr\fP parameter is not NULL and the connection protocol provides the source address, the callback should fill this in. See
.BR recvfrom(2)
.TP 18
.B \fI asendv\fP
.B ares_ssize_t(*)(ares_socket_t \fI fd\fP, const struct iovec * \fI data\fP, int \fI len\fP, void * \fI user_data\fP)
.br
Send data, as provided by the iovec array \fI data\fP , to the socket endpoint. See
.BR writev(2),
.PP
The
.B ares_socket_functions
struct provided is not copied but directly referenced,
and must thus remain valid through out the channels and any created socket's lifetime.
.SH AVAILABILITY
Added in c-ares 1.13.0
.SH SEE ALSO
.BR ares_init_options (3),
.BR socket (2),
.BR close (2),
.BR connect (2),
.BR recv (2),
.BR recvfrom (2),
.BR send (2),
.BR writev (2)