]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ipc/SharedListen.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / ipc / SharedListen.cc
CommitLineData
0d0bce6a 1/*
bbc27441
AJ
2 * Copyright (C) 1996-2014 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.
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
3d41e53a
FC
24#include <map>
25
0d0bce6a
AR
26/// holds information necessary to handle JoinListen response
27class PendingOpenRequest
28{
29public:
30 Ipc::OpenListenerParams params; ///< actual comm_open_sharedListen() parameters
31 AsyncCall::Pointer callback; // who to notify
32};
33
34/// maps ID assigned at request time to the response callback
35typedef std::map<int, PendingOpenRequest> SharedListenRequestMap;
36static SharedListenRequestMap TheSharedListenRequestMap;
37
38static int
39AddToMap(const PendingOpenRequest &por)
40{
41 // find unused ID using linear seach; there should not be many entries
42 for (int id = 0; true; ++id) {
43 if (TheSharedListenRequestMap.find(id) == TheSharedListenRequestMap.end()) {
44 TheSharedListenRequestMap[id] = por;
45 return id;
46 }
47 }
48 assert(false); // not reached
49 return -1;
50}
51
52Ipc::OpenListenerParams::OpenListenerParams()
53{
e297be13 54 memset(this, 0, sizeof(*this));
0d0bce6a
AR
55}
56
57bool
58Ipc::OpenListenerParams::operator <(const OpenListenerParams &p) const
59{
60 if (sock_type != p.sock_type)
61 return sock_type < p.sock_type;
62
63 if (proto != p.proto)
64 return proto < p.proto;
65
66 // ignore flags and fdNote differences because they do not affect binding
67
68 return addr.compareWhole(p.addr) < 0;
69}
70
0d0bce6a
AR
71Ipc::SharedListenRequest::SharedListenRequest(): requestorId(-1), mapId(-1)
72{
73 // caller will then set public data members
74}
75
76Ipc::SharedListenRequest::SharedListenRequest(const TypedMsgHdr &hdrMsg)
77{
8822ebee
AR
78 hdrMsg.checkType(mtSharedListenRequest);
79 hdrMsg.getPod(*this);
0d0bce6a
AR
80}
81
82void Ipc::SharedListenRequest::pack(TypedMsgHdr &hdrMsg) const
83{
8822ebee
AR
84 hdrMsg.setType(mtSharedListenRequest);
85 hdrMsg.putPod(*this);
0d0bce6a
AR
86}
87
b72fb55d 88Ipc::SharedListenResponse::SharedListenResponse(int aFd, int anErrNo, int aMapId):
f53969cc 89 fd(aFd), errNo(anErrNo), mapId(aMapId)
0d0bce6a
AR
90{
91}
92
93Ipc::SharedListenResponse::SharedListenResponse(const TypedMsgHdr &hdrMsg):
f53969cc 94 fd(-1), errNo(0), mapId(-1)
0d0bce6a 95{
8822ebee
AR
96 hdrMsg.checkType(mtSharedListenResponse);
97 hdrMsg.getPod(*this);
b72fb55d 98 fd = hdrMsg.getFd();
e0d28505 99 // other conn details are passed in OpenListenerParams and filled out by SharedListenJoin()
0d0bce6a
AR
100}
101
102void Ipc::SharedListenResponse::pack(TypedMsgHdr &hdrMsg) const
103{
8822ebee
AR
104 hdrMsg.setType(mtSharedListenResponse);
105 hdrMsg.putPod(*this);
b72fb55d 106 hdrMsg.putFd(fd);
0d0bce6a
AR
107}
108
0d0bce6a 109void Ipc::JoinSharedListen(const OpenListenerParams &params,
5667a628 110 AsyncCall::Pointer &callback)
0d0bce6a
AR
111{
112 PendingOpenRequest por;
113 por.params = params;
114 por.callback = callback;
115
116 SharedListenRequest request;
117 request.requestorId = KidIdentifier;
118 request.params = por.params;
119 request.mapId = AddToMap(por);
120
121 debugs(54, 3, HERE << "getting listening FD for " << request.params.addr <<
5667a628 122 " mapId=" << request.mapId);
0d0bce6a
AR
123
124 TypedMsgHdr message;
125 request.pack(message);
1ee292b7 126 SendMessage(Ipc::Port::CoordinatorAddr(), message);
0d0bce6a
AR
127}
128
129void Ipc::SharedListenJoined(const SharedListenResponse &response)
130{
e0d28505 131 // Dont debugs c fully since only FD is filled right now.
b72fb55d 132 debugs(54, 3, HERE << "got listening FD " << response.fd << " errNo=" <<
5667a628 133 response.errNo << " mapId=" << response.mapId);
0d0bce6a
AR
134
135 Must(TheSharedListenRequestMap.find(response.mapId) != TheSharedListenRequestMap.end());
136 PendingOpenRequest por = TheSharedListenRequestMap[response.mapId];
137 Must(por.callback != NULL);
138 TheSharedListenRequestMap.erase(response.mapId);
139
b72fb55d
CT
140 StartListeningCb *cbd = dynamic_cast<StartListeningCb*>(por.callback->getDialer());
141 assert(cbd && cbd->conn != NULL);
142 Must(cbd && cbd->conn != NULL);
143 cbd->conn->fd = response.fd;
144
145 if (Comm::IsConnOpen(cbd->conn)) {
0d0bce6a 146 OpenListenerParams &p = por.params;
b72fb55d
CT
147 cbd->conn->local = p.addr;
148 cbd->conn->flags = p.flags;
e0d28505 149 // XXX: leave the comm AI stuff to comm_import_opened()?
0d0bce6a 150 struct addrinfo *AI = NULL;
4dd643d5 151 p.addr.getAddrInfo(AI);
0d0bce6a
AR
152 AI->ai_socktype = p.sock_type;
153 AI->ai_protocol = p.proto;
b72fb55d 154 comm_import_opened(cbd->conn, FdNote(p.fdNote), AI);
851614a8 155 Ip::Address::FreeAddr(AI);
0d0bce6a
AR
156 }
157
0d0bce6a 158 cbd->errNo = response.errNo;
e0d28505 159 cbd->handlerSubscription = por.params.handlerSubscription;
0d0bce6a
AR
160 ScheduleCallHere(por.callback);
161}
f53969cc 162