Merge branch 'master' into wspp-schema
[ira/wip.git] / lib / tsocket / tsocket_guide.txt
index 929875d31a6b91c69ea7a46f08286ec8600894e8..a02fa373faf64000217895fcf9525778be287831 100644 (file)
@@ -280,3 +280,224 @@ on failure.
 Note: if the socket is readable and writeable, only the writeable
       handler is called, this avoids deadlocks at the application level.
 
+Async helper functions
+======================
+
+To make the life easier for the callers, there're 'tevent_req' based
+helper functions for non-blocking io-operations. For each of this functions
+to work the caller must attach the tevent_context to the tsocket_context
+with tsocket_set_event_context(). Please remember that attching a new
+tevent_context will reset the event state of the socket and should only
+be done, when there's no async request is pending on the socket!
+
+The detailed calling conventions for 'tevent_req' based programming
+will be explained in the 'tevent' documentation.
+
+To receive the next availabe datagram from socket there's a wrapper
+for tsocket_recvfrom(). The caller virtually sends its desire to receive
+the next available datagram by calling the tsocket_recvfrom_send() function
+and attaches a callback function to the returned tevent_req via tevent_req_set_callback().
+The callback function is called when a datagram is available or an error has happened.
+The callback function needs to get the result by calling
+tsocket_recvfrom_recv(). The return value of tsocket_recvfrom_recv()
+matches the return value from tsocket_recvfrom(). A possible errno is delivered
+via the perrno parameter instead of the global errno variable. The datagram
+buffer and optional the source tsocket_address of the datagram are returned as talloc
+childs of the mem_ctx passed to tsocket_recvfrom_recv().
+It's important that the caller garanties that there's only one async
+read request on the socket at a time.
+
+   struct tevent_req *tsocket_recvfrom_send(struct tsocket_context *sock,
+                                            TALLOC_CTX *mem_ctx);
+   ssize_t tsocket_recvfrom_recv(struct tevent_req *req,
+                                 int *perrno,
+                                 TALLOC_CTX *mem_ctx,
+                                 uint8_t **buf,
+                                 struct tsocket_address **src);
+
+To send a datagram there's a wrapper for tsocket_sendto().
+The caller calls tsocket_sendto_send() instead of tsocket_sendto()
+which returns a tevent_req allocated on the given TALLOC_CTX.
+The caller attaches a callback function to the returned tevent_req via
+tevent_req_set_callback(). The callback function is called when a datagram was
+deliviered into the socket or an error has happened.
+The callback function needs to get the result by calling
+tsocket_sendto_recv(). The return value of tsocket_sendto_recv()
+matches the return value from tsocket_sendto(). A possible errno is delivered
+via the perrno parameter instead of the global errno variable.
+Normal callers should not use this function directly, they should use
+tsocket_sendto_queue_send/recv() instead.
+
+   struct tevent_req *tsocket_sendto_send(struct tsocket_context *sock,
+                                          TALLOC_CTX *mem_ctx,
+                                          const uint8_t *buf,
+                                          size_t len,
+                                          const struct tsocket_address *dst);
+   ssize_t tsocket_sendto_recv(struct tevent_req *req, int *perrno);
+
+As only one async tsocket_sendto() call should happen at a time,
+there's a 'tevent_queue' is used to serialize the sendto requests.
+
+   struct tevent_req *tsocket_sendto_queue_send(TALLOC_CTX *mem_ctx,
+                                                struct tsocket_context *sock,
+                                                struct tevent_queue *queue,
+                                                const uint8_t *buf,
+                                                size_t len,
+                                                struct tsocket_address *dst);
+   ssize_t tsocket_sendto_queue_recv(struct tevent_req *req, int *perrno);
+
+Ther's an async helper for tsocket_connect(), which should be used
+to connect TSOCKET_TYPE_STREAM based sockets.
+The caller virtually sends its desire to connect to the destination
+tsocket_address by calling tsocket_connect_send() and gets back a tevent_req.
+The caller sets a callback function via tevent_req_set_callback().
+The callback function is called if the tsocket is connected or an error has happened.
+The callback function needs to get the result by calling
+tsocket_connect_recv(). The return value of tsocket_connect_recv()
+matches the return value from tsocket_connect()/tsocket_get_status().
+A possible errno is delivered via the perrno parameter instead of the global
+errno variable.
+
+   struct tevent_req *tsocket_connect_send(struct tsocket_context *sock,
+                                           TALLOC_CTX *mem_ctx,
+                                           const struct tsocket_address *dst);
+   int tsocket_connect_recv(struct tevent_req *req, int *perrno);
+
+To send an 'iovec' there's a wrapper for tsocket_writev().
+The caller calls tsocket_writev_send() instead of tsocket_writev()
+which returns a tevent_req allocated on the given TALLOC_CTX.
+The caller attaches a callback function to the returned tevent_req via
+tevent_req_set_callback(). The callback function is called when the whole iovec
+was deliviered into the socket or an error has happened.
+The callback function needs to get the result by calling
+tsocket_writev_recv(). The return value of tsocket_writev_recv()
+matches the return value from tsocket_writev(). A possible errno is delivered
+via the perrno parameter instead of the global errno variable.
+Normal callers should not use this function directly, they should use
+tsocket_writev_queue_send/recv() instead.
+
+   struct tevent_req *tsocket_writev_send(struct tsocket_context *sock,
+                                          TALLOC_CTX *mem_ctx,
+                                          const struct iovec *vector,
+                                          size_t count);
+   int tsocket_writev_recv(struct tevent_req *req, int *perrno);
+
+As only one async tsocket_writev() call should happen at a time,
+there's a 'tevent_queue' is used to serialize the writev requests.
+
+   struct tevent_req *tsocket_writev_queue_send(TALLOC_CTX *mem_ctx,
+                                                struct tsocket_context *sock,
+                                                struct tevent_queue *queue,
+                                                const struct iovec *vector,
+                                                size_t count);
+   int tsocket_writev_queue_recv(struct tevent_req *req, int *perrno);
+
+For TSOCKET_TYPE_STREAM sockets, it's typically desired to split the stream
+into PDUs. That's why the helper function for tsocket_readv() is a bit
+different compared to the other helper functions. The general rule
+is still to get a tevent_req, set a callback which gets called when the
+operation is done. The callback function needs to get the result by
+calling tsocket_readv_recv(). The 'next_iovec' callback function
+makes the difference to the other helper function.
+The tsocket_writev_send/recv() logic asks the caller via the
+next_iovec_fn for an iovec array, which will be filled completely
+with bytes from the socket, then the next_iovec_fn is called for
+the next iovec array to fill, untill the next_iovec_fn returns an empty
+iovec array. That next_iovec_fn should allocate the array as child of the
+passed mem_ctx, while the buffers the array referr to belong to the caller.
+The tsocket_writev_send/recv() engine will modify and free the given array!
+The basic idea is that the caller allocates and maintains the real buffers.
+The next_iovec_fn should report error by returning -1 and setting errno to
+the specific error code. The engine will pass the error to the caller
+via tsocket_readv_recv().
+
+typedef int (*tsocket_readv_next_iovec_t)(struct tsocket_context *sock,
+                                         void *private_data,
+                                         TALLOC_CTX *mem_ctx,
+                                         struct iovec **vector,
+                                         size_t *count);
+struct tevent_req *tsocket_readv_send(struct tsocket_context *sock,
+                                     TALLOC_CTX *mem_ctx,
+                                     tsocket_readv_next_iovec_t next_iovec_fn,
+                                     void *private_data);
+int tsocket_readv_recv(struct tevent_req *req, int *perrno);
+
+Wrapper for BSD style sockets
+=============================
+
+Support for BSD style sockets of AF_INET, AF_INET6 and AF_UNIX
+are part of the main tsocket library.
+
+To wrap an existing fd into a tsocket_context the function
+tsocket_context_bsd_wrap_existing() can be used.
+The caller needs to make sure the fd is marked as non-blocking!
+Normaly the tsocket_disconnect() function would close the fd,
+but the caller can influence this behavior based on the close_on_disconnect
+parameter. The caller should also make sure that the socket is only
+accessed via the tsocket_context wrapper after the call to
+tsocket_context_bsd_wrap_existing().
+
+   int tsocket_context_bsd_wrap_existing(TALLOC_CTX *mem_ctx,
+                                         int fd, bool close_on_disconnect,
+                                         struct tsocket_context **_sock);
+
+To create a tsocket_address for an inet address you need to use
+the tsocket_address_inet_from_strings() function. It takes the family
+as parameter which can be "ipv4", "ipv6" or "ip", where "ip" autodetects
+"ipv4" or "ipv6", based on the given address string. Depending on the
+operating system, "ipv6" may not be supported. Note: NULL as address
+is mapped to "0.0.0.0" or "::" based on the given family.
+The address parameter only accepts valid ipv4 or ipv6 address strings
+and no names! The caller need to resolve names before using this function.
+
+   int tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
+                                         const char *family,
+                                         const char *address,
+                                         uint16_t port,
+                                         struct tsocket_address **addr);
+
+To get the address of the inet tsocket_address as string the
+tsocket_address_inet_addr_string() function should be used.
+The caller should not try to parse the tsocket_address_string() output!
+
+   char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
+                                          TALLOC_CTX *mem_ctx);
+
+To get the port number of the inet tsocket_address the
+tsocket_address_inet_port() function should be used.
+The caller should not try to parse the tsocket_address_string() output!
+
+   uint16_t tsocket_address_inet_port(const struct tsocket_address *addr);
+
+To alter the port number of an inet tsocket_address the
+tsocket_address_inet_set_port() function can be used.
+This is usefull if the caller gets the address from
+tsocket_address_copy(), tsocket_context_remote_address() or
+tsocket_context_remote_address() instead of tsocket_address_inet_from_strings().
+
+   int tsocket_address_inet_set_port(struct tsocket_address *addr,
+                                     uint16_t port);
+
+If the caller wants to create a broadcast socket, with the SO_BROADCAST
+socket option, the broadcast option needs to be set with the
+tsocket_address_inet_set_broadcast() function before calling
+tsocket_address_create_socket().
+
+   void tsocket_address_inet_set_broadcast(struct tsocket_address *addr,
+                                           bool broadcast);
+
+To create a tsocket_address for AF_UNIX style sockets the
+tsocket_address_unix_from_path() should be used.
+NULL as path is handled like "".
+
+   int tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
+                                      const char *path,
+                                      struct tsocket_address **addr);
+
+To get the unix path of an existing unix tsocket_address
+the tsocket_address_unix_path() should be used.
+The caller should not try to parse the tsocket_address_string() output!
+
+   char *tsocket_address_unix_path(const struct tsocket_address *addr,
+                                   TALLOC_CTX *mem_ctx);
+