]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ipc/UdsOp.cc
2 * Copyright (C) 1996-2016 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, HERE
<< '[' << this << "] pathAddr=" << pathAddr
);
29 debugs(54, 5, HERE
<< '[' << 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
):
87 retries(10), // TODO: make configurable?
88 timeout(10), // TODO: make configurable?
92 message
.address(address
);
95 void Ipc::UdsSender::swanSong()
97 // did we abort while waiting between retries?
104 void Ipc::UdsSender::start()
109 setTimeout(timeout
, "Ipc::UdsSender::noteTimeout");
112 bool Ipc::UdsSender::doneAll() const
114 return !writing
&& !sleeping
&& UdsOp::doneAll();
117 void Ipc::UdsSender::write()
120 typedef CommCbMemFunT
<UdsSender
, CommIoCbParams
> Dialer
;
121 AsyncCall::Pointer writeHandler
= JobCallback(54, 5,
122 Dialer
, this, UdsSender::wrote
);
123 Comm::Write(conn(), message
.raw(), message
.size(), writeHandler
, NULL
);
127 void Ipc::UdsSender::wrote(const CommIoCbParams
& params
)
129 debugs(54, 5, HERE
<< params
.conn
<< " flag " << params
.flag
<< " retries " << retries
<< " [" << this << ']');
131 if (params
.flag
!= Comm::OK
&& retries
-- > 0) {
132 // perhaps a fresh connection and more time will help?
138 /// pause for a while before resending the message
139 void Ipc::UdsSender::startSleep()
143 eventAdd("Ipc::UdsSender::DelayedRetry",
144 Ipc::UdsSender::DelayedRetry
,
145 new Pointer(this), 1, 0, false); // TODO: Use Fibonacci increments
148 /// stop sleeping (or do nothing if we were not)
149 void Ipc::UdsSender::cancelSleep()
152 // Why not delete the event? See Comm::ConnOpener::cancelSleep().
154 debugs(54, 9, "stops sleeping");
158 /// legacy wrapper for Ipc::UdsSender::delayedRetry()
159 void Ipc::UdsSender::DelayedRetry(void *data
)
161 Pointer
*ptr
= static_cast<Pointer
*>(data
);
163 if (UdsSender
*us
= dynamic_cast<UdsSender
*>(ptr
->valid())) {
164 // get back inside AsyncJob protection by scheduling an async job call
165 typedef NullaryMemFunT
<Ipc::UdsSender
> Dialer
;
166 AsyncCall::Pointer call
= JobCallback(54, 4, Dialer
, us
, Ipc::UdsSender::delayedRetry
);
167 ScheduleCallHere(call
);
172 /// make another sending attempt after a pause
173 void Ipc::UdsSender::delayedRetry()
175 debugs(54, 5, HERE
<< sleeping
);
178 write(); // reopens the connection if needed
182 void Ipc::UdsSender::timedout()
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_in addr
;
197 socklen_t len
= sizeof(addr
);
198 if (getsockname(conn
->fd
, reinterpret_cast<sockaddr
*>(&addr
), &len
) == 0) {
200 struct addrinfo
* addr_info
= NULL
;
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
));