]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ipc/SharedListen.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / ipc / SharedListen.cc
CommitLineData
0d0bce6a 1/*
4ac4a490 2 * Copyright (C) 1996-2017 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.
0d0bce6a
AR
7 */
8
bbc27441
AJ
9/* DEBUG: section 54 Interprocess Communication */
10
f7f3304a 11#include "squid.h"
a67d2b2e 12#include "base/TextException.h"
602d9612 13#include "comm.h"
e0d28505 14#include "comm/Connection.h"
582c2af2 15#include "globals.h"
0d0bce6a 16#include "ipc/Kids.h"
602d9612
A
17#include "ipc/Messages.h"
18#include "ipc/Port.h"
0d0bce6a 19#include "ipc/SharedListen.h"
602d9612
A
20#include "ipc/StartListening.h"
21#include "ipc/TypedMsgHdr.h"
5bed43d6 22#include "tools.h"
0d0bce6a 23
0dff3140 24#include <list>
3d41e53a
FC
25#include <map>
26
0d0bce6a
AR
27/// holds information necessary to handle JoinListen response
28class PendingOpenRequest
29{
30public:
31 Ipc::OpenListenerParams params; ///< actual comm_open_sharedListen() parameters
32 AsyncCall::Pointer callback; // who to notify
33};
34
35/// maps ID assigned at request time to the response callback
36typedef std::map<int, PendingOpenRequest> SharedListenRequestMap;
37static SharedListenRequestMap TheSharedListenRequestMap;
38
0dff3140
AR
39/// accumulates delayed requests until they are ready to be sent, in FIFO order
40typedef std::list<PendingOpenRequest> DelayedSharedListenRequests;
41static DelayedSharedListenRequests TheDelayedRequests;
42
0d0bce6a
AR
43static int
44AddToMap(const PendingOpenRequest &por)
45{
46 // find unused ID using linear seach; there should not be many entries
47 for (int id = 0; true; ++id) {
48 if (TheSharedListenRequestMap.find(id) == TheSharedListenRequestMap.end()) {
49 TheSharedListenRequestMap[id] = por;
50 return id;
51 }
52 }
53 assert(false); // not reached
54 return -1;
55}
56
57Ipc::OpenListenerParams::OpenListenerParams()
58{
e297be13 59 memset(this, 0, sizeof(*this));
0d0bce6a
AR
60}
61
62bool
63Ipc::OpenListenerParams::operator <(const OpenListenerParams &p) const
64{
65 if (sock_type != p.sock_type)
66 return sock_type < p.sock_type;
67
68 if (proto != p.proto)
69 return proto < p.proto;
70
71 // ignore flags and fdNote differences because they do not affect binding
72
73 return addr.compareWhole(p.addr) < 0;
74}
75
0d0bce6a
AR
76Ipc::SharedListenRequest::SharedListenRequest(): requestorId(-1), mapId(-1)
77{
78 // caller will then set public data members
79}
80
81Ipc::SharedListenRequest::SharedListenRequest(const TypedMsgHdr &hdrMsg)
82{
8822ebee
AR
83 hdrMsg.checkType(mtSharedListenRequest);
84 hdrMsg.getPod(*this);
0d0bce6a
AR
85}
86
87void Ipc::SharedListenRequest::pack(TypedMsgHdr &hdrMsg) const
88{
8822ebee
AR
89 hdrMsg.setType(mtSharedListenRequest);
90 hdrMsg.putPod(*this);
0d0bce6a
AR
91}
92
b72fb55d 93Ipc::SharedListenResponse::SharedListenResponse(int aFd, int anErrNo, int aMapId):
f53969cc 94 fd(aFd), errNo(anErrNo), mapId(aMapId)
0d0bce6a
AR
95{
96}
97
98Ipc::SharedListenResponse::SharedListenResponse(const TypedMsgHdr &hdrMsg):
f53969cc 99 fd(-1), errNo(0), mapId(-1)
0d0bce6a 100{
8822ebee
AR
101 hdrMsg.checkType(mtSharedListenResponse);
102 hdrMsg.getPod(*this);
b72fb55d 103 fd = hdrMsg.getFd();
e0d28505 104 // other conn details are passed in OpenListenerParams and filled out by SharedListenJoin()
0d0bce6a
AR
105}
106
107void Ipc::SharedListenResponse::pack(TypedMsgHdr &hdrMsg) const
108{
8822ebee
AR
109 hdrMsg.setType(mtSharedListenResponse);
110 hdrMsg.putPod(*this);
b72fb55d 111 hdrMsg.putFd(fd);
0d0bce6a
AR
112}
113
0dff3140
AR
114static void
115SendSharedListenRequest(const PendingOpenRequest &por)
0d0bce6a 116{
0dff3140 117 Ipc::SharedListenRequest request;
0d0bce6a
AR
118 request.requestorId = KidIdentifier;
119 request.params = por.params;
120 request.mapId = AddToMap(por);
121
0dff3140 122 debugs(54, 3, "getting listening FD for " << request.params.addr <<
5667a628 123 " mapId=" << request.mapId);
0d0bce6a 124
0dff3140 125 Ipc::TypedMsgHdr message;
0d0bce6a 126 request.pack(message);
1ee292b7 127 SendMessage(Ipc::Port::CoordinatorAddr(), message);
0d0bce6a
AR
128}
129
0dff3140
AR
130static void
131kickDelayedRequest()
132{
133 if (TheDelayedRequests.empty())
134 return; // no pending requests to resume
135
136 debugs(54, 3, "resuming with " << TheSharedListenRequestMap.size() <<
137 " active + " << TheDelayedRequests.size() << " delayed requests");
138
139 SendSharedListenRequest(*TheDelayedRequests.begin());
140 TheDelayedRequests.pop_front();
141}
142
143void
144Ipc::JoinSharedListen(const OpenListenerParams &params, AsyncCall::Pointer &cb)
145{
146 PendingOpenRequest por;
147 por.params = params;
148 por.callback = cb;
149
150 const DelayedSharedListenRequests::size_type concurrencyLimit = 1;
151 if (TheSharedListenRequestMap.size() >= concurrencyLimit) {
152 debugs(54, 3, "waiting for " << TheSharedListenRequestMap.size() <<
24296cbd 153 " active + " << TheDelayedRequests.size() << " delayed requests");
0dff3140
AR
154 TheDelayedRequests.push_back(por);
155 } else {
156 SendSharedListenRequest(por);
157 }
158}
159
0d0bce6a
AR
160void Ipc::SharedListenJoined(const SharedListenResponse &response)
161{
e0d28505 162 // Dont debugs c fully since only FD is filled right now.
0dff3140
AR
163 debugs(54, 3, "got listening FD " << response.fd << " errNo=" <<
164 response.errNo << " mapId=" << response.mapId << " with " <<
165 TheSharedListenRequestMap.size() << " active + " <<
166 TheDelayedRequests.size() << " delayed requests");
0d0bce6a
AR
167
168 Must(TheSharedListenRequestMap.find(response.mapId) != TheSharedListenRequestMap.end());
169 PendingOpenRequest por = TheSharedListenRequestMap[response.mapId];
170 Must(por.callback != NULL);
171 TheSharedListenRequestMap.erase(response.mapId);
172
b72fb55d
CT
173 StartListeningCb *cbd = dynamic_cast<StartListeningCb*>(por.callback->getDialer());
174 assert(cbd && cbd->conn != NULL);
175 Must(cbd && cbd->conn != NULL);
176 cbd->conn->fd = response.fd;
177
178 if (Comm::IsConnOpen(cbd->conn)) {
0d0bce6a 179 OpenListenerParams &p = por.params;
b72fb55d
CT
180 cbd->conn->local = p.addr;
181 cbd->conn->flags = p.flags;
e0d28505 182 // XXX: leave the comm AI stuff to comm_import_opened()?
0d0bce6a 183 struct addrinfo *AI = NULL;
4dd643d5 184 p.addr.getAddrInfo(AI);
0d0bce6a
AR
185 AI->ai_socktype = p.sock_type;
186 AI->ai_protocol = p.proto;
b72fb55d 187 comm_import_opened(cbd->conn, FdNote(p.fdNote), AI);
851614a8 188 Ip::Address::FreeAddr(AI);
0d0bce6a
AR
189 }
190
0d0bce6a 191 cbd->errNo = response.errNo;
e0d28505 192 cbd->handlerSubscription = por.params.handlerSubscription;
0d0bce6a 193 ScheduleCallHere(por.callback);
0dff3140
AR
194
195 kickDelayedRequest();
0d0bce6a 196}
f53969cc 197