3
* $Id: forward.cc,v 1.151 2006/09/13 15:54:21 adrian Exp $
5
* DEBUG: section 17 Request Forwarding
6
* AUTHOR: Duane Wessels
8
* SQUID Web Proxy Cache http://www.squid-cache.org/
9
* ----------------------------------------------------------
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.
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.
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.
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
32
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
39
#include "ACLChecklist.h"
41
#include "CacheManager.h"
43
#include "errorpage.h"
45
#include "HttpReply.h"
46
#include "HttpRequest.h"
47
#include "MemObject.h"
49
#include "SquidTime.h"
52
static PSC fwdStartCompleteWrapper;
53
static PF fwdServerClosedWrapper;
55
static PF fwdNegotiateSSLWrapper;
57
static PF fwdConnectTimeoutWrapper;
58
static EVH fwdConnectStartWrapper;
59
static CNCB fwdConnectDoneWrapper;
62
static void fwdServerFree(FwdServer * fs);
64
#define MAX_FWD_STATS_IDX 9
65
static int FwdReplyCodes[MAX_FWD_STATS_IDX + 1][HTTP_INVALID_HEADER + 1];
68
static void fwdLog(FwdState * fwdState);
69
static Logfile *logfile = NULL;
72
static PconnPool *fwdPconnPool = new PconnPool("server-side");
73
CBDATA_CLASS_INIT(FwdState);
76
FwdState::abort(void* d)
78
FwdState* fwd = (FwdState*)d;
80
if (fwd->server_fd >= 0) {
81
comm_close(fwd->server_fd);
88
/**** PUBLIC INTERFACE ********************************************************/
90
FwdState::FwdState(int fd, StoreEntry * e, HttpRequest * r)
95
request = HTTPMSGLOCK(r);
96
start_t = squid_curtime;
101
EBIT_SET(e->flags, ENTRY_FWD_HDR_WAIT);
103
self = this; // refcounted
105
storeRegisterAbort(e, FwdState::abort, this);
109
FwdState::completed()
111
if (flags.forward_completed == 1) {
112
debugs(17, 1, HERE << "FwdState::completed called on a completed request! Bad!");
115
flags.forward_completed = 1;
117
#if URL_CHECKSUM_DEBUG
119
entry->mem_obj->checkUrlChecksum();
126
if (entry->store_status == STORE_PENDING) {
127
if (entry->isEmpty()) {
129
errorAppendEntry(entry, err);
132
EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
134
storeReleaseRequest(entry);
138
if (storePendingNClients(entry) > 0)
139
assert(!EBIT_TEST(entry->flags, ENTRY_FWD_HDR_WAIT));
143
FwdState::~FwdState()
145
debugs(17, 3, HERE << "FwdState destructor starting");
146
if (! flags.forward_completed)
149
serversFree(&servers);
151
HTTPMSGUNLOCK(request);
156
storeUnregisterAbort(entry);
166
comm_remove_close_handler(fd, fwdServerClosedWrapper, this);
167
debug(17, 3) ("fwdStateFree: closing FD %d\n", fd);
170
debugs(17, 3, HERE << "FwdState destructor done");
174
* This is the entry point for client-side to start forwarding
175
* a transaction. It is a static method that may or may not
176
* allocate a FwdState.
179
FwdState::fwdStart(int client_fd, StoreEntry *entry, HttpRequest *request)
182
* client_addr == no_addr indicates this is an "internal" request
183
* from peer_digest.c, asn.c, netdb.c, etc and should always
184
* be allowed. yuck, I know.
187
if (request->client_addr.s_addr != no_addr.s_addr && request->protocol != PROTO_INTERNAL && request->protocol != PROTO_CACHEOBJ) {
189
* Check if this host is allowed to fetch MISSES from us (miss_access)
192
ch.src_addr = request->client_addr;
193
ch.my_addr = request->my_addr;
194
ch.my_port = request->my_port;
195
ch.request = HTTPMSGLOCK(request);
196
ch.accessList = cbdataReference(Config.accessList.miss);
197
/* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */
198
int answer = ch.fastCheck();
202
page_id = aclGetDenyInfoPage(&Config.denyInfoList, AclMatchedName);
204
if (page_id == ERR_NONE)
205
page_id = ERR_FORWARDING_DENIED;
207
ErrorState *anErr = errorCon(page_id, HTTP_FORBIDDEN, request);
209
errorAppendEntry(entry, anErr); // frees anErr
215
debug(17, 3) ("FwdState::start() '%s'\n", storeUrl(entry));
217
* This seems like an odd place to bind mem_obj and request.
218
* Might want to assert that request is NULL at this point
220
entry->mem_obj->request = HTTPMSGLOCK(request);
221
#if URL_CHECKSUM_DEBUG
223
entry->mem_obj->checkUrlChecksum();
228
ErrorState *anErr = errorCon(ERR_SHUTTING_DOWN, HTTP_SERVICE_UNAVAILABLE, request);
229
errorAppendEntry(entry, anErr); // frees anErr
233
switch (request->protocol) {
236
internalStart(request, entry);
240
cachemgrStart(client_fd, request, entry);
244
urnStart(request, entry);
248
FwdState *fwd = new FwdState(client_fd, entry, request);
249
fwd->flags.forward_completed = 0;
250
peerSelect(request, entry, fwdStartCompleteWrapper, fwd);
258
FwdState::fail(ErrorState * errorState)
260
debug(17, 3) ("fwdFail: %s \"%s\"\n\t%s\n",
261
err_type_str[errorState->type],
262
httpStatusString(errorState->httpStatus),
270
if (!errorState->request)
271
errorState->request = HTTPMSGLOCK(request);
275
* Frees fwdState without closing FD or generating an abort
278
FwdState::unregister(int fd)
280
debug(17, 3) ("fwdUnregister: %s\n", storeUrl(entry));
281
assert(fd == server_fd);
283
comm_remove_close_handler(fd, fwdServerClosedWrapper, this);
288
* server-side modules call fwdComplete() when they are done
289
* downloading an object. Then, we either 1) re-forward the
290
* request somewhere else if needed, or 2) call storeComplete()
296
StoreEntry *e = entry;
297
assert(entry->store_status == STORE_PENDING);
298
debug(17, 3) ("fwdComplete: %s\n\tstatus %d\n", storeUrl(e),
299
entry->getReply()->sline.status);
300
#if URL_CHECKSUM_DEBUG
302
entry->mem_obj->checkUrlChecksum();
305
logReplyStatus(n_tries, entry->getReply()->sline.status);
308
debug(17, 3) ("fwdComplete: re-forwarding %d %s\n",
309
entry->getReply()->sline.status,
313
unregister(server_fd);
318
* Need to re-establish the self-reference here since we'll
319
* be trying to forward the request again. Otherwise the
320
* ref count could go to zero before a connection is
323
self = this; // refcounted
325
startComplete(servers);
327
debug(17, 3) ("fwdComplete: not re-forwarding status %d\n",
328
entry->getReply()->sline.status);
329
EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
337
/**** CALLBACK WRAPPERS ************************************************************/
340
fwdStartCompleteWrapper(FwdServer * servers, void *data)
342
FwdState *fwd = (FwdState *) data;
343
fwd->startComplete(servers);
347
fwdServerClosedWrapper(int fd, void *data)
349
FwdState *fwd = (FwdState *) data;
350
fwd->serverClosed(fd);
354
fwdConnectStartWrapper(void *data)
356
FwdState *fwd = (FwdState *) data;
362
fwdNegotiateSSLWrapper(int fd, void *data)
364
FwdState *fwd = (FwdState *) data;
365
fwd->negotiateSSL(fd);
371
fwdConnectDoneWrapper(int server_fd, comm_err_t status, int xerrno, void *data)
373
FwdState *fwd = (FwdState *) data;
374
fwd->connectDone(server_fd, status, xerrno);
378
fwdConnectTimeoutWrapper(int fd, void *data)
380
FwdState *fwd = (FwdState *) data;
381
fwd->connectTimeout(fd);
385
* Accounts for closed persistent connections
388
fwdPeerClosed(int fd, void *data)
390
peer *p = (peer *)data;
391
p->stats.conn_open--;
394
/**** PRIVATE *****************************************************************/
397
FwdState::checkRetry()
402
if (entry->store_status != STORE_PENDING)
405
if (!entry->isEmpty())
411
if (origin_tries > 2)
414
if (squid_curtime - start_t > Config.Timeout.forward)
417
if (flags.dont_retry)
420
if (request->flags.body_sent)
427
FwdState::checkRetriable()
429
/* If there is a request body then Squid can only try once
430
* even if the method is indempotent
433
if (request->body_reader != NULL)
436
/* RFC2616 9.1 Safe and Idempotent Methods */
437
switch (request->method) {
438
/* 9.1.1 Safe Methods */
443
/* 9.1.2 Indepontent Methods */
462
FwdState::serverClosed(int fd)
464
debug(17, 2) ("fwdServerClosed: FD %d %s\n", fd, storeUrl(entry));
465
assert(server_fd == fd);
469
int originserver = (servers->_peer == NULL);
470
debug(17, 3) ("fwdServerClosed: re-forwarding (%d tries, %d secs)\n",
472
(int) (squid_curtime - start_t));
475
/* use next, or cycle if origin server isn't last */
476
FwdServer *fs = servers;
477
FwdServer **T, *T2 = NULL;
480
for (T = &servers; *T; T2 = *T, T = &(*T)->next)
483
if (T2 && T2->_peer) {
488
/* Use next. The last "direct" entry is retried multiple times */
495
/* use eventAdd to break potential call sequence loops and to slow things down a little */
496
eventAdd("fwdConnectStart", fwdConnectStartWrapper, this, originserver ? 0.05 : 0.005, 0);
501
if (!err && shutting_down) {
502
errorCon(ERR_SHUTTING_DOWN, HTTP_SERVICE_UNAVAILABLE, request);
505
self = NULL; // refcounted
510
FwdState::negotiateSSL(int fd)
512
FwdServer *fs = servers;
513
SSL *ssl = fd_table[fd].ssl;
516
if ((ret = SSL_connect(ssl)) <= 0) {
517
int ssl_error = SSL_get_error(ssl, ret);
521
case SSL_ERROR_WANT_READ:
522
commSetSelect(fd, COMM_SELECT_READ, fwdNegotiateSSLWrapper, this, 0);
525
case SSL_ERROR_WANT_WRITE:
526
commSetSelect(fd, COMM_SELECT_WRITE, fwdNegotiateSSLWrapper, this, 0);
530
debug(81, 1) ("fwdNegotiateSSL: Error negotiating SSL connection on FD %d: %s (%d/%d/%d)\n", fd, ERR_error_string(ERR_get_error(), NULL), ssl_error, ret, errno);
531
ErrorState *anErr = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
534
anErr->xerrno = EPROTO;
537
anErr->xerrno = EACCES;
543
peerConnectFailed(fs->_peer);
544
fs->_peer->stats.conn_open--;
552
if (fs->_peer && !SSL_session_reused(ssl)) {
553
if (fs->_peer->sslSession)
554
SSL_SESSION_free(fs->_peer->sslSession);
556
fs->_peer->sslSession = SSL_get1_session(ssl);
563
FwdState::initiateSSL()
565
FwdServer *fs = servers;
568
SSL_CTX *sslContext = NULL;
569
peer *peer = fs->_peer;
572
assert(peer->use_ssl);
573
sslContext = peer->sslContext;
575
sslContext = Config.ssl_client.sslContext;
580
if ((ssl = SSL_new(sslContext)) == NULL) {
581
debug(83, 1) ("fwdInitiateSSL: Error allocating handle: %s\n",
582
ERR_error_string(ERR_get_error(), NULL));
583
ErrorState *anErr = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR, request);
584
anErr->xerrno = errno;
586
self = NULL; // refcounted
594
SSL_set_ex_data(ssl, ssl_ex_index_server, peer->ssldomain);
599
SSL_set_ex_data(ssl, ssl_ex_index_server, peer->name);
604
SSL_set_ex_data(ssl, ssl_ex_index_server, peer->host);
606
if (peer->sslSession)
607
SSL_set_session(ssl, peer->sslSession);
610
SSL_set_ex_data(ssl, ssl_ex_index_server, request->host);
613
fd_table[fd].ssl = ssl;
614
fd_table[fd].read_method = &ssl_read_method;
615
fd_table[fd].write_method = &ssl_write_method;
622
FwdState::connectDone(int aServerFD, comm_err_t status, int xerrno)
624
FwdServer *fs = servers;
625
assert(server_fd == aServerFD);
627
if (Config.onoff.log_ip_on_direct && status != COMM_ERR_DNS && fs->code == HIER_DIRECT)
628
hierarchyNote(&request->hier, fs->code, fd_table[server_fd].ipaddr);
630
if (status == COMM_ERR_DNS) {
632
* Only set the dont_retry flag if the DNS lookup fails on
633
* a direct connection. If DNS lookup fails when trying
634
* a neighbor cache, we may want to retry another option.
637
if (NULL == fs->_peer)
638
flags.dont_retry = 1;
640
debug(17, 4) ("fwdConnectDone: Unknown host: %s\n",
643
ErrorState *anErr = errorCon(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
645
anErr->dnsserver_msg = xstrdup(dns_error_message);
649
comm_close(server_fd);
650
} else if (status != COMM_OK) {
652
ErrorState *anErr = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request);
653
anErr->xerrno = xerrno;
658
peerConnectFailed(fs->_peer);
660
comm_close(server_fd);
662
debug(17, 3) ("fwdConnectDone: FD %d: '%s'\n", server_fd, storeUrl(entry));
665
peerConnectSucceded(fs->_peer);
669
if ((fs->_peer && fs->_peer->use_ssl) ||
670
(!fs->_peer && request->protocol == PROTO_HTTPS)) {
681
FwdState::connectTimeout(int fd)
683
FwdServer *fs = servers;
685
debug(17, 2) ("fwdConnectTimeout: FD %d: '%s'\n", fd, storeUrl(entry));
686
assert(fd == server_fd);
688
if (Config.onoff.log_ip_on_direct && fs->code == HIER_DIRECT && fd_table[fd].ipaddr[0])
689
hierarchyNote(&request->hier, fs->code, fd_table[fd].ipaddr);
691
if (entry->isEmpty()) {
692
ErrorState *anErr = errorCon(ERR_CONNECT_FAIL, HTTP_GATEWAY_TIMEOUT, request);
693
anErr->xerrno = ETIMEDOUT;
696
* This marks the peer DOWN ...
701
peerConnectFailed(servers->_peer);
708
FwdState::connectStart()
710
const char *url = storeUrl(entry);
712
FwdServer *fs = servers;
715
const char *domain = NULL;
717
int ftimeout = Config.Timeout.forward - (squid_curtime - start_t);
719
struct IN_ADDR outgoing;
722
assert(server_fd == -1);
723
debug(17, 3) ("fwdConnectStart: %s\n", url);
726
host = fs->_peer->host;
727
port = fs->_peer->http_port;
728
ctimeout = fs->_peer->connect_timeout > 0 ? fs->_peer->connect_timeout
729
: Config.Timeout.peer_connect;
731
if (fs->_peer->options.originserver)
732
domain = request->host;
734
host = request->host;
735
port = request->port;
736
ctimeout = Config.Timeout.connect;
742
if (ftimeout < ctimeout)
745
if ((fd = fwdPconnPool->pop(host, port, domain)) >= 0) {
746
if (checkRetriable()) {
747
debug(17, 3) ("fwdConnectStart: reusing pconn FD %d\n", fd);
754
comm_add_close_handler(fd, fwdServerClosedWrapper, this);
760
/* Discard the persistent connection to not cause
761
* an imbalance in number of connections open if there
762
* is a lot of POST requests
768
#if URL_CHECKSUM_DEBUG
769
entry->mem_obj->checkUrlChecksum();
773
outgoing = getOutgoingAddr(request);
775
tos = getOutgoingTOS(request);
777
debug(17, 3) ("fwdConnectStart: got addr %s, tos %d\n",
778
inet_ntoa(outgoing), tos);
780
fd = comm_openex(SOCK_STREAM,
789
debug(50, 4) ("fwdConnectStart: %s\n", xstrerror());
790
ErrorState *anErr = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR, request);
791
anErr->xerrno = errno;
793
self = NULL; // refcounted
804
* stats.conn_open is used to account for the number of
805
* connections that we have open to the peer, so we can limit
806
* based on the max-conn option. We need to increment here,
807
* even if the connection may fail.
811
fs->_peer->stats.conn_open++;
812
comm_add_close_handler(fd, fwdPeerClosed, fs->_peer);
815
comm_add_close_handler(fd, fwdServerClosedWrapper, this);
817
commSetTimeout(fd, ctimeout, fwdConnectTimeoutWrapper, this);
820
hierarchyNote(&request->hier, fs->code, fs->_peer->host);
822
hierarchyNote(&request->hier, fs->code, request->host);
824
commConnectStart(fd, host, port, fwdConnectDoneWrapper, this);
828
FwdState::startComplete(FwdServer * theServers)
830
debug(17, 3) ("fwdStartComplete: %s\n", storeUrl(entry));
832
if (theServers != NULL) {
833
servers = theServers;
841
FwdState::startFail()
843
debug(17, 3) ("fwdStartFail: %s\n", storeUrl(entry));
844
ErrorState *anErr = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, request);
845
anErr->xerrno = errno;
847
self = NULL; // refcounted
854
debug(17, 3) ("fwdDispatch: FD %d: Fetching '%s %s'\n",
856
RequestMethodStr[request->method],
859
* Assert that server_fd is set. This is to guarantee that fwdState
860
* is attached to something and will be deallocated when server_fd
863
assert(server_fd > -1);
865
fd_note(server_fd, storeUrl(entry));
867
fd_table[server_fd].noteUse(fwdPconnPool);
869
/*assert(!EBIT_TEST(entry->flags, ENTRY_DISPATCHED)); */
870
assert(entry->ping_status != PING_WAITING);
872
assert(entry->lock_count);
874
EBIT_SET(entry->flags, ENTRY_DISPATCHED);
876
netdbPingSite(request->host);
878
if (servers && (p = servers->_peer)) {
880
request->peer_login = p->login;
881
request->peer_domain = p->domain;
884
request->peer_login = NULL;
885
request->peer_domain = NULL;
887
switch (request->protocol) {
916
fatal_dump("Should never get here");
924
debug(17, 1) ("fwdDispatch: Cannot retrieve '%s'\n",
926
ErrorState *anErr = errorCon(ERR_UNSUP_REQ, HTTP_BAD_REQUEST, request);
929
* Force a persistent connection to be closed because
930
* some Netscape browsers have a bug that sends CONNECT
931
* requests as GET's over persistent connections.
933
request->flags.proxy_keepalive = 0;
935
* Set the dont_retry flag becuase this is not a
936
* transient (network) error; its a bug.
938
flags.dont_retry = 1;
939
comm_close(server_fd);
945
* remove our self-refcount now that we've handed off the request
946
* to a server-side module
952
FwdState::reforward()
954
StoreEntry *e = entry;
955
FwdServer *fs = servers;
957
assert(e->store_status == STORE_PENDING);
959
#if URL_CHECKSUM_DEBUG
961
e->mem_obj->checkUrlChecksum();
964
debug(17, 3) ("fwdReforward: %s?\n", storeUrl(e));
966
if (!EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) {
967
debug(17, 3) ("fwdReforward: No, ENTRY_FWD_HDR_WAIT isn't set\n");
974
if (origin_tries > 1)
977
if (request->flags.body_sent)
986
if (servers == NULL) {
987
debug(17, 3) ("fwdReforward: No forward-servers left\n");
991
s = e->getReply()->sline.status;
992
debug(17, 3) ("fwdReforward: status %d\n", (int) s);
993
return reforwardableStatus(s);
997
fwdStats(StoreEntry * s)
1001
storeAppendPrintf(s, "Status");
1003
for (j = 0; j <= MAX_FWD_STATS_IDX; j++) {
1004
storeAppendPrintf(s, "\ttry#%d", j + 1);
1007
storeAppendPrintf(s, "\n");
1009
for (i = 0; i <= (int) HTTP_INVALID_HEADER; i++) {
1010
if (FwdReplyCodes[0][i] == 0)
1013
storeAppendPrintf(s, "%3d", i);
1015
for (j = 0; j <= MAX_FWD_STATS_IDX; j++) {
1016
storeAppendPrintf(s, "\t%d", FwdReplyCodes[j][i]);
1019
storeAppendPrintf(s, "\n");
1024
/**** STATIC MEMBER FUNCTIONS *************************************************/
1027
FwdState::reforwardableStatus(http_status s)
1031
case HTTP_BAD_GATEWAY:
1033
case HTTP_GATEWAY_TIMEOUT:
1036
case HTTP_FORBIDDEN:
1038
case HTTP_INTERNAL_SERVER_ERROR:
1040
case HTTP_NOT_IMPLEMENTED:
1042
case HTTP_SERVICE_UNAVAILABLE:
1043
return Config.retry.onerror;
1053
FwdState::pconnPush(int fd, const char *host, int port, const char *domain)
1055
fwdPconnPool->push(fd, host, port, domain);
1059
FwdState::initModule()
1061
memDataInit(MEM_FWD_SERVER, "FwdServer", sizeof(FwdServer), 0);
1067
else if (NULL == Config.Log.forward)
1070
logfile = logfileOpen(Config.Log.forward, 0, 1);
1076
FwdState::RegisterWithCacheManager(CacheManager & manager)
1078
manager.registerAction("forward",
1079
"Request Forwarding Statistics",
1084
FwdState::logReplyStatus(int tries, http_status status)
1086
if (status > HTTP_INVALID_HEADER)
1093
if (tries > MAX_FWD_STATS_IDX)
1094
tries = MAX_FWD_STATS_IDX;
1096
FwdReplyCodes[tries][status]++;
1100
FwdState::serversFree(FwdServer ** FSVR)
1104
while ((fs = *FSVR)) {
1110
/**** PRIVATE NON-MEMBER FUNCTIONS ********************************************/
1113
fwdServerFree(FwdServer * fs)
1115
cbdataReferenceDone(fs->_peer);
1116
memFree(fs, MEM_FWD_SERVER);
1119
static struct IN_ADDR
1120
aclMapAddr(acl_address * head, ACLChecklist * ch)
1124
struct IN_ADDR addr;
1126
for (l = head; l; l = l->next)
1128
if (ch->matchAclListFast(l->aclList))
1132
addr.s_addr = INADDR_ANY;
1137
aclMapTOS(acl_tos * head, ACLChecklist * ch)
1141
for (l = head; l; l = l->next) {
1142
if (ch->matchAclListFast(l->aclList))
1150
getOutgoingAddr(HttpRequest * request)
1156
ch.src_addr = request->client_addr;
1157
ch.my_addr = request->my_addr;
1158
ch.my_port = request->my_port;
1159
ch.request = HTTPMSGLOCK(request);
1162
return aclMapAddr(Config.accessList.outgoing_address, &ch);
1166
getOutgoingTOS(HttpRequest * request)
1171
ch.src_addr = request->client_addr;
1172
ch.my_addr = request->my_addr;
1173
ch.my_port = request->my_port;
1174
ch.request = HTTPMSGLOCK(request);
1177
return aclMapTOS(Config.accessList.outgoing_tos, &ch);
1181
/**** WIP_FWD_LOG *************************************************************/
1187
if (NULL == logfile)
1190
logfileClose(logfile);
1199
logfileRotate(logfile);
1205
if (NULL == logfile)
1208
logfilePrintf(logfile, "%9d.%03d %03d %s %s\n",
1209
(int) current_time.tv_sec,
1210
(int) current_time.tv_usec / 1000,
1212
RequestMethodStr[request->method],
1213
request->canonical);
1217
FwdState::status(http_status s)