src/transport.h
branchnew-lib-errors
changeset 219 cefec18b8268
parent 218 5229a5d098b2
equal deleted inserted replaced
218:5229a5d098b2 219:cefec18b8268
     1 #ifndef TRANSPORT_H
       
     2 #define TRANSPORT_H
       
     3 
       
     4 /**
       
     5  * @file
       
     6  *
       
     7  * Defines a intermediate-level (as opposed to high-level or low-level) API for connected streams of data, presumeably
       
     8  * non-blocking ones.
       
     9  */
       
    10 #include "error.h"
       
    11 
       
    12 /**
       
    13  * Opaque transport state handle.
       
    14  *
       
    15  * Transports are reliable byte streams, connected with some endpoint over some medium. Common implementations are
       
    16  * e.g. TCP, SSL or fifo transports (using the OS file/socket API).
       
    17  *
       
    18  * Transports can be connected or unconnected. For synchronous opens (e.g. fifo_open_read()), the transport returned
       
    19  * will already be connected, meaning that the transport_callbacks::on_connect callback is unused. For async connects
       
    20  * such as sock_tcp_connect()/sock_ssl_connect(), the transport returned is *not* connected, and you must wait for
       
    21  * transport_callbacks::on_connect to be called before being able to send/recieve data on the transport.
       
    22  *
       
    23  * Once you have an opened transport, sending and receiving data is simple - just call transport_read()/transport_write().
       
    24  * These implement unbuffered I/O, so they may do partial reads/writes. In terms of the system read/write calls, the
       
    25  * main difference is in the error return codes. On EOF, instead of returning zero, they return ERR_EOF (or
       
    26  * ERR_WRITE_EOF for transport_write, for whoever knows what that means...). This means that when the underlying
       
    27  * transport is unable to fufill the request due to lack of data/buffer space, these can return zero to signifiy
       
    28  * something simliar to EAGAIN.
       
    29  *
       
    30  * The transport API also implements non-blocking/event-based operation (usually on top of libevent), although at a
       
    31  * slightly different level than the normal select/poll API. Instead of the user asking the transport to notify for
       
    32  * read/write after transport_read/transport_write return zero, the transport will take care of this itself. 
       
    33  * 
       
    34  * Specifically, the user can supply a mask of events they are currently interested in. By default, this should be the
       
    35  * full TRANSPORT_READ | TRANSPORT_WRITE, as the transport will take care of managing events by itself. If you wish to
       
    36  * e.g. throttle read/write, you may set a different event mask using transport_events(), which will prevent the
       
    37  * relevant callback from being triggered.
       
    38  *
       
    39  * For reads, the transport maintains a persistent read event, and will always call on_read when data is available on
       
    40  * the socket (i.e. normal select() semantics). If masked out using transport_events(), there should be no event
       
    41  * activity on the transport (i.e. the fd read event is removed).
       
    42  *
       
    43  * For writes, the transport maintains a write event that is disabled by default. If transport_write() returns zero, it will
       
    44  * become enabled *once*, and consequently trigger transport_callbacks::on_write *once*, after which you must call
       
    45  * transport_write() to possibly enable it again. If masked out using transport_events(), transport_write() will not
       
    46  * enable the write event, and any pending write event is cancelled. If masked back in using transport_events(), the
       
    47  * write event will *not* be registered, so if you have pending data, do a transport_write() after enabling
       
    48  * TRANSPORT_WRITE.
       
    49  *
       
    50  * Note that transport_write() returning fewer bytes than given will *not* enable the write event! You must call
       
    51  * transport_write() until you have either written all of your data, or it returns zero!
       
    52  */
       
    53 struct transport;
       
    54 
       
    55 /**
       
    56  * @see transport
       
    57  */
       
    58 typedef struct transport transport_t;
       
    59 
       
    60 /**
       
    61  * User callbacks for transports
       
    62  *
       
    63  * @see transport
       
    64  */
       
    65 struct transport_callbacks {
       
    66     /**
       
    67      * The transport is now connected
       
    68      */
       
    69     void (*on_connect) (transport_t *transport, void *arg);
       
    70 
       
    71     /**
       
    72      * Data is now available for reading from the transport
       
    73      */
       
    74     void (*on_read) (transport_t *transport, void *arg);
       
    75 
       
    76     /**
       
    77      * The transport has become writeable
       
    78      */
       
    79     void (*on_write) (transport_t *transport, void *arg);
       
    80 
       
    81     /**
       
    82      * An asynchronous error has occured. This is only called for errors that occur while being called directly from
       
    83      * the underlying event loop, and never from inside an API function.
       
    84      *
       
    85      * You must call transport_destroy to release the transport.
       
    86      */
       
    87     void (*on_error) (transport_t *transport, const error_t *err, void *arg);
       
    88 };
       
    89 
       
    90 /**
       
    91  * Bitmask of available events
       
    92  *
       
    93  * @see transport
       
    94  */
       
    95 enum transport_event {
       
    96     TRANSPORT_READ  = 0x01,
       
    97     TRANSPORT_WRITE = 0x02,
       
    98 };
       
    99 
       
   100 /**
       
   101  * User info required to build a transport
       
   102  *
       
   103  * @see transport
       
   104  */
       
   105 struct transport_info {
       
   106     /** The callbacks table */
       
   107     const struct transport_callbacks *cb_tbl;
       
   108 
       
   109     /** The callback context argument */
       
   110     void *cb_arg;
       
   111 
       
   112     /** Initial event mask using transport_event flags */
       
   113     short ev_mask;
       
   114 };
       
   115 
       
   116 /**
       
   117  * Read a series of bytes from the transport into the given \a buf (up to \a len bytes). If succesfull, this returns
       
   118  * the number of bytes read (which will be less than or equal to \a len). If the transport is nonblocking, and there is
       
   119  * no data available, this returns zero, and need not be called again until transport_callbacks::on_read is invoked.
       
   120  *
       
   121  * On errors, this returns the negative error code, and more info via \a err. Note that as opposed to read(2), EOF is
       
   122  * handled as an error, returning ERR_EOF.
       
   123  *
       
   124  * @param transport the transport state
       
   125  * @param buf the buffer to read the bytes into
       
   126  * @param len the number of bytes to read into the buffer
       
   127  * @param err returned error info
       
   128  * @return bytes read, zero if none available, -err_t
       
   129  */
       
   130 int transport_read (transport_t *transport, void *buf, size_t len, error_t *err);
       
   131 
       
   132 /**
       
   133  * Write a series of bytes from the given \a buf (containing \a len bytes) to the transport. If succesfull, this
       
   134  * returns the number of bytes written (which may be less than \a len). If the transport is nonblocking, and the
       
   135  * operation would have blocked, no data will be written, and zero is returned; in this case, the transport's write
       
   136  * event is enabled (unless TRANSPORT_WRITE is masked out).
       
   137  *
       
   138  * On errors, this returns the negative error code, along with extended info via \a err.
       
   139  *
       
   140  * @param transport the transport state
       
   141  * @param buf the buffer to write the bytes from
       
   142  * @param len number of bytes to write
       
   143  * @param err returned error info
       
   144  * @return bytes written, zero if would have blocked, -err_t
       
   145  */
       
   146 int transport_write (transport_t *transport, const void *buf, size_t len, error_t *err);
       
   147 
       
   148 /**
       
   149  * Change the mask of enabled events.
       
   150  */
       
   151 err_t transport_events (transport_t *transport, short mask);
       
   152 
       
   153 /**
       
   154  * Install a new set of callback handlers, replacing the old ones.
       
   155  */
       
   156 void transport_set_callbacks (transport_t *transport, const struct transport_callbacks *cb_tbl, void *cb_arg);
       
   157 
       
   158 /**
       
   159  * Close and destroy the transport immediately, severing any established connection rudely.
       
   160  *
       
   161  * This will release all resources associated with the transport, including the transport itself, which must not be
       
   162  * used anymore.
       
   163  */
       
   164 void transport_destroy (transport_t *transport);
       
   165 
       
   166 #endif