]> git.ipfire.org Git - thirdparty/squid.git/blame - src/tunnel.cc
Summary: Final MSVC fixups.
[thirdparty/squid.git] / src / tunnel.cc
CommitLineData
95d659f0 1
983061ed 2/*
190154cf 3 * $Id: tunnel.cc,v 1.145 2003/08/10 11:00:44 robertc Exp $
983061ed 4 *
30a4f2a8 5 * DEBUG: section 26 Secure Sockets Layer Proxy
6 * AUTHOR: Duane Wessels
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 9 * ----------------------------------------------------------
30a4f2a8 10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see 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"
528b2c61 37#include "HttpRequest.h"
38#include "fde.h"
9f518b4a 39#include "comm.h"
528b2c61 40#include "client_side_request.h"
4fb35c3c 41#include "ACLChecklist.h"
b67e2c8c 42#if DELAY_POOLS
43#include "DelayId.h"
44#endif
a46d2c0e 45#include "client_side.h"
983061ed 46
a46d2c0e 47class SslStateData
62e76326 48{
a46d2c0e 49
50public:
51
52 class Connection;
53 void *operator new(size_t);
54 void operator delete (void *);
a46d2c0e 55 static void ReadClient(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data);
56 static void ReadServer(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data);
57 static void WriteClientDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data);
58 static void WriteServerDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data);
59
60 bool noConnections() const;
983061ed 61 char *url;
98ffb7e4 62 char *host; /* either request->host or proxy host */
63 u_short port;
190154cf 64 HttpRequest *request;
64d8034e 65 FwdServer *servers;
62e76326 66
a46d2c0e 67 class Connection
62e76326 68 {
a46d2c0e 69
70 public:
71 Connection() : len (0),buf ((char *)xmalloc(SQUID_TCP_SO_RCVBUF)), size_ptr(NULL), fd_(-1){}
72
73 ~Connection();
74 int const & fd() const { return fd_;}
75
76 void fd(int const newFD);
77 int bytesWanted(int lower=0, int upper = INT_MAX) const;
78 void bytesIn(int const &);
79#if DELAY_POOLS
80
81 void setDelayId(DelayId const &);
82#endif
83
84 void error(int const xerrno);
85 int Connection::debugLevelForError(int const xerrno) const;
86 void closeIfOpen();
87 void dataSent (size_t amount);
62e76326 88 int len;
89 char *buf;
a46d2c0e 90 size_t *size_ptr; /* pointer to size in an ConnStateData for logging */
62e76326 91
a46d2c0e 92 private:
93 int fd_;
59715b38 94#if DELAY_POOLS
62e76326 95
a46d2c0e 96 DelayId delayId;
59715b38 97#endif
62e76326 98
a46d2c0e 99 };
100
101 Connection client, server;
102 int *status_ptr; /* pointer to status for logging */
103 void copyRead(Connection &from, IOCB *completion);
104
105private:
106 CBDATA_CLASS(SslStateData);
107 void copy (size_t len, comm_err_t errcode, int xerrno, Connection &from, Connection &to, IOWCB *);
108 void readServer(char *buf, size_t len, comm_err_t errcode, int xerrno);
109 void readClient(char *buf, size_t len, comm_err_t errcode, int xerrno);
110 void writeClientDone(char *buf, size_t len, comm_err_t flag, int xerrno);
111 void writeServerDone(char *buf, size_t len, comm_err_t flag, int xerrno);
112};
983061ed 113
0ee4272b 114static const char *const conn_established = "HTTP/1.0 200 Connection established\r\n\r\n";
983061ed 115
54cff85f 116static CNCB sslConnectDone;
117static ERCB sslErrorComplete;
adb78bd4 118static PF sslServerClosed;
54cff85f 119static PF sslClientClosed;
5c5783a2 120static PF sslTimeout;
54cff85f 121static PSC sslPeerSelectComplete;
adb78bd4 122static void sslStateFree(SslStateData * sslState);
f5b8bbc4 123static void sslConnected(int fd, void *);
124static void sslProxyConnected(int fd, void *);
30a4f2a8 125
b8d8561b 126static void
adb78bd4 127sslServerClosed(int fd, void *data)
30a4f2a8 128{
e6ccf245 129 SslStateData *sslState = (SslStateData *)data;
adb78bd4 130 debug(26, 3) ("sslServerClosed: FD %d\n", fd);
a46d2c0e 131 assert(fd == sslState->server.fd());
132 sslState->server.fd(-1);
62e76326 133
a46d2c0e 134 if (sslState->noConnections())
62e76326 135 sslStateFree(sslState);
30a4f2a8 136}
137
b177367b 138static void
139sslClientClosed(int fd, void *data)
30a4f2a8 140{
e6ccf245 141 SslStateData *sslState = (SslStateData *)data;
a3d5953d 142 debug(26, 3) ("sslClientClosed: FD %d\n", fd);
a46d2c0e 143 assert(fd == sslState->client.fd());
144 sslState->client.fd(-1);
62e76326 145
a46d2c0e 146 if (sslState->noConnections())
62e76326 147 sslStateFree(sslState);
30a4f2a8 148}
983061ed 149
b177367b 150static void
adb78bd4 151sslStateFree(SslStateData * sslState)
983061ed 152{
adb78bd4 153 debug(26, 3) ("sslStateFree: sslState=%p\n", sslState);
154 assert(sslState != NULL);
a46d2c0e 155 assert(sslState->noConnections());
adb78bd4 156 safe_free(sslState->url);
64d8034e 157 fwdServersFree(&sslState->servers);
adb78bd4 158 sslState->host = NULL;
30a4f2a8 159 requestUnlink(sslState->request);
7dd44885 160 sslState->request = NULL;
00d77d6b 161 delete sslState;
983061ed 162}
163
a46d2c0e 164SslStateData::Connection::~Connection()
165{
166 safe_free (buf);
167}
168
169int
170SslStateData::Connection::bytesWanted(int lowerbound, int upperbound) const
447e176b 171{
a46d2c0e 172#if DELAY_POOLS
173 return delayId.bytesWanted(lowerbound, upperbound);
174#else
62e76326 175
a46d2c0e 176 return INT_MAX;
177#endif
178}
62e76326 179
a46d2c0e 180void
181SslStateData::Connection::bytesIn(int const &count)
182{
183#if DELAY_POOLS
184 delayId.bytesIn(count);
185#endif
62e76326 186
a46d2c0e 187 len += count;
447e176b 188}
62e76326 189
a46d2c0e 190int
191SslStateData::Connection::debugLevelForError(int const xerrno) const
192{
193#ifdef ECONNRESET
194
195 if (xerrno == ECONNRESET)
196 return 2;
197
447e176b 198#endif
199
a46d2c0e 200 if (ignoreErrno(xerrno))
201 return 3;
202
203 return 1;
204}
adb78bd4 205
983061ed 206/* Read from server side and queue it for writing to the client */
a46d2c0e 207void
208SslStateData::ReadServer(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data)
983061ed 209{
e6ccf245 210 SslStateData *sslState = (SslStateData *)data;
a46d2c0e 211 assert (cbdataReferenceValid (sslState));
c4b7a5a9 212
a46d2c0e 213 assert(fd == sslState->server.fd());
214 sslState->readServer(buf, len, errcode, xerrno);
215}
62e76326 216
a46d2c0e 217void
218SslStateData::readServer(char *buf, size_t len, comm_err_t errcode, int xerrno)
219{
220 /*
221 * Bail out early on COMM_ERR_CLOSING
222 * - close handlers will tidy up for us
223 */
a55f4cea 224
a46d2c0e 225 if (errcode == COMM_ERR_CLOSING)
226 return;
62e76326 227
a46d2c0e 228 debug(26, 3) ("sslReadServer: FD %d, read %d bytes\n", server.fd(), (int)len);
62e76326 229
ee1679df 230 if (len > 0) {
a46d2c0e 231 server.bytesIn(len);
62e76326 232 kb_incr(&statCounter.server.all.kbytes_in, len);
233 kb_incr(&statCounter.server.other.kbytes_in, len);
ee1679df 234 }
62e76326 235
a46d2c0e 236 copy (len, errcode, xerrno, server, client, WriteClientDone);
237}
238
239void
240SslStateData::Connection::error(int const xerrno)
241{
242 /* XXX fixme xstrerror and xerrno... */
243 errno = xerrno;
244
245 if (xerrno == COMM_ERR_CLOSING)
a55f4cea 246 return;
62e76326 247
a46d2c0e 248 debug(50, debugLevelForError(xerrno))
249 ("sslReadServer: FD %d: read failure: %s\n", fd(), xstrerror());
62e76326 250
a46d2c0e 251 if (!ignoreErrno(xerrno))
252 comm_close(fd());
983061ed 253}
254
255/* Read from client side and queue it for writing to the server */
a46d2c0e 256void
257SslStateData::ReadClient(int fd, char *buf, size_t len, comm_err_t errcode, int xerrno, void *data)
983061ed 258{
e6ccf245 259 SslStateData *sslState = (SslStateData *)data;
a46d2c0e 260 assert (cbdataReferenceValid (sslState));
62e76326 261
a46d2c0e 262 assert(fd == sslState->client.fd());
263 sslState->readClient(buf, len, errcode, xerrno);
264}
62e76326 265
a46d2c0e 266void
267SslStateData::readClient(char *buf, size_t len, comm_err_t errcode, int xerrno)
268{
269 /*
270 * Bail out early on COMM_ERR_CLOSING
271 * - close handlers will tidy up for us
272 */
a55f4cea 273
a46d2c0e 274 if (errcode == COMM_ERR_CLOSING)
275 return;
a55f4cea 276
a46d2c0e 277 debug(26, 3) ("sslReadClient: FD %d, read %d bytes\n", client.fd(), (int) len);
62e76326 278
a46d2c0e 279 if (len > 0) {
280 client.bytesIn(len);
281 kb_incr(&statCounter.client_http.kbytes_in, len);
282 }
62e76326 283
a46d2c0e 284 copy (len, errcode, xerrno, client, server, WriteServerDone);
285}
62e76326 286
a46d2c0e 287void
288SslStateData::copy (size_t len, comm_err_t errcode, int xerrno, Connection &from, Connection &to, IOWCB *completion)
289{
290 /* I think this is to prevent free-while-in-a-callback behaviour
291 * - RBC 20030229
292 */
293 cbdataInternalLock(this); /* ??? should be locked by the caller... */
62e76326 294
a46d2c0e 295 if (len < 0 || errcode)
296 from.error (xerrno);
297 else if (len == 0 || to.fd() == -1) {
298 comm_close(from.fd());
62e76326 299 /* Only close the remote end if we've finished queueing data to it */
300
a46d2c0e 301 if (from.len == 0 && to.fd() != -1) {
302 comm_close(to.fd());
c4b7a5a9 303 }
a46d2c0e 304 } else if (cbdataReferenceValid(this))
305 comm_write(to.fd(), from.buf, len, completion, this);
a55f4cea 306
a46d2c0e 307 cbdataInternalUnlock(this); /* ??? */
983061ed 308}
309
310/* Writes data from the client buffer to the server side */
a46d2c0e 311void
312SslStateData::WriteServerDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
983061ed 313{
e6ccf245 314 SslStateData *sslState = (SslStateData *)data;
a46d2c0e 315 assert (cbdataReferenceValid (sslState));
316
317 assert(fd == sslState->server.fd());
318 sslState->writeServerDone(buf, len, flag, xerrno);
319}
a55f4cea 320
a46d2c0e 321void
322SslStateData::writeServerDone(char *buf, size_t len, comm_err_t flag, int xerrno)
323{
324 debug(26, 3) ("sslWriteServer: FD %d, %d bytes written\n", server.fd(), (int)len);
c4b7a5a9 325 /* Valid data */
62e76326 326
ee1679df 327 if (len > 0) {
62e76326 328 kb_incr(&statCounter.server.all.kbytes_out, len);
329 kb_incr(&statCounter.server.other.kbytes_out, len);
a46d2c0e 330 client.dataSent(len);
c4b7a5a9 331 }
62e76326 332
a46d2c0e 333 /* EOF */
334 if (len == 0) {
335 comm_close(server.fd());
336 return;
337 }
62e76326 338
a46d2c0e 339 /* If the other end has closed, so should we */
340 if (client.fd() == -1) {
341 comm_close(server.fd());
a55f4cea 342 return;
c4b7a5a9 343 }
62e76326 344
a46d2c0e 345 cbdataInternalLock(this); /* ??? should be locked by the caller... */
346 /* Error? */
347
348 if (len < 0)
349 server.error(xerrno);
350 else if (cbdataReferenceValid(this))
351 copyRead(client, ReadClient);
352
353 cbdataInternalUnlock(this); /* ??? */
983061ed 354}
355
356/* Writes data from the server buffer to the client side */
a46d2c0e 357void
358SslStateData::WriteClientDone(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
983061ed 359{
e6ccf245 360 SslStateData *sslState = (SslStateData *)data;
a46d2c0e 361 assert (cbdataReferenceValid (sslState));
362
363 assert(fd == sslState->client.fd());
364 sslState->writeClientDone(buf, len, flag, xerrno);
365}
366
367void
368SslStateData::Connection::dataSent (size_t amount)
369{
370 assert(amount == (size_t)len);
371 len =0;
372 /* increment total object size */
373
374 if (size_ptr)
375 *size_ptr += amount;
376}
377
378void
379SslStateData::writeClientDone(char *buf, size_t len, comm_err_t flag, int xerrno)
380{
381 debug(26, 3) ("sslWriteClient: FD %d, %d bytes written\n", client.fd(), (int)len);
62e76326 382
ee1679df 383 if (len > 0) {
62e76326 384 kb_incr(&statCounter.client_http.kbytes_out, len);
a46d2c0e 385 server.dataSent(len);
c4b7a5a9 386 }
62e76326 387
a55f4cea 388 /* EOF */
a46d2c0e 389 if (len == 0) {
390 comm_close(client.fd());
62e76326 391 return;
983061ed 392 }
62e76326 393
a46d2c0e 394 /* If the other end has closed, so should we */
395 if (server.fd() == -1) {
396 comm_close(client.fd());
a55f4cea 397 return;
983061ed 398 }
62e76326 399
a46d2c0e 400 cbdataInternalLock(this); /* ??? should be locked by the caller... */
401 /* Error? */
a55f4cea 402
a46d2c0e 403 if (len < 0)
404 client.error(xerrno);
405 else if (cbdataReferenceValid(this))
406 copyRead(server, ReadServer);
2c202d66 407
a46d2c0e 408 cbdataInternalUnlock(this); /* ??? */
983061ed 409}
410
b8d8561b 411static void
5c5783a2 412sslTimeout(int fd, void *data)
983061ed 413{
e6ccf245 414 SslStateData *sslState = (SslStateData *)data;
a3d5953d 415 debug(26, 3) ("sslTimeout: FD %d\n", fd);
a46d2c0e 416 /* Temporary lock to protect our own feets (comm_close -> sslClientClosed -> Free) */
417 cbdataInternalLock(sslState);
a55f4cea 418
a46d2c0e 419 sslState->client.closeIfOpen();
420 sslState->server.closeIfOpen();
421 cbdataInternalUnlock(sslState);
422}
62e76326 423
a46d2c0e 424void
425SslStateData::Connection::closeIfOpen()
426{
427 if (fd() != -1)
428 comm_close(fd());
429}
430
431void
432SslStateData::copyRead(Connection &from, IOCB *completion)
433{
434 assert(from.len == 0);
435 comm_read(from.fd(), from.buf, from.bytesWanted(1, SQUID_TCP_SO_RCVBUF), completion, this);
983061ed 436}
437
a46d2c0e 438
c4b7a5a9 439static void
4dcb4cc5 440sslConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
c4b7a5a9 441{
62e76326 442 SslStateData *sslState = (SslStateData *)data;
443
444 if (flag != COMM_OK) {
445 sslErrorComplete(fd, data, 0);
446 return;
447 }
448
449 if (cbdataReferenceValid(sslState)) {
a46d2c0e 450 sslState->copyRead(sslState->server, SslStateData::ReadServer);
451 sslState->copyRead(sslState->client, SslStateData::ReadClient);
62e76326 452 }
c4b7a5a9 453}
454
c4b7a5a9 455/*
456 * handle the write completion from a proxy request to an upstream proxy
457 */
458static void
459sslProxyConnectedWriteDone(int fd, char *buf, size_t size, comm_err_t flag, void *data)
460{
a46d2c0e 461 sslConnectedWriteDone(fd, buf, size, flag, 0, data);
c4b7a5a9 462}
463
b8d8561b 464static void
b177367b 465sslConnected(int fd, void *data)
983061ed 466{
e6ccf245 467 SslStateData *sslState = (SslStateData *)data;
a3d5953d 468 debug(26, 3) ("sslConnected: FD %d sslState=%p\n", fd, sslState);
974ba0ee 469 *sslState->status_ptr = HTTP_OK;
a46d2c0e 470 comm_write(sslState->client.fd(), conn_established, strlen(conn_established),
62e76326 471 sslConnectedWriteDone, sslState);
983061ed 472}
473
b8d8561b 474static void
adb78bd4 475sslErrorComplete(int fdnotused, void *data, size_t sizenotused)
30a4f2a8 476{
e6ccf245 477 SslStateData *sslState = (SslStateData *)data;
9b312a19 478 assert(sslState != NULL);
62e76326 479
a46d2c0e 480 if (sslState->client.fd() > -1)
481 comm_close(sslState->client.fd());
62e76326 482
a46d2c0e 483 if (sslState->server.fd() > -1)
484 comm_close(sslState->server.fd());
30a4f2a8 485}
486
983061ed 487
b8d8561b 488static void
f3400a93 489sslConnectDone(int fdnotused, comm_err_t status, int xerrno, void *data)
983061ed 490{
e6ccf245 491 SslStateData *sslState = (SslStateData *)data;
190154cf 492 HttpRequest *request = sslState->request;
9b312a19 493 ErrorState *err = NULL;
62e76326 494
29b8d8d6 495 if (sslState->servers->_peer)
62e76326 496 hierarchyNote(&sslState->request->hier, sslState->servers->code,
497 sslState->servers->_peer->host);
890b0fa8 498 else if (Config.onoff.log_ip_on_direct)
62e76326 499 hierarchyNote(&sslState->request->hier, sslState->servers->code,
a46d2c0e 500 fd_table[sslState->server.fd()].ipaddr);
890b0fa8 501 else
62e76326 502 hierarchyNote(&sslState->request->hier, sslState->servers->code,
503 sslState->host);
504
edeb28fd 505 if (status == COMM_ERR_DNS) {
62e76326 506 debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host);
507 err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND);
508 *sslState->status_ptr = HTTP_NOT_FOUND;
509 err->request = requestLink(request);
510 err->dnsserver_msg = xstrdup(dns_error_message);
511 err->callback = sslErrorComplete;
512 err->callback_data = sslState;
a46d2c0e 513 errorSend(sslState->client.fd(), err);
edeb28fd 514 } else if (status != COMM_OK) {
62e76326 515 err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE);
516 *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
f3400a93 517 err->xerrno = xerrno;
62e76326 518 err->host = xstrdup(sslState->host);
519 err->port = sslState->port;
520 err->request = requestLink(request);
521 err->callback = sslErrorComplete;
522 err->callback_data = sslState;
a46d2c0e 523 errorSend(sslState->client.fd(), err);
fe40a877 524 } else {
62e76326 525 if (sslState->servers->_peer)
a46d2c0e 526 sslProxyConnected(sslState->server.fd(), sslState);
62e76326 527 else {
a46d2c0e 528 sslConnected(sslState->server.fd(), sslState);
62e76326 529 }
530
a46d2c0e 531 commSetTimeout(sslState->server.fd(),
62e76326 532 Config.Timeout.read,
533 sslTimeout,
534 sslState);
983061ed 535 }
983061ed 536}
30a4f2a8 537
770f051d 538void
d5964d58 539sslStart(clientHttpRequest * http, size_t * size_ptr, int *status_ptr)
30a4f2a8 540{
541 /* Create state structure. */
542 SslStateData *sslState = NULL;
543 int sock;
9b312a19 544 ErrorState *err = NULL;
f1003989 545 int answer;
98242069 546 int fd = http->getConn()->fd;
190154cf 547 HttpRequest *request = http->request;
d5964d58 548 char *url = http->uri;
f1003989 549 /*
a4b8110e 550 * client_addr == no_addr indicates this is an "internal" request
551 * from peer_digest.c, asn.c, netdb.c, etc and should always
552 * be allowed. yuck, I know.
553 */
62e76326 554
f1003989 555 if (request->client_addr.s_addr != no_addr.s_addr) {
62e76326 556 /*
557 * Check if this host is allowed to fetch MISSES from us (miss_access)
558 */
559 ACLChecklist ch;
560 ch.src_addr = request->client_addr;
561 ch.my_addr = request->my_addr;
562 ch.my_port = request->my_port;
563 ch.request = requestLink(request);
564 answer = aclCheckFast(Config.accessList.miss, &ch);
565
566 if (answer == 0) {
567 err = errorCon(ERR_FORWARDING_DENIED, HTTP_FORBIDDEN);
568 *status_ptr = HTTP_FORBIDDEN;
569 err->request = requestLink(request);
570 err->src_addr = request->client_addr;
571 errorSend(fd, err);
572 return;
573 }
f1003989 574 }
62e76326 575
a3d5953d 576 debug(26, 3) ("sslStart: '%s %s'\n",
62e76326 577 RequestMethodStr[request->method], url);
83704487 578 statCounter.server.all.requests++;
579 statCounter.server.other.requests++;
30a4f2a8 580 /* Create socket. */
d6827718 581 sock = comm_openex(SOCK_STREAM,
bdb741f4 582 IPPROTO_TCP,
62e76326 583 getOutgoingAddr(request),
584 0,
585 COMM_NONBLOCKING,
586 getOutgoingTOS(request),
587 url);
588
30a4f2a8 589 if (sock == COMM_ERROR) {
62e76326 590 debug(26, 4) ("sslStart: Failed because we're out of sockets.\n");
591 err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
592 *status_ptr = HTTP_INTERNAL_SERVER_ERROR;
593 err->xerrno = errno;
594 err->request = requestLink(request);
595 errorSend(fd, err);
596 return;
30a4f2a8 597 }
62e76326 598
a46d2c0e 599 sslState = new SslStateData;
59715b38 600#if DELAY_POOLS
62e76326 601
a46d2c0e 602 sslState->server.setDelayId(DelayId::DelayClient(http));
59715b38 603#endif
62e76326 604
30a4f2a8 605 sslState->url = xstrdup(url);
606 sslState->request = requestLink(request);
a46d2c0e 607 sslState->server.size_ptr = size_ptr;
974ba0ee 608 sslState->status_ptr = status_ptr;
a46d2c0e 609 sslState->client.fd(fd);
610 sslState->server.fd(sock);
611 comm_add_close_handler(sslState->server.fd(),
62e76326 612 sslServerClosed,
613 sslState);
a46d2c0e 614 comm_add_close_handler(sslState->client.fd(),
62e76326 615 sslClientClosed,
616 sslState);
a46d2c0e 617 commSetTimeout(sslState->client.fd(),
62e76326 618 Config.Timeout.lifetime,
619 sslTimeout,
620 sslState);
a46d2c0e 621 commSetTimeout(sslState->server.fd(),
62e76326 622 Config.Timeout.connect,
623 sslTimeout,
624 sslState);
b6c0e933 625 peerSelect(request,
62e76326 626 NULL,
627 sslPeerSelectComplete,
628 sslState);
adb78bd4 629 /*
630 * Disable the client read handler until peer selection is complete
631 * Take control away from client_side.c.
632 */
a46d2c0e 633 commSetSelect(sslState->client.fd(), COMM_SELECT_READ, NULL, NULL, 0);
30a4f2a8 634}
98ffb7e4 635
b8d8561b 636static void
b177367b 637sslProxyConnected(int fd, void *data)
98ffb7e4 638{
e6ccf245 639 SslStateData *sslState = (SslStateData *)data;
e1e72f06 640 MemBuf mb;
75faaa7a 641 HttpHeader hdr_out(hoRequest);
e1e72f06 642 Packer p;
b4b5fd95 643 http_state_flags flags;
a3d5953d 644 debug(26, 3) ("sslProxyConnected: FD %d sslState=%p\n", fd, sslState);
b4b5fd95 645 memset(&flags, '\0', sizeof(flags));
2f2b4d20 646 flags.proxying = sslState->request->flags.proxying;
e1e72f06 647 memBufDefInit(&mb);
648 memBufPrintf(&mb, "CONNECT %s HTTP/1.0\r\n", sslState->url);
649 httpBuildRequestHeader(sslState->request,
62e76326 650 sslState->request,
651 NULL, /* StoreEntry */
652 &hdr_out,
653 flags); /* flags */
e1e72f06 654 packerToMemInit(&p, &mb);
655 httpHeaderPackInto(&hdr_out, &p);
656 httpHeaderClean(&hdr_out);
657 packerClean(&p);
658 memBufAppend(&mb, "\r\n", 2);
c4b7a5a9 659
a46d2c0e 660 comm_old_write_mbuf(sslState->server.fd(), mb, sslProxyConnectedWriteDone, sslState);
c4b7a5a9 661
a46d2c0e 662 commSetTimeout(sslState->server.fd(),
62e76326 663 Config.Timeout.read,
664 sslTimeout,
665 sslState);
98ffb7e4 666}
33ea9fff 667
33ea9fff 668static void
db1cd23c 669sslPeerSelectComplete(FwdServer * fs, void *data)
33ea9fff 670{
e6ccf245 671 SslStateData *sslState = (SslStateData *)data;
190154cf 672 HttpRequest *request = sslState->request;
deb79f06 673 peer *g = NULL;
62e76326 674
db1cd23c 675 if (fs == NULL) {
62e76326 676 ErrorState *err;
677 err = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE);
678 *sslState->status_ptr = HTTP_SERVICE_UNAVAILABLE;
679 err->request = requestLink(sslState->request);
680 err->callback = sslErrorComplete;
681 err->callback_data = sslState;
a46d2c0e 682 errorSend(sslState->client.fd(), err);
62e76326 683 return;
db1cd23c 684 }
62e76326 685
64d8034e 686 sslState->servers = fs;
29b8d8d6 687 sslState->host = fs->_peer ? fs->_peer->host : request->host;
62e76326 688
29b8d8d6 689 if (fs->_peer == NULL) {
62e76326 690 sslState->port = request->port;
29b8d8d6 691 } else if (fs->_peer->http_port != 0) {
62e76326 692 sslState->port = fs->_peer->http_port;
29b8d8d6 693 } else if ((g = peerFindByName(fs->_peer->host))) {
62e76326 694 sslState->port = g->http_port;
33ea9fff 695 } else {
62e76326 696 sslState->port = CACHE_HTTP_PORT;
33ea9fff 697 }
62e76326 698
29b8d8d6 699 if (fs->_peer) {
62e76326 700 sslState->request->peer_login = fs->_peer->login;
701 sslState->request->flags.proxying = 1;
1f38f50a 702 } else {
62e76326 703 sslState->request->peer_login = NULL;
704 sslState->request->flags.proxying = 0;
1f38f50a 705 }
62e76326 706
59715b38 707#if DELAY_POOLS
708 /* no point using the delayIsNoDelay stuff since ssl is nice and simple */
a46d2c0e 709 if (g && g->options.no_delay)
710 sslState->server.setDelayId(DelayId());
62e76326 711
59715b38 712#endif
a46d2c0e 713
714 commConnectStart(sslState->server.fd(),
62e76326 715 sslState->host,
716 sslState->port,
717 sslConnectDone,
718 sslState);
33ea9fff 719}
a46d2c0e 720
721CBDATA_CLASS_INIT(SslStateData);
722
723void *
724SslStateData::operator new (size_t)
725{
726 CBDATA_INIT_TYPE(SslStateData);
727 SslStateData *result = cbdataAlloc(SslStateData);
728 return result;
729}
730
731void
732SslStateData::operator delete (void *address)
733{
734 SslStateData *t = static_cast<SslStateData *>(address);
735 cbdataFree(t);
736}
737
a46d2c0e 738void
739SslStateData::Connection::fd(int const newFD)
740{
741 fd_ = newFD;
742}
743
744bool
745SslStateData::noConnections() const
746{
747 return (server.fd() == -1) && (client.fd() == -1);
748}
749
750#if DELAY_POOLS
751void
752SslStateData::Connection::setDelayId(DelayId const &newDelay)
753{
754 delayId = newDelay;
755}
756
757#endif