]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ipc/UdsOp.cc
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 54 Interprocess Communication */
12 #include "base/TextException.h"
14 #include "comm/Connection.h"
15 #include "comm/Write.h"
16 #include "CommCalls.h"
17 #include "ipc/UdsOp.h"
19 Ipc::UdsOp::UdsOp(const String
& pathAddr
):
20 AsyncJob("Ipc::UdsOp"),
21 address(PathToAddress(pathAddr
)),
22 options(COMM_NONBLOCKING
)
24 debugs(54, 5, '[' << this << "] pathAddr=" << pathAddr
);
29 debugs(54, 5, '[' << this << ']');
30 if (Comm::IsConnOpen(conn_
))
35 void Ipc::UdsOp::setOptions(int newOptions
)
40 Comm::ConnectionPointer
&
43 if (!Comm::IsConnOpen(conn_
)) {
44 if (options
& COMM_DOBIND
)
45 unlink(address
.sun_path
);
47 conn_
= new Comm::Connection
;
48 conn_
->fd
= comm_open_uds(SOCK_DGRAM
, 0, &address
, options
);
49 Must(Comm::IsConnOpen(conn_
));
54 void Ipc::UdsOp::setTimeout(int seconds
, const char *handlerName
)
56 typedef CommCbMemFunT
<UdsOp
, CommTimeoutCbParams
> Dialer
;
57 AsyncCall::Pointer handler
= asyncCall(54,5, handlerName
,
58 Dialer(CbcPointer
<UdsOp
>(this), &UdsOp::noteTimeout
));
59 commSetConnTimeout(conn(), seconds
, handler
);
62 void Ipc::UdsOp::clearTimeout()
64 commUnsetConnTimeout(conn());
67 void Ipc::UdsOp::noteTimeout(const CommTimeoutCbParams
&)
69 timedout(); // our kid handles communication timeout
73 Ipc::PathToAddress(const String
& pathAddr
) {
74 assert(pathAddr
.size() != 0);
75 struct sockaddr_un unixAddr
;
76 memset(&unixAddr
, 0, sizeof(unixAddr
));
77 unixAddr
.sun_family
= AF_LOCAL
;
78 xstrncpy(unixAddr
.sun_path
, pathAddr
.termedBuf(), sizeof(unixAddr
.sun_path
));
82 CBDATA_NAMESPACED_CLASS_INIT(Ipc
, UdsSender
);
84 Ipc::UdsSender::UdsSender(const String
& pathAddr
, const TypedMsgHdr
& aMessage
):
86 codeContext(CodeContext::Current()),
88 retries(10), // TODO: make configurable?
89 timeout(10), // TODO: make configurable?
93 message
.address(address
);
96 void Ipc::UdsSender::swanSong()
98 // did we abort while waiting between retries?
105 void Ipc::UdsSender::start()
110 setTimeout(timeout
, "Ipc::UdsSender::noteTimeout");
113 bool Ipc::UdsSender::doneAll() const
115 return !writing
&& !sleeping
&& UdsOp::doneAll();
118 void Ipc::UdsSender::write()
120 debugs(54, 5, MYNAME
);
121 typedef CommCbMemFunT
<UdsSender
, CommIoCbParams
> Dialer
;
122 AsyncCall::Pointer writeHandler
= JobCallback(54, 5,
123 Dialer
, this, UdsSender::wrote
);
124 Comm::Write(conn(), message
.raw(), message
.size(), writeHandler
, nullptr);
128 void Ipc::UdsSender::wrote(const CommIoCbParams
& params
)
130 debugs(54, 5, params
.conn
<< " flag " << params
.flag
<< " retries " << retries
<< " [" << this << ']');
132 if (params
.flag
!= Comm::OK
&& retries
-- > 0) {
133 // perhaps a fresh connection and more time will help?
139 /// pause for a while before resending the message
140 void Ipc::UdsSender::startSleep()
144 eventAdd("Ipc::UdsSender::DelayedRetry",
145 Ipc::UdsSender::DelayedRetry
,
146 new Pointer(this), 1, 0, false); // TODO: Use Fibonacci increments
149 /// stop sleeping (or do nothing if we were not)
150 void Ipc::UdsSender::cancelSleep()
153 // Why not delete the event? See Comm::ConnOpener::cancelSleep().
155 debugs(54, 9, "stops sleeping");
159 /// legacy wrapper for Ipc::UdsSender::delayedRetry()
160 void Ipc::UdsSender::DelayedRetry(void *data
)
162 Pointer
*ptr
= static_cast<Pointer
*>(data
);
164 if (UdsSender
*us
= dynamic_cast<UdsSender
*>(ptr
->valid())) {
165 CallBack(us
->codeContext
, [&us
] {
166 CallJobHere(54, 4, us
, UdsSender
, delayedRetry
);
172 /// make another sending attempt after a pause
173 void Ipc::UdsSender::delayedRetry()
175 debugs(54, 5, sleeping
);
178 write(); // reopens the connection if needed
182 void Ipc::UdsSender::timedout()
184 debugs(54, 5, MYNAME
);
185 mustStop("timedout");
188 void Ipc::SendMessage(const String
& toAddress
, const TypedMsgHdr
&message
)
190 AsyncJob::Start(new UdsSender(toAddress
, message
));
193 const Comm::ConnectionPointer
&
194 Ipc::ImportFdIntoComm(const Comm::ConnectionPointer
&conn
, int socktype
, int protocol
, Ipc::FdNoteId noteId
)
196 struct sockaddr_storage addr
;
197 socklen_t len
= sizeof(addr
);
198 if (getsockname(conn
->fd
, reinterpret_cast<sockaddr
*>(&addr
), &len
) == 0) {
200 struct addrinfo
* addr_info
= nullptr;
201 conn
->remote
.getAddrInfo(addr_info
);
202 addr_info
->ai_socktype
= socktype
;
203 addr_info
->ai_protocol
= protocol
;
204 comm_import_opened(conn
, Ipc::FdNote(noteId
), addr_info
);
205 Ip::Address::FreeAddr(addr_info
);
208 debugs(54, DBG_CRITICAL
, "ERROR: Ipc::ImportFdIntoComm: " << conn
<< ' ' << xstrerr(xerrno
));