]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ipc/UdsOp.cc
Fix typo in rev.13441
[thirdparty/squid.git] / src / ipc / UdsOp.cc
CommitLineData
10cefb7b 1/*
10cefb7b 2 * DEBUG: section 54 Interprocess Communication
3 *
4 */
5
f7f3304a 6#include "squid.h"
602d9612 7#include "base/TextException.h"
10cefb7b 8#include "comm.h"
8942ceb3 9#include "comm/Connection.h"
ec41b64c 10#include "comm/Write.h"
602d9612 11#include "CommCalls.h"
10cefb7b 12#include "ipc/UdsOp.h"
13
ba568924 14Ipc::UdsOp::UdsOp(const String& pathAddr):
5667a628
AR
15 AsyncJob("Ipc::UdsOp"),
16 address(PathToAddress(pathAddr)),
e0d28505 17 options(COMM_NONBLOCKING)
10cefb7b 18{
ba568924 19 debugs(54, 5, HERE << '[' << this << "] pathAddr=" << pathAddr);
10cefb7b 20}
21
22Ipc::UdsOp::~UdsOp()
23{
24 debugs(54, 5, HERE << '[' << this << ']');
e0d28505
AJ
25 if (Comm::IsConnOpen(conn_))
26 conn_->close();
27 conn_ = NULL;
10cefb7b 28}
29
ba568924 30void Ipc::UdsOp::setOptions(int newOptions)
10cefb7b 31{
ba568924 32 options = newOptions;
10cefb7b 33}
34
e0d28505
AJ
35Comm::ConnectionPointer &
36Ipc::UdsOp::conn()
10cefb7b 37{
e0d28505 38 if (!Comm::IsConnOpen(conn_)) {
ba568924 39 if (options & COMM_DOBIND)
1bac0258 40 unlink(address.sun_path);
e0d28505
AJ
41 if (conn_ == NULL)
42 conn_ = new Comm::Connection;
43 conn_->fd = comm_open_uds(SOCK_DGRAM, 0, &address, options);
44 Must(Comm::IsConnOpen(conn_));
10cefb7b 45 }
e0d28505 46 return conn_;
10cefb7b 47}
48
ba568924 49void Ipc::UdsOp::setTimeout(int seconds, const char *handlerName)
10cefb7b 50{
4299f876 51 typedef CommCbMemFunT<UdsOp, CommTimeoutCbParams> Dialer;
ba568924 52 AsyncCall::Pointer handler = asyncCall(54,5, handlerName,
4299f876 53 Dialer(CbcPointer<UdsOp>(this), &UdsOp::noteTimeout));
8d77a37c 54 commSetConnTimeout(conn(), seconds, handler);
ba568924
AR
55}
56
57void Ipc::UdsOp::clearTimeout()
58{
8d77a37c 59 commUnsetConnTimeout(conn());
ba568924
AR
60}
61
62void Ipc::UdsOp::noteTimeout(const CommTimeoutCbParams &)
63{
64 timedout(); // our kid handles communication timeout
10cefb7b 65}
66
1bac0258 67struct sockaddr_un
5667a628 68Ipc::PathToAddress(const String& pathAddr) {
1bac0258
AR
69 assert(pathAddr.size() != 0);
70 struct sockaddr_un unixAddr;
71 memset(&unixAddr, 0, sizeof(unixAddr));
72 unixAddr.sun_family = AF_LOCAL;
73 xstrncpy(unixAddr.sun_path, pathAddr.termedBuf(), sizeof(unixAddr.sun_path));
74 return unixAddr;
75}
76
10cefb7b 77CBDATA_NAMESPACED_CLASS_INIT(Ipc, UdsSender);
78
1bac0258 79Ipc::UdsSender::UdsSender(const String& pathAddr, const TypedMsgHdr& aMessage):
5667a628
AR
80 UdsOp(pathAddr),
81 message(aMessage),
82 retries(10), // TODO: make configurable?
83 timeout(10), // TODO: make configurable?
3e81ed3a 84 sleeping(false),
5667a628 85 writing(false)
10cefb7b 86{
1bac0258 87 message.address(address);
10cefb7b 88}
89
3e81ed3a
AR
90void Ipc::UdsSender::swanSong()
91{
92 // did we abort while waiting between retries?
93 if (sleeping)
94 cancelSleep();
95
96 UdsOp::swanSong();
97}
98
10cefb7b 99void Ipc::UdsSender::start()
100{
ba568924 101 UdsOp::start();
10cefb7b 102 write();
103 if (timeout > 0)
ba568924 104 setTimeout(timeout, "Ipc::UdsSender::noteTimeout");
10cefb7b 105}
106
ba568924 107bool Ipc::UdsSender::doneAll() const
10cefb7b 108{
3e81ed3a 109 return !writing && !sleeping && UdsOp::doneAll();
10cefb7b 110}
111
112void Ipc::UdsSender::write()
113{
114 debugs(54, 5, HERE);
4299f876
AR
115 typedef CommCbMemFunT<UdsSender, CommIoCbParams> Dialer;
116 AsyncCall::Pointer writeHandler = JobCallback(54, 5,
4cb2536f 117 Dialer, this, UdsSender::wrote);
b0388924 118 Comm::Write(conn(), message.raw(), message.size(), writeHandler, NULL);
ba568924 119 writing = true;
10cefb7b 120}
121
ba568924 122void Ipc::UdsSender::wrote(const CommIoCbParams& params)
10cefb7b 123{
8bbb16e3 124 debugs(54, 5, HERE << params.conn << " flag " << params.flag << " retries " << retries << " [" << this << ']');
ba568924 125 writing = false;
1bac0258 126 if (params.flag != COMM_OK && retries-- > 0) {
3e81ed3a
AR
127 // perhaps a fresh connection and more time will help?
128 conn()->close();
6905e266 129 startSleep();
3e81ed3a
AR
130 }
131}
132
133/// pause for a while before resending the message
6905e266 134void Ipc::UdsSender::startSleep()
3e81ed3a
AR
135{
136 Must(!sleeping);
137 sleeping = true;
138 eventAdd("Ipc::UdsSender::DelayedRetry",
139 Ipc::UdsSender::DelayedRetry,
140 new Pointer(this), 1, 0, false); // TODO: Use Fibonacci increments
141}
142
143/// stop sleeping (or do nothing if we were not)
144void Ipc::UdsSender::cancelSleep()
145{
146 if (sleeping) {
147 // Why not delete the event? See Comm::ConnOpener::cancelSleep().
148 sleeping = false;
149 debugs(54, 9, "stops sleeping");
150 }
151}
152
153/// legacy wrapper for Ipc::UdsSender::delayedRetry()
154void Ipc::UdsSender::DelayedRetry(void *data)
155{
156 Pointer *ptr = static_cast<Pointer*>(data);
157 assert(ptr);
158 if (UdsSender *us = dynamic_cast<UdsSender*>(ptr->valid())) {
159 // get back inside AsyncJob protection by scheduling an async job call
160 typedef NullaryMemFunT<Ipc::UdsSender> Dialer;
161 AsyncCall::Pointer call = JobCallback(54, 4, Dialer, us, Ipc::UdsSender::delayedRetry);
162 ScheduleCallHere(call);
163 }
164 delete ptr;
165}
166
167/// make another sending attempt after a pause
168void Ipc::UdsSender::delayedRetry()
169{
170 debugs(54, 5, HERE << sleeping);
171 if (sleeping) {
172 sleeping = false;
173 write(); // reopens the connection if needed
1bac0258 174 }
10cefb7b 175}
176
ba568924 177void Ipc::UdsSender::timedout()
10cefb7b 178{
179 debugs(54, 5, HERE);
ba568924 180 mustStop("timedout");
10cefb7b 181}
182
1bac0258 183void Ipc::SendMessage(const String& toAddress, const TypedMsgHdr &message)
10cefb7b 184{
4299f876 185 AsyncJob::Start(new UdsSender(toAddress, message));
10cefb7b 186}
51ea0904 187
1b76e6c1
AJ
188const Comm::ConnectionPointer &
189Ipc::ImportFdIntoComm(const Comm::ConnectionPointer &conn, int socktype, int protocol, Ipc::FdNoteId noteId)
51ea0904
CT
190{
191 struct sockaddr_in addr;
192 socklen_t len = sizeof(addr);
1b76e6c1
AJ
193 if (getsockname(conn->fd, reinterpret_cast<sockaddr*>(&addr), &len) == 0) {
194 conn->remote = addr;
51ea0904 195 struct addrinfo* addr_info = NULL;
4dd643d5 196 conn->remote.getAddrInfo(addr_info);
51ea0904
CT
197 addr_info->ai_socktype = socktype;
198 addr_info->ai_protocol = protocol;
1b76e6c1 199 comm_import_opened(conn, Ipc::FdNote(noteId), addr_info);
4dd643d5 200 Ip::Address::FreeAddrInfo(addr_info);
51ea0904 201 } else {
1b76e6c1
AJ
202 debugs(54, DBG_CRITICAL, "ERROR: Ipc::ImportFdIntoComm: " << conn << ' ' << xstrerror());
203 conn->close();
51ea0904 204 }
1b76e6c1 205 return conn;
51ea0904 206}