--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 54 Interprocess Communication
+ *
+ */
+
+
+#include "config.h"
+#include <string.h>
+#include "TextException.h"
+#include "ipc/TypedMsgHdr.h"
+
+Ipc::TypedMsgHdr::TypedMsgHdr()
+{
+ xmemset(this, 0, sizeof(*this));
+ sync();
+}
+
+Ipc::TypedMsgHdr::TypedMsgHdr(const TypedMsgHdr &tmh)
+{
+ xmemcpy(this, &tmh, sizeof(*this));
+ sync();
+}
+
+Ipc::TypedMsgHdr &Ipc::TypedMsgHdr::operator =(const TypedMsgHdr &tmh)
+{
+ if (this != &tmh) { // skip assignment to self
+ xmemcpy(this, &tmh, sizeof(*this));
+ sync();
+ }
+ return *this;
+}
+
+// update msghdr and ios pointers based on msghdr counters
+void Ipc::TypedMsgHdr::sync()
+{
+ if (msg_name) { // we have a name
+ msg_name = &name;
+ } else {
+ Must(!msg_namelen && !msg_name);
+ }
+
+ if (msg_iov) { // we have a data component
+ Must(msg_iovlen == 1);
+ msg_iov = ios;
+ ios[0].iov_base = &data;
+ Must(ios[0].iov_len == sizeof(data));
+ } else {
+ Must(!msg_iovlen && !msg_iov);
+ }
+
+ if (msg_control) { // we have a control component
+ Must(msg_controllen > 0);
+ msg_control = &ctrl;
+ } else {
+ Must(!msg_controllen && !msg_control);
+ }
+}
+
+
+
+int
+Ipc::TypedMsgHdr::type() const
+{
+ Must(msg_iovlen == 1);
+ return data.type_;
+}
+
+void
+Ipc::TypedMsgHdr::address(const struct sockaddr_un& addr)
+{
+ allocName();
+ name = addr;
+ msg_name = &name;
+ msg_namelen = SUN_LEN(&name);
+}
+
+void
+Ipc::TypedMsgHdr::getData(int destType, void *raw, size_t size) const
+{
+ Must(type() == destType);
+ Must(size == data.size);
+ xmemcpy(raw, data.raw, size);
+}
+
+void
+Ipc::TypedMsgHdr::putData(int aType, const void *raw, size_t size)
+{
+ Must(size <= sizeof(data.raw));
+ allocData();
+ data.type_ = aType;
+ data.size = size;
+ xmemcpy(data.raw, raw, size);
+}
+
+void
+Ipc::TypedMsgHdr::putFd(int fd)
+{
+ Must(fd >= 0);
+ allocControl();
+
+ const int fdCount = 1;
+
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fdCount);
+
+ int *fdStore = reinterpret_cast<int*>(CMSG_DATA(cmsg));
+ xmemcpy(fdStore, &fd, fdCount * sizeof(int));
+ msg_controllen = cmsg->cmsg_len;
+}
+
+int
+Ipc::TypedMsgHdr::getFd() const
+{
+ Must(msg_control && msg_controllen);
+
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(this);
+ Must(cmsg->cmsg_level == SOL_SOCKET);
+ Must(cmsg->cmsg_type == SCM_RIGHTS);
+
+ const int fdCount = 1;
+ const int *fdStore = reinterpret_cast<const int*>(CMSG_DATA(cmsg));
+ int fd = -1;
+ xmemcpy(&fd, fdStore, fdCount * sizeof(int));
+ return fd;
+}
+
+void
+Ipc::TypedMsgHdr::prepForReading()
+{
+ xmemset(this, 0, sizeof(*this));
+ allocName();
+ allocData();
+ allocControl();
+}
+
+/// initialize io vector with one io record
+void
+Ipc::TypedMsgHdr::allocData()
+{
+ Must(!msg_iovlen && !msg_iov);
+ msg_iovlen = 1;
+ msg_iov = ios;
+ ios[0].iov_base = &data;
+ ios[0].iov_len = sizeof(data);
+ data.type_ = 0;
+ data.size = 0;
+}
+
+void
+Ipc::TypedMsgHdr::allocName()
+{
+ Must(!msg_name && !msg_namelen);
+ msg_name = &name;
+ msg_namelen = sizeof(name); // is that the right size?
+}
+
+void
+Ipc::TypedMsgHdr::allocControl()
+{
+ Must(!msg_control && !msg_controllen);
+ msg_control = &ctrl;
+ msg_controllen = sizeof(ctrl);
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 54 Interprocess Communication
+ *
+ */
+
+#ifndef SQUID_IPC_TYPED_MSG_HDR_H
+#define SQUID_IPC_TYPED_MSG_HDR_H
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#if HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
+namespace Ipc
+{
+
+/// struct msghdr with a known type, fixed-size I/O and control buffers
+class TypedMsgHdr: public msghdr
+{
+public:
+ TypedMsgHdr();
+ TypedMsgHdr(const TypedMsgHdr &tmh);
+ TypedMsgHdr &operator =(const TypedMsgHdr &tmh);
+
+ // type-safe access to message details
+ int type() const; ///< returns stored type or zero if none
+ void address(const struct sockaddr_un& addr); ///< sets [dest.] address
+ void getData(int ofType, void *raw, size_t size) const; ///< checks type
+ void putData(int aType, const void *raw, size_t size); ///< stores type
+ void putFd(int aFd); ///< stores descriptor
+ int getFd() const; ///< returns descriptor
+
+ /// raw, type-independent access for I/O
+ void prepForReading(); ///< reset and provide all buffers
+ char *raw() { return reinterpret_cast<char*>(this); }
+ const char *raw() const { return reinterpret_cast<const char*>(this); }
+ size_t size() const { return sizeof(*this); } ///< not true message size
+
+private:
+ void sync();
+ void allocData();
+ void allocName();
+ void allocControl();
+
+private:
+ struct sockaddr_un name; ///< same as .msg_name
+
+ struct iovec ios[1]; ///< same as .msg_iov[]
+
+ struct DataBuffer {
+ int type_; ///< Message kind, uses MessageType values
+ size_t size; ///< actual raw data size (for sanity checks)
+ char raw[250]; ///< buffer with type-specific data
+ } data; ///< same as .msg_iov[0].iov_base
+
+ struct CtrlBuffer {
+ char raw[CMSG_SPACE(sizeof(int))]; ///< control buffer space for one fd
+ } ctrl; ///< same as .msg_control
+};
+
+} // namespace Ipc
+
+#endif /* SQUID_IPC_TYPED_MSG_HDR_H */