]>
Commit | Line | Data |
---|---|---|
95d659f0 | 1 | |
983061ed | 2 | /* |
db1cd23c | 3 | * $Id: tunnel.cc,v 1.91 1998/12/05 00:54:40 wessels Exp $ |
983061ed | 4 | * |
30a4f2a8 | 5 | * DEBUG: section 26 Secure Sockets Layer Proxy |
6 | * AUTHOR: Duane Wessels | |
7 | * | |
42c04c16 | 8 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ |
e25c139f | 9 | * ---------------------------------------------------------- |
30a4f2a8 | 10 | * |
11 | * Squid is the result of efforts by numerous individuals from the | |
12 | * Internet community. Development is led by Duane Wessels of the | |
e25c139f | 13 | * National Laboratory for Applied Network Research and funded by the |
14 | * National Science Foundation. Squid is Copyrighted (C) 1998 by | |
15 | * Duane Wessels and the University of California San Diego. Please | |
16 | * see the COPYRIGHT file for full details. Squid incorporates | |
17 | * software developed and/or copyrighted by other sources. Please see | |
18 | * the CREDITS file for full details. | |
30a4f2a8 | 19 | * |
20 | * This program is free software; you can redistribute it and/or modify | |
21 | * it under the terms of the GNU General Public License as published by | |
22 | * the Free Software Foundation; either version 2 of the License, or | |
23 | * (at your option) any later version. | |
24 | * | |
25 | * This program is distributed in the hope that it will be useful, | |
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 | * GNU General Public License for more details. | |
29 | * | |
30 | * You should have received a copy of the GNU General Public License | |
31 | * along with this program; if not, write to the Free Software | |
cbdec147 | 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
e25c139f | 33 | * |
983061ed | 34 | */ |
983061ed | 35 | |
30a4f2a8 | 36 | #include "squid.h" |
983061ed | 37 | |
38 | typedef struct { | |
39 | char *url; | |
98ffb7e4 | 40 | char *host; /* either request->host or proxy host */ |
41 | u_short port; | |
983061ed | 42 | request_t *request; |
983061ed | 43 | struct { |
44 | int fd; | |
45 | int len; | |
983061ed | 46 | char *buf; |
47 | } client, server; | |
88738790 | 48 | size_t *size_ptr; /* pointer to size in an ConnStateData for logging */ |
93868820 | 49 | int proxying; |
983061ed | 50 | } SslStateData; |
51 | ||
0ee4272b | 52 | static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n"; |
983061ed | 53 | |
54cff85f | 54 | static CNCB sslConnectDone; |
55 | static ERCB sslErrorComplete; | |
adb78bd4 | 56 | static PF sslServerClosed; |
54cff85f | 57 | static PF sslClientClosed; |
58 | static PF sslReadClient; | |
59 | static PF sslReadServer; | |
5c5783a2 | 60 | static PF sslTimeout; |
54cff85f | 61 | static PF sslWriteClient; |
62 | static PF sslWriteServer; | |
63 | static PSC sslPeerSelectComplete; | |
adb78bd4 | 64 | static void sslStateFree(SslStateData * sslState); |
f5b8bbc4 | 65 | static void sslConnected(int fd, void *); |
66 | static void sslProxyConnected(int fd, void *); | |
adb78bd4 | 67 | static void sslSetSelect(SslStateData * sslState); |
447e176b | 68 | #if DELAY_POOLS |
69 | static DEFER sslDeferServerRead; | |
70 | #endif | |
30a4f2a8 | 71 | |
b8d8561b | 72 | static void |
adb78bd4 | 73 | sslServerClosed(int fd, void *data) |
30a4f2a8 | 74 | { |
adb78bd4 | 75 | SslStateData *sslState = data; |
76 | debug(26, 3) ("sslServerClosed: FD %d\n", fd); | |
77 | assert(fd == sslState->server.fd); | |
78 | sslState->server.fd = -1; | |
79 | if (sslState->client.fd == -1) | |
80 | sslStateFree(sslState); | |
30a4f2a8 | 81 | } |
82 | ||
b177367b | 83 | static void |
84 | sslClientClosed(int fd, void *data) | |
30a4f2a8 | 85 | { |
b177367b | 86 | SslStateData *sslState = data; |
a3d5953d | 87 | debug(26, 3) ("sslClientClosed: FD %d\n", fd); |
adb78bd4 | 88 | assert(fd == sslState->client.fd); |
89 | sslState->client.fd = -1; | |
90 | if (sslState->server.fd == -1) | |
91 | sslStateFree(sslState); | |
30a4f2a8 | 92 | } |
983061ed | 93 | |
b177367b | 94 | static void |
adb78bd4 | 95 | sslStateFree(SslStateData * sslState) |
983061ed | 96 | { |
adb78bd4 | 97 | debug(26, 3) ("sslStateFree: sslState=%p\n", sslState); |
98 | assert(sslState != NULL); | |
99 | assert(sslState->client.fd == -1); | |
100 | assert(sslState->server.fd == -1); | |
983061ed | 101 | safe_free(sslState->server.buf); |
102 | safe_free(sslState->client.buf); | |
adb78bd4 | 103 | safe_free(sslState->url); |
104 | sslState->host = NULL; | |
30a4f2a8 | 105 | requestUnlink(sslState->request); |
7dd44885 | 106 | sslState->request = NULL; |
107 | cbdataFree(sslState); | |
983061ed | 108 | } |
109 | ||
447e176b | 110 | #if DELAY_POOLS |
111 | static int | |
112 | sslDeferServerRead(int fdnotused, void *data) | |
113 | { | |
114 | request_t *r = data; | |
56e64999 | 115 | return delayBytesWanted(r->delay_id, 0, 1) == 0; |
447e176b | 116 | } |
117 | #endif | |
118 | ||
adb78bd4 | 119 | static void |
120 | sslSetSelect(SslStateData * sslState) | |
121 | { | |
447e176b | 122 | size_t read_sz = SQUID_TCP_SO_RCVBUF; |
adb78bd4 | 123 | assert(sslState->server.fd > -1 || sslState->client.fd > -1); |
124 | if (sslState->client.fd > -1) { | |
125 | if (sslState->server.len > 0) { | |
126 | commSetSelect(sslState->client.fd, | |
127 | COMM_SELECT_WRITE, | |
128 | sslWriteClient, | |
129 | sslState, | |
130 | 0); | |
131 | } | |
447e176b | 132 | if (sslState->client.len < read_sz) { |
adb78bd4 | 133 | commSetSelect(sslState->client.fd, |
134 | COMM_SELECT_READ, | |
135 | sslReadClient, | |
136 | sslState, | |
137 | Config.Timeout.read); | |
138 | } | |
139 | } else if (sslState->client.len == 0) { | |
140 | comm_close(sslState->server.fd); | |
141 | } | |
142 | if (sslState->server.fd > -1) { | |
143 | if (sslState->client.len > 0) { | |
144 | commSetSelect(sslState->server.fd, | |
145 | COMM_SELECT_WRITE, | |
146 | sslWriteServer, | |
147 | sslState, | |
148 | 0); | |
149 | } | |
447e176b | 150 | #if DELAY_POOLS |
56e64999 | 151 | /* If this was allowed to return 0, there would be a possibility |
e82d6d21 | 152 | * of the socket becoming "hung" with data accumulating but no |
153 | * write handler (server.len==0) and no read handler (!(0<0)) and | |
154 | * no data flowing in the other direction. Hence the argument of | |
155 | * 1 as min. | |
156 | */ | |
56e64999 | 157 | read_sz = delayBytesWanted(sslState->request->delay_id, 1, read_sz); |
447e176b | 158 | #endif |
159 | if (sslState->server.len < read_sz) { | |
adb78bd4 | 160 | /* Have room to read more */ |
161 | commSetSelect(sslState->server.fd, | |
162 | COMM_SELECT_READ, | |
163 | sslReadServer, | |
164 | sslState, | |
165 | Config.Timeout.read); | |
166 | } | |
167 | } else if (sslState->client.fd == -1) { | |
168 | /* client already closed, nothing more to do */ | |
169 | } else if (sslState->server.len == 0) { | |
170 | comm_close(sslState->client.fd); | |
171 | } | |
172 | } | |
173 | ||
983061ed | 174 | /* Read from server side and queue it for writing to the client */ |
b8d8561b | 175 | static void |
b177367b | 176 | sslReadServer(int fd, void *data) |
983061ed | 177 | { |
b177367b | 178 | SslStateData *sslState = data; |
983061ed | 179 | int len; |
447e176b | 180 | size_t read_sz = SQUID_TCP_SO_RCVBUF - sslState->server.len; |
adb78bd4 | 181 | assert(fd == sslState->server.fd); |
182 | debug(26, 3) ("sslReadServer: FD %d, reading %d bytes at offset %d\n", | |
447e176b | 183 | fd, read_sz, sslState->server.len); |
184 | errno = 0; | |
185 | #if DELAY_POOLS | |
56e64999 | 186 | read_sz = delayBytesWanted(sslState->request->delay_id, 1, read_sz); |
447e176b | 187 | #endif |
886f2785 | 188 | Counter.syscalls.sock.reads++; |
447e176b | 189 | len = read(fd, sslState->server.buf + sslState->server.len, read_sz); |
adb78bd4 | 190 | debug(26, 3) ("sslReadServer: FD %d, read %d bytes\n", fd, len); |
ee1679df | 191 | if (len > 0) { |
adb78bd4 | 192 | fd_bytes(fd, len, FD_READ); |
447e176b | 193 | #if DELAY_POOLS |
194 | delayBytesIn(sslState->request->delay_id, len); | |
195 | #endif | |
a0f32775 | 196 | kb_incr(&Counter.server.all.kbytes_in, len); |
197 | kb_incr(&Counter.server.other.kbytes_in, len); | |
adb78bd4 | 198 | sslState->server.len += len; |
ee1679df | 199 | } |
adb78bd4 | 200 | cbdataLock(sslState); |
983061ed | 201 | if (len < 0) { |
a3d5953d | 202 | debug(50, 1) ("sslReadServer: FD %d: read failure: %s\n", |
adb78bd4 | 203 | fd, xstrerror()); |
204 | if (!ignoreErrno(errno)) | |
205 | comm_close(fd); | |
983061ed | 206 | } else if (len == 0) { |
adb78bd4 | 207 | comm_close(sslState->server.fd); |
983061ed | 208 | } |
adb78bd4 | 209 | if (cbdataValid(sslState)) |
210 | sslSetSelect(sslState); | |
211 | cbdataUnlock(sslState); | |
983061ed | 212 | } |
213 | ||
214 | /* Read from client side and queue it for writing to the server */ | |
b8d8561b | 215 | static void |
b177367b | 216 | sslReadClient(int fd, void *data) |
983061ed | 217 | { |
b177367b | 218 | SslStateData *sslState = data; |
983061ed | 219 | int len; |
adb78bd4 | 220 | assert(fd == sslState->client.fd); |
221 | debug(26, 3) ("sslReadClient: FD %d, reading %d bytes at offset %d\n", | |
222 | fd, SQUID_TCP_SO_RCVBUF - sslState->client.len, | |
223 | sslState->client.len); | |
886f2785 | 224 | Counter.syscalls.sock.reads++; |
adb78bd4 | 225 | len = read(fd, |
226 | sslState->client.buf + sslState->client.len, | |
227 | SQUID_TCP_SO_RCVBUF - sslState->client.len); | |
228 | debug(26, 3) ("sslReadClient: FD %d, read %d bytes\n", fd, len); | |
ee1679df | 229 | if (len > 0) { |
adb78bd4 | 230 | fd_bytes(fd, len, FD_READ); |
ee1679df | 231 | kb_incr(&Counter.client_http.kbytes_in, len); |
adb78bd4 | 232 | sslState->client.len += len; |
ee1679df | 233 | } |
adb78bd4 | 234 | cbdataLock(sslState); |
983061ed | 235 | if (len < 0) { |
a3d5953d | 236 | debug(50, 1) ("sslReadClient: FD %d: read failure: %s\n", |
983061ed | 237 | fd, xstrerror()); |
adb78bd4 | 238 | if (!ignoreErrno(errno)) |
239 | comm_close(fd); | |
983061ed | 240 | } else if (len == 0) { |
adb78bd4 | 241 | comm_close(fd); |
983061ed | 242 | } |
adb78bd4 | 243 | if (cbdataValid(sslState)) |
244 | sslSetSelect(sslState); | |
245 | cbdataUnlock(sslState); | |
983061ed | 246 | } |
247 | ||
248 | /* Writes data from the client buffer to the server side */ | |
b8d8561b | 249 | static void |
b177367b | 250 | sslWriteServer(int fd, void *data) |
983061ed | 251 | { |
b177367b | 252 | SslStateData *sslState = data; |
983061ed | 253 | int len; |
adb78bd4 | 254 | assert(fd == sslState->server.fd); |
255 | debug(26, 3) ("sslWriteServer: FD %d, %d bytes to write\n", | |
256 | fd, sslState->client.len); | |
886f2785 | 257 | Counter.syscalls.sock.writes++; |
adb78bd4 | 258 | len = write(fd, |
259 | sslState->client.buf, | |
260 | sslState->client.len); | |
261 | debug(26, 3) ("sslWriteServer: FD %d, %d bytes written\n", fd, len); | |
ee1679df | 262 | if (len > 0) { |
adb78bd4 | 263 | fd_bytes(fd, len, FD_WRITE); |
a0f32775 | 264 | kb_incr(&Counter.server.all.kbytes_out, len); |
265 | kb_incr(&Counter.server.other.kbytes_out, len); | |
adb78bd4 | 266 | assert(len <= sslState->client.len); |
267 | sslState->client.len -= len; | |
268 | if (sslState->client.len > 0) { | |
269 | /* we didn't write the whole thing */ | |
270 | xmemmove(sslState->client.buf, | |
271 | sslState->client.buf + len, | |
272 | sslState->client.len); | |
0a0bf5db | 273 | } |
983061ed | 274 | } |
adb78bd4 | 275 | cbdataLock(sslState); |
276 | if (len < 0) { | |
277 | debug(50, 1) ("sslWriteServer: FD %d: write failure: %s.\n", | |
278 | fd, xstrerror()); | |
279 | if (!ignoreErrno(errno)) | |
280 | comm_close(fd); | |
983061ed | 281 | } |
adb78bd4 | 282 | if (cbdataValid(sslState)) |
283 | sslSetSelect(sslState); | |
284 | cbdataUnlock(sslState); | |
983061ed | 285 | } |
286 | ||
287 | /* Writes data from the server buffer to the client side */ | |
b8d8561b | 288 | static void |
b177367b | 289 | sslWriteClient(int fd, void *data) |
983061ed | 290 | { |
b177367b | 291 | SslStateData *sslState = data; |
983061ed | 292 | int len; |
adb78bd4 | 293 | assert(fd == sslState->client.fd); |
294 | debug(26, 3) ("sslWriteClient: FD %d, %d bytes to write\n", | |
295 | fd, sslState->server.len); | |
886f2785 | 296 | Counter.syscalls.sock.writes++; |
adb78bd4 | 297 | len = write(fd, |
298 | sslState->server.buf, | |
299 | sslState->server.len); | |
300 | debug(26, 3) ("sslWriteClient: FD %d, %d bytes written\n", fd, len); | |
ee1679df | 301 | if (len > 0) { |
adb78bd4 | 302 | fd_bytes(fd, len, FD_WRITE); |
ee1679df | 303 | kb_incr(&Counter.client_http.kbytes_out, len); |
adb78bd4 | 304 | assert(len <= sslState->server.len); |
305 | sslState->server.len -= len; | |
306 | /* increment total object size */ | |
307 | if (sslState->size_ptr) | |
308 | *sslState->size_ptr += len; | |
309 | if (sslState->server.len > 0) { | |
310 | /* we didn't write the whole thing */ | |
311 | xmemmove(sslState->server.buf, | |
312 | sslState->server.buf + len, | |
313 | sslState->server.len); | |
0a0bf5db | 314 | } |
983061ed | 315 | } |
adb78bd4 | 316 | cbdataLock(sslState); |
317 | if (len < 0) { | |
318 | debug(50, 1) ("sslWriteClient: FD %d: write failure: %s.\n", | |
319 | fd, xstrerror()); | |
320 | if (!ignoreErrno(errno)) | |
321 | comm_close(fd); | |
983061ed | 322 | } |
adb78bd4 | 323 | if (cbdataValid(sslState)) |
324 | sslSetSelect(sslState); | |
325 | cbdataUnlock(sslState); | |
983061ed | 326 | } |
327 | ||
b8d8561b | 328 | static void |
5c5783a2 | 329 | sslTimeout(int fd, void *data) |
983061ed | 330 | { |
b177367b | 331 | SslStateData *sslState = data; |
a3d5953d | 332 | debug(26, 3) ("sslTimeout: FD %d\n", fd); |
adb78bd4 | 333 | if (sslState->client.fd > -1) |
334 | comm_close(sslState->client.fd); | |
335 | if (sslState->server.fd > -1) | |
336 | comm_close(sslState->server.fd); | |
983061ed | 337 | } |
338 | ||
b8d8561b | 339 | static void |
b177367b | 340 | sslConnected(int fd, void *data) |
983061ed | 341 | { |
b177367b | 342 | SslStateData *sslState = data; |
a3d5953d | 343 | debug(26, 3) ("sslConnected: FD %d sslState=%p\n", fd, sslState); |
54cff85f | 344 | xstrncpy(sslState->server.buf, conn_established, SQUID_TCP_SO_RCVBUF); |
983061ed | 345 | sslState->server.len = strlen(conn_established); |
adb78bd4 | 346 | sslSetSelect(sslState); |
983061ed | 347 | } |
348 | ||
b8d8561b | 349 | static void |
adb78bd4 | 350 | sslErrorComplete(int fdnotused, void *data, size_t sizenotused) |
30a4f2a8 | 351 | { |
adb78bd4 | 352 | SslStateData *sslState = data; |
9b312a19 | 353 | assert(sslState != NULL); |
adb78bd4 | 354 | if (sslState->client.fd > -1) |
355 | comm_close(sslState->client.fd); | |
356 | if (sslState->server.fd > -1) | |
357 | comm_close(sslState->server.fd); | |
30a4f2a8 | 358 | } |
359 | ||
983061ed | 360 | |
b8d8561b | 361 | static void |
79d39a72 | 362 | sslConnectDone(int fdnotused, int status, void *data) |
983061ed | 363 | { |
b15fe823 | 364 | SslStateData *sslState = data; |
30a4f2a8 | 365 | request_t *request = sslState->request; |
9b312a19 | 366 | ErrorState *err = NULL; |
edeb28fd | 367 | if (status == COMM_ERR_DNS) { |
a3d5953d | 368 | debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host); |
fe40a877 | 369 | err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND); |
9b312a19 | 370 | err->request = requestLink(request); |
371 | err->dnsserver_msg = xstrdup(dns_error_message); | |
372 | err->callback = sslErrorComplete; | |
373 | err->callback_data = sslState; | |
374 | errorSend(sslState->client.fd, err); | |
edeb28fd | 375 | } else if (status != COMM_OK) { |
fe40a877 | 376 | err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE); |
c45ed9ad | 377 | err->xerrno = errno; |
9b312a19 | 378 | err->host = xstrdup(sslState->host); |
379 | err->port = sslState->port; | |
380 | err->request = requestLink(request); | |
381 | err->callback = sslErrorComplete; | |
382 | err->callback_data = sslState; | |
383 | errorSend(sslState->client.fd, err); | |
fe40a877 | 384 | } else { |
385 | if (sslState->proxying) | |
386 | sslProxyConnected(sslState->server.fd, sslState); | |
4e3f29eb | 387 | else |
fe40a877 | 388 | sslConnected(sslState->server.fd, sslState); |
1afe05c5 | 389 | commSetTimeout(sslState->server.fd, |
390 | Config.Timeout.read, | |
391 | sslTimeout, | |
392 | sslState); | |
447e176b | 393 | #if DELAY_POOLS |
394 | commSetDefer(sslState->server.fd, sslDeferServerRead, sslState->request); | |
395 | #endif | |
983061ed | 396 | } |
983061ed | 397 | } |
30a4f2a8 | 398 | |
770f051d | 399 | void |
9b312a19 | 400 | sslStart(int fd, const char *url, request_t * request, size_t * size_ptr) |
30a4f2a8 | 401 | { |
402 | /* Create state structure. */ | |
403 | SslStateData *sslState = NULL; | |
404 | int sock; | |
9b312a19 | 405 | ErrorState *err = NULL; |
a3d5953d | 406 | debug(26, 3) ("sslStart: '%s %s'\n", |
30a4f2a8 | 407 | RequestMethodStr[request->method], url); |
a0f32775 | 408 | Counter.server.all.requests++; |
409 | Counter.server.other.requests++; | |
30a4f2a8 | 410 | /* Create socket. */ |
16b204c4 | 411 | sock = comm_open(SOCK_STREAM, |
412 | 0, | |
413 | Config.Addrs.tcp_outgoing, | |
414 | 0, | |
415 | COMM_NONBLOCKING, | |
416 | url); | |
30a4f2a8 | 417 | if (sock == COMM_ERROR) { |
a3d5953d | 418 | debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); |
fe40a877 | 419 | err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); |
c45ed9ad | 420 | err->xerrno = errno; |
9b312a19 | 421 | err->request = requestLink(request); |
422 | errorSend(fd, err); | |
770f051d | 423 | return; |
30a4f2a8 | 424 | } |
425 | sslState = xcalloc(1, sizeof(SslStateData)); | |
db1cd23c | 426 | cbdataAdd(sslState, cbdataXfree, 0); |
30a4f2a8 | 427 | sslState->url = xstrdup(url); |
428 | sslState->request = requestLink(request); | |
30a4f2a8 | 429 | sslState->size_ptr = size_ptr; |
430 | sslState->client.fd = fd; | |
431 | sslState->server.fd = sock; | |
432 | sslState->server.buf = xmalloc(SQUID_TCP_SO_RCVBUF); | |
433 | sslState->client.buf = xmalloc(SQUID_TCP_SO_RCVBUF); | |
434 | comm_add_close_handler(sslState->server.fd, | |
adb78bd4 | 435 | sslServerClosed, |
cd1fb0eb | 436 | sslState); |
30a4f2a8 | 437 | comm_add_close_handler(sslState->client.fd, |
b177367b | 438 | sslClientClosed, |
cd1fb0eb | 439 | sslState); |
5c5783a2 | 440 | commSetTimeout(sslState->client.fd, |
4f92c80c | 441 | Config.Timeout.lifetime, |
442 | sslTimeout, | |
443 | sslState); | |
cf1edeae | 444 | commSetTimeout(sslState->server.fd, |
445 | Config.Timeout.connect, | |
446 | sslTimeout, | |
447 | sslState); | |
b6c0e933 | 448 | peerSelect(request, |
641941c0 | 449 | NULL, |
b6c0e933 | 450 | sslPeerSelectComplete, |
b6c0e933 | 451 | sslState); |
adb78bd4 | 452 | /* |
453 | * Disable the client read handler until peer selection is complete | |
454 | * Take control away from client_side.c. | |
455 | */ | |
456 | commSetSelect(sslState->client.fd, COMM_SELECT_READ, NULL, NULL, 0); | |
30a4f2a8 | 457 | } |
98ffb7e4 | 458 | |
b8d8561b | 459 | static void |
b177367b | 460 | sslProxyConnected(int fd, void *data) |
98ffb7e4 | 461 | { |
b177367b | 462 | SslStateData *sslState = data; |
e1e72f06 | 463 | MemBuf mb; |
464 | HttpHeader hdr_out; | |
465 | Packer p; | |
b4b5fd95 | 466 | http_state_flags flags; |
a3d5953d | 467 | debug(26, 3) ("sslProxyConnected: FD %d sslState=%p\n", fd, sslState); |
b4b5fd95 | 468 | memset(&flags, '\0', sizeof(flags)); |
e1e72f06 | 469 | memBufDefInit(&mb); |
470 | memBufPrintf(&mb, "CONNECT %s HTTP/1.0\r\n", sslState->url); | |
471 | httpBuildRequestHeader(sslState->request, | |
472 | sslState->request, | |
5999b776 | 473 | NULL, /* StoreEntry */ |
e1e72f06 | 474 | &hdr_out, |
475 | sslState->client.fd, | |
b4b5fd95 | 476 | flags); /* flags */ |
e1e72f06 | 477 | packerToMemInit(&p, &mb); |
478 | httpHeaderPackInto(&hdr_out, &p); | |
479 | httpHeaderClean(&hdr_out); | |
480 | packerClean(&p); | |
481 | memBufAppend(&mb, "\r\n", 2); | |
482 | xstrncpy(sslState->client.buf, mb.buf, SQUID_TCP_SO_RCVBUF); | |
483 | debug(26, 3) ("sslProxyConnected: Sending {%s}\n", sslState->client.buf); | |
484 | sslState->client.len = mb.size; | |
e1e72f06 | 485 | memBufClean(&mb); |
86cf9987 | 486 | commSetTimeout(sslState->server.fd, |
487 | Config.Timeout.read, | |
488 | sslTimeout, | |
489 | sslState); | |
adb78bd4 | 490 | sslSetSelect(sslState); |
98ffb7e4 | 491 | } |
33ea9fff | 492 | |
33ea9fff | 493 | static void |
db1cd23c | 494 | sslPeerSelectComplete(FwdServer * fs, void *data) |
33ea9fff | 495 | { |
496 | SslStateData *sslState = data; | |
497 | request_t *request = sslState->request; | |
deb79f06 | 498 | peer *g = NULL; |
db1cd23c | 499 | |
500 | if (fs == NULL) { | |
501 | ErrorState *err; | |
502 | err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE); | |
503 | err->request = requestLink(sslState->request); | |
504 | err->callback = sslErrorComplete; | |
505 | err->callback_data = sslState; | |
506 | errorSend(sslState->client.fd, err); | |
507 | return; | |
508 | } | |
509 | sslState->proxying = fs->peer ? 1 : 0; | |
510 | sslState->host = fs->peer ? fs->peer->host : request->host; | |
511 | if (fs->peer == NULL) { | |
b3b64e58 | 512 | sslState->port = request->port; |
db1cd23c | 513 | } else if (fs->peer->http_port != 0) { |
514 | sslState->port = fs->peer->http_port; | |
515 | } else if ((g = peerFindByName(fs->peer->host))) { | |
b3b64e58 | 516 | sslState->port = g->http_port; |
33ea9fff | 517 | } else { |
b3b64e58 | 518 | sslState->port = CACHE_HTTP_PORT; |
33ea9fff | 519 | } |
edeb28fd | 520 | commConnectStart(sslState->server.fd, |
521 | sslState->host, | |
522 | sslState->port, | |
523 | sslConnectDone, | |
33ea9fff | 524 | sslState); |
525 | } |