blob: 86782c34d64b09344ce7803143c92d08c1d1c638 [file] [log] [blame]
Willy Tarreau4658c4d2012-05-26 00:18:09 +02001An FD has a state :
2 - CLOSED
3 - READY
4 - ERROR (?)
5 - LISTEN (?)
6
7A connection has a state :
8 - CLOSED
9 - ACCEPTED
10 - CONNECTING
11 - ESTABLISHED
12 - ERROR
13
14A stream interface has a state :
15 - INI, REQ, QUE, TAR, ASS, CON, CER, EST, DIS, CLO
16
17Note that CON and CER might be replaced by EST if the connection state is used
18instead. CON might even be more suited than EST to indicate that a connection
19is known.
20
21
22si_shutw() must do :
23
24 data_shutw()
25 if (shutr) {
26 data_close()
27 ctrl_shutw()
28 ctrl_close()
29 }
30
31si_shutr() must do :
32 data_shutr()
33 if (shutw) {
34 data_close()
35 ctrl_shutr()
36 ctrl_close()
37 }
38
39Each of these steps may fail, in which case the step must be retained and the
40operations postponed in an asynchronous task.
41
42The first asynchronous data_shut() might already fail so it is mandatory to
43save the other side's status with the connection in order to let the async task
44know whether the 3 next steps must be performed.
45
46The connection (or perhaps the FD) needs to know :
47 - the desired close operations : DSHR, DSHW, CSHR, CSHW
48 - the completed close operations : DSHR, DSHW, CSHR, CSHW
49
50
51On the accept() side, we probably need to know :
52 - if a header is expected (eg: accept-proxy)
53 - if this header is still being waited for
54 => maybe both info might be combined into one bit
55
56 - if a data-layer accept() is expected
57 - if a data-layer accept() has been started
58 - if a data-layer accept() has been performed
59 => possibly 2 bits, to indicate the need to free()
60
Joseph Herlant02cedc42018-11-13 19:45:17 -080061On the connect() side, we need to know :
Willy Tarreau4658c4d2012-05-26 00:18:09 +020062 - the desire to send a header (eg: send-proxy)
63 - if this header has been sent
64 => maybe both info might be combined
65
66 - if a data-layer connect() is expected
67 - if a data-layer connect() has been started
68 - if a data-layer connect() has been completed
69 => possibly 2 bits, to indicate the need to free()
70
71On the response side, we also need to know :
72 - the desire to send a header (eg: health check response for monitor-net)
73 - if this header was sent
74 => might be the same as sending a header over a new connection
75
76Note: monitor-net has precedence over proxy proto and data layers. Same for
77 health mode.
78
79For multi-step operations, use 2 bits :
80 00 = operation not desired, not performed
81 10 = operation desired, not started
82 11 = operation desired, started but not completed
83 01 = operation desired, started and completed
84
85 => X != 00 ==> operation desired
86 X & 01 ==> operation at least started
87 X & 10 ==> operation not completed
88
89Note: no way to store status information for error reporting.
90
91Note2: it would be nice if "tcp-request connection" rules could work at the
92connection level, just after headers ! This means support for tracking stick
93tables, possibly not too much complicated.
94
95
96Proposal for incoming connection sequence :
97
98- accept()
99- if monitor-net matches or if mode health => try to send response
100- if accept-proxy, wait for proxy request
101- if tcp-request connection, process tcp rules and possibly keep the
102 pointer to stick-table
103- if SSL is enabled, switch to SSL handshake
104- then switch to DATA state and instantiate a session
105
106We just need a map of handshake handlers on the connection. They all manage the
107FD status themselves and set the callbacks themselves. If their work succeeds,
108they remove themselves from the list. If it fails, they remain subscribed and
109enable the required polling until they are woken up again or the timeout strikes.
110
111Identified handshake handlers for incoming connections :
112 - HH_HEALTH (tries to send OK and dies)
113 - HH_MONITOR_IN (matches src IP and adds/removes HH_SEND_OK/HH_SEND_HTTP_OK)
114 - HH_SEND_OK (tries to send "OK" and dies)
115 - HH_SEND_HTTP_OK (tries to send "HTTP/1.0 200 OK" and dies)
116 - HH_ACCEPT_PROXY (waits for PROXY line and parses it)
117 - HH_TCP_RULES (processes TCP rules)
118 - HH_SSL_HS (starts SSL handshake)
Ilya Shipitsin2075ca82020-03-06 23:22:22 +0500119 - HH_ACCEPT_SESSION (instantiates a session)
Willy Tarreau4658c4d2012-05-26 00:18:09 +0200120
121Identified handshake handlers for outgoing connections :
122 - HH_SEND_PROXY (tries to build and send the PROXY line)
123 - HH_SSL_HS (starts SSL handshake)
124
125For the pollers, we could check that handshake handlers are not 0 and decide to
126call a generic connection handshake handler instead of usual callbacks. Problem
127is that pollers don't know connections, they know fds. So entities which manage
128handlers should update change the FD callbacks accordingly.
129
130With a bit of care, we could have :
131 - HH_SEND_LAST_CHUNK (sends the chunk pointed to by a pointer and dies)
132 => merges HEALTH, SEND_OK and SEND_HTTP_OK
133
134It sounds like the ctrl vs data state for the connection are per-direction
135(eg: support an async ctrl shutw while still reading data).
136
137Also support shutr/shutw status at L4/L7.
138
139In practice, what we really need is :
140
141shutdown(conn) =
142 conn.data.shut()
143 conn.ctrl.shut()
144 conn.fd.shut()
145
146close(conn) =
147 conn.data.close()
148 conn.ctrl.close()
149 conn.fd.close()
150
151With SSL over Remote TCP (RTCP + RSSL) to reach the server, we would have :
152
153 HTTP -> RTCP+RSSL connection <-> RTCP+RRAW connection -> TCP+SSL connection
154
155The connection has to be closed at 3 places after a successful response :
156 - DATA (RSSL over RTCP)
157 - CTRL (RTCP to close connection to server)
158 - SOCK (FD to close connection to second process)
159
160Externally, the connection is seen with very few flags :
161 - SHR
162 - SHW
163 - ERR
164
165We don't need a CLOSED flag as a connection must always be detached when it's closed.
166
167The internal status doesn't need to be exposed :
168 - FD allocated (Y/N)
169 - CTRL initialized (Y/N)
170 - CTRL connected (Y/N)
171 - CTRL handlers done (Y/N)
172 - CTRL failed (Y/N)
173 - CTRL shutr (Y/N)
174 - CTRL shutw (Y/N)
175 - DATA initialized (Y/N)
176 - DATA connected (Y/N)
177 - DATA handlers done (Y/N)
178 - DATA failed (Y/N)
179 - DATA shutr (Y/N)
180 - DATA shutw (Y/N)
181
182(note that having flags for operations needing to be completed might be easier)
183--------------
184
185Maybe we need to be able to call conn->fdset() and conn->fdclr() but it sounds
186very unlikely since the only functions manipulating this are in the code of
187the data/ctrl handlers.
188
189FDSET/FDCLR cannot be directly controlled by the stream interface since it also
190depends on the DATA layer (WANT_READ/wANT_WRITE).
191
192But FDSET/FDCLR is probably controlled by who owns the connection (eg: DATA).
193