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 |
|