blob: 712dfbaa30c73b4a05a2e464ef5f129082b712b7 [file] [log] [blame]
Willy Tarreau59f98392012-07-06 14:13:49 +02001/*
2 * Connection management functions
3 *
4 * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <common/compat.h>
14#include <common/config.h>
15
16#include <types/connection.h>
Willy Tarreau2c6be842012-07-06 17:12:34 +020017
Willy Tarreau2da156f2012-07-23 15:07:23 +020018#include <proto/proto_tcp.h>
Willy Tarreau2c6be842012-07-06 17:12:34 +020019#include <proto/stream_interface.h>
Willy Tarreau59f98392012-07-06 14:13:49 +020020
21/* I/O callback for fd-based connections. It calls the read/write handlers
22 * provided by the connection's sock_ops, which must be valid. It returns
23 * FD_WAIT_*.
24 */
25int conn_fd_handler(int fd)
26{
Willy Tarreau80184712012-07-06 14:54:49 +020027 struct connection *conn = fdtab[fd].owner;
Willy Tarreau59f98392012-07-06 14:13:49 +020028 int ret = 0;
29
Willy Tarreauc76ae332012-07-12 15:32:13 +020030 if (unlikely(!conn))
Willy Tarreau2c6be842012-07-06 17:12:34 +020031 goto leave;
Willy Tarreau59f98392012-07-06 14:13:49 +020032
Willy Tarreauc76ae332012-07-12 15:32:13 +020033 process_handshake:
34 while (unlikely(conn->flags & CO_FL_HANDSHAKE)) {
35 if (unlikely(conn->flags & CO_FL_ERROR))
Willy Tarreau2c6be842012-07-06 17:12:34 +020036 goto leave;
Willy Tarreau59f98392012-07-06 14:13:49 +020037
Willy Tarreauc76ae332012-07-12 15:32:13 +020038 if (conn->flags & CO_FL_SI_SEND_PROXY)
39 if ((ret = conn_si_send_proxy(conn, CO_FL_SI_SEND_PROXY)))
40 goto leave;
41 }
42
43 /* OK now we're in the data phase now */
44
Willy Tarreau59f98392012-07-06 14:13:49 +020045 if (fdtab[fd].ev & (FD_POLL_IN | FD_POLL_HUP | FD_POLL_ERR))
Willy Tarreau239d7182012-07-23 18:53:03 +020046 if (!conn->data->read(conn))
Willy Tarreau59f98392012-07-06 14:13:49 +020047 ret |= FD_WAIT_READ;
48
Willy Tarreauc76ae332012-07-12 15:32:13 +020049 if (unlikely(conn->flags & CO_FL_ERROR))
Willy Tarreau2c6be842012-07-06 17:12:34 +020050 goto leave;
Willy Tarreau59f98392012-07-06 14:13:49 +020051
Willy Tarreauc76ae332012-07-12 15:32:13 +020052 /* It may happen during the data phase that a handshake is
53 * enabled again (eg: SSL)
54 */
55 if (unlikely(conn->flags & CO_FL_HANDSHAKE))
56 goto process_handshake;
57
Willy Tarreau59f98392012-07-06 14:13:49 +020058 if (fdtab[fd].ev & (FD_POLL_OUT | FD_POLL_ERR))
Willy Tarreau239d7182012-07-23 18:53:03 +020059 if (!conn->data->write(conn))
Willy Tarreau59f98392012-07-06 14:13:49 +020060 ret |= FD_WAIT_WRITE;
Willy Tarreau2da156f2012-07-23 15:07:23 +020061
Willy Tarreauc76ae332012-07-12 15:32:13 +020062 if (unlikely(conn->flags & CO_FL_ERROR))
Willy Tarreau2da156f2012-07-23 15:07:23 +020063 goto leave;
64
Willy Tarreauc76ae332012-07-12 15:32:13 +020065 /* It may happen during the data phase that a handshake is
66 * enabled again (eg: SSL)
67 */
68 if (unlikely(conn->flags & CO_FL_HANDSHAKE))
69 goto process_handshake;
70
71 if (unlikely(conn->flags & CO_FL_WAIT_L4_CONN)) {
Willy Tarreau2da156f2012-07-23 15:07:23 +020072 /* still waiting for a connection to establish and no data to
73 * send in order to probe it ? Then let's retry the connect().
74 */
Willy Tarreau239d7182012-07-23 18:53:03 +020075 if (!tcp_connect_probe(conn))
Willy Tarreau2da156f2012-07-23 15:07:23 +020076 ret |= FD_WAIT_WRITE;
77 }
78
Willy Tarreau2c6be842012-07-06 17:12:34 +020079 leave:
Willy Tarreaufd31e532012-07-23 18:24:25 +020080 if (conn->flags & CO_FL_NOTIFY_SI)
81 stream_sock_update_conn(conn);
82
Willy Tarreau8f8c92f2012-07-23 19:45:44 +020083 /* Last check, verify if the connection just established */
Willy Tarreauc76ae332012-07-12 15:32:13 +020084 if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED))))
Willy Tarreau8f8c92f2012-07-23 19:45:44 +020085 conn->flags |= CO_FL_CONNECTED;
86
Willy Tarreau61ace1b2012-07-23 12:14:26 +020087 /* remove the events before leaving */
88 fdtab[fd].ev &= ~(FD_POLL_IN | FD_POLL_OUT | FD_POLL_HUP | FD_POLL_ERR);
Willy Tarreau59f98392012-07-06 14:13:49 +020089 return ret;
90}
Willy Tarreaub5e2cbd2012-08-17 11:55:04 +020091
92/* set polling depending on the change between the CURR part of the
93 * flags and the new flags in connection C. The connection flags are
94 * updated with the new flags at the end of the operation. Only the bits
95 * relevant to CO_FL_CURR_* from <flags> are considered.
96 */
97void conn_set_polling(struct connection *c, unsigned int new)
98{
99 unsigned int old = c->flags; /* for CO_FL_CURR_* */
100
101 /* update read status if needed */
102 if ((old & (CO_FL_CURR_RD_ENA|CO_FL_CURR_RD_POL)) != (CO_FL_CURR_RD_ENA|CO_FL_CURR_RD_POL) &&
103 (new & (CO_FL_CURR_RD_ENA|CO_FL_CURR_RD_POL)) == (CO_FL_CURR_RD_ENA|CO_FL_CURR_RD_POL))
104 fd_poll_recv(c->t.sock.fd);
105 else if (!(old & CO_FL_CURR_RD_ENA) && (new & CO_FL_CURR_RD_ENA))
106 fd_want_recv(c->t.sock.fd);
107 else if ((old & CO_FL_CURR_RD_ENA) && !(new & CO_FL_CURR_RD_ENA))
108 fd_stop_recv(c->t.sock.fd);
109
110 /* update write status if needed */
111 if ((old & (CO_FL_CURR_WR_ENA|CO_FL_CURR_WR_POL)) != (CO_FL_CURR_WR_ENA|CO_FL_CURR_WR_POL) &&
112 (new & (CO_FL_CURR_WR_ENA|CO_FL_CURR_WR_POL)) == (CO_FL_CURR_WR_ENA|CO_FL_CURR_WR_POL))
113 fd_poll_send(c->t.sock.fd);
114 else if (!(old & CO_FL_CURR_WR_ENA) && (new & CO_FL_CURR_WR_ENA))
115 fd_want_send(c->t.sock.fd);
116 else if ((old & CO_FL_CURR_WR_ENA) && !(new & CO_FL_CURR_WR_ENA))
117 fd_stop_send(c->t.sock.fd);
118
119 c->flags &= ~(CO_FL_CURR_WR_POL|CO_FL_CURR_WR_ENA|CO_FL_CURR_RD_POL|CO_FL_CURR_RD_ENA);
120 c->flags |= new & (CO_FL_CURR_WR_POL|CO_FL_CURR_WR_ENA|CO_FL_CURR_RD_POL|CO_FL_CURR_RD_ENA);
121}