connection.h revision 4b9e7a8752803928aa0897f8cc1fc34592452f07
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#ifndef CONNECTION_H
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#define CONNECTION_H
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "net.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct connection;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenenum connection_behavior {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen CONNECTION_BEHAVIOR_DESTROY = 0,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen CONNECTION_BEHAVIOR_ALLOW
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenenum connection_disconnect_reason {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* not disconnected yet */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen CONNECTION_DISCONNECT_NOT = 0,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* normal requested disconnection */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen CONNECTION_DISCONNECT_DEINIT,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* input buffer full */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen CONNECTION_DISCONNECT_BUFFER_FULL,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* connection got disconnected */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen CONNECTION_DISCONNECT_CONN_CLOSED,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* connect() timed out */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen CONNECTION_DISCONNECT_CONNECT_TIMEOUT,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* remote didn't send input */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen CONNECTION_DISCONNECT_IDLE_TIMEOUT
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct connection_vfuncs {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen void (*destroy)(struct connection *conn);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* For UNIX socket clients this gets called immediately (unless
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen delayed_unix_client_connected_callback=TRUE) with success=TRUE,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for IP connections it gets called later:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen If connect() fails, sets success=FALSE and errno. Streams aren't
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen initialized in that situation either. destroy() is called after
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen the callback. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen void (*client_connected)(struct connection *conn, bool success);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* implement one of the input*() methods.
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen They return 1 = ok, continue. 0 = ok, but stop processing more
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen lines, -1 = error, disconnect the client. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen void (*input)(struct connection *conn);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen int (*input_line)(struct connection *conn, const char *line);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen int (*input_args)(struct connection *conn, const char *const *args);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct connection_settings {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *service_name_in;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *service_name_out;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int major_version, minor_version;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int client_connect_timeout_msecs;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int input_idle_timeout_secs;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen size_t input_max_size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen size_t output_max_size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen enum connection_behavior input_full_behavior;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bool client;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bool dont_send_version;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* By default when only input_args() is used, or when
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen connection_input_line_default() is used, empty lines aren't allowed
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen since it would result in additional args[0] == NULL check. Setting
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen this to TRUE passes it through instead of logging an error. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bool allow_empty_args_input;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* Don't call client_connected() immediately on
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen connection_client_connect() with UNIX sockets. This is mainly
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen to make the functionality identical with inet sockets, which may
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen simplify the calling code. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bool delayed_unix_client_connected_callback;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* If connect() to UNIX socket fails with EAGAIN, retry for this many
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen milliseconds before giving up (0 = try once) */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int unix_client_connect_msecs;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct connection {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct connection *prev, *next;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct connection_list *list;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen char *name;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen int fd_in, fd_out;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct io *io;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct istream *input;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct ostream *output;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct timeout *to;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen time_t last_input;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct timeval last_input_tv;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct timeval connect_started;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct timeval connect_finished;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* for IP client: */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct ip_addr ip;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen in_port_t port;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* received minor version */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int minor_version;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen enum connection_disconnect_reason disconnect_reason;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bool version_received:1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bool unix_socket:1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct connection_list {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct connection *connections;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int connections_count;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct connection_settings set;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct connection_vfuncs v;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid connection_init(struct connection_list *list,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct connection *conn);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid connection_init_server(struct connection_list *list,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct connection *conn, const char *name,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen int fd_in, int fd_out);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid connection_init_client_ip(struct connection_list *list,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct connection *conn,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct ip_addr *ip, in_port_t port);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid connection_init_client_unix(struct connection_list *list,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct connection *conn, const char *path);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid connection_init_from_streams(struct connection_list *list,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct connection *conn, const char *name,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct istream *input, struct ostream *output);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint connection_client_connect(struct connection *conn);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid connection_disconnect(struct connection *conn);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid connection_deinit(struct connection *conn);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Returns -1 = disconnected, 0 = nothing new, 1 = something new.
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen If input_full_behavior is ALLOW, may return also -2 = buffer full. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint connection_input_read(struct connection *conn);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Verify that VERSION input matches what we expect. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint connection_verify_version(struct connection *conn, const char *const *args);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Returns human-readable reason for why connection was disconnected. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconst char *connection_disconnect_reason(struct connection *conn);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen/* Returns human-readable reason for why connection timed out,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen e.g. "No input for 10.023 secs". */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconst char *connection_input_timeout_reason(struct connection *conn);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid connection_switch_ioloop(struct connection *conn);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct connection_list *
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconnection_list_init(const struct connection_settings *set,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct connection_vfuncs *vfuncs);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid connection_list_deinit(struct connection_list **list);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid connection_input_default(struct connection *conn);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint connection_input_line_default(struct connection *conn, const char *line);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#endif
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen