]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1996-2025 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 | #ifndef SQUID_SRC_IPC_TYPEDMSGHDR_H | |
12 | #define SQUID_SRC_IPC_TYPEDMSGHDR_H | |
13 | ||
14 | #include "compat/cmsg.h" | |
15 | #include "ipc/Messages.h" | |
16 | #if HAVE_SYS_SOCKET_H | |
17 | #include <sys/socket.h> | |
18 | #endif | |
19 | #if HAVE_SYS_UIO_H | |
20 | #include <sys/uio.h> | |
21 | #endif | |
22 | #if HAVE_SYS_UN_H | |
23 | #include <sys/un.h> | |
24 | #endif | |
25 | ||
26 | #include <type_traits> | |
27 | ||
28 | class String; | |
29 | ||
30 | namespace Ipc | |
31 | { | |
32 | ||
33 | /// struct msghdr with a known type, fixed-size I/O and control buffers | |
34 | class TypedMsgHdr: public msghdr | |
35 | { | |
36 | public: | |
37 | enum {maxSize = 4096}; | |
38 | ||
39 | public: | |
40 | TypedMsgHdr(); | |
41 | TypedMsgHdr(const TypedMsgHdr &tmh); | |
42 | TypedMsgHdr &operator =(const TypedMsgHdr &tmh); | |
43 | ||
44 | void address(const struct sockaddr_un &addr); ///< sets [dest.] address | |
45 | ||
46 | /* message type manipulation; these must be called before put/get*() */ | |
47 | void setType(int aType); ///< sets message type; use MessageType enum | |
48 | void checkType(int aType) const; ///< throws if stored type is not aType | |
49 | /// received or set message kind; may not be a MessageType value | |
50 | /// \returns 0 if no message kind has been received or set | |
51 | int rawType() const { return msg_iov ? data.type_ : 0; } | |
52 | ||
53 | /* access for TriviallyCopyable (a.k.a. Plain Old Data or POD) message parts */ | |
54 | template <class Pod> void getPod(Pod &pod) const; ///< load POD | |
55 | template <class Pod> void putPod(const Pod &pod); ///< store POD | |
56 | ||
57 | /* access to message parts for selected commonly-used part types */ | |
58 | void getString(String &s) const; ///< load variable-length string | |
59 | void putString(const String &s); ///< store variable-length string | |
60 | int getInt() const; ///< load an integer | |
61 | void putInt(int n); ///< store an integer | |
62 | void getFixed(void *raw, size_t size) const; ///< always load size bytes | |
63 | void putFixed(const void *raw, size_t size); ///< always store size bytes | |
64 | ||
65 | /// returns true if there is data to extract; handy for optional parts | |
66 | bool hasMoreData() const { return offset < data.size; } | |
67 | ||
68 | /* access to a "file" descriptor that can be passed between processes */ | |
69 | void putFd(int aFd); ///< stores descriptor | |
70 | int getFd() const; ///< returns stored descriptor | |
71 | bool hasFd() const; ///< whether the message has a descriptor stored | |
72 | ||
73 | /* raw, type-independent access for I/O */ | |
74 | void prepForReading(); ///< reset and provide all buffers | |
75 | char *raw() { return reinterpret_cast<char*>(this); } | |
76 | const char *raw() const { return reinterpret_cast<const char*>(this); } | |
77 | size_t size() const { return sizeof(*this); } ///< not true message size | |
78 | ||
79 | private: | |
80 | void clear(); | |
81 | void sync(); | |
82 | void allocData(); | |
83 | void allocName(); | |
84 | void allocControl(); | |
85 | ||
86 | /* raw, type-independent manipulation used by type-specific methods */ | |
87 | void getRaw(void *raw, size_t size) const; | |
88 | void putRaw(const void *raw, size_t size); | |
89 | ||
90 | private: | |
91 | struct sockaddr_un name; ///< same as .msg_name | |
92 | ||
93 | struct iovec ios[1]; ///< same as .msg_iov[] | |
94 | ||
95 | struct DataBuffer { | |
96 | DataBuffer() { memset(raw, 0, sizeof(raw)); } | |
97 | ||
98 | int type_ = 0; ///< Message kind, uses MessageType values | |
99 | size_t size = 0; ///< actual raw data size (for sanity checks) | |
100 | char raw[maxSize]; ///< buffer with type-specific data | |
101 | } data; ///< same as .msg_iov[0].iov_base | |
102 | ||
103 | struct CtrlBuffer { | |
104 | CtrlBuffer() { memset(raw, 0, sizeof(raw)); } | |
105 | ||
106 | /// control buffer space for one fd | |
107 | char raw[SQUID_CMSG_SPACE(sizeof(int))]; | |
108 | } ctrl; ///< same as .msg_control | |
109 | ||
110 | /// data offset for the next get/put*() to start with | |
111 | mutable unsigned int offset = 0; | |
112 | }; | |
113 | ||
114 | } // namespace Ipc | |
115 | ||
116 | template <class Pod> | |
117 | void | |
118 | Ipc::TypedMsgHdr::getPod(Pod &pod) const | |
119 | { | |
120 | static_assert(std::is_trivially_copyable<Pod>::value, "getPod() used for a POD"); | |
121 | getFixed(&pod, sizeof(pod)); | |
122 | } | |
123 | ||
124 | template <class Pod> | |
125 | void | |
126 | Ipc::TypedMsgHdr::putPod(const Pod &pod) | |
127 | { | |
128 | static_assert(std::is_trivially_copyable<Pod>::value, "putPod() used for a POD"); | |
129 | putFixed(&pod, sizeof(pod)); | |
130 | } | |
131 | ||
132 | #endif /* SQUID_SRC_IPC_TYPEDMSGHDR_H */ | |
133 |