blob: 0c90eb22943c961c2c92bcd7e300ebca57f4cb89 [file] [log] [blame]
Willy Tarreauc14b7d92014-06-19 16:03:41 +020012013/10/17 - server connection management and reuse
2
3Current state
4-------------
5
6At the moment, a connection entity is needed to carry any address
7information. This means in the following situations, we need a server
8connection :
9
10- server is elected and the server's destination address is set
11
12- transparent mode is elected and the destination address is set from
13 the incoming connection
14
15- proxy mode is enabled, and the destination's address is set during
16 the parsing of the HTTP request
17
18- connection to the server fails and must be retried on the same
19 server using the same parameters, especially the destination
20 address (SN_ADDR_SET not removed)
21
22
23On the accepting side, we have further requirements :
24
25- allocate a clean connection without a stream interface
26
27- incrementally set the accepted connection's parameters without
28 clearing it, and keep track of what is set (eg: getsockname).
29
30- initialize a stream interface in established mode
31
32- attach the accepted connection to a stream interface
33
34
35This means several things :
36
37- the connection has to be allocated on the fly the first time it is
38 needed to store the source or destination address ;
39
40- the connection has to be attached to the stream interface at this
41 moment ;
42
43- it must be possible to incrementally set some settings on the
44 connection's addresses regardless of the connection's current state
45
46- the connection must not be released across connection retries ;
47
48- it must be possible to clear a connection's parameters for a
49 redispatch without having to detach/attach the connection ;
50
51- we need to allocate a connection without an existing stream interface
52
53So on the accept() side, it looks like this :
54
55 fd = accept();
56 conn = new_conn();
57 get_some_addr_info(&conn->addr);
58 ...
59 si = new_si();
60 si_attach_conn(si, conn);
61 si_set_state(si, SI_ST_EST);
62 ...
63 get_more_addr_info(&conn->addr);
64
65On the connect() side, it looks like this :
66
67 si = new_si();
68 while (!properly_connected) {
69 if (!(conn = si->end)) {
70 conn = new_conn();
71 conn_clear(conn);
72 si_attach_conn(si, conn);
73 }
74 else {
75 if (connected) {
76 f = conn->flags & CO_FL_XPRT_TRACKED;
77 conn->flags &= ~CO_FL_XPRT_TRACKED;
78 conn_close(conn);
79 conn->flags |= f;
80 }
81 if (!correct_dest)
82 conn_clear(conn);
83 }
84 set_some_addr_info(&conn->addr);
85 si_set_state(si, SI_ST_CON);
86 ...
87 set_more_addr_info(&conn->addr);
88 conn->connect();
89 if (must_retry) {
90 close_conn(conn);
91 }
92 }
93
94Note: we need to be able to set the control and transport protocols.
95On outgoing connections, this is set once we know the destination address.
96On incoming connections, this is set the earliest possible (once we know
97the source address).
98
99The problem analysed below was solved on 2013/10/22
100
101| ==> the real requirement is to know whether a connection is still valid or not
102| before deciding to close it. CO_FL_CONNECTED could be enough, though it
103| will not indicate connections that are still waiting for a connect to occur.
104| This combined with CO_FL_WAIT_L4_CONN and CO_FL_WAIT_L6_CONN should be OK.
105|
106| Alternatively, conn->xprt could be used for this, but needs some careful checks
107| (it's used by conn_full_close at least).
108|
109| Right now, conn_xprt_close() checks conn->xprt and sets it to NULL.
110| conn_full_close() also checks conn->xprt and sets it to NULL, except
111| that the check on ctrl is performed within xprt. So conn_xprt_close()
112| followed by conn_full_close() will not close the file descriptor.
113| Note that conn_xprt_close() is never called, maybe we should kill it ?
114|
115| Note: at the moment, it's problematic to leave conn->xprt to NULL before doing
116| xprt_init() because we might end up with a pending file descriptor. Or at
117| least with some transport not de-initialized. We might thus need
118| conn_xprt_close() when conn_xprt_init() fails.
119|
120| The fd should be conditionned by ->ctrl only, and the transport layer by ->xprt.
121|
122| - conn_prepare_ctrl(conn, ctrl)
123| - conn_prepare_xprt(conn, xprt)
124| - conn_prepare_data(conn, data)
125|
126| Note: conn_xprt_init() needs conn->xprt so it's not a problem to set it early.
127|
128| One problem might be with conn_xprt_close() not being able to know if xprt_init()
129| was called or not. That's where it might make sense to only set ->xprt during init.
130| Except that it does not fly with outgoing connections (xprt_init is called after
131| connect()).
132|
133| => currently conn_xprt_close() is only used by ssl_sock.c and decides whether
134| to do something based on ->xprt_ctx which is set by ->init() from xprt_init().
135| So there is nothing to worry about. We just need to restore conn_xprt_close()
136| and rely on ->ctrl to close the fd instead of ->xprt.
137|
138| => we have the same issue with conn_ctrl_close() : when is the fd supposed to be
139| valid ? On outgoing connections, the control is set much before the fd...