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