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