source: trunk/server/lib/tsocket/tsocket_guide.txt

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

File size: 19.2 KB
Line 
1
2Basic design of the tsocket abstraction
3=======================================
4
5The tsocket abstraction is splitted into two
6different kinds of communitation interfaces.
7
8There's the "tstream_context" interface with abstracts
9the communication through a bidirectional
10byte stream between two endpoints.
11
12And there's the "tdgram_context" interface
13with abstracts datagram based communication between any
14number of endpoints.
15
16Both interfaces share the "tsocket_address" abstraction
17for endpoint addresses.
18
19The whole library is based on the talloc(3) and 'tevent' libraries
20and provides "tevent_req" based "foo_send()"/"foo_recv()" functions pairs
21for all abstracted methods that need to be async.
22
23The tsocket_address abstraction
24===============================
25
26A tsocket_address represents a generic socket endpoint.
27It behaves like an abstract class, therefore it has no direct constructor.
28Constructors are described in later sections of this document.
29
30A function get the string representation of an endpoint for debugging is
31available but callers SHOULD NOT try to parse this string. To get more
32details callers should use getter methods of the specific tsocket_address
33implemention.
34
35 char *tsocket_address_string(const struct tsocket_address *addr,
36 TALLOC_CTX *mem_ctx);
37
38A function to create a copy of the tsocket_address is also avilable.
39This is useful before doing modifications to a socket
40via 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
45The tdgram_context abstraction
46==============================
47
48The tdgram_context is like an abstract class for datagram
49based sockets. The interface provides async 'tevent_req' based
50functions similar to recvfrom(2)/sendto(2)/close(2) syscalls.
51
52The tdgram_recvfrom_send() method can be called to ask for the
53next available datagram from the abstracted tdgram_context.
54It returns a 'tevent_req' handle, where the caller can register
55a callback with tevent_req_set_callback(). The callback is triggered
56when a datagram is available or an error occurs.
57
58The callback is then supposed to get the result by calling
59tdgram_recvfrom_recv() on the 'tevent_req'. It returns -1
60and sets '*perrno' to the actual 'errno' on failure.
61Otherwise it returns the length of the datagram
62(0 is never returned!). '*buf' will contain the buffer of the
63datagram and '*src' the abstracted tsocket_address of the sender
64of the received datagram.
65
66The caller can only have one outstanding tdgram_recvfrom_send()
67at 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
79The tdgram_sendto_send() method can be called to send a
80datagram (specified by a buf/len) to a destination endpoint
81(specified by dst). It's not allowed for len to be 0.
82It returns a 'tevent_req' handle, where the caller can register a
83callback with tevent_req_set_callback(). The callback is triggered
84when the specific implementation (thinks it)
85has delivered the datagram to the "wire".
86
87The callback is then supposed to get the result by calling
88tdgram_sendto_recv() on the 'tevent_req'. It returns -1
89and sets '*perrno' to the actual 'errno' on failure.
90Otherwise it returns the length of the datagram
91(0 is never returned!).
92
93The caller can only have one outstanding tdgram_sendto_send()
94at 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
105The tdgram_disconnect_send() method should be used to normally
106shutdown/close the abstracted socket.
107
108The caller should make sure there're no outstanding tdgram_recvfrom_send()
109and tdgram_sendto_send() calls otherwise the caller will get '*perrno = EBUSY'.
110
111Note: you can always use talloc_free(tdgram) to cleanup the resources
112of 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
121The tstream_context abstraction
122===============================
123
124A tstream_context is like an abstract class for stream
125based sockets. The interface provides async 'tevent_req' based
126functions similar to the readv(2)/writev(2)/close(2) syscalls.
127
128The tstream_pending_bytes() function is able to report how many bytes of
129the incoming stream have been received but have not been consumed yet.
130It returns -1 and sets 'errno' on failure.
131Otherwise it returns the number of uncomsumed bytes (it can return 0!).
132
133 ssize_t tstream_pending_bytes(struct tstream_context *stream);
134
135The tstream_readv_send() method can be called to read a
136specific amount of bytes from the stream into the buffers
137of the given iovec vector. The caller has to preallocate the buffers
138in the iovec vector. The caller might need to use
139tstream_pending_bytes() if the protocol doesn't have a fixed pdu header
140containing the pdu size. tstream_readv_send() returns a 'tevent_req' handle,
141where the caller can register a callback with tevent_req_set_callback().
142The callback is triggered when all iovec buffers are completely
143filled with bytes from the socket or an error occurs.
144
145The callback is then supposed to get the result by calling
146tstream_readv_recv() on the 'tevent_req'. It returns -1
147and sets '*perrno' to the actual 'errno' on failure.
148Otherwise it returns the length of the datagram (0 is never returned!).
149
150The caller can only have one outstanding tstream_readv_send()
151at a time otherwise the caller will get *perrno = EBUSY.
152
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);
158
159 int tstream_readv_recv(struct tevent_req *req,
160 int *perrno);
161
162The tstream_writev_send() method can be called to write
163buffers in the given iovec vector into the stream socket.
164It is invalid to pass an empty vector.
165tstream_writev_send() returns a 'tevent_req' handle,
166where the caller can register a callback with tevent_req_set_callback().
167The callback is triggered when the specific implementation (thinks it)
168has delivered the all buffers to the "wire".
169
170The callback is then supposed to get the result by calling
171tstream_writev_recv() on the 'tevent_req'. It returns -1
172and sets '*perrno' to the actual 'errno' on failure.
173Otherwise it returns the total amount of bytes sent.
174(0 is never returned!).
175
176The caller can only have one outstanding tstream_writev_send()
177at 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
185 int tstream_writev_recv(struct tevent_req *req,
186 int *perrno);
187
188The tstream_disconnect_send() method should normally be used to
189shutdown/close the abstracted socket.
190
191The caller should make sure there're no outstanding tstream_readv_send()
192and tstream_writev_send() calls otherwise the caller will get '*perrno = EBUSY'.
193
194Note: you can always use talloc_free(tstream) to cleanup the resources
195of the tstream_context on a fatal error.
196
197 struct tevent_req *tstream_disconnect_send(TALLOC_CTX *mem_ctx,
198 struct tevent_context *ev,
199 struct tstream_context *stream);
200
201 int tstream_disconnect_recv(struct tevent_req *req,
202 int *perrno);
203
204PDU receive helper functions
205============================
206
207In order to simplify the job, for callers that want to implement
208a function to receive a full PDU with a single async function pair,
209some helper functions are provided.
210
211The caller can use the tstream_readv_pdu_send() function
212to ask for the next available PDU on the abstracted tstream_context.
213The caller needs to provide a "next_vector" function and a private
214state for this function. The tstream_readv_pdu engine will ask
215the next_vector function for the next iovec vector to be used.
216There's a tstream_readv_send/recv pair for each vector returned
217by the next_vector function. If the next_vector function detects
218it received a full pdu, it returns an empty vector. The the callback
219of the tevent_req (returned by tstream_readv_pdu_send()) is triggered.
220Note: the buffer allocation is completely up to the next_vector function
221and its private state.
222
223See the 'dcerpc_read_ncacn_packet_send/recv' functions in Samba as an
224example.
225
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);
231
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);
237
238 int tstream_readv_pdu_recv(struct tevent_req *req, int *perrno);
239
240Async 'tevent_queue' based helper functions
241===========================================
242
243In some cases the caller doesn't care about the IO ordering on the
244abstracted 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).
247
248Some helpers that use 'tevent_queue' are avilable to simplify handling
249multiple IO requests. The functions just get a 'queue' argument and
250internally serialize all operations.
251
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);
259
260 ssize_t tdgram_sendto_queue_recv(struct tevent_req *req, int *perrno);
261
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);
268
269 int tstream_readv_pdu_queue_recv(struct tevent_req *req, int *perrno);
270
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);
277
278 int tstream_writev_queue_recv(struct tevent_req *req, int *perrno);
279
280BSD sockets: ipv4, ipv6 and unix
281================================
282
283The main tsocket library comes with implentations
284for BSD style ipv4, ipv6 and unix sockets.
285
286You can use the tsocket_address_inet_from_strings()
287function to create a tsocket_address for ipv4 and ipv6
288endpoint addresses. "family" can be "ipv4", "ipv6" or "ip".
289With "ip" is autodetects "ipv4" or "ipv6" based on the
290"addr_string" string. "addr_string" must be a valid
291ip address string based on the selected family
292(dns names are not allowed!). But it's valid to pass NULL,
293which gets mapped to "0.0.0.0" or "::".
294It returns -1 and sets errno on error. Otherwise it returns 0.
295
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);
301
302To get the ip address string of an existing 'inet' tsocket_address
303you can use the tsocket_address_inet_addr_string() function.
304It will return NULL and set errno to EINVAL if the tsocket_address
305doesn't represent an ipv4 or ipv6 endpoint address.
306
307 char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
308 TALLOC_CTX *mem_ctx);
309
310To get the port number of an existing 'inet' tsocket_address
311you can use the tsocket_address_inet_port() function.
312It will return 0 and set errno to EINVAL if the tsocket_address
313doesn't represent an ipv4 or ipv6 endpoint address.
314
315 uint16_t tsocket_address_inet_port(const struct tsocket_address *addr);
316
317To set the port number of an existing 'inet' tsocket_address
318you can use the tsocket_address_inet_set_port() function.
319It will return -1 and set errno to EINVAL if the tsocket_address
320doesn't represent an ipv4 or ipv6 endpoint address.
321It returns 0 on success.
322
323 int tsocket_address_inet_set_port(struct tsocket_address *addr,
324 uint16_t port);
325
326You can use the tsocket_address_unix_from_path()
327function to create a tsocket_address for unix domain
328endpoint addresses. "path" is the filesystem path
329(NULL will map ""). If the path is longer than
330the low level kernel supports the function will
331return -1 and set errno to ENAMETOOLONG.
332On success it returns 0.
333
334 int tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
335 const char *path,
336 struct tsocket_address **addr);
337
338To get the path of an 'unix' tsocket_address
339you can use the tsocket_address_unix_path() function.
340It will return NULL and set errno to EINVAL if the tsocket_address
341doesn't represent a unix domain endpoint path.
342
343 char *tsocket_address_unix_path(const struct tsocket_address *addr,
344 TALLOC_CTX *mem_ctx);
345
346You can use tdgram_inet_udp_socket() to create a tdgram_context
347for ipv4 or ipv6 UDP communication. "local_address" has to be
348an 'inet' tsocket_address and it has to represent the local
349endpoint. "remote_address" can be NULL or an 'inet' tsocket_address
350presenting a remote endpoint. It returns -1 ans sets errno on error
351and it returns 0 on success.
352
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);
357
358You can use tdgram_unix_socket() to create a tdgram_context
359for unix domain datagram communication. "local_address" has to be
360an 'unix' tsocket_address and it has to represent the local
361endpoint. "remote_address" can be NULL or an 'unix' tsocket_address
362presenting a remote endpoint. It returns -1 ans sets errno on error
363and it returns 0 on success.
364
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);
369
370You can use tstream_inet_tcp_connect_send to asynchronously
371connect to a remote ipv4 or ipv6 TCP endpoint and create a
372tstream_context for the stream based communication. "local_address" has to be
373an 'inet' tsocket_address and it has to represent the local
374endpoint. "remote_address" has to be an 'inet' tsocket_address
375presenting a remote endpoint. It returns a 'tevent_req' handle,
376where the caller can register a callback with tevent_req_set_callback().
377The callback is triggered when a socket is connected and ready for IO
378or an error happened.
379
380The callback is then supposed to get the result by calling
381tstream_inet_tcp_connect_recv() on the 'tevent_req'. It returns -1
382and sets '*perrno' to the actual 'errno' on failure.
383It returns 0 on success and returns the new tstream_context
384in '*stream'.
385
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);
390
391 int tstream_inet_tcp_connect_recv(struct tevent_req *req,
392 int *perrno,
393 TALLOC_CTX *mem_ctx,
394 struct tstream_context **stream);
395
396You can use tstream_unix_connect_send to asynchronously
397connect to a unix domain endpoint and create a
398tstream_context for the stream based communication.
399"local_address" has to be an 'unix' tsocket_address and
400it has to represent the local endpoint. "remote_address"
401has to be an 'inet' tsocket_address presenting a remote endpoint.
402It returns a 'tevent_req' handle, where the caller can register
403a callback with tevent_req_set_callback(). The callback is
404triggered when a socket is connected and ready for IO
405or an error happened.
406
407The callback is then supposed to get the result by calling
408tstream_unix_connect_recv() on the 'tevent_req'. It returns -1
409and sets '*perrno' to the actual 'errno' on failure.
410It returns 0 on success and returns the new tstream_context
411in '*stream'.
412
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);
417
418 int _tstream_unix_connect_recv(struct tevent_req *req,
419 int *perrno,
420 TALLOC_CTX *mem_ctx,
421 struct tstream_context **stream);
422
423You can use tstream_unix_socketpair to create two connected
424'unix' tsocket_contexts for the stream based communication.
425It returns -1 and sets errno on error and it returns 0 on
426success.
427
428 int tstream_unix_socketpair(TALLOC_CTX *mem_ctx1,
429 struct tstream_context **stream1,
430 TALLOC_CTX *mem_ctx2,
431 struct tstream_context **stream2);
432
433In some situations it's needed to create a tsocket_address from
434a given 'struct sockaddr'. You can use tsocket_address_bsd_from_sockaddr()
435for that. This should only be used if really needed, because of
436already existing fixed APIs. Only AF_INET, AF_INET6 and AF_UNIX
437sockets are allowed. The function returns -1 and sets errno on error.
438Otherwise it returns 0.
439
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);
444
445In some situations it's needed to get a 'struct sockaddr' from a
446given tsocket_address . You can use tsocket_address_bsd_sockaddr()
447for that. This should only be used if really needed. Only AF_INET,
448AF_INET6 and AF_UNIX are supported. It returns the size of '*sa' on
449success, otherwise it returns -1 and sets 'errno'.
450
451 ssize_t tsocket_address_bsd_sockaddr(const struct tsocket_address *addr,
452 struct sockaddr *sa,
453 socklen_t sa_socklen);
454
455In some situations it's needed to wrap existing file descriptors
456into the tstream abstraction. You can use tstream_bsd_existing_socket()
457for that. But you should read the tsocket_bsd.c code and unterstand it
458in order use this function. E.g. the fd has to be non blocking already.
459It will return -1 and set errno on error. Otherwise it returns 0
460and sets '*stream' to point to the new tstream_context.
461
462 int tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx,
463 int fd,
464 struct tstream_context **stream);
465
466Virtual Sockets
467===============
468
469The abstracted layout of tdgram_context and tstream_context
470allow implementations arround virtual sockets for encrypted tunnels
471(like TLS, SASL or GSSAPI) or named pipes over smb.
472
473Named Pipe Auth (NPA) Sockets
474=============================
475
476Samba has an implementation to abstract named pipes over smb
477(within the server side). See libcli/named_pipe_auth/npa_tstream.[ch]
478for the core code. The current callers are located in source4/ntvfs/ipc/vfs_ipc.c
479and source4/rpc_server/service_rpc.c for the users.
480
Note: See TracBrowser for help on using the repository browser.