1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "private-lib-core.h"
26
27 struct lws *
lws_client_connect_4_established(struct lws * wsi,struct lws * wsi_piggyback,ssize_t plen)28 lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback,
29 ssize_t plen)
30 {
31 #if defined(LWS_CLIENT_HTTP_PROXYING)
32 struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
33 #endif
34 const char *meth;
35 struct lws_pollfd pfd;
36 const char *cce = "";
37 int n, m, rawish = 0;
38
39 meth = lws_wsi_client_stash_item(wsi, CIS_METHOD,
40 _WSI_TOKEN_CLIENT_METHOD);
41
42 if (meth && (!strcmp(meth, "RAW")
43 #if defined(LWS_ROLE_MQTT)
44 || !strcmp(meth, "MQTT")
45 #endif
46 ))
47 rawish = 1;
48
49 if (wsi_piggyback)
50 goto send_hs;
51
52 #if defined(LWS_CLIENT_HTTP_PROXYING)
53 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
54 /* we are connected to server, or proxy */
55
56 /* http proxy */
57 if (wsi->a.vhost->http.http_proxy_port) {
58 const char *cpa;
59
60 cpa = lws_wsi_client_stash_item(wsi, CIS_ADDRESS,
61 _WSI_TOKEN_CLIENT_PEER_ADDRESS);
62 if (!cpa)
63 goto failed;
64
65 lwsl_wsi_info(wsi, "going via proxy");
66
67 plen = lws_snprintf((char *)pt->serv_buf, 256,
68 "CONNECT %s:%u HTTP/1.1\x0d\x0a"
69 "Host: %s:%u\x0d\x0a"
70 "User-agent: lws\x0d\x0a", cpa, wsi->ocport,
71 cpa, wsi->ocport);
72
73 #if defined(LWS_WITH_HTTP_BASIC_AUTH)
74 if (wsi->a.vhost->proxy_basic_auth_token[0])
75 plen += lws_snprintf((char *)pt->serv_buf + plen, 256,
76 "Proxy-authorization: basic %s\x0d\x0a",
77 wsi->a.vhost->proxy_basic_auth_token);
78 #endif
79
80 plen += lws_snprintf((char *)pt->serv_buf + plen, 5,
81 "\x0d\x0a");
82
83 /* lwsl_hexdump_notice(pt->serv_buf, plen); */
84
85 /*
86 * OK from now on we talk via the proxy, so connect to that
87 */
88 if (wsi->stash)
89 wsi->stash->cis[CIS_ADDRESS] =
90 wsi->a.vhost->http.http_proxy_address;
91 else
92 if (lws_hdr_simple_create(wsi,
93 _WSI_TOKEN_CLIENT_PEER_ADDRESS,
94 wsi->a.vhost->http.http_proxy_address))
95 goto failed;
96 wsi->c_port = (uint16_t)wsi->a.vhost->http.http_proxy_port;
97
98 n = (int)send(wsi->desc.sockfd, (char *)pt->serv_buf,
99 (unsigned int)plen,
100 MSG_NOSIGNAL);
101 if (n < 0) {
102 lwsl_wsi_debug(wsi, "ERROR writing to proxy socket");
103 cce = "proxy write failed";
104 goto failed;
105 }
106
107 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
108 (int)wsi->a.context->timeout_secs);
109
110 wsi->conn_port = wsi->c_port;
111 lwsi_set_state(wsi, LRS_WAITING_PROXY_REPLY);
112
113 return wsi;
114 }
115 #endif
116 #endif
117
118 /* coverity */
119 if (!wsi->a.protocol)
120 return NULL;
121
122 #if defined(LWS_WITH_SOCKS5)
123 if (lwsi_state(wsi) != LRS_ESTABLISHED)
124 switch (lws_socks5c_greet(wsi, &cce)) {
125 case -1:
126 goto failed;
127 case 1:
128 return wsi;
129 default:
130 break;
131 }
132 #endif
133
134 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
135 send_hs:
136
137 if (wsi_piggyback &&
138 !lws_dll2_is_detached(&wsi->dll2_cli_txn_queue)) {
139 /*
140 * We are pipelining on an already-established connection...
141 * we can skip tls establishment.
142 *
143 * Set these queued guys to a state where they won't actually
144 * send their headers until we decide later.
145 */
146
147 lwsi_set_state(wsi, LRS_H2_WAITING_TO_SEND_HEADERS);
148
149 /*
150 * we can't send our headers directly, because they have to
151 * be sent when the parent is writeable. The parent will check
152 * for anybody on his client transaction queue that is in
153 * LRS_H1C_ISSUE_HANDSHAKE2, and let them write.
154 *
155 * If we are trying to do this too early, before the network
156 * connection has written his own headers, then it will just
157 * wait in the queue until it's possible to send them.
158 */
159 lws_callback_on_writable(wsi_piggyback);
160
161 lwsl_wsi_info(wsi, "waiting to send hdrs (par state 0x%x)",
162 lwsi_state(wsi_piggyback));
163 } else {
164 lwsl_wsi_info(wsi, "%s %s client created own conn "
165 "(raw %d) vh %s st 0x%x",
166 wsi->role_ops->name, wsi->a.protocol->name, rawish,
167 wsi->a.vhost->name, lwsi_state(wsi));
168
169 /* we are making our own connection */
170
171 if (!rawish
172 #if defined(LWS_WITH_TLS)
173 // && (!(wsi->tls.use_ssl & LCCSCF_USE_SSL) || wsi->tls.ssl)
174 #endif
175 ) {
176
177 if (lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2)
178 lwsi_set_state(wsi, LRS_H1C_ISSUE_HANDSHAKE);
179 } else {
180 /* for a method = "RAW" connection, this makes us
181 * established */
182
183 #if defined(LWS_WITH_TLS)// && !defined(LWS_WITH_MBEDTLS)
184
185 /* we have connected if we got here */
186
187 if (lwsi_state(wsi) == LRS_WAITING_CONNECT &&
188 (wsi->tls.use_ssl & LCCSCF_USE_SSL)) {
189 int result;
190
191 //lwsi_set_state(wsi, LRS_WAITING_SSL);
192
193 /*
194 * We can retry this... just cook the SSL BIO
195 * the first time
196 */
197
198 result = lws_client_create_tls(wsi, &cce, 1);
199 switch (result) {
200 case CCTLS_RETURN_DONE:
201 break;
202 case CCTLS_RETURN_RETRY:
203 lwsl_wsi_debug(wsi, "create_tls RETRY");
204 return wsi;
205 default:
206 lwsl_wsi_debug(wsi, "create_tls FAIL");
207 goto failed;
208 }
209
210 /*
211 * We succeeded to negotiate a new client tls
212 * tunnel. If it's h2 alpn, we have arranged
213 * to send the h2 prefix and set our state to
214 * LRS_H2_WAITING_TO_SEND_HEADERS already.
215 */
216
217 lwsl_wsi_notice(wsi, "tls established st 0x%x, "
218 "client_h2_alpn %d", lwsi_state(wsi),
219 wsi->client_h2_alpn);
220
221 if (lwsi_state(wsi) !=
222 LRS_H2_WAITING_TO_SEND_HEADERS)
223 lwsi_set_state(wsi,
224 LRS_H1C_ISSUE_HANDSHAKE2);
225 lws_set_timeout(wsi,
226 PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
227 (int)wsi->a.context->timeout_secs);
228 #if 0
229 /* ensure pollin enabled */
230 if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
231 lwsl_wsi_notice(wsi,
232 "unable to set POLLIN");
233 #endif
234
235 goto provoke_service;
236 }
237 #endif
238
239 /* clear his established timeout */
240 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
241
242 m = wsi->role_ops->adoption_cb[0];
243 if (m) {
244 n = user_callback_handle_rxflow(
245 wsi->a.protocol->callback, wsi,
246 (enum lws_callback_reasons)m,
247 wsi->user_space, NULL, 0);
248 if (n < 0) {
249 lwsl_wsi_info(wsi, "RAW_PROXY_CLI_ADOPT err");
250 goto failed;
251 }
252 }
253
254 /* service.c pollout processing wants this */
255 wsi->hdr_parsing_completed = 1;
256 #if defined(LWS_ROLE_MQTT)
257 if (meth && !strcmp(meth, "MQTT")) {
258 #if defined(LWS_WITH_TLS)
259 if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
260 lwsi_set_state(wsi, LRS_WAITING_SSL);
261 return wsi;
262 }
263 #endif
264 lwsl_wsi_info(wsi, "settings LRS_MQTTC_IDLE");
265 lwsi_set_state(wsi, LRS_MQTTC_IDLE);
266
267 /*
268 * provoke service to issue the CONNECT
269 * directly.
270 */
271 lws_set_timeout(wsi,
272 PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
273 (int)wsi->a.context->timeout_secs);
274
275 assert(lws_socket_is_valid(wsi->desc.sockfd));
276
277 pfd.fd = wsi->desc.sockfd;
278 pfd.events = LWS_POLLIN;
279 pfd.revents = LWS_POLLOUT;
280
281 lwsl_wsi_info(wsi, "going to service fd");
282 n = lws_service_fd(wsi->a.context, &pfd);
283 if (n < 0) {
284 cce = "first service failed";
285 goto failed;
286 }
287 if (n)
288 /* returns 1 on fail after close wsi */
289 return NULL;
290 return wsi;
291 }
292 #endif
293 lwsl_wsi_info(wsi, "setting ESTABLISHED");
294 lwsi_set_state(wsi, LRS_ESTABLISHED);
295
296 return wsi;
297 }
298
299 /*
300 * provoke service to issue the handshake directly.
301 *
302 * we need to do it this way because in the proxy case, this is
303 * the next state and executed only if and when we get a good
304 * proxy response inside the state machine... but notice in
305 * SSL case this may not have sent anything yet with 0 return,
306 * and won't until many retries from main loop. To stop that
307 * becoming endless, cover with a timeout.
308 */
309 #if defined(LWS_WITH_TLS) //&& !defined(LWS_WITH_MBEDTLS)
310 provoke_service:
311 #endif
312 lws_set_timeout(wsi, PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE,
313 (int)wsi->a.context->timeout_secs);
314
315 assert(lws_socket_is_valid(wsi->desc.sockfd));
316
317 pfd.fd = wsi->desc.sockfd;
318 pfd.events = LWS_POLLIN;
319 pfd.revents = LWS_POLLIN;
320
321 n = lws_service_fd(wsi->a.context, &pfd);
322 if (n < 0) {
323 cce = "first service failed";
324 goto failed;
325 }
326 if (n) /* returns 1 on failure after closing wsi */
327 return NULL;
328 }
329 #endif
330 return wsi;
331
332 failed:
333 lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
334
335 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect4");
336
337 return NULL;
338 }
339