Mstdlib-1.24.0

Modules

 DNS Functions
 
 Network Interface Enumeration
 

Typedefs

typedef enum M_io_net_type M_io_net_type_t
 

Enumerations

enum  M_io_net_type {
  M_IO_NET_ANY = 1 ,
  M_IO_NET_IPV4 = 2 ,
  M_IO_NET_IPV6 = 3
}
 

Functions

M_io_error_t M_io_net_server_create (M_io_t **io_out, unsigned short port, const char *bind_ip, M_io_net_type_t type)
 
M_io_error_t M_io_net_client_create (M_io_t **io_out, M_dns_t *dns, const char *host, unsigned short port, M_io_net_type_t type)
 
M_bool M_io_net_set_keepalives (M_io_t *io, M_uint64 idle_time_s, M_uint64 retry_time_s, M_uint64 retry_cnt)
 
M_bool M_io_net_set_nagle (M_io_t *io, M_bool nagle_enabled)
 
M_bool M_io_net_set_connect_timeout_ms (M_io_t *io, M_uint64 timeout_ms)
 
char * M_io_net_get_fqdn (void)
 
const char * M_io_net_get_host (M_io_t *io)
 
const char * M_io_net_get_ipaddr (M_io_t *io)
 
const char * M_io_net_get_server_ipaddr (M_io_t *io)
 
unsigned short M_io_net_get_port (M_io_t *io)
 
unsigned short M_io_net_get_ephemeral_port (M_io_t *io)
 
enum M_io_net_type M_io_net_get_type (M_io_t *io)
 
M_uint64 M_io_net_get_connect_timeout_ms (M_io_t *io)
 
M_uint64 M_io_net_time_dns_ms (M_io_t *io)
 
M_uint64 M_io_net_time_connect_ms (M_io_t *io)
 
M_bool M_io_net_ipaddr_to_bin (unsigned char *ipaddr_bin, size_t ipaddr_bin_size, const char *ipaddr_str, size_t *ipaddr_bin_len)
 
M_bool M_io_net_bin_to_ipaddr (char *ipaddr_str, size_t ipaddr_str_size, const unsigned char *ipaddr_bin, size_t ipaddr_bin_len)
 

Detailed Description

Network I/O functions

Capable of functioning as a network server and client.

Examples

Client

Example network client which downloads google.com's home page. This uses a network client connection wrapped in TLS. A trace layer is provided and is commented out.

#include <mstdlib/mstdlib.h>
#include <mstdlib/mstdlib_io.h>
#include <mstdlib/mstdlib_tls.h>
static void do_trace(void *cb_arg, M_io_trace_type_t type, M_event_type_t event_type, const unsigned char *data, size_t data_len)
{
char *out;
switch (type) {
M_printf("READ:\n");
break;
M_printf("WRITE:\n");
break;
default:
return;
}
out = M_str_hexdump(M_STR_HEXDUMP_HEADER, 0, "\t", data, data_len);
M_printf("%s\n", out);
M_free(out);
}
static void run_cb(M_event_t *el, M_event_type_t etype, M_io_t *io, void *thunk)
{
M_buf_t *connected_buf = thunk;
char buf[128] = { 0 };
size_t len_written = 0;
switch (etype) {
M_printf("CONNECTED: %s%s%s:%d (%s: %s - session%sreused)\n",
M_io_write_from_buf(io, connected_buf);
break;
M_io_read(io, (unsigned char *)buf, sizeof(buf), &len_written);
if (len_written > 0) {
M_printf("%.*s", (int)len_written, buf);
}
break;
M_io_write_from_buf(io, connected_buf);
break;
break;
break;
}
}
int main(int argc, char **argv)
{
M_event_t *el;
M_dns_t *dns;
M_buf_t *buf;
M_io_t *io;
size_t layer_id;
dns = M_dns_create();
buf = M_buf_create();
M_buf_add_str(buf, "GET / HTTP/1.1\r\n");
M_buf_add_str(buf, "Host: www.google.com\r\n");
M_buf_add_str(buf, "Connection: close\r\n");
M_buf_add_str(buf, "\r\n");
M_io_net_client_create(&io, dns, "google.com", 443, M_IO_NET_ANY);
M_io_tls_client_add(io, ctx, NULL, &layer_id);
//M_io_add_trace(io, &layer_id, do_trace, NULL, NULL, NULL);
M_event_add(el, io, run_cb, buf);
M_event_loop(el, M_TIMEOUT_INF);
return 0;
}
struct M_buf M_buf_t
Definition: m_buf.h:77
M_buf_t * M_buf_create(void) M_WARN_UNUSED_RESULT M_MALLOC
void M_buf_add_str(M_buf_t *buf, const char *str)
void M_buf_cancel(M_buf_t *buf) M_FREE(1)
M_bool M_dns_destroy(M_dns_t *dns)
struct M_dns M_dns_t
Definition: m_dns.h:43
M_dns_t * M_dns_create(M_event_t *event)
void M_event_destroy(M_event_t *event)
enum M_event_type M_event_type_t
Definition: m_event.h:189
struct M_event M_event_t
Definition: m_event.h:210
M_bool M_event_add(M_event_t *event, M_io_t *io, M_event_callback_t callback, void *cb_data)
void M_event_done(M_event_t *event)
M_event_err_t M_event_loop(M_event_t *event, M_uint64 timeout_ms)
M_event_t * M_event_create(M_uint32 flags)
void M_event_done_with_disconnect(M_event_t *event, M_uint64 timeout_before_disconnect_ms, M_uint64 disconnect_timeout_ms)
@ M_EVENT_TYPE_WRITE
Definition: m_event.h:184
@ M_EVENT_TYPE_ACCEPT
Definition: m_event.h:174
@ M_EVENT_TYPE_DISCONNECTED
Definition: m_event.h:176
@ M_EVENT_TYPE_OTHER
Definition: m_event.h:185
@ M_EVENT_TYPE_READ
Definition: m_event.h:175
@ M_EVENT_TYPE_CONNECTED
Definition: m_event.h:173
@ M_EVENT_TYPE_ERROR
Definition: m_event.h:181
@ M_EVENT_FLAG_NONE
Definition: m_event.h:232
ssize_t M_printf(const char *fmt,...)
unsigned short M_io_net_get_port(M_io_t *io)
enum M_io_net_type M_io_net_get_type(M_io_t *io)
M_io_error_t M_io_net_client_create(M_io_t **io_out, M_dns_t *dns, const char *host, unsigned short port, M_io_net_type_t type)
const char * M_io_net_get_ipaddr(M_io_t *io)
@ M_IO_NET_ANY
Definition: m_io_net.h:336
@ M_IO_NET_IPV6
Definition: m_io_net.h:338
enum M_io_trace_type M_io_trace_type_t
Definition: m_io_trace.h:54
@ M_IO_TRACE_TYPE_READ
Definition: m_io_trace.h:50
@ M_IO_TRACE_TYPE_WRITE
Definition: m_io_trace.h:51
void M_io_destroy(M_io_t *comm)
struct M_io M_io_t
Definition: m_io.h:59
M_io_error_t M_io_write_from_buf(M_io_t *comm, M_buf_t *buf)
M_io_error_t M_io_read(M_io_t *comm, unsigned char *buf, size_t buf_len, size_t *len_read)
#define M_IO_LAYER_FIND_FIRST_ID
Definition: m_io.h:110
void M_free(void *ptr) M_FREE(1)
char * M_str_hexdump(int flags, size_t bytes_per_line, const char *line_prefix, const unsigned char *data, size_t data_len)
@ M_STR_HEXDUMP_HEADER
Definition: m_str.h:1875
M_bool M_tls_clientctx_set_default_trust(M_tls_clientctx_t *ctx)
const char * M_tls_get_cipher(M_io_t *io, size_t id)
const char * M_tls_protocols_to_str(M_tls_protocols_t protocol)
M_bool M_tls_get_sessionreused(M_io_t *io, size_t id)
M_tls_clientctx_t * M_tls_clientctx_create(void)
struct M_tls_clientctx M_tls_clientctx_t
Definition: m_tls.h:45
M_tls_protocols_t M_tls_get_protocol(M_io_t *io, size_t id)
M_io_error_t M_io_tls_client_add(M_io_t *io, M_tls_clientctx_t *ctx, const char *hostname, size_t *layer_id)
void M_tls_clientctx_destroy(M_tls_clientctx_t *ctx)

Server

Example network sever. This is an echo server which uses a state machine to determine what operation it should perform.

#include <mstdlib/mstdlib.h>
#include <mstdlib/mstdlib_io.h>
typedef enum {
STATE_CHECK = 1,
STATE_ECHO,
STATE_EXIT
} states_t;
typedef struct {
M_buf_t *write_buf;
M_parser_t *read_parser;
M_io_t *io;
M_event_t *el;
} ldata_t;
static M_state_machine_status_t state_check(void *data, M_uint64 *next)
{
ldata_t *ldata = data;
(void)next;
M_parser_mark(ldata->read_parser);
if (M_parser_len(ldata->read_parser) == 0 || M_parser_consume_until(ldata->read_parser, (const unsigned char *)"\n", 1, M_TRUE) == 0) {
M_parser_mark_rewind(ldata->read_parser);
}
}
static M_state_machine_status_t state_echo(void *data, M_uint64 *next)
{
ldata_t *ldata = data;
char *out;
out = M_parser_read_strdup_mark(ldata->read_parser);
M_buf_add_str(ldata->write_buf, out);
M_io_write_from_buf(ldata->io, ldata->write_buf);
if (!M_str_eq(out, "EXIT\r\n") && !M_str_eq(out, "EXIT\n"))
*next = STATE_CHECK;
M_free(out);
}
static M_state_machine_status_t state_exit(void *data, M_uint64 *next)
{
ldata_t *ldata = data;
(void)next;
M_event_done_with_disconnect(ldata->el, 0, 1000);
}
static void connection_cb(M_event_t *el, M_event_type_t etype, M_io_t *io, void *thunk)
{
ldata_t *ldata = thunk;
char error[256] = { 0 };
M_bool clean = M_FALSE;
switch (etype) {
M_printf("CLIENT CONNECTED: %s%s%s:%d\n",
break;
if (M_io_read_into_parser(io, ldata->read_parser) == M_IO_ERROR_SUCCESS) {
status = M_state_machine_run(ldata->sm, ldata);
if (status != M_STATE_MACHINE_STATUS_WAIT) {
}
}
break;
if (M_buf_len(ldata->write_buf) > 0) {
M_io_write_from_buf(io, ldata->write_buf);
}
break;
clean = M_TRUE;
if (!clean) {
M_io_get_error_string(io, error, sizeof(error));
}
M_printf("CLIENT DISCONNECTED: %s%s%s:%d (%s%s%s)\n",
clean?"clean":"unclean", clean?"":" - ", clean?"":error);
M_buf_cancel(ldata->write_buf);
M_parser_destroy(ldata->read_parser);
M_free(ldata);
break;
}
}
static void listen_cb(M_event_t *el, M_event_type_t etype, M_io_t *io, void *thunk)
{
M_io_t *io_out = NULL;
ldata_t *ldata;
M_io_error_t ioerr;
char error[256] = { 0 };
(void)thunk;
switch (etype) {
ioerr = M_io_accept(&io_out, io);
if (ioerr == M_IO_ERROR_WOULDBLOCK) {
return;
} else if (ioerr != M_IO_ERROR_SUCCESS || io_out == NULL) {
M_io_get_error_string(io, error, sizeof(error));
M_printf("ACCEPT FAILURE: %s\n", error);
M_io_destroy(io_out);
}
ldata = M_malloc_zero(sizeof(*ldata));
ldata->el = el;
ldata->write_buf = M_buf_create();
ldata->read_parser = M_parser_create(M_PARSER_FLAG_NONE);
ldata->io = io_out;
M_state_machine_insert_state(ldata->sm, STATE_CHECK, 0, NULL, state_check, NULL, NULL);
M_state_machine_insert_state(ldata->sm, STATE_ECHO, 0, NULL, state_echo, NULL, NULL);
M_state_machine_insert_state(ldata->sm, STATE_EXIT, 0, NULL, state_exit, NULL, NULL);
M_event_add(el, io_out, connection_cb, ldata);
break;
break;
break;
}
}
int main(int argc, char *argv)
{
M_event_t *el;
M_io_t *io = NULL;
M_io_error_t ioerr;
ioerr = M_io_net_server_create(&io, 8999, NULL, M_IO_NET_IPV4);
if (ioerr != M_IO_ERROR_SUCCESS) {
M_printf("Could not start server: %s\n", M_io_error_string(ioerr));
return 0;
}
M_event_add(el, io, listen_cb, NULL);
M_event_loop(el, M_TIMEOUT_INF);
return 0;
}
size_t M_buf_len(const M_buf_t *buf)
M_io_error_t M_io_net_server_create(M_io_t **io_out, unsigned short port, const char *bind_ip, M_io_net_type_t type)
@ M_IO_NET_IPV4
Definition: m_io_net.h:337
void M_io_disconnect(M_io_t *comm)
M_io_error_t M_io_read_into_parser(M_io_t *comm, M_parser_t *parser)
enum M_io_error M_io_error_t
Definition: m_io.h:93
void M_io_get_error_string(M_io_t *io, char *error, size_t err_len)
M_io_error_t M_io_accept(M_io_t **io_out, M_io_t *server_io)
const char * M_io_error_string(M_io_error_t error)
@ M_IO_ERROR_SUCCESS
Definition: m_io.h:69
@ M_IO_ERROR_WOULDBLOCK
Definition: m_io.h:70
void * M_malloc_zero(size_t size) M_ALLOC_SIZE(1) M_WARN_UNUSED_RESULT M_MALLOC
size_t M_parser_len(const M_parser_t *parser)
void M_parser_destroy(M_parser_t *parser)
struct M_parser M_parser_t
Definition: m_parser.h:52
char * M_parser_read_strdup_mark(M_parser_t *parser)
M_parser_t * M_parser_create(M_uint32 flags)
size_t M_parser_mark_rewind(M_parser_t *parser)
void M_parser_mark(M_parser_t *parser)
size_t M_parser_consume_until(M_parser_t *parser, const unsigned char *pat, size_t len, M_bool eat_pat)
@ M_PARSER_FLAG_NONE
Definition: m_parser.h:60
M_state_machine_status_t M_state_machine_run(M_state_machine_t *m, void *data)
M_bool M_state_machine_insert_state(M_state_machine_t *m, M_uint64 id, M_uint64 ndescr, const char *descr, M_state_machine_state_cb func, M_state_machine_cleanup_t *cleanup, M_list_u64_t *next_ids)
M_state_machine_t * M_state_machine_create(M_uint64 ndescr, const char *descr, M_uint32 flags)
M_state_machine_status_t
Definition: m_state_machine.h:565
struct M_state_machine M_state_machine_t
Definition: m_state_machine.h:556
void M_state_machine_destroy(M_state_machine_t *m)
@ M_STATE_MACHINE_NONE
Definition: m_state_machine.h:633
@ M_STATE_MACHINE_STATUS_WAIT
Definition: m_state_machine.h:598
@ M_STATE_MACHINE_STATUS_NEXT
Definition: m_state_machine.h:568
M_bool M_str_eq(const char *s1, const char *s2)

Typedef Documentation

◆ M_io_net_type_t

Enumeration Type Documentation

◆ M_io_net_type

IP connection type.

Enumerator
M_IO_NET_ANY 

Either ipv4 or ipv6

M_IO_NET_IPV4 

ipv4 only

M_IO_NET_IPV6 

ipv6 only

Function Documentation

◆ M_io_net_server_create()

M_io_error_t M_io_net_server_create ( M_io_t **  io_out,
unsigned short  port,
const char *  bind_ip,
M_io_net_type_t  type 
)

Create a server listener net object.

Parameters
[out]io_outio object for communication.
[in]portPort to listen on. If 0 is used, the OS will assign an unused port which can be retrieved immediately after successful return of this function via M_io_net_get_port().
[in]bind_ipNULL to listen on all interfaces, or an explicit ip address to listen on. Note that listening on localhost ::1 will be ipv6 only, or localhost 127.0.0.1 will be ipv4 only.
[in]typeConnection type.
Returns
Result.

◆ M_io_net_client_create()

M_io_error_t M_io_net_client_create ( M_io_t **  io_out,
M_dns_t dns,
const char *  host,
unsigned short  port,
M_io_net_type_t  type 
)

Create a client net object.

Parameters
[out]io_outio object for communication.
[in]dnsDNS object for host name lookup. Required. It will be reference counted allowing it to be destroyed while still in use by the io object.
[in]hostHost to connect to. Can be a host name or ip address.
[in]portPort to connect to.
[in]typeConnection type.
Returns
Result.

◆ M_io_net_set_keepalives()

M_bool M_io_net_set_keepalives ( M_io_t io,
M_uint64  idle_time_s,
M_uint64  retry_time_s,
M_uint64  retry_cnt 
)

Set keep alive.

Parameters
[in]ioio object.
[in]idle_time_sIdle time in seconds.
[in]retry_time_sRetry time in seconds.
[in]retry_cntRetry count.
Returns
M_TRUE on success, otherwise M_FALSE on failure.

◆ M_io_net_set_nagle()

M_bool M_io_net_set_nagle ( M_io_t io,
M_bool  nagle_enabled 
)

Enable/disable Nagle algorithm.

Parameters
[in]ioio object.
[in]nagle_enabledM_TRUE to enable, M_FALSE to disable.
Returns
M_TRUE on success, otherwise M_FALSE on error. Will return M_TRUE if state being set is the same as already set. Meaning, enabling on an io that already has it enabled will return success.

◆ M_io_net_set_connect_timeout_ms()

M_bool M_io_net_set_connect_timeout_ms ( M_io_t io,
M_uint64  timeout_ms 
)

Set connect timeout.

This is the timeout to wait for a connection to finish.

Parameters
[in]ioio object.
[in]timeout_msTimeout in milliseconds.
Returns
M_TRUE on success, otherwise M_FALSE on error.

◆ M_io_net_get_fqdn()

char * M_io_net_get_fqdn ( void  )

Get the Fully Qualified Domain Name.

Returns
String.

◆ M_io_net_get_host()

const char * M_io_net_get_host ( M_io_t io)

Get the hostname of the connected endpoint.

This may return an IP address for inbound connections, or for outbound connections where an ip address was passed. This will not do a reverse hostname lookup.

Parameters
[in]ioio object.
Returns
String.

◆ M_io_net_get_ipaddr()

const char * M_io_net_get_ipaddr ( M_io_t io)

Get the IP address of the connected endpoint.

Parameters
[in]ioio object.
Returns
String.

◆ M_io_net_get_server_ipaddr()

const char * M_io_net_get_server_ipaddr ( M_io_t io)

Get the IP address of the server interface the end point connected to.

Parameters
[in]ioio object.
Returns
String.

◆ M_io_net_get_port()

unsigned short M_io_net_get_port ( M_io_t io)

Get the port of the connected endpoint.

Parameters
[in]ioio object.
Returns
Port.

◆ M_io_net_get_ephemeral_port()

unsigned short M_io_net_get_ephemeral_port ( M_io_t io)

Get the ephemeral (dynamic) port of the connected endpoint

Parameters
[in]ioio object.
Returns
Port.

◆ M_io_net_get_type()

enum M_io_net_type M_io_net_get_type ( M_io_t io)

Get connection type

Parameters
[in]ioio object.
Returns
Type.

◆ M_io_net_get_connect_timeout_ms()

M_uint64 M_io_net_get_connect_timeout_ms ( M_io_t io)

Get connection timeout

This is not the amount of time connec took, this is the timeout allowe for connect to take place.

Parameters
[in]ioio object.
Returns
Timeout in milliseconds.

◆ M_io_net_time_dns_ms()

M_uint64 M_io_net_time_dns_ms ( M_io_t io)

Amount of time DNS query took

Parameters
[in]ioio object.
Returns
Time in milliseconds.

◆ M_io_net_time_connect_ms()

M_uint64 M_io_net_time_connect_ms ( M_io_t io)

Amount of time connection establishment took, not including DNS resolution time

Parameters
[in]ioio object.
Returns
Time in milliseconds.

◆ M_io_net_ipaddr_to_bin()

M_bool M_io_net_ipaddr_to_bin ( unsigned char *  ipaddr_bin,
size_t  ipaddr_bin_size,
const char *  ipaddr_str,
size_t *  ipaddr_bin_len 
)

Convert an ip address in string form into its binary network byte order representation.

Parameters
[out]ipaddr_binUser-supplied buffer of at least 16 bytes to store result.
[in]ipaddr_bin_sizeSize of user-supplied buffer.
[in]ipaddr_strIPv4 or IPv6 address in string form.
[out]ipaddr_bin_lenPointer to hold length of ip address in binary form. Result will be 4 or 16 depending on the address type.
Returns
M_TRUE if conversion was possible, M_FALSE otherwise

◆ M_io_net_bin_to_ipaddr()

M_bool M_io_net_bin_to_ipaddr ( char *  ipaddr_str,
size_t  ipaddr_str_size,
const unsigned char *  ipaddr_bin,
size_t  ipaddr_bin_len 
)

Convert an ip address in its binary network byte order representation to string form.

Parameters
[out]ipaddr_strUser-supplied buffer of at least 40 bytes to store IPv6 address, or 16 bytes to store IPv4 address.
[in]ipaddr_str_sizeSize of user-supplied buffer.
[in]ipaddr_binIPv4 or IPv6 address in binary form.
[in]ipaddr_bin_lenLength of ip address in binary form (must be 4 or 16).
Returns
M_TRUE if conversion was possible, M_FALSE otherwise