talloc: use the system pytalloc-util for python3 as well
[sfrench/samba-autobuild/.git] / lib / tsocket / tsocket_guide.txt
1
2 Basic design of the tsocket abstraction
3 =======================================
4
5 The tsocket abstraction is split into two
6 different kinds of communitation interfaces.
7
8 There is the "tstream_context" interface which abstracts
9 the communication through a bidirectional
10 byte stream between two endpoints.
11
12 And there is the "tdgram_context" interface
13 which abstracts datagram based communication between any
14 number of endpoints.
15
16 Both interfaces share the "tsocket_address" abstraction
17 for endpoint addresses.
18
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.
22
23 The tsocket_address abstraction
24 ===============================
25
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.
29
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.
34
35   char *tsocket_address_string(const struct tsocket_address *addr,
36       TALLOC_CTX *mem_ctx);
37
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.
41
42   struct tsocket_address *tsocket_address_copy(const struct tsocket_address *addr,
43       TALLOC_CTX *mem_ctx);
44
45 The tdgram_context abstraction
46 ==============================
47
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.
51
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.
57
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.
65
66 The caller can only have one outstanding tdgram_recvfrom_send()
67 at a time otherwise the caller will get '*perrno = EBUSY'.
68
69   struct tevent_req *tdgram_recvfrom_send(TALLOC_CTX *mem_ctx,
70       struct tevent_context *ev,
71       struct tdgram_context *dgram);
72
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);
78
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".
86
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!).
92
93 The caller can only have one outstanding tdgram_sendto_send()
94 at a time otherwise the caller will get '*perrno = EBUSY'.
95
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);
101
102   ssize_t tdgram_sendto_recv(struct tevent_req *req,
103       int *perrno);
104
105 The tdgram_disconnect_send() method should be used to normally
106 shutdown/close the abstracted socket.
107
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'.
110
111 Note: you can always use talloc_free(tdgram) to cleanup the resources
112 of the tdgram_context on a fatal error.
113
114   struct tevent_req *tdgram_disconnect_send(TALLOC_CTX *mem_ctx,
115       struct tevent_context *ev,
116       struct tdgram_context *dgram);
117
118   int tdgram_disconnect_recv(struct tevent_req *req,
119       int *perrno);
120
121 The tstream_context abstraction
122 ===============================
123
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.
127
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!).
132
133   ssize_t tstream_pending_bytes(struct tstream_context *stream);
134
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.
144
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!).
150
151 The caller can only have one outstanding tstream_readv_send()
152 at a time otherwise the caller will get *perrno = EBUSY.
153
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);
159
160   int tstream_readv_recv(struct tevent_req *req,
161       int *perrno);
162
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".
170
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!).
176
177 The caller can only have one outstanding tstream_writev_send()
178 at a time otherwise the caller will get '*perrno = EBUSY'.
179
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);
185
186   int tstream_writev_recv(struct tevent_req *req,
187       int *perrno);
188
189 The tstream_disconnect_send() method should normally be used to
190 shutdown/close the abstracted socket.
191
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'.
194
195 Note: you can always use talloc_free(tstream) to cleanup the resources
196 of the tstream_context on a fatal error.
197
198   struct tevent_req *tstream_disconnect_send(TALLOC_CTX *mem_ctx,
199       struct tevent_context *ev,
200       struct tstream_context *stream);
201
202   int tstream_disconnect_recv(struct tevent_req *req,
203       int *perrno);
204
205 PDU receive helper functions
206 ============================
207
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.
211
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.
223
224 See the 'dcerpc_read_ncacn_packet_send/recv' functions in Samba as an
225 example.
226
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);
232
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);
238
239   int tstream_readv_pdu_recv(struct tevent_req *req, int *perrno);
240
241 Async 'tevent_queue' based helper functions
242 ===========================================
243
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).
248
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.
252
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);
260
261   ssize_t tdgram_sendto_queue_recv(struct tevent_req *req, int *perrno);
262
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);
269
270   int tstream_readv_pdu_queue_recv(struct tevent_req *req, int *perrno);
271
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);
278
279   int tstream_writev_queue_recv(struct tevent_req *req, int *perrno);
280
281 BSD sockets: ipv4, ipv6 and unix
282 ================================
283
284 The main tsocket library comes with implementations
285 for BSD style ipv4, ipv6 and unix sockets.
286
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.
296
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);
302
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.
307
308   char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
309       TALLOC_CTX *mem_ctx);
310
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.
315
316   uint16_t tsocket_address_inet_port(const struct tsocket_address *addr);
317
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.
323
324   int tsocket_address_inet_set_port(struct tsocket_address *addr,
325       uint16_t port);
326
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.
334
335   int tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
336       const char *path,
337       struct tsocket_address **addr);
338
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.
343
344   char *tsocket_address_unix_path(const struct tsocket_address *addr,
345       TALLOC_CTX *mem_ctx);
346
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.
353
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);
358
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.
365
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);
370
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.
380
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'.
386
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);
391
392   int tstream_inet_tcp_connect_recv(struct tevent_req *req,
393       int *perrno,
394       TALLOC_CTX *mem_ctx,
395       struct tstream_context **stream);
396
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.
407
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'.
413
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);
418
419   int _tstream_unix_connect_recv(struct tevent_req *req,
420       int *perrno,
421       TALLOC_CTX *mem_ctx,
422       struct tstream_context **stream);
423
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.
428
429   int tstream_unix_socketpair(TALLOC_CTX *mem_ctx1,
430       struct tstream_context **stream1,
431       TALLOC_CTX *mem_ctx2,
432       struct tstream_context **stream2);
433
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.
440
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);
445
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'.
451
452   ssize_t tsocket_address_bsd_sockaddr(const struct tsocket_address *addr,
453       struct sockaddr *sa,
454       socklen_t sa_socklen);
455
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.
462
463   int tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx,
464       int fd,
465       struct tstream_context **stream);
466
467 Virtual Sockets
468 ===============
469
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.
473
474 Named Pipe Auth (NPA) Sockets
475 =============================
476
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.
481