]> git.ipfire.org Git - thirdparty/squid.git/blob - src/comm/Connection.cc
4401dab5bd1efdbf59e5516dfb025e7c2c441f69
[thirdparty/squid.git] / src / comm / Connection.cc
1 /*
2 * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 #include "squid.h"
10 #include "CachePeer.h"
11 #include "cbdata.h"
12 #include "comm.h"
13 #include "comm/Connection.h"
14 #include "fde.h"
15 #include "FwdState.h"
16 #include "neighbors.h"
17 #include "security/NegotiationHistory.h"
18 #include "SquidConfig.h"
19 #include "SquidTime.h"
20 #include <ostream>
21
22 class CachePeer;
23 bool
24 Comm::IsConnOpen(const Comm::ConnectionPointer &conn)
25 {
26 return conn != NULL && conn->isOpen();
27 }
28
29 Comm::Connection::Connection() :
30 peerType(HIER_NONE),
31 fd(-1),
32 tos(0),
33 nfmark(0),
34 flags(COMM_NONBLOCKING),
35 peer_(nullptr),
36 startTime_(squid_curtime),
37 tlsHistory(nullptr)
38 {
39 *rfc931 = 0; // quick init the head. the rest does not matter.
40 }
41
42 static int64_t lost_conn = 0;
43 Comm::Connection::~Connection()
44 {
45 if (fd >= 0) {
46 debugs(5, 4, "BUG #3329: Orphan Comm::Connection: " << *this);
47 debugs(5, 4, "NOTE: " << ++lost_conn << " Orphans since last started.");
48 close();
49 }
50
51 cbdataReferenceDone(peer_);
52
53 delete tlsHistory;
54 }
55
56 Comm::ConnectionPointer
57 Comm::Connection::copyDetails() const
58 {
59 ConnectionPointer c = new Comm::Connection;
60
61 c->setAddrs(local, remote);
62 c->peerType = peerType;
63 c->tos = tos;
64 c->nfmark = nfmark;
65 c->flags = flags;
66 c->startTime_ = startTime_;
67
68 // ensure FD is not open in the new copy.
69 c->fd = -1;
70
71 // ensure we have a cbdata reference to peer_ not a straight ptr copy.
72 c->peer_ = cbdataReference(getPeer());
73
74 return c;
75 }
76
77 void
78 Comm::Connection::close()
79 {
80 if (isOpen()) {
81 comm_close(fd);
82 noteClosure();
83 }
84 }
85
86 void
87 Comm::Connection::noteClosure()
88 {
89 if (isOpen()) {
90 fd = -1;
91 if (CachePeer *p=getPeer())
92 peerConnClosed(p);
93 }
94 }
95
96 CachePeer *
97 Comm::Connection::getPeer() const
98 {
99 if (cbdataReferenceValid(peer_))
100 return peer_;
101
102 return NULL;
103 }
104
105 void
106 Comm::Connection::setPeer(CachePeer *p)
107 {
108 /* set to self. nothing to do. */
109 if (getPeer() == p)
110 return;
111
112 cbdataReferenceDone(peer_);
113 if (p) {
114 peer_ = cbdataReference(p);
115 }
116 }
117
118 time_t
119 Comm::Connection::timeLeft(const time_t idleTimeout) const
120 {
121 if (!Config.Timeout.pconnLifetime)
122 return idleTimeout;
123
124 const time_t lifeTimeLeft = lifeTime() < Config.Timeout.pconnLifetime ? Config.Timeout.pconnLifetime - lifeTime() : 1;
125 return min(lifeTimeLeft, idleTimeout);
126 }
127
128 Security::NegotiationHistory *
129 Comm::Connection::tlsNegotiations()
130 {
131 if (!tlsHistory)
132 tlsHistory = new Security::NegotiationHistory;
133 return tlsHistory;
134 }
135
136 time_t
137 Comm::Connection::connectTimeout(const time_t fwdStart) const
138 {
139 // a connection opening timeout (ignoring forwarding time limits for now)
140 const CachePeer *peer = getPeer();
141 const time_t ctimeout = peer ? peerConnectTimeout(peer) : Config.Timeout.connect;
142
143 // time we have left to finish the whole forwarding process
144 const time_t fwdTimeLeft = FwdState::ForwardTimeout(fwdStart);
145
146 // The caller decided to connect. If there is no time left, to protect
147 // connecting code from trying to establish a connection while a zero (i.e.,
148 // "immediate") timeout notification is firing, ensure a positive timeout.
149 // XXX: This hack gives some timed-out forwarding sequences more time than
150 // some sequences that have not quite reached the forwarding timeout yet!
151 const time_t ftimeout = fwdTimeLeft ? fwdTimeLeft : 5; // seconds
152
153 return min(ctimeout, ftimeout);
154 }
155
156 std::ostream &
157 operator << (std::ostream &os, const Comm::Connection &conn)
158 {
159 os << "local=" << conn.local << " remote=" << conn.remote;
160 if (conn.peerType)
161 os << ' ' << hier_code_str[conn.peerType];
162 if (conn.fd >= 0)
163 os << " FD " << conn.fd;
164 if (conn.flags != COMM_UNSET)
165 os << " flags=" << conn.flags;
166 #if USE_IDENT
167 if (*conn.rfc931)
168 os << " IDENT::" << conn.rfc931;
169 #endif
170 return os;
171 }
172