1 | /* |
2 | * Copyright (C) 2010 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 | * THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #pragma once |
27 | |
28 | #include "ArgumentCoder.h" |
29 | #include "Attachment.h" |
30 | #include "StringReference.h" |
31 | #include <wtf/EnumTraits.h> |
32 | #include <wtf/Vector.h> |
33 | |
34 | #if HAVE(QOS_CLASSES) |
35 | #include <pthread/qos.h> |
36 | #endif |
37 | |
38 | namespace IPC { |
39 | |
40 | class DataReference; |
41 | class ImportanceAssertion; |
42 | |
43 | class Decoder { |
44 | WTF_MAKE_FAST_ALLOCATED; |
45 | public: |
46 | Decoder(const uint8_t* buffer, size_t bufferSize, void (*bufferDeallocator)(const uint8_t*, size_t), Vector<Attachment>&&); |
47 | ~Decoder(); |
48 | |
49 | Decoder(const Decoder&) = delete; |
50 | Decoder(Decoder&&) = delete; |
51 | |
52 | StringReference messageReceiverName() const { return m_messageReceiverName; } |
53 | StringReference messageName() const { return m_messageName; } |
54 | uint64_t destinationID() const { return m_destinationID; } |
55 | |
56 | bool isSyncMessage() const; |
57 | bool shouldDispatchMessageWhenWaitingForSyncReply() const; |
58 | bool shouldUseFullySynchronousModeForTesting() const; |
59 | |
60 | #if PLATFORM(MAC) |
61 | void setImportanceAssertion(std::unique_ptr<ImportanceAssertion>); |
62 | #endif |
63 | |
64 | #if HAVE(QOS_CLASSES) |
65 | void setQOSClassOverride(pthread_override_t override) { m_qosClassOverride = override; } |
66 | #endif |
67 | |
68 | static std::unique_ptr<Decoder> unwrapForTesting(Decoder&); |
69 | |
70 | size_t length() const { return m_bufferEnd - m_buffer; } |
71 | |
72 | bool isInvalid() const { return m_bufferPos > m_bufferEnd; } |
73 | void markInvalid() { m_bufferPos = m_bufferEnd + 1; } |
74 | |
75 | bool decodeFixedLengthData(uint8_t*, size_t, unsigned alignment); |
76 | |
77 | // The data in the data reference here will only be valid for the lifetime of the ArgumentDecoder object. |
78 | bool decodeVariableLengthByteArray(DataReference&); |
79 | |
80 | bool decode(bool&); |
81 | Decoder& operator>>(Optional<bool>&); |
82 | bool decode(uint8_t&); |
83 | Decoder& operator>>(Optional<uint8_t>&); |
84 | bool decode(uint16_t&); |
85 | Decoder& operator>>(Optional<uint16_t>&); |
86 | bool decode(uint32_t&); |
87 | Decoder& operator>>(Optional<uint32_t>&); |
88 | bool decode(uint64_t&); |
89 | Decoder& operator>>(Optional<uint64_t>&); |
90 | bool decode(int16_t&); |
91 | Decoder& operator>>(Optional<int16_t>&); |
92 | bool decode(int32_t&); |
93 | Decoder& operator>>(Optional<int32_t>&); |
94 | bool decode(int64_t&); |
95 | Decoder& operator>>(Optional<int64_t>&); |
96 | bool decode(float&); |
97 | Decoder& operator>>(Optional<float>&); |
98 | bool decode(double&); |
99 | Decoder& operator>>(Optional<double>&); |
100 | |
101 | template<typename E> |
102 | auto decode(E& e) -> std::enable_if_t<std::is_enum<E>::value, bool> |
103 | { |
104 | uint64_t value; |
105 | if (!decode(value)) |
106 | return false; |
107 | if (!isValidEnum<E>(value)) |
108 | return false; |
109 | |
110 | e = static_cast<E>(value); |
111 | return true; |
112 | } |
113 | |
114 | template<typename E, std::enable_if_t<std::is_enum<E>::value>* = nullptr> |
115 | Decoder& operator>>(Optional<E>& optional) |
116 | { |
117 | Optional<uint64_t> value; |
118 | *this >> value; |
119 | if (value && isValidEnum<E>(*value)) |
120 | optional = static_cast<E>(*value); |
121 | return *this; |
122 | } |
123 | |
124 | template<typename T> bool decodeEnum(T& result) |
125 | { |
126 | static_assert(sizeof(T) <= 8, "Enum type T must not be larger than 64 bits!" ); |
127 | |
128 | uint64_t value; |
129 | if (!decode(value)) |
130 | return false; |
131 | |
132 | result = static_cast<T>(value); |
133 | return true; |
134 | } |
135 | |
136 | template<typename T> |
137 | bool bufferIsLargeEnoughToContain(size_t numElements) const |
138 | { |
139 | static_assert(std::is_arithmetic<T>::value, "Type T must have a fixed, known encoded size!" ); |
140 | |
141 | if (numElements > std::numeric_limits<size_t>::max() / sizeof(T)) |
142 | return false; |
143 | |
144 | return bufferIsLargeEnoughToContain(alignof(T), numElements * sizeof(T)); |
145 | } |
146 | |
147 | template<typename T, std::enable_if_t<!std::is_enum<T>::value && UsesLegacyDecoder<T>::value>* = nullptr> |
148 | bool decode(T& t) |
149 | { |
150 | return ArgumentCoder<T>::decode(*this, t); |
151 | } |
152 | |
153 | template<typename T, std::enable_if_t<!std::is_enum<T>::value && !UsesLegacyDecoder<T>::value>* = nullptr> |
154 | bool decode(T& t) |
155 | { |
156 | Optional<T> optional; |
157 | *this >> optional; |
158 | if (!optional) |
159 | return false; |
160 | t = WTFMove(*optional); |
161 | return true; |
162 | } |
163 | |
164 | template<typename T, std::enable_if_t<UsesModernDecoder<T>::value>* = nullptr> |
165 | Decoder& operator>>(Optional<T>& t) |
166 | { |
167 | t = ArgumentCoder<T>::decode(*this); |
168 | return *this; |
169 | } |
170 | |
171 | template<typename T, std::enable_if_t<!std::is_enum<T>::value && !UsesModernDecoder<T>::value>* = nullptr> |
172 | Decoder& operator>>(Optional<T>& optional) |
173 | { |
174 | T t; |
175 | if (ArgumentCoder<T>::decode(*this, t)) { |
176 | optional = WTFMove(t); |
177 | return *this; |
178 | } |
179 | optional = WTF::nullopt; |
180 | return *this; |
181 | } |
182 | |
183 | bool removeAttachment(Attachment&); |
184 | |
185 | static const bool isIPCDecoder = true; |
186 | |
187 | private: |
188 | bool alignBufferPosition(unsigned alignment, size_t); |
189 | bool bufferIsLargeEnoughToContain(unsigned alignment, size_t) const; |
190 | template<typename Type> Decoder& getOptional(Optional<Type>&); |
191 | |
192 | const uint8_t* m_buffer; |
193 | const uint8_t* m_bufferPos; |
194 | const uint8_t* m_bufferEnd; |
195 | void (*m_bufferDeallocator)(const uint8_t*, size_t); |
196 | |
197 | Vector<Attachment> m_attachments; |
198 | |
199 | uint8_t m_messageFlags; |
200 | StringReference m_messageReceiverName; |
201 | StringReference m_messageName; |
202 | |
203 | uint64_t m_destinationID; |
204 | |
205 | #if PLATFORM(MAC) |
206 | std::unique_ptr<ImportanceAssertion> m_importanceAssertion; |
207 | #endif |
208 | |
209 | #if HAVE(QOS_CLASSES) |
210 | pthread_override_t m_qosClassOverride { nullptr }; |
211 | #endif |
212 | }; |
213 | |
214 | } // namespace IPC |
215 | |