script/autobuild.py: add --branch option
[Samba/bb.git] / lib / tsocket / tsocket_guide.txt
blob45e20b5103a97d474fd211de991a8754f480e25f
2 Basic design of the tsocket abstraction
3 =======================================
5 The tsocket abstraction is split into two
6 different kinds of communitation interfaces.
8 There is the "tstream_context" interface which abstracts
9 the communication through a bidirectional
10 byte stream between two endpoints.
12 And there is the "tdgram_context" interface
13 which abstracts datagram based communication between any
14 number of endpoints.
16 Both interfaces share the "tsocket_address" abstraction
17 for endpoint addresses.
19 The whole library is based on the talloc(3) and 'tevent' libraries
20 and provides "tevent_req" based "foo_send()"/"foo_recv()" functions pairs
21 for all abstracted methods that need to be async.
23 The tsocket_address abstraction
24 ===============================
26 A tsocket_address represents a generic socket endpoint.
27 It behaves like an abstract class, therefore it has no direct constructor.
28 Constructors are described in later sections of this document.
30 A function to get the string representation of an endpoint for debugging is
31 available but callers SHOULD NOT try to parse this string. To get more
32 details, callers should use getter methods of the specific tsocket_address
33 implemention.
35   char *tsocket_address_string(const struct tsocket_address *addr,
36       TALLOC_CTX *mem_ctx);
38 A function to create a copy of the tsocket_address is also avilable.
39 This is useful before doing modifications to a socket
40 via additional methods of the specific tsocket_address implementation.
42   struct tsocket_address *tsocket_address_copy(const struct tsocket_address *addr,
43       TALLOC_CTX *mem_ctx);
45 The tdgram_context abstraction
46 ==============================
48 The tdgram_context is like an abstract class for datagram
49 based sockets. The interface provides async 'tevent_req' based
50 functions similar to recvfrom(2)/sendto(2)/close(2) syscalls.
52 The tdgram_recvfrom_send() method can be called to ask for the
53 next available datagram from the abstracted tdgram_context.
54 It returns a 'tevent_req' handle, where the caller can register
55 a callback with tevent_req_set_callback(). The callback is triggered
56 when a datagram is available or an error occurs.
58 The callback is then supposed to get the result by calling
59 tdgram_recvfrom_recv() on the 'tevent_req'. It returns -1
60 and sets '*perrno' to the actual 'errno' on failure.
61 Otherwise it returns the length of the datagram
62 (0 is never returned!). '*buf' will contain the buffer of the
63 datagram and '*src' the abstracted tsocket_address of the sender
64 of the received datagram.
66 The caller can only have one outstanding tdgram_recvfrom_send()
67 at a time otherwise the caller will get '*perrno = EBUSY'.
69   struct tevent_req *tdgram_recvfrom_send(TALLOC_CTX *mem_ctx,
70       struct tevent_context *ev,
71       struct tdgram_context *dgram);
73   ssize_t tdgram_recvfrom_recv(struct tevent_req *req,
74       int *perrno,
75       TALLOC_CTX *mem_ctx,
76       uint8_t **buf,
77       struct tsocket_address **src);
79 The tdgram_sendto_send() method can be called to send a
80 datagram (specified by a buf/len) to a destination endpoint
81 (specified by dst). It is not allowed for len to be 0.
82 It returns a 'tevent_req' handle, where the caller can register a
83 callback with tevent_req_set_callback(). The callback is triggered
84 when the specific implementation (thinks it)
85 has delivered the datagram to the "wire".
87 The callback is then supposed to get the result by calling
88 tdgram_sendto_recv() on the 'tevent_req'. It returns -1
89 and sets '*perrno' to the actual 'errno' on failure.
90 Otherwise it returns the length of the datagram
91 (0 is never returned!).
93 The caller can only have one outstanding tdgram_sendto_send()
94 at a time otherwise the caller will get '*perrno = EBUSY'.
96   struct tevent_req *tdgram_sendto_send(TALLOC_CTX *mem_ctx,
97       struct tevent_context *ev,
98       struct tdgram_context *dgram,
99       const uint8_t *buf, size_t len,
100       const struct tsocket_address *dst);
102   ssize_t tdgram_sendto_recv(struct tevent_req *req,
103       int *perrno);
105 The tdgram_disconnect_send() method should be used to normally
106 shutdown/close the abstracted socket.
108 The caller should make sure there are no outstanding tdgram_recvfrom_send()
109 and tdgram_sendto_send() calls otherwise the caller will get '*perrno = EBUSY'.
111 Note: you can always use talloc_free(tdgram) to cleanup the resources
112 of the tdgram_context on a fatal error.
114   struct tevent_req *tdgram_disconnect_send(TALLOC_CTX *mem_ctx,
115       struct tevent_context *ev,
116       struct tdgram_context *dgram);
118   int tdgram_disconnect_recv(struct tevent_req *req,
119       int *perrno);
121 The tstream_context abstraction
122 ===============================
124 A tstream_context is like an abstract class for stream
125 based sockets. The interface provides async 'tevent_req' based
126 functions similar to the readv(2)/writev(2)/close(2) syscalls.
128 The tstream_pending_bytes() function is able to report how many bytes of
129 the incoming stream have been received but have not been consumed yet.
130 It returns -1 and sets 'errno' on failure.
131 Otherwise it returns the number of uncomsumed bytes (it can return 0!).
133   ssize_t tstream_pending_bytes(struct tstream_context *stream);
135 The tstream_readv_send() method can be called to read a
136 specific amount of bytes from the stream into the buffers
137 of the given iovec vector. The caller has to preallocate the buffers
138 in the iovec vector. The caller might need to use
139 tstream_pending_bytes() if the protocol does not have a fixed pdu header
140 containing the pdu size. tstream_readv_send() returns a 'tevent_req' handle,
141 where the caller can register a callback with tevent_req_set_callback().
142 The callback is triggered when all iovec buffers are completely
143 filled with bytes from the socket or an error occurs.
145 The callback is then supposed to get the result by calling
146 tstream_readv_recv() on the 'tevent_req'. It returns -1
147 and sets '*perrno' to the actual 'errno' on failure.
148 Otherwise it returns the total number of bytes received
149 (0 is never returned!).
151 The caller can only have one outstanding tstream_readv_send()
152 at a time otherwise the caller will get *perrno = EBUSY.
154   struct tevent_req *tstream_readv_send(TALLOC_CTX *mem_ctx,
155       struct tevent_context *ev,
156       struct tstream_context *stream,
157       struct iovec *vector,
158       size_t count);
160   int tstream_readv_recv(struct tevent_req *req,
161       int *perrno);
163 The tstream_writev_send() method can be called to write
164 buffers in the given iovec vector into the stream socket.
165 It is invalid to pass an empty vector.
166 tstream_writev_send() returns a 'tevent_req' handle,
167 where the caller can register a callback with tevent_req_set_callback().
168 The callback is triggered when the specific implementation (thinks it)
169 has delivered the all buffers to the "wire".
171 The callback is then supposed to get the result by calling
172 tstream_writev_recv() on the 'tevent_req'. It returns -1
173 and sets '*perrno' to the actual 'errno' on failure.
174 Otherwise it returns the total amount of bytes sent
175 (0 is never returned!).
177 The caller can only have one outstanding tstream_writev_send()
178 at a time otherwise the caller will get '*perrno = EBUSY'.
180   struct tevent_req *tstream_writev_send(TALLOC_CTX *mem_ctx,
181       struct tevent_context *ev,
182       struct tstream_context *stream,
183       const struct iovec *vector,
184       size_t count);
186   int tstream_writev_recv(struct tevent_req *req,
187       int *perrno);
189 The tstream_disconnect_send() method should normally be used to
190 shutdown/close the abstracted socket.
192 The caller should make sure there are no outstanding tstream_readv_send()
193 and tstream_writev_send() calls otherwise the caller will get '*perrno = EBUSY'.
195 Note: you can always use talloc_free(tstream) to cleanup the resources
196 of the tstream_context on a fatal error.
198   struct tevent_req *tstream_disconnect_send(TALLOC_CTX *mem_ctx,
199       struct tevent_context *ev,
200       struct tstream_context *stream);
202   int tstream_disconnect_recv(struct tevent_req *req,
203       int *perrno);
205 PDU receive helper functions
206 ============================
208 In order to simplify the job, for callers that want to implement
209 a function to receive a full PDU with a single async function pair,
210 some helper functions are provided.
212 The caller can use the tstream_readv_pdu_send() function
213 to ask for the next available PDU on the abstracted tstream_context.
214 The caller needs to provide a "next_vector" function and a private
215 state for this function. The tstream_readv_pdu engine will ask
216 the next_vector function for the next iovec vector to be used.
217 There is a tstream_readv_send/recv pair for each vector returned
218 by the next_vector function. If the next_vector function detects
219 it received a full pdu, it returns an empty vector. The the callback
220 of the tevent_req (returned by tstream_readv_pdu_send()) is triggered.
221 Note: the buffer allocation is completely up to the next_vector function
222 and its private state.
224 See the 'dcerpc_read_ncacn_packet_send/recv' functions in Samba as an
225 example.
227   typedef int (*tstream_readv_pdu_next_vector_t)(struct tstream_context *stream,
228       void *private_data,
229       TALLOC_CTX *mem_ctx,
230       struct iovec **vector,
231       size_t *count);
233   struct tevent_req *tstream_readv_pdu_send(TALLOC_CTX *mem_ctx,
234       struct tevent_context *ev,
235       struct tstream_context *stream,
236       tstream_readv_pdu_next_vector_t next_vector_fn,
237       void *next_vector_private);
239   int tstream_readv_pdu_recv(struct tevent_req *req, int *perrno);
241 Async 'tevent_queue' based helper functions
242 ===========================================
244 In some cases, the caller does not care about the IO ordering on the
245 abstracted socket.
246 (Remember at the low level there is always only one IO in a specific
247  direction allowed, only one tdgram_sendto_send() at a time).
249 Some helpers that use 'tevent_queue' are avilable to simplify handling
250 multiple IO requests. The functions just get a 'queue' argument and
251 internally serialize all operations.
253   struct tevent_req *tdgram_sendto_queue_send(TALLOC_CTX *mem_ctx,
254       struct tevent_context *ev,
255       struct tdgram_context *dgram,
256       struct tevent_queue *queue,
257       const uint8_t *buf,
258       size_t len,
259       struct tsocket_address *dst);
261   ssize_t tdgram_sendto_queue_recv(struct tevent_req *req, int *perrno);
263   struct tevent_req *tstream_readv_pdu_queue_send(TALLOC_CTX *mem_ctx,
264       struct tevent_context *ev,
265       struct tstream_context *stream,
266       struct tevent_queue *queue,
267       tstream_readv_pdu_next_vector_t next_vector_fn,
268       void *next_vector_private);
270   int tstream_readv_pdu_queue_recv(struct tevent_req *req, int *perrno);
272   struct tevent_req *tstream_writev_queue_send(TALLOC_CTX *mem_ctx,
273       struct tevent_context *ev,
274       struct tstream_context *stream,
275       struct tevent_queue *queue,
276       const struct iovec *vector,
277       size_t count);
279   int tstream_writev_queue_recv(struct tevent_req *req, int *perrno);
281 BSD sockets: ipv4, ipv6 and unix
282 ================================
284 The main tsocket library comes with implementations
285 for BSD style ipv4, ipv6 and unix sockets.
287 You can use the tsocket_address_inet_from_strings()
288 function to create a tsocket_address for ipv4 and ipv6
289 endpoint addresses. "family" can be "ipv4", "ipv6" or "ip".
290 With "ip" it autodetects "ipv4" or "ipv6" based on the
291 "addr_string" string. "addr_string" must be a valid
292 ip address string based on the selected family
293 (dns names are not allowed!). But it is valid to pass NULL,
294 which gets mapped to "0.0.0.0" or "::".
295 It returns -1 and sets errno on error. Otherwise it returns 0.
297   int tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
298       const char *family,
299       const char *addr_string,
300       uint16_t port,
301       struct tsocket_address **addr);
303 To get the ip address string of an existing 'inet' tsocket_address
304 you can use the tsocket_address_inet_addr_string() function.
305 It will return NULL and set errno to EINVAL if the tsocket_address
306 does not represent an ipv4 or ipv6 endpoint address.
308   char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
309       TALLOC_CTX *mem_ctx);
311 To get the port number of an existing 'inet' tsocket_address
312 you can use the tsocket_address_inet_port() function.
313 It will return 0 and set errno to EINVAL if the tsocket_address
314 does not represent an ipv4 or ipv6 endpoint address.
316   uint16_t tsocket_address_inet_port(const struct tsocket_address *addr);
318 To set the port number of an existing 'inet' tsocket_address
319 you can use the tsocket_address_inet_set_port() function.
320 It will return -1 and set errno to EINVAL if the tsocket_address
321 does not represent an ipv4 or ipv6 endpoint address.
322 It returns 0 on success.
324   int tsocket_address_inet_set_port(struct tsocket_address *addr,
325       uint16_t port);
327 You can use the tsocket_address_unix_from_path()
328 function to create a tsocket_address for unix domain
329 endpoint addresses. "path" is the filesystem path
330 (NULL will map ""). If the path is longer than
331 the low level kernel supports the function will
332 return -1 and set errno to ENAMETOOLONG.
333 On success it returns 0.
335   int tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
336       const char *path,
337       struct tsocket_address **addr);
339 To get the path of a 'unix' tsocket_address
340 you can use the tsocket_address_unix_path() function.
341 It will return NULL and set errno to EINVAL if the tsocket_address
342 does not represent a unix domain endpoint path.
344   char *tsocket_address_unix_path(const struct tsocket_address *addr,
345       TALLOC_CTX *mem_ctx);
347 You can use tdgram_inet_udp_socket() to create a tdgram_context
348 for ipv4 or ipv6 UDP communication. "local_address" has to be
349 an 'inet' tsocket_address and it has to represent the local
350 endpoint. "remote_address" can be NULL or an 'inet' tsocket_address
351 presenting a remote endpoint. It returns -1 ans sets errno on error
352 and it returns 0 on success.
354   int tdgram_inet_udp_socket(const struct tsocket_address *local_address,
355       const struct tsocket_address *remote_address,
356       TALLOC_CTX *mem_ctx,
357       struct tdgram_context **dgram);
359 You can use tdgram_unix_socket() to create a tdgram_context
360 for unix domain datagram communication. "local_address" has to be
361 an 'unix' tsocket_address and it has to represent the local
362 endpoint. "remote_address" can be NULL or an 'unix' tsocket_address
363 presenting a remote endpoint. It returns -1 ans sets errno on error
364 and it returns 0 on success.
366   int tdgram_unix_socket(const struct tsocket_address *local,
367       const struct tsocket_address *remote,
368       TALLOC_CTX *mem_ctx,
369       struct tdgram_context **dgram);
371 You can use tstream_inet_tcp_connect_send to asynchronously
372 connect to a remote ipv4 or ipv6 TCP endpoint and create a
373 tstream_context for the stream based communication. "local_address" has to be
374 an 'inet' tsocket_address and it has to represent the local
375 endpoint. "remote_address" has to be an 'inet' tsocket_address
376 presenting a remote endpoint. It returns a 'tevent_req' handle,
377 where the caller can register a callback with tevent_req_set_callback().
378 The callback is triggered when a socket is connected and ready for IO
379 or an error happened.
381 The callback is then supposed to get the result by calling
382 tstream_inet_tcp_connect_recv() on the 'tevent_req'. It returns -1
383 and sets '*perrno' to the actual 'errno' on failure.
384 It returns 0 on success and returns the new tstream_context
385 in '*stream'.
387   struct tevent_req *tstream_inet_tcp_connect_send(TALLOC_CTX *mem_ctx,
388       struct tevent_context *ev,
389       const struct tsocket_address *local_address,
390       const struct tsocket_address *remote_address);
392   int tstream_inet_tcp_connect_recv(struct tevent_req *req,
393       int *perrno,
394       TALLOC_CTX *mem_ctx,
395       struct tstream_context **stream);
397 You can use tstream_unix_connect_send to asynchronously
398 connect to a unix domain endpoint and create a
399 tstream_context for the stream based communication.
400 "local_address" has to be an 'unix' tsocket_address and
401 it has to represent the local endpoint. "remote_address"
402 has to be an 'inet' tsocket_address presenting a remote endpoint.
403 It returns a 'tevent_req' handle, where the caller can register
404 a callback with tevent_req_set_callback(). The callback is
405 triggered when a socket is connected and ready for IO
406 or an error happened.
408 The callback is then supposed to get the result by calling
409 tstream_unix_connect_recv() on the 'tevent_req'. It returns -1
410 and sets '*perrno' to the actual 'errno' on failure.
411 It returns 0 on success and returns the new tstream_context
412 in '*stream'.
414   struct tevent_req *tstream_unix_connect_send(TALLOC_CTX *mem_ctx,
415       struct tevent_context *ev,
416       const struct tsocket_address *local,
417       const struct tsocket_address *remote);
419   int _tstream_unix_connect_recv(struct tevent_req *req,
420       int *perrno,
421       TALLOC_CTX *mem_ctx,
422       struct tstream_context **stream);
424 You can use tstream_unix_socketpair to create two connected
425 'unix' tsocket_contexts for the stream based communication.
426 It returns -1 and sets errno on error and it returns 0 on
427 success.
429   int tstream_unix_socketpair(TALLOC_CTX *mem_ctx1,
430       struct tstream_context **stream1,
431       TALLOC_CTX *mem_ctx2,
432       struct tstream_context **stream2);
434 In some situations, it is needed to create a tsocket_address from
435 a given 'struct sockaddr'. You can use tsocket_address_bsd_from_sockaddr()
436 for that. This should only be used if really needed, because of
437 already existing fixed APIs. Only AF_INET, AF_INET6 and AF_UNIX
438 sockets are allowed. The function returns -1 and sets errno on error.
439 Otherwise it returns 0.
441   int tsocket_address_bsd_from_sockaddr(TALLOC_CTX *mem_ctx,
442       struct sockaddr *sa,
443       socklen_t sa_socklen,
444       struct tsocket_address **addr);
446 In some situations, it is needed to get a 'struct sockaddr' from a
447 given tsocket_address . You can use tsocket_address_bsd_sockaddr()
448 for that. This should only be used if really needed. Only AF_INET,
449 AF_INET6 and AF_UNIX are supported. It returns the size of '*sa' on
450 success, otherwise it returns -1 and sets 'errno'.
452   ssize_t tsocket_address_bsd_sockaddr(const struct tsocket_address *addr,
453       struct sockaddr *sa,
454       socklen_t sa_socklen);
456 In some situations, it is needed to wrap existing file descriptors
457 into the tstream abstraction. You can use tstream_bsd_existing_socket()
458 for that. But you should read the tsocket_bsd.c code and unterstand it
459 in order use this function. E.g. the fd has to be non blocking already.
460 It will return -1 and set errno on error. Otherwise it returns 0
461 and sets '*stream' to point to the new tstream_context.
463   int tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx,
464       int fd,
465       struct tstream_context **stream);
467 Virtual Sockets
468 ===============
470 The abstracted layout of tdgram_context and tstream_context
471 allow implementations arround virtual sockets for encrypted tunnels
472 (like TLS, SASL or GSSAPI) or named pipes over smb.
474 Named Pipe Auth (NPA) Sockets
475 =============================
477 Samba has an implementation to abstract named pipes over smb
478 (within the server side). See libcli/named_pipe_auth/npa_tstream.[ch]
479 for the core code. The current callers are located in source4/ntvfs/ipc/vfs_ipc.c
480 and source4/rpc_server/service_rpc.c for the users.