| 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 | 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.
|
|---|
| 29 |
|
|---|
| 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.
|
|---|
| 34 |
|
|---|
| 35 | char *tsocket_address_string(const struct tsocket_address *addr,
|
|---|
| 36 | TALLOC_CTX *mem_ctx);
|
|---|
| 37 |
|
|---|
| 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.
|
|---|
| 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 similar to recvfrom(2)/sendto(2)/close(2) syscalls.
|
|---|
| 51 |
|
|---|
| 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.
|
|---|
| 57 |
|
|---|
| 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.
|
|---|
| 65 |
|
|---|
| 66 | The caller can only have one outstanding tdgram_recvfrom_send()
|
|---|
| 67 | at 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 |
|
|---|
| 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 |
|
|---|
| 102 | ssize_t tdgram_sendto_recv(struct tevent_req *req,
|
|---|
| 103 | int *perrno);
|
|---|
| 104 |
|
|---|
| 105 | The tdgram_disconnect_send() method should be used to normally
|
|---|
| 106 | shutdown/close the abstracted socket.
|
|---|
| 107 |
|
|---|
| 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'.
|
|---|
| 110 |
|
|---|
| 111 | Note: you can always use talloc_free(tdgram) to cleanup the resources
|
|---|
| 112 | of 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 |
|
|---|
| 121 | The tstream_context abstraction
|
|---|
| 122 | ===============================
|
|---|
| 123 |
|
|---|
| 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.
|
|---|
| 127 |
|
|---|
| 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!).
|
|---|
| 132 |
|
|---|
| 133 | ssize_t tstream_pending_bytes(struct tstream_context *stream);
|
|---|
| 134 |
|
|---|
| 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.
|
|---|
| 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 (0 is never returned!).
|
|---|
| 149 |
|
|---|
| 150 | The caller can only have one outstanding tstream_readv_send()
|
|---|
| 151 | at 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 |
|
|---|
| 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".
|
|---|
| 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 |
|
|---|
| 185 | int tstream_writev_recv(struct tevent_req *req,
|
|---|
| 186 | int *perrno);
|
|---|
| 187 |
|
|---|
| 188 | The tstream_disconnect_send() method should normally be used to
|
|---|
| 189 | shutdown/close the abstracted socket.
|
|---|
| 190 |
|
|---|
| 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'.
|
|---|
| 193 |
|
|---|
| 194 | Note: you can always use talloc_free(tstream) to cleanup the resources
|
|---|
| 195 | of 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 |
|
|---|
| 204 | PDU receive helper functions
|
|---|
| 205 | ============================
|
|---|
| 206 |
|
|---|
| 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.
|
|---|
| 210 |
|
|---|
| 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.
|
|---|
| 222 |
|
|---|
| 223 | See the 'dcerpc_read_ncacn_packet_send/recv' functions in Samba as an
|
|---|
| 224 | example.
|
|---|
| 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 |
|
|---|
| 240 | Async 'tevent_queue' based helper functions
|
|---|
| 241 | ===========================================
|
|---|
| 242 |
|
|---|
| 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).
|
|---|
| 247 |
|
|---|
| 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.
|
|---|
| 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 |
|
|---|
| 280 | BSD sockets: ipv4, ipv6 and unix
|
|---|
| 281 | ================================
|
|---|
| 282 |
|
|---|
| 283 | The main tsocket library comes with implentations
|
|---|
| 284 | for BSD style ipv4, ipv6 and unix sockets.
|
|---|
| 285 |
|
|---|
| 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.
|
|---|
| 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 |
|
|---|
| 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.
|
|---|
| 306 |
|
|---|
| 307 | char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
|
|---|
| 308 | TALLOC_CTX *mem_ctx);
|
|---|
| 309 |
|
|---|
| 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.
|
|---|
| 314 |
|
|---|
| 315 | uint16_t tsocket_address_inet_port(const struct tsocket_address *addr);
|
|---|
| 316 |
|
|---|
| 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.
|
|---|
| 322 |
|
|---|
| 323 | int tsocket_address_inet_set_port(struct tsocket_address *addr,
|
|---|
| 324 | uint16_t port);
|
|---|
| 325 |
|
|---|
| 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.
|
|---|
| 333 |
|
|---|
| 334 | int tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
|
|---|
| 335 | const char *path,
|
|---|
| 336 | struct tsocket_address **addr);
|
|---|
| 337 |
|
|---|
| 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.
|
|---|
| 342 |
|
|---|
| 343 | char *tsocket_address_unix_path(const struct tsocket_address *addr,
|
|---|
| 344 | TALLOC_CTX *mem_ctx);
|
|---|
| 345 |
|
|---|
| 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.
|
|---|
| 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 |
|
|---|
| 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.
|
|---|
| 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 |
|
|---|
| 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.
|
|---|
| 379 |
|
|---|
| 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'.
|
|---|
| 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 |
|
|---|
| 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.
|
|---|
| 406 |
|
|---|
| 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'.
|
|---|
| 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 |
|
|---|
| 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.
|
|---|
| 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 |
|
|---|
| 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.
|
|---|
| 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 |
|
|---|
| 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'.
|
|---|
| 450 |
|
|---|
| 451 | ssize_t tsocket_address_bsd_sockaddr(const struct tsocket_address *addr,
|
|---|
| 452 | struct sockaddr *sa,
|
|---|
| 453 | socklen_t sa_socklen);
|
|---|
| 454 |
|
|---|
| 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.
|
|---|
| 461 |
|
|---|
| 462 | int tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx,
|
|---|
| 463 | int fd,
|
|---|
| 464 | struct tstream_context **stream);
|
|---|
| 465 |
|
|---|
| 466 | Virtual Sockets
|
|---|
| 467 | ===============
|
|---|
| 468 |
|
|---|
| 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.
|
|---|
| 472 |
|
|---|
| 473 | Named Pipe Auth (NPA) Sockets
|
|---|
| 474 | =============================
|
|---|
| 475 |
|
|---|
| 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.
|
|---|
| 480 |
|
|---|