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