]> git.ipfire.org Git - thirdparty/squid.git/blame - src/comm/Connection.cc
Bug 5055: FATAL FwdState::noteDestinationsEnd exception: opening (#877)
[thirdparty/squid.git] / src / comm / Connection.cc
CommitLineData
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 23InstanceIdDefinitions(Comm::Connection, "conn", uint64_t);
ccfbe8f4 24
a011edee 25class CachePeer;
97c81191
AJ
26bool
27Comm::IsConnOpen(const Comm::ConnectionPointer &conn)
28{
29 return conn != NULL && conn->isOpen();
30}
31
cfd66529 32Comm::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 45Comm::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 63Comm::ConnectionPointer
2b6b1bcb 64Comm::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
104void
105Comm::Connection::close()
106{
5229395c 107 if (isOpen()) {
55cbb02b 108 comm_close(fd);
b54a7c5a
CT
109 noteClosure();
110 }
111}
112
113void
114Comm::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 123CachePeer *
418b3087
AJ
124Comm::Connection::getPeer() const
125{
a3c6762c
FC
126 if (cbdataReferenceValid(peer_))
127 return peer_;
418b3087
AJ
128
129 return NULL;
130}
131
739b352a 132void
a3c6762c 133Comm::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
145time_t
146Comm::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
155Security::NegotiationHistory *
156Comm::Connection::tlsNegotiations()
157{
158 if (!tlsHistory)
159 tlsHistory = new Security::NegotiationHistory;
160 return tlsHistory;
161}
162
0ce8e93b
EB
163time_t
164Comm::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
183ScopedId
184Comm::Connection::codeContextGist() const {
185 return id.detach();
186}
187
188std::ostream &
189Comm::Connection::detailCodeContext(std::ostream &os) const
190{
191 return os << Debug::Extra << "connection: " << *this;
192}
193
6043e368
AR
194std::ostream &
195operator << (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