Mstdlib-1.24.0

Enumerations

enum  M_io_proxy_protocol_flags_t {
  M_IO_PROXY_PROTOCOL_FLAG_NONE = 0 ,
  M_IO_PROXY_PROTOCOL_FLAG_V1 = 1 << 0 ,
  M_IO_PROXY_PROTOCOL_FLAG_V2 = 1 << 1
}
 

Functions

M_io_error_t M_io_proxy_protocol_inbound_add (M_io_t *io, size_t *layer_id, M_uint32 flags)
 
M_io_error_t M_io_proxy_protocol_outbound_add (M_io_t *io, size_t *layer_id, M_uint32 flags)
 
M_bool M_io_proxy_protocol_relayed (M_io_t *io)
 
const char * M_io_proxy_protocol_source_ipaddr (M_io_t *io)
 
const char * M_io_proxy_protocol_dest_ipaddr (M_io_t *io)
 
M_uint16 M_io_proxy_protocol_source_port (M_io_t *io)
 
M_uint16 M_io_proxy_protocol_dest_port (M_io_t *io)
 
M_io_net_type_t M_io_proxy_protocol_proxied_type (M_io_t *io)
 
const char * M_io_proxy_protocol_get_ipaddr (M_io_t *io)
 
M_bool M_io_proxy_protocol_set_connect_timeout_ms (M_io_t *io, M_uint64 timeout_ms)
 
M_bool M_io_proxy_protocol_set_source_endpoints (M_io_t *io, const char *source_ipaddr, const char *dest_ipaddr, M_uint16 source_port, M_uint16 dest_port)
 

Detailed Description

Overview

Inbound or outbound connection layer for handling The PROXY protocol as defined by HAProxy.

Supports versions:

Source is the client connecting to the system (Client). Destination is the server accepting the connection which will then relay using proxy protocol (proxy server). There can be multiple proxies in a chain between the source and the final server that is going to process the data. A such the destination address may not be the connection address for the final server's connection.

Examples

Proxy Server

This server accepts inbound connections, and sends the data to another system using the proxy protocol. The inbound client is not using proxy protocol. The server the proxy is relaying the data to is using proxy protocol.

client <-> proxy server example (sends proxy protocol) <-> final server (receives proxy protocol)

#include <mstdlib/mstdlib.h>
#include <mstdlib/mstdlib_io.h>
typedef struct {
M_buf_t *source_to_dest_buf;
M_buf_t *dest_to_source_buf;
M_io_t *source_io;
M_io_t *dest_io;
} ldata_t;
static M_dns_t *dns;
static void destination_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("CONNECTED TO SERVER: %s%s%s:%d\n",
break;
M_io_read_into_buf(io, ldata->dest_to_source_buf);
if (M_buf_len(ldata->dest_to_source_buf) > 0) {
M_io_write_from_buf(ldata->source_io, ldata->dest_to_source_buf);
}
break;
if (M_buf_len(ldata->source_to_dest_buf) > 0) {
M_io_write_from_buf(io, ldata->source_to_dest_buf);
}
break;
if (etype == M_EVENT_TYPE_DISCONNECTED) {
clean = M_TRUE;
} else {
M_io_get_error_string(io, error, sizeof(error));
}
M_printf("SERVER %s: %s%s%s:%d (%s%s%s)\n",
etype == M_EVENT_TYPE_DISCONNECTED ? "DISCONNECTED" : "ABORT",
clean?"clean":"unclean", clean?"":" - ", clean?"":error);
M_io_disconnect(ldata->source_io);
break;
}
}
static void source_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 = thunk;
char error[256] = { 0 };
M_bool clean = M_FALSE;
M_io_error_t ioerr;
switch (etype) {
M_printf("CLIENT CONNECTED: %s%s%s:%d\n",
// Create a connetion to the destination echo server.
ioerr = M_io_net_client_create(&io_out, dns, "localhost", 8999, M_IO_NET_ANY);
if (ioerr != M_IO_ERROR_SUCCESS) {
M_printf("Could not create client: %s\n", M_io_error_string(ioerr));
}
// Add the proxy protocol to the destination connection so the
// source information will be relayed to the echo server.
// Store the echo server's io object so we can communicate with it.
ldata->dest_io = io_out;
M_event_add(el, io_out, destination_cb, ldata);
break;
M_io_read_into_buf(io, ldata->source_to_dest_buf);
if (M_buf_len(ldata->source_to_dest_buf) > 0) {
M_io_write_from_buf(ldata->dest_io, ldata->source_to_dest_buf);
}
break;
if (M_buf_len(ldata->dest_to_source_buf) > 0) {
M_io_write_from_buf(io, ldata->dest_to_source_buf);
}
break;
if (etype == M_EVENT_TYPE_DISCONNECTED) {
clean = M_TRUE;
} else {
M_io_get_error_string(io, error, sizeof(error));
}
M_printf("CLIENT %s: %s%s%s:%d (%s%s%s)\n",
etype == M_EVENT_TYPE_DISCONNECTED ? "DISCONNECTED" : "ABORT",
clean?"clean":"unclean", clean?"":" - ", clean?"":error);
M_io_destroy(ldata->dest_io);
M_buf_cancel(ldata->source_to_dest_buf);
M_buf_cancel(ldata->dest_to_source_buf);
M_free(ldata);
break;
}
}
static void source_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) {
// Accept connection form source and create an io object to communicate with it.
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->source_to_dest_buf = M_buf_create();
ldata->dest_to_source_buf = M_buf_create();
ldata->source_io = io_out;
M_event_add(el, io_out, source_cb, ldata);
break;
break;
break;
}
}
int main(int argc, char **argv)
{
M_event_t *el;
M_io_t *io_source = NULL;
M_io_error_t ioerr;
dns = M_dns_create();
// Setup our listening server which will listen for source connections.
ioerr = M_io_net_server_create(&io_source, 8998, NULL, M_IO_NET_ANY);
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_source, source_listen_cb, NULL);
M_event_loop(el, M_TIMEOUT_INF);
return 0;
}
struct M_buf M_buf_t
Definition: m_buf.h:77
size_t M_buf_len(const M_buf_t *buf)
M_buf_t * M_buf_create(void) M_WARN_UNUSED_RESULT M_MALLOC
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)
M_event_err_t M_event_loop(M_event_t *event, M_uint64 timeout_ms)
M_event_t * M_event_create(M_uint32 flags)
@ 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)
unsigned short M_io_net_get_ephemeral_port(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)
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)
const char * M_io_net_get_ipaddr(M_io_t *io)
const char * M_io_net_get_server_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
M_bool M_io_proxy_protocol_set_source_endpoints(M_io_t *io, const char *source_ipaddr, const char *dest_ipaddr, M_uint16 source_port, M_uint16 dest_port)
M_io_error_t M_io_proxy_protocol_outbound_add(M_io_t *io, size_t *layer_id, M_uint32 flags)
@ M_IO_PROXY_PROTOCOL_FLAG_NONE
Definition: m_io_proxy_protocol.h:511
void M_io_disconnect(M_io_t *comm)
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)
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)
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)
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
void M_free(void *ptr) M_FREE(1)

Echo Server (accepting proxy protocol)

This is a basic echo server where any data received is echoed back out. The server only accepts connections that use proxy protocol.

#include <mstdlib/mstdlib.h>
#include <mstdlib/mstdlib_io.h>
// Echo server states.
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 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 M_state_machine_status_t state_check(void *data, M_uint64 *next)
{
ldata_t *ldata = data;
(void)next;
// Check for new line which indicates full message to echo.
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;
// Echo the data.
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);
// Check for exit command.
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;
// Exit the server.
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",
M_printf("SERVER IP: %s%s%s\n",
M_printf("PROXYED SOURCE: %s%s%s:%d\n",
M_printf("PROXYED DEST: %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;
if (etype == M_EVENT_TYPE_DISCONNECTED) {
clean = M_TRUE;
} else {
M_io_get_error_string(io, error, sizeof(error));
}
M_printf("CLIENT %s: %s%s%s:%d (%s%s%s)\n",
etype == M_EVENT_TYPE_DISCONNECTED ? "DISCONNECTED" : "ABORT",
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);
break;
}
// If tracing, adding before the proxy protocol will output the proxy
// protocol in the trace data. Putting after will not show the proxy
// protocol data as it would have been eaten by the proxy protocol
// layer, prior to being sent to the trace layer.
//M_io_add_trace(io_out, NULL, do_trace, NULL, NULL, NULL);
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_ANY);
if (ioerr != M_IO_ERROR_SUCCESS) {
M_printf("Could not start server: %s\n", M_io_error_string(ioerr));
return 0;
}
if (ioerr != M_IO_ERROR_SUCCESS) {
M_printf("Could not add proxy protocol layer: %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;
}
void M_buf_add_str(M_buf_t *buf, const char *str)
void M_event_done_with_disconnect(M_event_t *event, M_uint64 timeout_before_disconnect_ms, M_uint64 disconnect_timeout_ms)
M_io_net_type_t M_io_proxy_protocol_proxied_type(M_io_t *io)
const char * M_io_proxy_protocol_source_ipaddr(M_io_t *io)
M_uint16 M_io_proxy_protocol_dest_port(M_io_t *io)
const char * M_io_proxy_protocol_dest_ipaddr(M_io_t *io)
M_io_error_t M_io_proxy_protocol_inbound_add(M_io_t *io, size_t *layer_id, M_uint32 flags)
M_uint16 M_io_proxy_protocol_source_port(M_io_t *io)
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
M_io_error_t M_io_read_into_parser(M_io_t *comm, M_parser_t *parser)
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)
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

Using Proxy Server and Echo Server Examples

  1. Compile the proxy server
  2. Compile the echo server
  3. Start proxy server
  4. Start echo server
  5. Use something like telnet to connect to the proxy server
  6. You should see:
    • Proxy server shows connection from telnet
    • Proxy server shows it connected to echo server
    • Echo server shows a connection from proxy server
    • Echo server shows proxied information for the first (in cases where the chain has been expanded to include multiple) proxy server(s) and the telnet client.

Enumeration Type Documentation

◆ M_io_proxy_protocol_flags_t

Flags controlling behavior.

Enumerator
M_IO_PROXY_PROTOCOL_FLAG_NONE 

Default operation. Support both V1 and V2 in inbound configuration. Send V2 in client configuration.

M_IO_PROXY_PROTOCOL_FLAG_V1 

Only allow V1 connections for inbound configuration. Receiving V2 is an error condition. Send V1 format for outbound connections. Specifying with V2 flag negates this flag operation.

M_IO_PROXY_PROTOCOL_FLAG_V2 

Only allow V2 connections for inbound configuration. Receiving V1 is an error condition. Send V2 format for outbound connections. Specifying with V1 flag negates this flag operation.

Function Documentation

◆ M_io_proxy_protocol_inbound_add()

M_io_error_t M_io_proxy_protocol_inbound_add ( M_io_t io,
size_t *  layer_id,
M_uint32  flags 
)

Add an inbound handler for proxy protocol connections.

The system will look for the PROXY protocol data upon connect. If Proxy protocol data is not present this is considered an error condition per the proxy protocol spec. An error event will be generated instead of a connect event in this situation.

This should be added to an io object created by M_io_accept during a server M_EVENT_TYPE_ACCEPT event. It should not be added to the server io object created by M_io_net_server_create.

The proxy protocol data will be parsed and accessible though the relevant helper functions.

Parameters
[in]ioio object.
[out]layer_idLayer id this is added at.
[in]flagsM_io_proxy_protocol_flags_t flags.
Returns
Result.

◆ M_io_proxy_protocol_outbound_add()

M_io_error_t M_io_proxy_protocol_outbound_add ( M_io_t io,
size_t *  layer_id,
M_uint32  flags 
)

Add an outbound handler for proxy protocol connections.

Information about the proxyed endpoints (source and destination) need to be set before the connect event. If endpoints are not set the connection is assumed to be local where any data is being sent by the proxy itself and not being relayed on behalf of another client.

Parameters
[in]ioio object.
[out]layer_idLayer id this is added at.
[in]flagsM_io_proxy_protocol_flags_t flags.
Returns
Result.
See also
M_io_proxy_protocol_set_source_endpoints

◆ M_io_proxy_protocol_relayed()

M_bool M_io_proxy_protocol_relayed ( M_io_t io)

Whether data is being is being relayed via a proxy.

A connection is relayed when the data is being sent on behalf of another system (proxied). When it is not relayed it is a local connection that has been established by the proxy for the proxy's own communication with the system. Typically, this is used for health checking.

return M_TRUE if relayed. Otherwise, M_FALSE.

◆ M_io_proxy_protocol_source_ipaddr()

const char * M_io_proxy_protocol_source_ipaddr ( M_io_t io)

Source IP address.

IP address of the client that connected to the proxy.

Parameters
[in]ioio object.
Returns
IP address as string.

◆ M_io_proxy_protocol_dest_ipaddr()

const char * M_io_proxy_protocol_dest_ipaddr ( M_io_t io)

Destination IP address.

IP address of the proxy server that is relaying the client's (source) data.

Parameters
[in]ioio object.
Returns
IP address as string.

◆ M_io_proxy_protocol_source_port()

M_uint16 M_io_proxy_protocol_source_port ( M_io_t io)

Source port.

Ephemeral port the client is connecting out on.

Parameters
[in]ioio object.
Returns
Port

◆ M_io_proxy_protocol_dest_port()

M_uint16 M_io_proxy_protocol_dest_port ( M_io_t io)

Destination port.

Destination port the client is connecting to.

Parameters
[in]ioio object.
Returns
Port

◆ M_io_proxy_protocol_proxied_type()

M_io_net_type_t M_io_proxy_protocol_proxied_type ( M_io_t io)

Connection type that was used between source and destination.

Parameters
[in]ioio object.
Returns
Type

◆ M_io_proxy_protocol_get_ipaddr()

const char * M_io_proxy_protocol_get_ipaddr ( M_io_t io)

Get the IP address of the client falling back to the network connection.

When using proxy protocol this should be used instead of M_io_net_get_ipaddr in most instances. This can be used even when proxy protocol is not in use. This is especially useful when using an internal IP based blacklist for denying connections to a client as part of an intrusion prevention system (IPS).

This function is the equivalent of checking M_io_proxy_protocol_relayed and then calling either M_io_proxy_protocol_source_ipaddr or M_io_net_get_ipaddr based on whether the connection is relayed.

This is a conscience especially for instances where proxy protocol could be used. For example, a configuration option or when some but not all connections will use the protocol. This function allows for use in both scenerios and will always return the correct IP address for the client, whether proxied for not.

param[in] io io object.

Returns
String

◆ M_io_proxy_protocol_set_connect_timeout_ms()

M_bool M_io_proxy_protocol_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 receive all proxy protocol data. This timeout applies after the net connect timeout.

Proxy protocol is designed for all data to fit within a single TCP frame. Meaning, the data should not buffer between multiple events. As such the default timeout is 500 ms. This function can be used to increase that timeout for obscenely slow connections.

Connect timeout applies to both inbound and outbound (receiving and writing), the proxy data.

param[in] io io object. param[in] timeout_ms Timeout in milliseconds.

Returns
M_TRUE when proxy protocol in use. Otherwise, M_FALSE.

◆ M_io_proxy_protocol_set_source_endpoints()

M_bool M_io_proxy_protocol_set_source_endpoints ( M_io_t io,
const char *  source_ipaddr,
const char *  dest_ipaddr,
M_uint16  source_port,
M_uint16  dest_port 
)

Source and destination information that will be sent on connect.

Only applies to outbound connections.

The source and destination IP address must be the same address family (IPv4/IPv6). If IP addresses are NULL the connection is assumed to be local (not proxied data).

This can be called multiple times setting or clearing proxy client information. However, the information is only sent on connect. Multiple inbound connections cannot be multiplexed on the same outbound connection. If changing endpoint information the outbound connection needs to disconnect first.

This should be called using an inbound network connection to determine the connection information.

Parameters
[in]ioio object.
[in]source_ipaddrSource ipaddress
[in]dest_ipaddrDestination ipaddress
[in]source_portSource port
[in]dest_portDestination port