]>
Commit | Line | Data |
---|---|---|
bbc27441 | 1 | /* |
f70aedc4 | 2 | * Copyright (C) 1996-2021 The Squid Software Foundation and contributors |
bbc27441 AJ |
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 | ||
f7f3304a | 9 | #include "squid.h" |
2b6b1bcb | 10 | #include "base/JobWait.h" |
a011edee | 11 | #include "CachePeer.h" |
cfd66529 AJ |
12 | #include "cbdata.h" |
13 | #include "comm.h" | |
14 | #include "comm/Connection.h" | |
be364179 | 15 | #include "fde.h" |
0ce8e93b | 16 | #include "FwdState.h" |
e8dca475 | 17 | #include "neighbors.h" |
4b307ad4 | 18 | #include "security/NegotiationHistory.h" |
c5c06f02 | 19 | #include "SquidConfig.h" |
be364179 | 20 | #include "SquidTime.h" |
6043e368 | 21 | #include <ostream> |
cfd66529 | 22 | |
a120b7a8 | 23 | InstanceIdDefinitions(Comm::Connection, "conn", uint64_t); |
ccfbe8f4 | 24 | |
a011edee | 25 | class CachePeer; |
97c81191 AJ |
26 | bool |
27 | Comm::IsConnOpen(const Comm::ConnectionPointer &conn) | |
28 | { | |
29 | return conn != NULL && conn->isOpen(); | |
30 | } | |
31 | ||
cfd66529 | 32 | Comm::Connection::Connection() : |
f53969cc SM |
33 | peerType(HIER_NONE), |
34 | fd(-1), | |
35 | tos(0), | |
36 | nfmark(0), | |
37 | flags(COMM_NONBLOCKING), | |
d59e4742 | 38 | peer_(nullptr), |
2bcab852 CT |
39 | startTime_(squid_curtime), |
40 | tlsHistory(nullptr) | |
73c36fd9 AJ |
41 | { |
42 | *rfc931 = 0; // quick init the head. the rest does not matter. | |
43 | } | |
cfd66529 | 44 | |
aed188fd | 45 | Comm::Connection::~Connection() |
739b352a | 46 | { |
be364179 | 47 | if (fd >= 0) { |
1c2b4465 CT |
48 | if (flags & COMM_ORPHANED) { |
49 | debugs(5, 5, "closing orphan: " << *this); | |
50 | } else { | |
51 | static uint64_t losses = 0; | |
52 | ++losses; | |
53 | debugs(5, 4, "BUG #3329: Lost orphan #" << losses << ": " << *this); | |
54 | } | |
42a61e53 | 55 | close(); |
be364179 AJ |
56 | } |
57 | ||
a3c6762c | 58 | cbdataReferenceDone(peer_); |
2bcab852 CT |
59 | |
60 | delete tlsHistory; | |
739b352a AJ |
61 | } |
62 | ||
5ae21d99 | 63 | Comm::ConnectionPointer |
2b6b1bcb | 64 | Comm::Connection::cloneProfile() const |
739b352a | 65 | { |
2b6b1bcb AR |
66 | const ConnectionPointer clone = new Comm::Connection; |
67 | auto &c = *clone; // optimization | |
68 | ||
69 | /* | |
70 | * Copy or excuse each data member. Excused members do not belong to a | |
71 | * Connection configuration profile because their values cannot be reused | |
72 | * across (co-existing) Connection objects and/or are tied to their own | |
73 | * object lifetime. | |
74 | */ | |
75 | ||
76 | c.setAddrs(local, remote); | |
77 | c.peerType = peerType; | |
78 | // fd excused | |
79 | c.tos = tos; | |
80 | c.nfmark = nfmark; | |
81 | c.nfConnmark = nfConnmark; | |
82 | // COMM_ORPHANED is not a part of connection opening instructions | |
83 | c.flags = flags & ~COMM_ORPHANED; | |
84 | // rfc931 is excused | |
85 | ||
86 | #if USE_SQUID_EUI | |
87 | // These are currently only set when accepting connections and never used | |
88 | // for establishing new ones, so this copying is currently in vain, but, | |
89 | // technically, they can be a part of connection opening instructions. | |
90 | c.remoteEui48 = remoteEui48; | |
91 | c.remoteEui64 = remoteEui64; | |
92 | #endif | |
93 | ||
94 | // id excused | |
95 | c.peer_ = cbdataReference(getPeer()); | |
96 | // startTime_ excused | |
97 | // tlsHistory excused | |
98 | ||
99 | debugs(5, 5, this << " made " << c); | |
100 | assert(!c.isOpen()); | |
101 | return clone; | |
cfd66529 | 102 | } |
739b352a | 103 | |
55cbb02b AJ |
104 | void |
105 | Comm::Connection::close() | |
106 | { | |
5229395c | 107 | if (isOpen()) { |
55cbb02b | 108 | comm_close(fd); |
b54a7c5a CT |
109 | noteClosure(); |
110 | } | |
111 | } | |
112 | ||
113 | void | |
114 | Comm::Connection::noteClosure() | |
115 | { | |
116 | if (isOpen()) { | |
5229395c | 117 | fd = -1; |
a3c6762c | 118 | if (CachePeer *p=getPeer()) |
e8dca475 | 119 | peerConnClosed(p); |
5229395c | 120 | } |
55cbb02b AJ |
121 | } |
122 | ||
a3c6762c | 123 | CachePeer * |
418b3087 AJ |
124 | Comm::Connection::getPeer() const |
125 | { | |
a3c6762c FC |
126 | if (cbdataReferenceValid(peer_)) |
127 | return peer_; | |
418b3087 AJ |
128 | |
129 | return NULL; | |
130 | } | |
131 | ||
739b352a | 132 | void |
a3c6762c | 133 | Comm::Connection::setPeer(CachePeer *p) |
739b352a AJ |
134 | { |
135 | /* set to self. nothing to do. */ | |
418b3087 | 136 | if (getPeer() == p) |
739b352a AJ |
137 | return; |
138 | ||
a3c6762c | 139 | cbdataReferenceDone(peer_); |
746beefe | 140 | if (p) { |
a3c6762c | 141 | peer_ = cbdataReference(p); |
746beefe | 142 | } |
739b352a | 143 | } |
f53969cc | 144 | |
c5c06f02 CT |
145 | time_t |
146 | Comm::Connection::timeLeft(const time_t idleTimeout) const | |
147 | { | |
148 | if (!Config.Timeout.pconnLifetime) | |
149 | return idleTimeout; | |
150 | ||
151 | const time_t lifeTimeLeft = lifeTime() < Config.Timeout.pconnLifetime ? Config.Timeout.pconnLifetime - lifeTime() : 1; | |
152 | return min(lifeTimeLeft, idleTimeout); | |
153 | } | |
6a515ac4 | 154 | |
2bcab852 CT |
155 | Security::NegotiationHistory * |
156 | Comm::Connection::tlsNegotiations() | |
157 | { | |
158 | if (!tlsHistory) | |
159 | tlsHistory = new Security::NegotiationHistory; | |
160 | return tlsHistory; | |
161 | } | |
162 | ||
0ce8e93b EB |
163 | time_t |
164 | Comm::Connection::connectTimeout(const time_t fwdStart) const | |
165 | { | |
166 | // a connection opening timeout (ignoring forwarding time limits for now) | |
167 | const CachePeer *peer = getPeer(); | |
5f5d319e | 168 | const auto ctimeout = peer ? peer->connectTimeout() : Config.Timeout.connect; |
0ce8e93b EB |
169 | |
170 | // time we have left to finish the whole forwarding process | |
171 | const time_t fwdTimeLeft = FwdState::ForwardTimeout(fwdStart); | |
172 | ||
173 | // The caller decided to connect. If there is no time left, to protect | |
174 | // connecting code from trying to establish a connection while a zero (i.e., | |
175 | // "immediate") timeout notification is firing, ensure a positive timeout. | |
176 | // XXX: This hack gives some timed-out forwarding sequences more time than | |
177 | // some sequences that have not quite reached the forwarding timeout yet! | |
178 | const time_t ftimeout = fwdTimeLeft ? fwdTimeLeft : 5; // seconds | |
179 | ||
180 | return min(ctimeout, ftimeout); | |
181 | } | |
182 | ||
ccfbe8f4 AR |
183 | ScopedId |
184 | Comm::Connection::codeContextGist() const { | |
185 | return id.detach(); | |
186 | } | |
187 | ||
188 | std::ostream & | |
189 | Comm::Connection::detailCodeContext(std::ostream &os) const | |
190 | { | |
191 | return os << Debug::Extra << "connection: " << *this; | |
192 | } | |
193 | ||
6043e368 AR |
194 | std::ostream & |
195 | operator << (std::ostream &os, const Comm::Connection &conn) | |
196 | { | |
ccfbe8f4 AR |
197 | os << conn.id; |
198 | if (!conn.local.isNoAddr() || conn.local.port()) | |
199 | os << " local=" << conn.local; | |
200 | if (!conn.remote.isNoAddr() || conn.remote.port()) | |
201 | os << " remote=" << conn.remote; | |
6043e368 AR |
202 | if (conn.peerType) |
203 | os << ' ' << hier_code_str[conn.peerType]; | |
204 | if (conn.fd >= 0) | |
205 | os << " FD " << conn.fd; | |
206 | if (conn.flags != COMM_UNSET) | |
207 | os << " flags=" << conn.flags; | |
208 | #if USE_IDENT | |
209 | if (*conn.rfc931) | |
210 | os << " IDENT::" << conn.rfc931; | |
211 | #endif | |
212 | return os; | |
213 | } | |
d22511f9 | 214 |