2 Basic design of the tsocket abstraction
3 =======================================
5 The tsocket layer is designed to match more or less
6 the bsd socket layer, but it hides the filedescriptor
7 within a opaque 'tsocket_context' structure to make virtual
8 sockets possible. The virtual sockets can be encrypted tunnels
9 (like TLS, SASL or GSSAPI) or named pipes over smb.
11 The tsocket layer is a bit like an abstract class, which defines
12 common methods to work with sockets in a non blocking fashion.
14 The whole library is based on the talloc(3) and 'tevent' libraries.
16 The 'tsocket_address' structure is the 2nd abstracted class
17 which represends the address of a socket endpoint.
19 Each different type of socket has its own constructor.
21 Typically the constructor for a tsocket_context is attached to
22 the tsocket_address of the source endpoint. That means
23 the tsocket_address_create_socket() function takes the
24 tsocket_address of the local endpoint and creates a tsocket_context
25 for the communication.
27 For some usecases it's possible to wrap an existing socket into a
28 tsocket_context, e.g. to wrap an existing pipe(2) into
29 tsocket_context, so that you can use the same functions to
30 communicate over the pipe.
32 The tsocket_address abstraction
33 ===============================
35 The tsocket_address represents an socket endpoint genericly.
36 As it's like an abstract class it has no specific constructor.
37 The specific constructors are descripted later sections.
39 There's a function get the string representation of the
40 endpoint for debugging. Callers should not try to parse
41 the string! The should use additional methods of the specific
42 tsocket_address implemention to get more details.
44 char *tsocket_address_string(const struct tsocket_address *addr,
47 There's a function to create a copy of the tsocket_address.
48 This is useful when before doing modifications to a socket
49 via additional methods of the specific tsocket_address implementation.
51 struct tsocket_address *tsocket_address_copy(const struct tsocket_address *addr,
54 There's a function to create a tsocket_context based on the given local
55 socket endpoint. The return value is 0 on success and -1 on failure
56 with errno holding the specific error. Specific details are descripted in later
57 sections. Note not all specific implementation have to implement all socket
61 TSOCKET_TYPE_STREAM = 1,
66 int tsocket_address_create_socket(const struct tsocket_address *addr,
67 enum tsocket_type type,
69 struct tsocket_context **sock);
71 The tsocket_context abstraction
72 ===============================
74 The tsocket_context is like an abstract class and represents
75 a socket similar to bsd style sockets. The methods are more
76 or less equal to the bsd socket api, while the filedescriptor
77 is replaced by tsocket_context and sockaddr, socklen_t pairs
78 are replaced by tsocket_address. The 'bind' operation happens
79 in the specific constructor as the constructor is typically based
80 on tsocket_address of local socket endpoint.
82 All operations are by design non blocking and can return error
83 values like EAGAIN, EINPROGRESS, EWOULDBLOCK or EINTR which
84 indicate that the caller should retry the operation later.
85 Also read the "The glue to tevent" section.
87 The socket can of types:
88 - TSOCKET_TYPE_STREAM is the equivalent to SOCK_STREAM in the bsd socket api.
89 - TSOCKET_TYPE_DGRAM is the equivalent to SOCK_DGRAM in the bsd socket api.
90 - TSOCKET_TYPE_MESSAGE operates on a connected socket and is therefore
91 like TSOCKET_TYPE_STREAM, but the consumer needs to first read all
92 data of a message, which was generated by one message 'write' on the sender,
93 before the consumer gets data of the next message. This matches a bit
94 like message mode pipes on windows. The concept is to transfer ordered
95 messages between to endpoints.
97 There's a function to connect to a remote endpoint. The behavior
98 and error codes match the connect(2) function of the bsd socket api.
99 Maybe the specific tsocket_context implementation speficied some
102 int tsocket_connect(struct tsocket_context *sock,
103 const struct tsocket_address *remote_addr);
105 There's a function to listen for incoming connections. The behavior
106 and error codes match the listen(2) function of the bsd socket api.
107 Maybe the specific tsocket_context implementation speficied some
110 int tsocket_listen(struct tsocket_context *sock,
113 There's a function to accept incoming connections. The behavior
114 and error codes match the accept(2) function of the bsd socket api.
115 Maybe the specific tsocket_context implementation speficied some
118 int tsocket_accept(struct tsocket_context *sock,
120 struct tsocket_context **new_sock);
122 There's a function to ask how many bytes are in input buffer
123 of the connection. For sockets of type TSOCKET_TYPE_DGRAM or
124 TSOCKET_TYPE_MESSAGE the size of the next available dgram/message
125 is returned. A return value of -1 indicates a socket error
126 and errno will hold the specific error code. If no data
127 is available 0 is returned, but retry error codes like
128 EINTR can also be returned.
130 ssize_t tsocket_pending(struct tsocket_context *sock);
132 There's a function to read data from the socket. The behavior
133 and error codes match the readv(3) function, also take a look
134 at the recv(2) function of the bsd socket api.
135 Maybe the specific tsocket_context implementation speficied some
138 int tsocket_readv(struct tsocket_context *sock,
139 const struct iovec *vector, size_t count);
141 There's a function to write data from the socket. The behavior
142 and error codes match the writev(3) function, also take a look
143 at the send(2) function of the bsd socket api.
144 Maybe the specific tsocket_context implementation speficied some
147 int tsocket_writev(struct tsocket_context *sock,
148 const struct iovec *vector, size_t count);
150 There's a function to read a datagram from a remote endpoint.
151 The behavior and error codes match the recvfrom(2) function of
152 the bsd socket api. As TSOCKET_TYPE_DGRAM sockets can also be
153 used in connected mode src_addr can be NULL, if the caller don't
154 want to get the source address. Maybe the specific tsocket_context
155 implementation speficied some further details.
157 ssize_t tsocket_recvfrom(struct tsocket_context *sock,
158 uint8_t *data, size_t len,
159 TALLOC_CTX *addr_ctx,
160 struct tsocket_address **src_addr);
162 There's a function to send a datagram to a remote endpoint the socket.
163 The behavior and error codes match the recvfrom(2) function of the
164 bsd socket api. As TSOCKET_TYPE_DGRAM sockets can also be used in
165 connected mode dest_addr must be NULL in connected mode and a valid
166 tsocket_address otherwise. Maybe the specific tsocket_context
167 implementation speficied some further details.
169 ssize_t tsocket_sendto(struct tsocket_context *sock,
170 const uint8_t *data, size_t len,
171 const struct tsocket_address *dest_addr);
173 There's a function to get the current status of the socket.
174 The behavior and error codes match the getsockopt(2) function
175 of the bsd socket api, with SOL_SOCKET and SO_ERROR as arguments.
176 Maybe the specific tsocket_context implementation speficied some
179 int tsocket_get_status(const struct tsocket_context *sock);
181 There's a function to get tsocket_address of the local endpoint.
182 The behavior and error codes match the getsockname(2) function
183 of the bsd socket api. Maybe the specific tsocket_context
184 implementation speficied some further details.
186 int tsocket_get_local_address(const struct tsocket_context *sock,
188 struct tsocket_address **local_addr);
190 There's a function to get tsocket_address of the remote endpoint
191 of a connected socket. The behavior and error codes match the
192 getpeername(2) function of the bsd socket api. Maybe the specific
193 tsocket_context implementation speficied some further details.
195 int tsocket_get_remote_address(const struct tsocket_context *sock,
197 struct tsocket_address **remote_addr,
198 const char *location);
200 There's a function to ask for specific options of the socket.
201 The behavior and error codes match the getsockopt(2) function
202 of the bsd socket api. The option and value are represented as string
203 values, where the 'value' parameter can be NULL is the caller don't want to
204 get the value. The supported options and values are up to the specific
205 tsocket_context implementation.
207 int tsocket_get_option(const struct tsocket_context *sock,
212 There's a function to set specific options of the socket.
213 The behavior and error codes match the setsockopt(2) function
214 of the bsd socket api. The option and value are represented as string
215 values, where the 'value' parameter can be NULL. The supported options
216 and values are up to the specific tsocket_context implementation.
217 The 'force' parameter specifies whether an error should be returned
218 for unsupported options.
220 int tsocket_set_option(const struct tsocket_context *sock,
225 There's a function to disconnect the socket. The behavior
226 and error codes match the close(2) function of the bsd socket api.
227 Maybe the specific tsocket_context implementation speficied some
230 void tsocket_disconnect(struct tsocket_context *sock);
235 As the tsocket library is based on the tevent library,
236 there need to be functions to let the caller register
237 callback functions, which are triggered when the socket
238 is writeable or readable. Typically one would use
239 tevent fd events, but in order to hide the filedescriptor
240 the tsocket_context abstraction has their own functions.
242 There's a function to set the currently active tevent_context
243 for the socket. It's important there's only one tevent_context
244 actively used with the socket. A second call will cancel
245 all low level events made on the old tevent_context, it will
246 also resets the send and recv handlers to NULL. If the caller
247 sets attaches a new event context to the socket, the callback
248 function also need to be registered again. It's important
249 that the caller keeps the given tevent_context in memory
250 and actively calls tsocket_set_event_context(sock, NULL)
251 before calling talloc_free(event_context).
252 The function returns 0 on success and -1 together with an errno
255 int tsocket_set_event_context(struct tsocket_context *sock,
256 struct tevent_context *ev);
258 There's a function to register a callback function which is called
259 when the socket is readable. If the caller don't want to get notified
260 anymore the function should be called with NULL as handler.
261 The function returns 0 on success and -1 together with an errno
264 typedef void (*tsocket_event_handler_t)(struct tsocket_context *, void *);
265 int tsocket_set_readable_handler(struct tsocket_context *sock,
266 tsocket_event_handler_t handler,
269 There's a function to register a callback function which is called
270 when the socket is writeable. If the caller don't want to get notified
271 anymore the function should be called with NULL as handler.
272 The function returns 0 on success and -1 together with an errno
275 typedef void (*tsocket_event_handler_t)(struct tsocket_context *, void *);
276 int tsocket_set_writeable_handler(struct tsocket_context *sock,
277 tsocket_event_handler_t handler,
280 Note: if the socket is readable and writeable, only the writeable
281 handler is called, this avoids deadlocks at the application level.
283 Async helper functions
284 ======================
286 To make the life easier for the callers, there're 'tevent_req' based
287 helper functions for non-blocking io-operations. For each of this functions
288 to work the caller must attach the tevent_context to the tsocket_context
289 with tsocket_set_event_context(). Please remember that attching a new
290 tevent_context will reset the event state of the socket and should only
291 be done, when there's no async request is pending on the socket!
293 The detailed calling conventions for 'tevent_req' based programming
294 will be explained in the 'tevent' documentation.
296 To receive the next availabe datagram from socket there's a wrapper
297 for tsocket_recvfrom(). The caller virtually sends its desire to receive
298 the next available datagram by calling the tsocket_recvfrom_send() function
299 and attaches a callback function to the returned tevent_req via tevent_req_set_callback().
300 The callback function is called when a datagram is available or an error has happened.
301 The callback function needs to get the result by calling
302 tsocket_recvfrom_recv(). The return value of tsocket_recvfrom_recv()
303 matches the return value from tsocket_recvfrom(). A possible errno is delivered
304 via the perrno parameter instead of the global errno variable. The datagram
305 buffer and optional the source tsocket_address of the datagram are returned as talloc
306 childs of the mem_ctx passed to tsocket_recvfrom_recv().
307 It's important that the caller garanties that there's only one async
308 read request on the socket at a time.
310 struct tevent_req *tsocket_recvfrom_send(struct tsocket_context *sock,
311 TALLOC_CTX *mem_ctx);
312 ssize_t tsocket_recvfrom_recv(struct tevent_req *req,
316 struct tsocket_address **src);
318 To send a datagram there's a wrapper for tsocket_sendto().
319 The caller calls tsocket_sendto_send() instead of tsocket_sendto()
320 which returns a tevent_req allocated on the given TALLOC_CTX.
321 The caller attaches a callback function to the returned tevent_req via
322 tevent_req_set_callback(). The callback function is called when a datagram was
323 deliviered into the socket or an error has happened.
324 The callback function needs to get the result by calling
325 tsocket_sendto_recv(). The return value of tsocket_sendto_recv()
326 matches the return value from tsocket_sendto(). A possible errno is delivered
327 via the perrno parameter instead of the global errno variable.
328 Normal callers should not use this function directly, they should use
329 tsocket_sendto_queue_send/recv() instead.
331 struct tevent_req *tsocket_sendto_send(struct tsocket_context *sock,
335 const struct tsocket_address *dst);
336 ssize_t tsocket_sendto_recv(struct tevent_req *req, int *perrno);
338 As only one async tsocket_sendto() call should happen at a time,
339 there's a 'tevent_queue' is used to serialize the sendto requests.
341 struct tevent_req *tsocket_sendto_queue_send(TALLOC_CTX *mem_ctx,
342 struct tsocket_context *sock,
343 struct tevent_queue *queue,
346 struct tsocket_address *dst);
347 ssize_t tsocket_sendto_queue_recv(struct tevent_req *req, int *perrno);
349 Ther's an async helper for tsocket_connect(), which should be used
350 to connect TSOCKET_TYPE_STREAM based sockets.
351 The caller virtually sends its desire to connect to the destination
352 tsocket_address by calling tsocket_connect_send() and gets back a tevent_req.
353 The caller sets a callback function via tevent_req_set_callback().
354 The callback function is called if the tsocket is connected or an error has happened.
355 The callback function needs to get the result by calling
356 tsocket_connect_recv(). The return value of tsocket_connect_recv()
357 matches the return value from tsocket_connect()/tsocket_get_status().
358 A possible errno is delivered via the perrno parameter instead of the global
361 struct tevent_req *tsocket_connect_send(struct tsocket_context *sock,
363 const struct tsocket_address *dst);
364 int tsocket_connect_recv(struct tevent_req *req, int *perrno);
366 To send an 'iovec' there's a wrapper for tsocket_writev().
367 The caller calls tsocket_writev_send() instead of tsocket_writev()
368 which returns a tevent_req allocated on the given TALLOC_CTX.
369 The caller attaches a callback function to the returned tevent_req via
370 tevent_req_set_callback(). The callback function is called when the whole iovec
371 was deliviered into the socket or an error has happened.
372 The callback function needs to get the result by calling
373 tsocket_writev_recv(). The return value of tsocket_writev_recv()
374 matches the return value from tsocket_writev(). A possible errno is delivered
375 via the perrno parameter instead of the global errno variable.
376 Normal callers should not use this function directly, they should use
377 tsocket_writev_queue_send/recv() instead.
379 struct tevent_req *tsocket_writev_send(struct tsocket_context *sock,
381 const struct iovec *vector,
383 int tsocket_writev_recv(struct tevent_req *req, int *perrno);
385 As only one async tsocket_writev() call should happen at a time,
386 there's a 'tevent_queue' is used to serialize the writev requests.
388 struct tevent_req *tsocket_writev_queue_send(TALLOC_CTX *mem_ctx,
389 struct tsocket_context *sock,
390 struct tevent_queue *queue,
391 const struct iovec *vector,
393 int tsocket_writev_queue_recv(struct tevent_req *req, int *perrno);
395 For TSOCKET_TYPE_STREAM sockets, it's typically desired to split the stream
396 into PDUs. That's why the helper function for tsocket_readv() is a bit
397 different compared to the other helper functions. The general rule
398 is still to get a tevent_req, set a callback which gets called when the
399 operation is done. The callback function needs to get the result by
400 calling tsocket_readv_recv(). The 'next_iovec' callback function
401 makes the difference to the other helper function.
402 The tsocket_writev_send/recv() logic asks the caller via the
403 next_iovec_fn for an iovec array, which will be filled completely
404 with bytes from the socket, then the next_iovec_fn is called for
405 the next iovec array to fill, untill the next_iovec_fn returns an empty
406 iovec array. That next_iovec_fn should allocate the array as child of the
407 passed mem_ctx, while the buffers the array referr to belong to the caller.
408 The tsocket_writev_send/recv() engine will modify and free the given array!
409 The basic idea is that the caller allocates and maintains the real buffers.
410 The next_iovec_fn should report error by returning -1 and setting errno to
411 the specific error code. The engine will pass the error to the caller
412 via tsocket_readv_recv().
414 typedef int (*tsocket_readv_next_iovec_t)(struct tsocket_context *sock,
417 struct iovec **vector,
419 struct tevent_req *tsocket_readv_send(struct tsocket_context *sock,
421 tsocket_readv_next_iovec_t next_iovec_fn,
423 int tsocket_readv_recv(struct tevent_req *req, int *perrno);
425 Wrapper for BSD style sockets
426 =============================
428 Support for BSD style sockets of AF_INET, AF_INET6 and AF_UNIX
429 are part of the main tsocket library.
431 To wrap an existing fd into a tsocket_context the function
432 tsocket_context_bsd_wrap_existing() can be used.
433 The caller needs to make sure the fd is marked as non-blocking!
434 Normaly the tsocket_disconnect() function would close the fd,
435 but the caller can influence this behavior based on the close_on_disconnect
436 parameter. The caller should also make sure that the socket is only
437 accessed via the tsocket_context wrapper after the call to
438 tsocket_context_bsd_wrap_existing().
440 int tsocket_context_bsd_wrap_existing(TALLOC_CTX *mem_ctx,
441 int fd, bool close_on_disconnect,
442 struct tsocket_context **_sock);
444 To create a tsocket_address for an inet address you need to use
445 the tsocket_address_inet_from_strings() function. It takes the family
446 as parameter which can be "ipv4", "ipv6" or "ip", where "ip" autodetects
447 "ipv4" or "ipv6", based on the given address string. Depending on the
448 operating system, "ipv6" may not be supported. Note: NULL as address
449 is mapped to "0.0.0.0" or "::" based on the given family.
450 The address parameter only accepts valid ipv4 or ipv6 address strings
451 and no names! The caller need to resolve names before using this function.
453 int tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
457 struct tsocket_address **addr);
459 To get the address of the inet tsocket_address as string the
460 tsocket_address_inet_addr_string() function should be used.
461 The caller should not try to parse the tsocket_address_string() output!
463 char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
464 TALLOC_CTX *mem_ctx);
466 To get the port number of the inet tsocket_address the
467 tsocket_address_inet_port() function should be used.
468 The caller should not try to parse the tsocket_address_string() output!
470 uint16_t tsocket_address_inet_port(const struct tsocket_address *addr);
472 To alter the port number of an inet tsocket_address the
473 tsocket_address_inet_set_port() function can be used.
474 This is usefull if the caller gets the address from
475 tsocket_address_copy(), tsocket_context_remote_address() or
476 tsocket_context_remote_address() instead of tsocket_address_inet_from_strings().
478 int tsocket_address_inet_set_port(struct tsocket_address *addr,
481 If the caller wants to create a broadcast socket, with the SO_BROADCAST
482 socket option, the broadcast option needs to be set with the
483 tsocket_address_inet_set_broadcast() function before calling
484 tsocket_address_create_socket().
486 void tsocket_address_inet_set_broadcast(struct tsocket_address *addr,
489 To create a tsocket_address for AF_UNIX style sockets the
490 tsocket_address_unix_from_path() should be used.
491 NULL as path is handled like "".
493 int tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
495 struct tsocket_address **addr);
497 To get the unix path of an existing unix tsocket_address
498 the tsocket_address_unix_path() should be used.
499 The caller should not try to parse the tsocket_address_string() output!
501 char *tsocket_address_unix_path(const struct tsocket_address *addr,
502 TALLOC_CTX *mem_ctx);