Mstdlib-1.24.0
m_io.h
1/* The MIT License (MIT)
2 *
3 * Copyright (c) 2017 Monetra Technologies, LLC.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#ifndef __M_IO_H__
25#define __M_IO_H__
26
27/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
28
29#include <mstdlib/base/m_defs.h>
30#include <mstdlib/base/m_types.h>
31#include <mstdlib/base/m_parser.h>
32#include <mstdlib/base/m_buf.h>
33
34/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
35
36__BEGIN_DECLS
37
38/*! \addtogroup m_io Common I/O functions
39 * \ingroup m_eventio
40 *
41 * Common IO functions
42 *
43 * @{
44 */
45
46/*! io type */
48 M_IO_TYPE_STREAM = 1, /*!< Object is a stream handle, can read and write */
49 M_IO_TYPE_WRITER = 2, /*!< Object is write only, such as a one-way pipe */
50 M_IO_TYPE_READER = 3, /*!< Object is read only, such as a one-way pipe */
51 M_IO_TYPE_LISTENER = 4, /*!< Object is a listener for acceptance of new connections */
52 M_IO_TYPE_EVENT = 5 /*!< Object just handles events, cannot connect, read or write */
53};
55
56
57/*! io object. */
58struct M_io;
59typedef struct M_io M_io_t;
60
61
62/*! io meta object. */
63struct M_io_meta;
64typedef struct M_io_meta M_io_meta_t;
65
66
67/*! io error. */
69 M_IO_ERROR_SUCCESS = 0, /*!< Success. No Error */
70 M_IO_ERROR_WOULDBLOCK = 1, /*!< Operation would block */
71 M_IO_ERROR_DISCONNECT = 2, /*!< Connection disconnected during operation */
72 M_IO_ERROR_ERROR = 3, /*!< Generic Undefined error occurred */
73 M_IO_ERROR_NOTCONNECTED = 4, /*!< Connection is not established, invalid operation */
74 M_IO_ERROR_NOTPERM = 5, /*!< Not a permitted action for this io object */
75 M_IO_ERROR_CONNRESET = 6, /*!< Connection was reset by peer */
76 M_IO_ERROR_CONNABORTED = 7, /*!< Connection aborted */
77 M_IO_ERROR_ADDRINUSE = 8, /*!< Address or Port already in use */
78 M_IO_ERROR_PROTONOTSUPPORTED = 9, /*!< Protocol not supported by OS */
79 M_IO_ERROR_CONNREFUSED = 10, /*!< Connection refused */
80 M_IO_ERROR_NETUNREACHABLE = 11, /*!< Network requested is unreachable */
81 M_IO_ERROR_TIMEDOUT = 12, /*!< Operation timed out at the OS level */
82 M_IO_ERROR_NOSYSRESOURCES = 13, /*!< System reported not enough resources */
83 M_IO_ERROR_INVALID = 14, /*!< Invalid use or order of operation */
84 M_IO_ERROR_NOTIMPL = 15, /*!< OS Does not implement the command or parameters */
85 M_IO_ERROR_NOTFOUND = 16, /*!< Host/File/Path not found */
86 M_IO_ERROR_BADCERTIFICATE = 17, /*!< Bad Peer Certificate (TLS) */
87/* Potential future errors
88 M_IO_ERROR_AUTHFAILED -- could be used by proxies, maybe others
89 M_IO_ERROR_BADCERTIFICATE -- Certificate verification failure, ssl
90*/
91 M_IO_ERROR_INTERRUPTED = 99 /*!< Should never be returned to a user */
92};
94
95
96/*! io state. */
98 M_IO_STATE_INIT = 0, /*!< Initializing, not yet prompted to start connecting */
99 M_IO_STATE_LISTENING = 1, /*!< Listening for a client connection */
100 M_IO_STATE_CONNECTING = 2, /*!< Attempting to establish a connection */
101 M_IO_STATE_CONNECTED = 3, /*!< Connected */
102 M_IO_STATE_DISCONNECTING = 4, /*!< In-progress graceful disconnect */
103 M_IO_STATE_DISCONNECTED = 5, /*!< Connection Closed/Disconnected */
104 M_IO_STATE_ERROR = 6 /*!< Connection in error state (not connected) */
107
108
109/*! Passed to M_io_layer_acquire() to search for matching layer by name */
110#define M_IO_LAYER_FIND_FIRST_ID SIZE_MAX
111
112
113/*! Convert an error code to a string.
114 *
115 * \param[in] error Error code.
116 *
117 * \return String description.
118 */
119M_API const char *M_io_error_string(M_io_error_t error);
120
121
122/*! Create an io meta data object.
123 *
124 * \return io meta data object.
125 */
127
128
129/*! Destory an io meta data object.
130 *
131 * \param[in] meta meta data object.
132 */
134
135
136/*! Read from an io object.
137 *
138 * \param[in] comm io object.
139 * \param[out] buf Buffer to store data read from io object.
140 * \param[in] buf_len Lenght of provided buffer.
141 * \param[out] len_read Number of bytes fread from the io object.
142 *
143 * \return Result.
144 *
145 * \see M_io_read_meta
146 */
147M_API M_io_error_t M_io_read(M_io_t *comm, unsigned char *buf, size_t buf_len, size_t *len_read);
148
149
150/*! Read from an io object into an M_buf_t.
151 *
152 * This will read all available data into the buffer.
153 *
154 * \param[in] comm io object.
155 * \param[out] buf Buffer to store data read from io object.
156 *
157 * \return Result.
158 *
159 * \see M_io_read_into_buf_meta
160 */
162
163
164/*! Read from an io object into an M_parser_t.
165 *
166 * This will read all available data into the buffer.
167 *
168 * \param[in] comm io object.
169 * \param[out] parser Parser to store data read from io object.
170 *
171 * \return Result.
172 *
173 * \see M_io_read_into_parser_meta
174 */
176
177
178/*! Read from an io object with a meta data object.
179 *
180 * \param[in] comm io object.
181 * \param[out] buf Buffer to store data read from io object.
182 * \param[in] buf_len Lenght of provided buffer.
183 * \param[out] len_read Number of bytes fread from the io object.
184 * \param[in] meta Meta data object.
185 *
186 * \return Result.
187 *
188 * \see M_io_read
189 */
190M_API M_io_error_t M_io_read_meta(M_io_t *comm, unsigned char *buf, size_t buf_len, size_t *len_read, M_io_meta_t *meta);
191
192
193/*! Read from an io object into an M_buf_t with a meta data object.
194 *
195 * This will read all available data into the buffer.
196 *
197 * \param[in] comm io object.
198 * \param[out] buf Buffer to store data read from io object.
199 * \param[in] meta Meta data object.
200 *
201 * \return Result.
202 *
203 * \see M_io_read_into_buf
204 */
206
207
208/*! Read from an io object into an M_parser_t with a meta data object.
209 *
210 * This will read all available data into the buffer.
211 *
212 * \param[in] comm io object.
213 * \param[out] parser Parser to store data read from io object.
214 * \param[in] meta Meta data object.
215 *
216 * \return Result.
217 *
218 * \see M_io_read_into_parser
219 */
221
222
223/*! Clear/Flush the read buffer to consume all data and dispose of it.
224 *
225 * \param[in] io io object
226 * \return M_IO_ERROR_SUCCESS if data was flushed and the connection is still
227 * active. M_IO_ERROR_WOULDBLOCK if no data to flush, otherwise one
228 * of the additional errors if the connection failed.
229 */
231
232
233/*! Write data to an io object.
234 *
235 * This function will attempt to write as much data as possible. If not all data
236 * is written the application should wait until the next write event and then try
237 * writing more data.
238 *
239 * \param[in] comm io object.
240 * \param[in] buf Buffer to write from.
241 * \param[in] buf_len Number of bytes in buffer to write.
242 * \param[out] len_written Number of bytes from the buffer written.
243 *
244 * \return Result.
245 *
246 * \see M_io_write_meta
247 */
248M_API M_io_error_t M_io_write(M_io_t *comm, const unsigned char *buf, size_t buf_len, size_t *len_written);
249
250
251/*! Write data to an io object from an M_buf_t.
252 *
253 * This function will attempt to write as much data as possible. If not all data
254 * is written the application should wait until the next write event and then try
255 * writing more data.
256 *
257 * \param[in] comm io object.
258 * \param[in] buf Buffer to write from.
259 *
260 * \return Result.
261 *
262 * \see M_io_write_from_buf_meta
263 */
265
266
267/*! Write data to an io object with a meta data object.
268 *
269 * This function will attempt to write as much data as possible. If not all data
270 * is written the application should wait until the next write event and then try
271 * writing more data.
272 *
273 * \param[in] comm io object.
274 * \param[in] buf Buffer to write from.
275 * \param[in] buf_len Number of bytes in buffer to write.
276 * \param[out] len_written Number of bytes from the buffer written.
277 * \param[in] meta Meta data object.
278 *
279 * \return Result.
280 *
281 * \see M_io_write
282 */
283M_API M_io_error_t M_io_write_meta(M_io_t *comm, const unsigned char *buf, size_t buf_len, size_t *len_written, M_io_meta_t *meta);
284
285
286/*! Write data to an io object from an M_buf_t with a meta data object.
287 *
288 * This function will attempt to write as much data as possible. If not all data
289 * is written the application should wait until the next write event and then try
290 * writing more data.
291 *
292 * \param[in] comm io object.
293 * \param[in] buf Buffer to write from.
294 * \param[in] meta Meta data object.
295 *
296 * \return Result.
297 *
298 * \see M_io_write_from_buf
299 */
301
302
303/*! Accept an io connection.
304 *
305 * Typically used with network io when a connection is setup as a listening socket.
306 * The io object will remain valid and a new io object for the connection will be created.
307 *
308 * A return of M_IO_ERROR_WOULDBLOCK should not be treated as an error. It means either
309 * there is more data that needs to be received and the event will trigger again. Or
310 * there is no more outstanding connections waiting to be accepted.
311 *
312 * Example:
313 *
314 * void ipserver_listen_callback(M_event_t *el, M_event_type_t type, M_io_t *io, void *thunk)
315 * {
316 * M_io_t *io_out = NULL;
317 * M_io_error_t ioerr;
318 *
319 * (void)thunk;
320 *
321 * if (type != M_EVENT_TYPE_ACCEPT)
322 * return;
323 *
324 * ioerr = M_io_accept(&io_out, io);
325 * if (ioerr != M_IO_ERROR_SUCCESS || io_out == NULL) {
326 * if (ioerr != M_IO_ERROR_WOULDBLOCK) {
327 * // Connection error
328 * }
329 * return;
330 * }
331 *
332 * M_event_add(el, io_out, ipserver_connection_callback, NULL);
333 * }
334 *
335 * \param[out] io_out io object created from the accept.
336 * \param[in] server_io io object which was listening.
337 *
338 * \return Result.
339 */
340M_API M_io_error_t M_io_accept(M_io_t **io_out, M_io_t *server_io);
341
342
343/*! Current state of an io object
344 *
345 * \param[in] io io object;
346 *
347 * \return State.
348 */
350
351
352/*! Current state of a layer within an io object
353 *
354 * \param[in] io io object
355 * \param[in] id id of a layer to query (0 for base layer)
356 *
357 * \return State.
358 */
360
361
362/*! Retrieve the number of layers from an io object
363 *
364 * \param[in] io io object
365 *
366 * \return count of layers in object
367 */
368M_API size_t M_io_layer_count(M_io_t *io);
369
370
371/*! Retrieve the name of the layer at the specified index.
372 *
373 * \param[in] io io object
374 * \param[in] idx index of layer (0 - M_io_layer_count())
375 * \return internal name of layer in string form
376 */
377M_API const char *M_io_layer_name(M_io_t *io, size_t idx);
378
379/*! Get the last error associated with the io object.
380 *
381 * \param[in] io io object.
382 * \return an M_io_error_t error
383 */
385
386
387/*! Get a textual error message associated with the io object.
388 *
389 * This message is populated by the layer that reported the error. The message
390 * could come from an external library such as an TLS library. It is meant
391 * to be a human readable description and should not be used programmatically.
392 *
393 * \param[in] io io object.
394 * \param[out] error Error buffer.
395 * \param[in] err_len Size of error buffer.
396 */
397M_API void M_io_get_error_string(M_io_t *io, char *error, size_t err_len);
398
399
400/*! Request system to tear down existing connection and reconnect using the same
401 * configuration and layers as are currently in use. Will preserve existing
402 * event handle and callbacks.
403 *
404 * \param[in] io io object.
405 * \return M_TRUE if object can be reconnected, M_FALSE if cannot be. This
406 * returning M_TRUE does NOT mean the reconnect itself was successful, must
407 * still wait for CONNECT or ERROR event.
408 */
409M_API M_bool M_io_reconnect(M_io_t *io);
410
411
412/*! Gracefully issue a disconnect to the communications object, a DISCONNECTED (or ERROR)
413 * event will be triggered when complete.
414 *
415 * \param[in] comm io object.
416 */
417M_API void M_io_disconnect(M_io_t *comm);
418
419
420/*! Forcibly close the io object without destroying the entire object. If the connection
421 * is still active, this will perform a dirty disconnect (not recommended).
422 *
423 * This is primarily used after receiving a disconnect or error event with the anticipation
424 * of performing a reconnect at some point in the future, but not immediately.
425 *
426 * This will detach from the event subsystem and clean up the OS handles.
427 *
428 * \param[in] comm io object.
429 *
430 * \return M_FALSE on error, M_TRUE on success.
431 */
432M_API M_bool M_io_close(M_io_t *comm);
433
434
435/*! Query if disconnect/error might have been generated by a call to M_io_disconnect()
436 * rather than triggered by a system-level event.
437 *
438 * This might be useful for things like HTTP connections where we can M_io_reconnect()
439 * after a remote disconnect.
440 *
441 * \param[in] io io object.
442 * \return M_TRUE if disconnect/error was triggered by M_io_disconnecT(), M_FALSE otherwise.
443 */
445
446
447/*! Destroy any communications object.
448 *
449 * This can be called from a different thread than the thread the event loop the io object
450 * is running on. When this happens the destroy is queued and will happen once the event loop
451 * the io object is associated with has finished processing all queued events.
452 *
453 * \param[in] comm io object.
454 */
455M_API void M_io_destroy(M_io_t *comm);
456
457/*! @} */
458
459__END_DECLS
460
461#endif /* __M_IO_H__ */
struct M_buf M_buf_t
Definition: m_buf.h:77
void M_io_disconnect(M_io_t *comm)
M_io_error_t M_io_write_from_buf_meta(M_io_t *comm, M_buf_t *buf, M_io_meta_t *meta)
M_io_error_t M_io_read_into_parser(M_io_t *comm, M_parser_t *parser)
void M_io_destroy(M_io_t *comm)
M_io_error_t M_io_read_into_buf(M_io_t *comm, M_buf_t *buf)
M_io_error_t M_io_read_meta(M_io_t *comm, unsigned char *buf, size_t buf_len, size_t *len_read, M_io_meta_t *meta)
M_io_error
Definition: m_io.h:68
enum M_io_error M_io_error_t
Definition: m_io.h:93
M_io_state_t M_io_get_layer_state(M_io_t *io, size_t id)
void M_io_get_error_string(M_io_t *io, char *error, size_t err_len)
M_io_error_t M_io_read_into_parser_meta(M_io_t *comm, M_parser_t *parser, M_io_meta_t *meta)
M_io_error_t M_io_write_meta(M_io_t *comm, const unsigned char *buf, size_t buf_len, size_t *len_written, M_io_meta_t *meta)
M_io_state
Definition: m_io.h:97
M_bool M_io_reconnect(M_io_t *io)
M_io_error_t M_io_accept(M_io_t **io_out, M_io_t *server_io)
void M_io_meta_destroy(M_io_meta_t *meta)
enum M_io_type M_io_type_t
Definition: m_io.h:54
const char * M_io_layer_name(M_io_t *io, size_t idx)
struct M_io M_io_t
Definition: m_io.h:59
M_bool M_io_is_user_initiated_disconnect(M_io_t *io)
M_io_error_t M_io_read_clear(M_io_t *io)
M_io_meta_t * M_io_meta_create(void)
M_io_error_t M_io_write_from_buf(M_io_t *comm, M_buf_t *buf)
struct M_io_meta M_io_meta_t
Definition: m_io.h:64
M_bool M_io_close(M_io_t *comm)
M_io_error_t M_io_read(M_io_t *comm, unsigned char *buf, size_t buf_len, size_t *len_read)
const char * M_io_error_string(M_io_error_t error)
size_t M_io_layer_count(M_io_t *io)
M_io_error_t M_io_read_into_buf_meta(M_io_t *comm, M_buf_t *buf, M_io_meta_t *meta)
M_io_state_t M_io_get_state(M_io_t *io)
M_io_error_t M_io_get_error(M_io_t *io)
enum M_io_state M_io_state_t
Definition: m_io.h:106
M_io_type
Definition: m_io.h:47
M_io_error_t M_io_write(M_io_t *comm, const unsigned char *buf, size_t buf_len, size_t *len_written)
@ M_IO_ERROR_DISCONNECT
Definition: m_io.h:71
@ M_IO_ERROR_NOTPERM
Definition: m_io.h:74
@ M_IO_ERROR_SUCCESS
Definition: m_io.h:69
@ M_IO_ERROR_NOTIMPL
Definition: m_io.h:84
@ M_IO_ERROR_WOULDBLOCK
Definition: m_io.h:70
@ M_IO_ERROR_CONNABORTED
Definition: m_io.h:76
@ M_IO_ERROR_CONNRESET
Definition: m_io.h:75
@ M_IO_ERROR_BADCERTIFICATE
Definition: m_io.h:86
@ M_IO_ERROR_PROTONOTSUPPORTED
Definition: m_io.h:78
@ M_IO_ERROR_TIMEDOUT
Definition: m_io.h:81
@ M_IO_ERROR_CONNREFUSED
Definition: m_io.h:79
@ M_IO_ERROR_INTERRUPTED
Definition: m_io.h:91
@ M_IO_ERROR_NOSYSRESOURCES
Definition: m_io.h:82
@ M_IO_ERROR_NOTCONNECTED
Definition: m_io.h:73
@ M_IO_ERROR_INVALID
Definition: m_io.h:83
@ M_IO_ERROR_ADDRINUSE
Definition: m_io.h:77
@ M_IO_ERROR_NOTFOUND
Definition: m_io.h:85
@ M_IO_ERROR_ERROR
Definition: m_io.h:72
@ M_IO_ERROR_NETUNREACHABLE
Definition: m_io.h:80
@ M_IO_STATE_CONNECTED
Definition: m_io.h:101
@ M_IO_STATE_LISTENING
Definition: m_io.h:99
@ M_IO_STATE_CONNECTING
Definition: m_io.h:100
@ M_IO_STATE_INIT
Definition: m_io.h:98
@ M_IO_STATE_ERROR
Definition: m_io.h:104
@ M_IO_STATE_DISCONNECTED
Definition: m_io.h:103
@ M_IO_STATE_DISCONNECTING
Definition: m_io.h:102
@ M_IO_TYPE_EVENT
Definition: m_io.h:52
@ M_IO_TYPE_READER
Definition: m_io.h:50
@ M_IO_TYPE_WRITER
Definition: m_io.h:49
@ M_IO_TYPE_LISTENER
Definition: m_io.h:51
@ M_IO_TYPE_STREAM
Definition: m_io.h:48
struct M_parser M_parser_t
Definition: m_parser.h:52