UdsOp.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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.
7  */
8 
9 /* DEBUG: section 54 Interprocess Communication */
10 
11 #include "squid.h"
12 #include "base/TextException.h"
13 #include "comm.h"
14 #include "comm/Connection.h"
15 #include "comm/Write.h"
16 #include "CommCalls.h"
17 #include "ipc/UdsOp.h"
18 
19 Ipc::UdsOp::UdsOp(const String& pathAddr):
20  AsyncJob("Ipc::UdsOp"),
21  address(PathToAddress(pathAddr)),
22  options(COMM_NONBLOCKING)
23 {
24  debugs(54, 5, HERE << '[' << this << "] pathAddr=" << pathAddr);
25 }
26 
28 {
29  debugs(54, 5, HERE << '[' << this << ']');
30  if (Comm::IsConnOpen(conn_))
31  conn_->close();
32  conn_ = NULL;
33 }
34 
35 void Ipc::UdsOp::setOptions(int newOptions)
36 {
37  options = newOptions;
38 }
39 
42 {
43  if (!Comm::IsConnOpen(conn_)) {
44  if (options & COMM_DOBIND)
45  unlink(address.sun_path);
46  if (conn_ == NULL)
47  conn_ = new Comm::Connection;
48  conn_->fd = comm_open_uds(SOCK_DGRAM, 0, &address, options);
49  Must(Comm::IsConnOpen(conn_));
50  }
51  return conn_;
52 }
53 
54 void Ipc::UdsOp::setTimeout(int seconds, const char *handlerName)
55 {
57  AsyncCall::Pointer handler = asyncCall(54,5, handlerName,
58  Dialer(CbcPointer<UdsOp>(this), &UdsOp::noteTimeout));
59  commSetConnTimeout(conn(), seconds, handler);
60 }
61 
63 {
65 }
66 
68 {
69  timedout(); // our kid handles communication timeout
70 }
71 
72 struct sockaddr_un
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));
79  return unixAddr;
80 }
81 
82 CBDATA_NAMESPACED_CLASS_INIT(Ipc, UdsSender);
83 
84 Ipc::UdsSender::UdsSender(const String& pathAddr, const TypedMsgHdr& aMessage):
85  UdsOp(pathAddr),
86  message(aMessage),
87  retries(10), // TODO: make configurable?
88  timeout(10), // TODO: make configurable?
89  sleeping(false),
90  writing(false)
91 {
93 }
94 
96 {
97  // did we abort while waiting between retries?
98  if (sleeping)
99  cancelSleep();
100 
101  UdsOp::swanSong();
102 }
103 
105 {
106  UdsOp::start();
107  write();
108  if (timeout > 0)
109  setTimeout(timeout, "Ipc::UdsSender::noteTimeout");
110 }
111 
113 {
114  return !writing && !sleeping && UdsOp::doneAll();
115 }
116 
118 {
119  debugs(54, 5, HERE);
121  AsyncCall::Pointer writeHandler = JobCallback(54, 5,
122  Dialer, this, UdsSender::wrote);
123  Comm::Write(conn(), message.raw(), message.size(), writeHandler, NULL);
124  writing = true;
125 }
126 
128 {
129  debugs(54, 5, HERE << params.conn << " flag " << params.flag << " retries " << retries << " [" << this << ']');
130  writing = false;
131  if (params.flag != Comm::OK && retries-- > 0) {
132  // perhaps a fresh connection and more time will help?
133  conn()->close();
134  startSleep();
135  }
136 }
137 
140 {
141  Must(!sleeping);
142  sleeping = true;
143  eventAdd("Ipc::UdsSender::DelayedRetry",
145  new Pointer(this), 1, 0, false); // TODO: Use Fibonacci increments
146 }
147 
150 {
151  if (sleeping) {
152  // Why not delete the event? See Comm::ConnOpener::cancelSleep().
153  sleeping = false;
154  debugs(54, 9, "stops sleeping");
155  }
156 }
157 
160 {
161  Pointer *ptr = static_cast<Pointer*>(data);
162  assert(ptr);
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;
167  ScheduleCallHere(call);
168  }
169  delete ptr;
170 }
171 
174 {
175  debugs(54, 5, HERE << sleeping);
176  if (sleeping) {
177  sleeping = false;
178  write(); // reopens the connection if needed
179  }
180 }
181 
183 {
184  debugs(54, 5, HERE);
185  mustStop("timedout");
186 }
187 
188 void Ipc::SendMessage(const String& toAddress, const TypedMsgHdr &message)
189 {
190  AsyncJob::Start(new UdsSender(toAddress, message));
191 }
192 
194 Ipc::ImportFdIntoComm(const Comm::ConnectionPointer &conn, int socktype, int protocol, Ipc::FdNoteId noteId)
195 {
196  struct sockaddr_storage addr;
197  socklen_t len = sizeof(addr);
198  if (getsockname(conn->fd, reinterpret_cast<sockaddr*>(&addr), &len) == 0) {
199  conn->remote = addr;
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);
206  } else {
207  int xerrno = errno;
208  debugs(54, DBG_CRITICAL, "ERROR: Ipc::ImportFdIntoComm: " << conn << ' ' << xstrerr(xerrno));
209  conn->close();
210  }
211  return conn;
212 }
213 
void setOptions(int newOptions)
changes socket options
Definition: UdsOp.cc:35
virtual bool doneAll() const
whether positive goal has been reached
Definition: AsyncJob.cc:96
int socklen_t
Definition: types.h:158
#define JobCallback(dbgSection, dbgLevel, Dialer, job, method)
Convenience macro to create a Dialer-based job callback.
Definition: AsyncJobCalls.h:68
const char * FdNote(int fdNodeId)
converts FdNoteId into a string
Definition: FdNotes.cc:16
#define assert(EX)
Definition: assert.h:17
int comm_open_uds(int sock_type, int proto, struct sockaddr_un *addr, int flags)
Create a unix-domain socket (UDS) that only supports FD_MSGHDR I/O.
Definition: comm.cc:1869
struct sockaddr_un PathToAddress(const String &pathAddr)
converts human-readable filename path into UDS address
Definition: UdsOp.cc:73
static void FreeAddr(struct addrinfo *&ai)
Definition: Address.cc:694
void comm_import_opened(const Comm::ConnectionPointer &conn, const char *note, struct addrinfo *AI)
update Comm state after getting a comm_open() FD from another process
Definition: comm.cc:499
void wrote(const CommIoCbParams &params)
done writing or error
Definition: UdsOp.cc:127
Definition: Flag.h:16
void clearTimeout()
remove previously set timeout, if any
Definition: UdsOp.cc:62
#define DBG_CRITICAL
Definition: Debug.h:44
int conn
the current server connection FD
Definition: Transport.cc:26
virtual void timedout()
called after setTimeout() if timed out
Definition: UdsOp.cc:182
virtual bool doneAll() const
whether positive goal has been reached
Definition: UdsOp.cc:112
struct sockaddr_un address
UDS address from path; treat as read-only.
Definition: UdsOp.h:36
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
FdNoteId
We cannot send char* FD notes to other processes. Pass int IDs and convert.
Definition: FdNotes.h:20
TypedMsgHdr message
what to send
Definition: UdsOp.h:90
void cancelSleep()
stop sleeping (or do nothing if we were not)
Definition: UdsOp.cc:149
static Pointer Start(AsyncJob *job)
starts a freshly created job (i.e., makes the job asynchronous)
Definition: AsyncJob.cc:23
#define COMM_DOBIND
Definition: Connection.h:47
Comm::ConnectionPointer conn
Definition: CommCalls.h:85
const char * xstrerr(int error)
Definition: xstrerror.cc:83
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:24
const Comm::ConnectionPointer & ImportFdIntoComm(const Comm::ConnectionPointer &conn, int socktype, int protocol, FdNoteId noteId)
import socket fd from another strand into our Comm state
Definition: UdsOp.cc:194
void const char HLPCB void * data
Definition: stub_helper.cc:16
int commUnsetConnTimeout(const Comm::ConnectionPointer &conn)
Definition: comm.cc:578
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
virtual void swanSong()
Definition: UdsOp.cc:95
virtual void swanSong()
Definition: AsyncJob.h:55
attempts to send an IPC message a few times, with a timeout
Definition: UdsOp.h:67
Cbc * valid() const
was set and is valid
Definition: CbcPointer.h:41
void * addr
Definition: membanger.c:46
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37
char sun_family
Definition: cmsg.h:107
static void handler(int signo)
Definition: purge.cc:860
void SendMessage(const String &toAddress, const TypedMsgHdr &message)
Definition: UdsOp.cc:188
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
virtual void start()
called by AsyncStart; do not call directly
Definition: UdsOp.cc:104
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:147
void startSleep()
pause for a while before resending the message
Definition: UdsOp.cc:139
#define Must(cond)
Definition: TextException.h:89
void delayedRetry()
make another sending attempt after a pause
Definition: UdsOp.cc:173
void write()
schedule writing
Definition: UdsOp.cc:117
void noteTimeout(const CommTimeoutCbParams &p)
Comm timeout callback; calls timedout()
Definition: UdsOp.cc:67
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
Definition: event.cc:109
void address(const struct sockaddr_un &addr)
sets [dest.] address
Definition: TypedMsgHdr.cc:75
Ip::Address remote
Definition: Connection.h:138
#define ScheduleCallHere(call)
Definition: AsyncCall.h:166
struct msghdr with a known type, fixed-size I/O and control buffers
Definition: TypedMsgHdr.h:31
Comm::ConnectionPointer & conn()
creates if needed and returns raw UDS socket descriptor
Definition: UdsOp.cc:41
Comm::Flag flag
comm layer result status.
Definition: CommCalls.h:87
UdsOp(const String &pathAddr)
Definition: UdsOp.cc:19
char sun_path[256]
Definition: cmsg.h:108
virtual ~UdsOp()
Definition: UdsOp.cc:27
static int retries
#define COMM_NONBLOCKING
Definition: Connection.h:44
virtual void start()
called by AsyncStart; do not call directly
Definition: AsyncJob.cc:43
CBDATA_NAMESPACED_CLASS_INIT(Ipc, UdsSender)
int commSetConnTimeout(const Comm::ConnectionPointer &conn, int timeout, AsyncCall::Pointer &callback)
Definition: comm.cc:552
#define NULL
Definition: types.h:166
static void DelayedRetry(void *data)
legacy wrapper for Ipc::UdsSender::delayedRetry()
Definition: UdsOp.cc:159
#define AF_LOCAL
Definition: cmsg.h:128
#define false
Definition: GnuRegex.c:233
void Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE *free_func)
Definition: Write.cc:35
void setTimeout(int seconds, const char *handlerName)
call timedout() if no UDS messages in a given number of seconds
Definition: UdsOp.cc:54
void getAddrInfo(struct addrinfo *&ai, int force=AF_UNSPEC) const
Definition: Address.cc:607
UdsSender(const String &pathAddr, const TypedMsgHdr &aMessage)
Definition: UdsOp.cc:84

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors