Ensure we keep last_access up to date when processing a request.
[Samba.git] / lib / tsocket / tsocket_guide.txt
blobdfe2dd44e1827b1415e66df60afce6919e2e703d
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 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.
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.
35   char *tsocket_address_string(const struct tsocket_address *addr,
36       TALLOC_CTX *mem_ctx);
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.
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 on top functionality is similar to the
51 recvfrom(2)/sendto(2)/close(2) syscalls.
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.
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.
67 The caller can only have one outstanding tdgram_recvfrom_send()
68 at a time otherwise the caller will get '*perrno = EBUSY'.
70   struct tevent_req *tdgram_recvfrom_send(TALLOC_CTX *mem_ctx,
71       struct tevent_context *ev,
72       struct tdgram_context *dgram);
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);
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".
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!).
94 The caller can only have one outstanding tdgram_sendto_send()
95 at a time otherwise the caller will get '*perrno = EBUSY'.
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);
103   ssize_t tdgram_sendto_recv(struct tevent_req *req,
104       int *perrno);
106 The tdgram_disconnect_send() method should be used to normally
107 shutdown/close the abstracted socket.
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'.
112 Note: you can always use talloc_free(tdgram) to cleanup the resources
113 of the tdgram_context on a fatal error.
115   struct tevent_req *tdgram_disconnect_send(TALLOC_CTX *mem_ctx,
116       struct tevent_context *ev,
117       struct tdgram_context *dgram);
119   int tdgram_disconnect_recv(struct tevent_req *req,
120       int *perrno);
122 The tstream_context abstraction
123 ===============================
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.
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!).
136   ssize_t tstream_pending_bytes(struct tstream_context *stream);
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.
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!).
154 The caller can only have one outstanding tstream_readv_send()
155 at a time otherwise the caller will get *perrno = EBUSY.
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);
163   int tstream_readv_recv(struct tevent_req *req,
164       int *perrno);
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".
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!).
180 The caller can only have one outstanding tstream_writev_send()
181 at a time otherwise the caller will get '*perrno = EBUSY'.
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);
189   int tstream_writev_recv(struct tevent_req *req,
190       int *perrno);
192 The tstream_disconnect_send() method should be used to normally
193 shutdown/close the abstracted socket.
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'.
198 Note: you can always use talloc_free(tstream) to cleanup the resources
199 of the tstream_context on a fatal error.
201   struct tevent_req *tstream_disconnect_send(TALLOC_CTX *mem_ctx,
202       struct tevent_context *ev,
203       struct tstream_context *stream);
205   int tstream_disconnect_recv(struct tevent_req *req,
206       int *perrno);
208 PDU receive helper functions
209 ============================
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.
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.
227 See the 'dcerpc_read_ncacn_packet_send/recv' functions in Samba as an
228 example.
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);
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);
242   int tstream_readv_pdu_recv(struct tevent_req *req, int *perrno);
244 Async 'tevent_queue' based helper functions
245 ===========================================
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).
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.
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);
264   ssize_t tdgram_sendto_queue_recv(struct tevent_req *req, int *perrno);
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);
273   int tstream_readv_pdu_queue_recv(struct tevent_req *req, int *perrno);
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);
282   int tstream_writev_queue_recv(struct tevent_req *req, int *perrno);
284 BSD sockets: ipv4, ipv6 and unix
285 ================================
287 The main tsocket library comes with implentations
288 for BSD style ipv4, ipv6 and unix sockets.
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.
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);
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.
311   char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
312       TALLOC_CTX *mem_ctx);
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.
319   uint16_t tsocket_address_inet_port(const struct tsocket_address *addr);
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.
327   int tsocket_address_inet_set_port(struct tsocket_address *addr,
328       uint16_t port);
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.
338   int tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
339       const char *path,
340       struct tsocket_address **addr);
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.
347   char *tsocket_address_unix_path(const struct tsocket_address *addr,
348       TALLOC_CTX *mem_ctx);
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.
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);
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.
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);
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.
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'.
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);
395   int tstream_inet_tcp_connect_recv(struct tevent_req *req,
396       int *perrno,
397       TALLOC_CTX *mem_ctx,
398       struct tstream_context **stream);
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.
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'.
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);
422   int _tstream_unix_connect_recv(struct tevent_req *req,
423       int *perrno,
424       TALLOC_CTX *mem_ctx,
425       struct tstream_context **stream);
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.
432   int tstream_unix_socketpair(TALLOC_CTX *mem_ctx1,
433       struct tstream_context **stream1,
434       TALLOC_CTX *mem_ctx2,
435       struct tstream_context **stream2);
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.
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);
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'.
455   ssize_t tsocket_address_bsd_sockaddr(const struct tsocket_address *addr,
456       struct sockaddr *sa,
457       socklen_t sa_socklen);
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.
466   int tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx,
467       int fd,
468       struct tstream_context **stream);
470 Virtual Sockets
471 ===============
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.
477 Named Pipe Auth (NPA) Sockets
478 =============================
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.