connection.c revision a327d9301f593433c228c4cc8cca05c95b37f6fb
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
66ae183b6e895216037bd921367670f4b0665911Timo Sirainenstatic void connection_idle_timeout(struct connection *conn)
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen conn->disconnect_reason = CONNECTION_DISCONNECT_IDLE_TIMEOUT;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void connection_connect_timeout(struct connection *conn)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen conn->disconnect_reason = CONNECTION_DISCONNECT_CONNECT_TIMEOUT;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenvoid connection_input_default(struct connection *conn)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (!input->closed && (line = i_stream_next_line(input)) != NULL) {
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen conn->disconnect_reason = CONNECTION_DISCONNECT_DEINIT;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint connection_verify_version(struct connection *conn,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen const char *const *args)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* VERSION <tab> service_name <tab> major version <tab> minor version */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen str_to_uint(args[2], &recv_major_version) < 0 ||
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen str_to_uint(args[3], &conn->minor_version) < 0) {
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen i_error("%s didn't reply with a valid VERSION line",
46c31f64b9f0949f00b7819f45b22f2d64b2ea27Timo Sirainen if (strcmp(args[1], conn->list->set.service_name_in) != 0) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_error("%s: Connected to wrong socket type. "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "We want '%s', but received '%s'", conn->name,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (recv_major_version != conn->list->set.major_version) {
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen i_error("%s: Socket supports major version %u, "
80fc743146da5130de34174cdaad2576f103723fTimo Sirainen "but we support only %u (mixed old and new binaries?)",
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainenint connection_input_line_default(struct connection *conn, const char *line)
20a802016205bbcafc90f164f769ea801f88d014Timo Sirainen const char *const *args;
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen if (connection_verify_version(conn, args) < 0)
1e923fcf497665fe071a154c31fb452766b0b2deTimo Sirainenstatic void connection_init_streams(struct connection *conn)
1e923fcf497665fe071a154c31fb452766b0b2deTimo Sirainen const struct connection_settings *set = &conn->list->set;
c27f03fa8fd2ef4acd1db814fae7d90e0eb9d3aeTimo Sirainen conn->version_received = set->major_version == 0;
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen conn->output = o_stream_create_fd(conn->fd_out,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen o_stream_set_no_error_handling(conn->output, TRUE);
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen conn->io = io_add(conn->fd_in, IO_READ, conn->list->v.input, conn);
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen conn->to = timeout_add(set->input_idle_timeout_secs*1000,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen if (set->major_version != 0 && !set->dont_send_version) {
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen o_stream_nsend_str(conn->output, t_strdup_printf(
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainen "VERSION\t%s\t%u\t%u\n", set->service_name_out,
c5454841b5067a22827556ca9bc7935d190f57baTimo Sirainenvoid connection_init_server(struct connection_list *list,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenvoid connection_init_client_ip(struct connection_list *list,
de12ff295bb3d0873b4dced5840612cbacd635efTimo Sirainen conn->name = i_strdup_printf("%s:%u", net_ip2addr(ip), port);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenvoid connection_init_client_unix(struct connection_list *list,
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenstatic void connection_connected(struct connection *conn)
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainenint connection_client_connect(struct connection *conn)
f23298fea47eecbeded985ee2537a34c4c4ef56bTimo Sirainen const struct connection_settings *set = &conn->list->set;
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen fd = net_connect_ip(&conn->ip, conn->port, NULL);
519e0a461271843833a2b42626ad93f6e7ddc497Timo Sirainen conn->to = timeout_add(set->client_connect_timeout_msecs,
6a04c5112961c5f4fb2d2f25192b3dc424d62ad0Timo Sirainenvoid connection_disconnect(struct connection *conn)
6825360d446542046757b06064282301c4c6b27cTimo Sirainen i_error("close(%s/out) failed: %m", conn->name);
6825360d446542046757b06064282301c4c6b27cTimo Sirainenvoid connection_deinit(struct connection *conn)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen DLLIST_REMOVE(&conn->list->connections, conn);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenint connection_input_read(struct connection *conn)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen /* buffer full */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen switch (conn->list->set.input_full_behavior) {
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen /* disconnected */
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen /* nothing new read */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen /* something was read */
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenconst char *connection_disconnect_reason(struct connection *conn)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen if (conn->input != NULL && conn->input->stream_errno != 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen else if (conn->output != NULL && conn->output->stream_errno != 0)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainen return errno == 0 || errno == EPIPE ? "Connection closed" :
4b231ca0bbe3b536acbd350101e183441ce0247aTimo Sirainenvoid connection_switch_ioloop(struct connection *conn)
e4b09b008ab544eb8994beecbfffefa21d855e43Timo Sirainenconnection_list_init(const struct connection_settings *set,
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen set->input_full_behavior != CONNECTION_BEHAVIOR_ALLOW);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen list->v.input_line = connection_input_line_default;