From: Alex Rousskov Date: Sat, 1 May 2010 23:47:46 +0000 (-0600) Subject: Added previously forgotten sources. X-Git-Tag: SQUID_3_2_0_1~93^2~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=98d9bd29ac550872b6b68d281f05f54816d0e5d3;p=thirdparty%2Fsquid.git Added previously forgotten sources. --- diff --git a/src/ipc/TypedMsgHdr.cc b/src/ipc/TypedMsgHdr.cc new file mode 100644 index 0000000000..b596b80c1d --- /dev/null +++ b/src/ipc/TypedMsgHdr.cc @@ -0,0 +1,167 @@ +/* + * $Id$ + * + * DEBUG: section 54 Interprocess Communication + * + */ + + +#include "config.h" +#include +#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(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(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); +} diff --git a/src/ipc/TypedMsgHdr.h b/src/ipc/TypedMsgHdr.h new file mode 100644 index 0000000000..2ed26060a9 --- /dev/null +++ b/src/ipc/TypedMsgHdr.h @@ -0,0 +1,66 @@ +/* + * $Id$ + * + * DEBUG: section 54 Interprocess Communication + * + */ + +#ifndef SQUID_IPC_TYPED_MSG_HDR_H +#define SQUID_IPC_TYPED_MSG_HDR_H + +#include +#include +#if HAVE_SYS_UN_H +#include +#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(this); } + const char *raw() const { return reinterpret_cast(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 */