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