s3: improve WHATSNEW around kerberos changes
[Samba.git] / lib / tsocket / tsocket_guide.txt
blobf937385a82af75a6eeaf04383f8339d4cb2cae5f
2 Basic design of the tsocket abstraction
3 =======================================
5 The tsocket abstraction is splitted into two
6 different kinds of communitation interfaces.
8 There's the "tstream_context" interface with abstracts
9 the communication through a bidirectional
10 byte stream between two endpoints.
12 And there's the "tdgram_context" interface
13 with 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 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'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".
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're 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 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 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 length of the datagram (0 is never returned!).
150 The caller can only have one outstanding tstream_readv_send()
151 at a time otherwise the caller will get *perrno = EBUSY.
153   struct tevent_req *tstream_readv_send(TALLOC_CTX *mem_ctx,
154       struct tevent_context *ev,
155       struct tstream_context *stream,
156       struct iovec *vector,
157       size_t count);
159   int tstream_readv_recv(struct tevent_req *req,
160       int *perrno);
162 The tstream_writev_send() method can be called to write
163 buffers in the given iovec vector into the stream socket.
164 It is 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".
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!).
176 The caller can only have one outstanding tstream_writev_send()
177 at a time otherwise the caller will get '*perrno = EBUSY'.
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);
185   int tstream_writev_recv(struct tevent_req *req,
186       int *perrno);
188 The tstream_disconnect_send() method should normally be used to
189 shutdown/close the abstracted socket.
191 The caller should make sure there're no outstanding tstream_readv_send()
192 and tstream_writev_send() calls otherwise the caller will get '*perrno = EBUSY'.
194 Note: you can always use talloc_free(tstream) to cleanup the resources
195 of the tstream_context on a fatal error.
197   struct tevent_req *tstream_disconnect_send(TALLOC_CTX *mem_ctx,
198       struct tevent_context *ev,
199       struct tstream_context *stream);
201   int tstream_disconnect_recv(struct tevent_req *req,
202       int *perrno);
204 PDU receive helper functions
205 ============================
207 In order to simplify the job, for callers that want to implement
208 a function to receive a full PDU with a single async function pair,
209 some helper functions are provided.
211 The caller can use the tstream_readv_pdu_send() function
212 to ask for the next available PDU on the abstracted tstream_context.
213 The caller needs to provide a "next_vector" function and a private
214 state for this function. The tstream_readv_pdu engine will ask
215 the next_vector function for the next iovec vector to be used.
216 There's a tstream_readv_send/recv pair for each vector returned
217 by the next_vector function. If the next_vector function detects
218 it received a full pdu, it returns an empty vector. The the callback
219 of the tevent_req (returned by tstream_readv_pdu_send()) is triggered.
220 Note: the buffer allocation is completely up to the next_vector function
221 and its private state.
223 See the 'dcerpc_read_ncacn_packet_send/recv' functions in Samba as an
224 example.
226   typedef int (*tstream_readv_pdu_next_vector_t)(struct tstream_context *stream,
227       void *private_data,
228       TALLOC_CTX *mem_ctx,
229       struct iovec **vector,
230       size_t *count);
232   struct tevent_req *tstream_readv_pdu_send(TALLOC_CTX *mem_ctx,
233       struct tevent_context *ev,
234       struct tstream_context *stream,
235       tstream_readv_pdu_next_vector_t next_vector_fn,
236       void *next_vector_private);
238   int tstream_readv_pdu_recv(struct tevent_req *req, int *perrno);
240 Async 'tevent_queue' based helper functions
241 ===========================================
243 In some cases the caller doesn't care about the IO ordering on the
244 abstracted socket.
245 (Remember at the low level there's always only one IO in a specific
246  direction allowed, only one tdgram_sendto_send() at a time).
248 Some helpers that use 'tevent_queue' are avilable to simplify handling
249 multiple IO requests. The functions just get a 'queue' argument and
250 internally serialize all operations.
252   struct tevent_req *tdgram_sendto_queue_send(TALLOC_CTX *mem_ctx,
253       struct tevent_context *ev,
254       struct tdgram_context *dgram,
255       struct tevent_queue *queue,
256       const uint8_t *buf,
257       size_t len,
258       struct tsocket_address *dst);
260   ssize_t tdgram_sendto_queue_recv(struct tevent_req *req, int *perrno);
262   struct tevent_req *tstream_readv_pdu_queue_send(TALLOC_CTX *mem_ctx,
263       struct tevent_context *ev,
264       struct tstream_context *stream,
265       struct tevent_queue *queue,
266       tstream_readv_pdu_next_vector_t next_vector_fn,
267       void *next_vector_private);
269   int tstream_readv_pdu_queue_recv(struct tevent_req *req, int *perrno);
271   struct tevent_req *tstream_writev_queue_send(TALLOC_CTX *mem_ctx,
272       struct tevent_context *ev,
273       struct tstream_context *stream,
274       struct tevent_queue *queue,
275       const struct iovec *vector,
276       size_t count);
278   int tstream_writev_queue_recv(struct tevent_req *req, int *perrno);
280 BSD sockets: ipv4, ipv6 and unix
281 ================================
283 The main tsocket library comes with implentations
284 for BSD style ipv4, ipv6 and unix sockets.
286 You can use the tsocket_address_inet_from_strings()
287 function to create a tsocket_address for ipv4 and ipv6
288 endpoint addresses. "family" can be "ipv4", "ipv6" or "ip".
289 With "ip" is autodetects "ipv4" or "ipv6" based on the
290 "addr_string" string. "addr_string" must be a valid
291 ip address string based on the selected family
292 (dns names are not allowed!). But it's valid to pass NULL,
293 which gets mapped to "0.0.0.0" or "::".
294 It returns -1 and sets errno on error. Otherwise it returns 0.
296   int tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
297       const char *family,
298       const char *addr_string,
299       uint16_t port,
300       struct tsocket_address **addr);
302 To get the ip address string of an existing 'inet' tsocket_address
303 you can use the tsocket_address_inet_addr_string() function.
304 It will return NULL and set errno to EINVAL if the tsocket_address
305 doesn't represent an ipv4 or ipv6 endpoint address.
307   char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
308       TALLOC_CTX *mem_ctx);
310 To get the port number of an existing 'inet' tsocket_address
311 you can use the tsocket_address_inet_port() function.
312 It will return 0 and set errno to EINVAL if the tsocket_address
313 doesn't represent an ipv4 or ipv6 endpoint address.
315   uint16_t tsocket_address_inet_port(const struct tsocket_address *addr);
317 To set the port number of an existing 'inet' tsocket_address
318 you can use the tsocket_address_inet_set_port() function.
319 It will return -1 and set errno to EINVAL if the tsocket_address
320 doesn't represent an ipv4 or ipv6 endpoint address.
321 It returns 0 on success.
323   int tsocket_address_inet_set_port(struct tsocket_address *addr,
324       uint16_t port);
326 You can use the tsocket_address_unix_from_path()
327 function to create a tsocket_address for unix domain
328 endpoint addresses. "path" is the filesystem path
329 (NULL will map ""). If the path is longer than
330 the low level kernel supports the function will
331 return -1 and set errno to ENAMETOOLONG.
332 On success it returns 0.
334   int tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
335       const char *path,
336       struct tsocket_address **addr);
338 To get the path of an 'unix' tsocket_address
339 you can use the tsocket_address_unix_path() function.
340 It will return NULL and set errno to EINVAL if the tsocket_address
341 doesn't represent a unix domain endpoint path.
343   char *tsocket_address_unix_path(const struct tsocket_address *addr,
344       TALLOC_CTX *mem_ctx);
346 You can use tdgram_inet_udp_socket() to create a tdgram_context
347 for ipv4 or ipv6 UDP communication. "local_address" has to be
348 an 'inet' tsocket_address and it has to represent the local
349 endpoint. "remote_address" can be NULL or an 'inet' tsocket_address
350 presenting a remote endpoint. It returns -1 ans sets errno on error
351 and it returns 0 on success.
353   int tdgram_inet_udp_socket(const struct tsocket_address *local_address,
354       const struct tsocket_address *remote_address,
355       TALLOC_CTX *mem_ctx,
356       struct tdgram_context **dgram);
358 You can use tdgram_unix_socket() to create a tdgram_context
359 for unix domain datagram communication. "local_address" has to be
360 an 'unix' tsocket_address and it has to represent the local
361 endpoint. "remote_address" can be NULL or an 'unix' tsocket_address
362 presenting a remote endpoint. It returns -1 ans sets errno on error
363 and it returns 0 on success.
365   int tdgram_unix_socket(const struct tsocket_address *local,
366       const struct tsocket_address *remote,
367       TALLOC_CTX *mem_ctx,
368       struct tdgram_context **dgram);
370 You can use tstream_inet_tcp_connect_send to asynchronously
371 connect to a remote ipv4 or ipv6 TCP endpoint and create a
372 tstream_context for the stream based communication. "local_address" has to be
373 an 'inet' tsocket_address and it has to represent the local
374 endpoint. "remote_address" has to be an 'inet' tsocket_address
375 presenting a remote endpoint. It returns a 'tevent_req' handle,
376 where the caller can register a callback with tevent_req_set_callback().
377 The callback is triggered when a socket is connected and ready for IO
378 or an error happened.
380 The callback is then supposed to get the result by calling
381 tstream_inet_tcp_connect_recv() on the 'tevent_req'. It returns -1
382 and sets '*perrno' to the actual 'errno' on failure.
383 It returns 0 on success and returns the new tstream_context
384 in '*stream'.
386   struct tevent_req *tstream_inet_tcp_connect_send(TALLOC_CTX *mem_ctx,
387       struct tevent_context *ev,
388       const struct tsocket_address *local_address,
389       const struct tsocket_address *remote_address);
391   int tstream_inet_tcp_connect_recv(struct tevent_req *req,
392       int *perrno,
393       TALLOC_CTX *mem_ctx,
394       struct tstream_context **stream);
396 You can use tstream_unix_connect_send to asynchronously
397 connect to a unix domain endpoint and create a
398 tstream_context for the stream based communication.
399 "local_address" has to be an 'unix' tsocket_address and
400 it has to represent the local endpoint. "remote_address"
401 has to be an 'inet' tsocket_address presenting a remote endpoint.
402 It returns a 'tevent_req' handle, where the caller can register
403 a callback with tevent_req_set_callback(). The callback is
404 triggered when a socket is connected and ready for IO
405 or an error happened.
407 The callback is then supposed to get the result by calling
408 tstream_unix_connect_recv() on the 'tevent_req'. It returns -1
409 and sets '*perrno' to the actual 'errno' on failure.
410 It returns 0 on success and returns the new tstream_context
411 in '*stream'.
413   struct tevent_req *tstream_unix_connect_send(TALLOC_CTX *mem_ctx,
414       struct tevent_context *ev,
415       const struct tsocket_address *local,
416       const struct tsocket_address *remote);
418   int _tstream_unix_connect_recv(struct tevent_req *req,
419       int *perrno,
420       TALLOC_CTX *mem_ctx,
421       struct tstream_context **stream);
423 You can use tstream_unix_socketpair to create two connected
424 'unix' tsocket_contexts for the stream based communication.
425 It returns -1 and sets errno on error and it returns 0 on
426 success.
428   int tstream_unix_socketpair(TALLOC_CTX *mem_ctx1,
429       struct tstream_context **stream1,
430       TALLOC_CTX *mem_ctx2,
431       struct tstream_context **stream2);
433 In some situations it's needed to create a tsocket_address from
434 a given 'struct sockaddr'. You can use tsocket_address_bsd_from_sockaddr()
435 for that. This should only be used if really needed, because of
436 already existing fixed APIs. Only AF_INET, AF_INET6 and AF_UNIX
437 sockets are allowed. The function returns -1 and sets errno on error.
438 Otherwise it returns 0.
440   int tsocket_address_bsd_from_sockaddr(TALLOC_CTX *mem_ctx,
441       struct sockaddr *sa,
442       socklen_t sa_socklen,
443       struct tsocket_address **addr);
445 In some situations it's needed to get a 'struct sockaddr' from a
446 given tsocket_address . You can use tsocket_address_bsd_sockaddr()
447 for that. This should only be used if really needed. Only AF_INET,
448 AF_INET6 and AF_UNIX are supported. It returns the size of '*sa' on
449 success, otherwise it returns -1 and sets 'errno'.
451   ssize_t tsocket_address_bsd_sockaddr(const struct tsocket_address *addr,
452       struct sockaddr *sa,
453       socklen_t sa_socklen);
455 In some situations it's needed to wrap existing file descriptors
456 into the tstream abstraction. You can use tstream_bsd_existing_socket()
457 for that. But you should read the tsocket_bsd.c code and unterstand it
458 in order use this function. E.g. the fd has to be non blocking already.
459 It will return -1 and set errno on error. Otherwise it returns 0
460 and sets '*stream' to point to the new tstream_context.
462   int tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx,
463       int fd,
464       struct tstream_context **stream);
466 Virtual Sockets
467 ===============
469 The abstracted layout of tdgram_context and tstream_context
470 allow implementations arround virtual sockets for encrypted tunnels
471 (like TLS, SASL or GSSAPI) or named pipes over smb.
473 Named Pipe Auth (NPA) Sockets
474 =============================
476 Samba has an implementation to abstract named pipes over smb
477 (within the server side). See libcli/named_pipe_auth/npa_tstream.[ch]
478 for the core code. The current callers are located in source4/ntvfs/ipc/vfs_ipc.c
479 and source4/rpc_server/service_rpc.c for the users.