|
1 | 1 | // |
2 | 2 | // WebSocketImpl.cpp |
3 | 3 | // |
4 | | -// $Id: //poco/1.4/Net/src/WebSocketImpl.cpp#2 $ |
| 4 | +// $Id: //poco/1.4/Net/src/WebSocketImpl.cpp#6 $ |
5 | 5 | // |
6 | 6 | // Library: Net |
7 | 7 | // Package: WebSocket |
@@ -118,89 +118,92 @@ int WebSocketImpl::sendBytes(const void* buffer, int length, int flags) |
118 | 118 | int WebSocketImpl::receiveBytes(void* buffer, int length, int) |
119 | 119 | { |
120 | 120 | char header[MAX_HEADER_LENGTH]; |
121 | | - int n = _pStreamSocketImpl->receiveBytes(header, 2); |
122 | | - if (n == 1) |
| 121 | + int n = receiveNBytes(header, 2); |
| 122 | + poco_assert (n == 2); |
| 123 | + Poco::UInt8 lengthByte = static_cast<Poco::UInt8>(header[1]); |
| 124 | + int maskOffset = 0; |
| 125 | + if (lengthByte & FRAME_FLAG_MASK) maskOffset += 4; |
| 126 | + lengthByte &= 0x7f; |
| 127 | + if (lengthByte + 2 + maskOffset < MAX_HEADER_LENGTH) |
123 | 128 | { |
124 | | - n += _pStreamSocketImpl->receiveBytes(header + 1, 1); |
| 129 | + n = receiveNBytes(header + 2, lengthByte + maskOffset); |
125 | 130 | } |
126 | | - if (n == 2) |
| 131 | + else |
127 | 132 | { |
128 | | - Poco::UInt8 lengthByte = static_cast<Poco::UInt8>(header[1]) & 0x7f; |
129 | | - if (lengthByte + 2 < MAX_HEADER_LENGTH) |
130 | | - { |
131 | | - n = _pStreamSocketImpl->receiveBytes(header + 2, lengthByte); |
132 | | - } |
133 | | - else |
134 | | - { |
135 | | - n = _pStreamSocketImpl->receiveBytes(header + 2, MAX_HEADER_LENGTH - 2); |
136 | | - } |
| 133 | + n = receiveNBytes(header + 2, MAX_HEADER_LENGTH - 2); |
137 | 134 | } |
138 | | - else throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME); |
139 | 135 |
|
140 | | - if (n > 0) |
| 136 | + poco_assert (n > 0); |
| 137 | + n += 2; |
| 138 | + Poco::MemoryInputStream istr(header, n); |
| 139 | + Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER); |
| 140 | + Poco::UInt8 flags; |
| 141 | + char mask[4]; |
| 142 | + reader >> flags >> lengthByte; |
| 143 | + _frameFlags = flags; |
| 144 | + int payloadLength = 0; |
| 145 | + int payloadOffset = 2; |
| 146 | + if ((lengthByte & 0x7f) == 127) |
141 | 147 | { |
142 | | - n += 2; |
143 | | - Poco::MemoryInputStream istr(header, n); |
144 | | - Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER); |
145 | | - Poco::UInt8 flags; |
146 | | - Poco::UInt8 lengthByte; |
147 | | - char mask[4]; |
148 | | - reader >> flags >> lengthByte; |
149 | | - _frameFlags = flags; |
150 | | - int payloadLength = 0; |
151 | | - int payloadOffset = 2; |
152 | | - if ((lengthByte & 0x7f) == 127) |
153 | | - { |
154 | | - Poco::UInt64 l; |
155 | | - reader >> l; |
156 | | - if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %Lu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG); |
157 | | - payloadLength = static_cast<int>(l); |
158 | | - payloadOffset += 8; |
159 | | - } |
160 | | - else if ((lengthByte & 0x7f) == 126) |
| 148 | + Poco::UInt64 l; |
| 149 | + reader >> l; |
| 150 | + if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %Lu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG); |
| 151 | + payloadLength = static_cast<int>(l); |
| 152 | + payloadOffset += 8; |
| 153 | + } |
| 154 | + else if ((lengthByte & 0x7f) == 126) |
| 155 | + { |
| 156 | + Poco::UInt16 l; |
| 157 | + reader >> l; |
| 158 | + if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %hu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG); |
| 159 | + payloadLength = static_cast<int>(l); |
| 160 | + payloadOffset += 2; |
| 161 | + } |
| 162 | + else |
| 163 | + { |
| 164 | + Poco::UInt8 l = lengthByte & 0x7f; |
| 165 | + if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %u", unsigned(l)), WebSocket::WS_ERR_PAYLOAD_TOO_BIG); |
| 166 | + payloadLength = static_cast<int>(l); |
| 167 | + } |
| 168 | + if (lengthByte & FRAME_FLAG_MASK) |
| 169 | + { |
| 170 | + reader.readRaw(mask, 4); |
| 171 | + payloadOffset += 4; |
| 172 | + } |
| 173 | + int received = 0; |
| 174 | + if (payloadOffset < n) |
| 175 | + { |
| 176 | + std::memcpy(buffer, header + payloadOffset, n - payloadOffset); |
| 177 | + received = n - payloadOffset; |
| 178 | + } |
| 179 | + if (received < payloadLength) |
| 180 | + { |
| 181 | + received += receiveNBytes(reinterpret_cast<char*>(buffer) + received, payloadLength - received); |
| 182 | + } |
| 183 | + if (lengthByte & FRAME_FLAG_MASK) |
| 184 | + { |
| 185 | + char* p = reinterpret_cast<char*>(buffer); |
| 186 | + for (int i = 0; i < received; i++) |
161 | 187 | { |
162 | | - Poco::UInt16 l; |
163 | | - reader >> l; |
164 | | - if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %hu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG); |
165 | | - payloadLength = static_cast<int>(l); |
166 | | - payloadOffset += 2; |
| 188 | + p[i] ^= mask[i % 4]; |
167 | 189 | } |
| 190 | + } |
| 191 | + return received; |
| 192 | +} |
| 193 | + |
| 194 | + |
| 195 | +int WebSocketImpl::receiveNBytes(void* buffer, int bytes) |
| 196 | +{ |
| 197 | + int received = _pStreamSocketImpl->receiveBytes(reinterpret_cast<char*>(buffer), bytes); |
| 198 | + while (received < bytes) |
| 199 | + { |
| 200 | + int n = _pStreamSocketImpl->receiveBytes(reinterpret_cast<char*>(buffer) + received, bytes - received); |
| 201 | + if (n > 0) |
| 202 | + received += n; |
168 | 203 | else |
169 | | - { |
170 | | - Poco::UInt8 l = lengthByte & 0x7f; |
171 | | - if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %u", unsigned(l)), WebSocket::WS_ERR_PAYLOAD_TOO_BIG); |
172 | | - payloadLength = static_cast<int>(l); |
173 | | - } |
174 | | - if (lengthByte & FRAME_FLAG_MASK) |
175 | | - { |
176 | | - reader.readRaw(mask, 4); |
177 | | - payloadOffset += 4; |
178 | | - } |
179 | | - int received = 0; |
180 | | - if (payloadOffset < n) |
181 | | - { |
182 | | - std::memcpy(buffer, header + payloadOffset, n - payloadOffset); |
183 | | - received = n - payloadOffset; |
184 | | - } |
185 | | - while (received < payloadLength) |
186 | | - { |
187 | | - n = _pStreamSocketImpl->receiveBytes(reinterpret_cast<char*>(buffer) + received, payloadLength - received); |
188 | | - if (n > 0) |
189 | | - received += n; |
190 | | - else |
191 | | - throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME); |
192 | | - } |
193 | | - if (lengthByte & FRAME_FLAG_MASK) |
194 | | - { |
195 | | - char* p = reinterpret_cast<char*>(buffer); |
196 | | - for (int i = 0; i < received; i++) |
197 | | - { |
198 | | - p[i] ^= mask[i % 4]; |
199 | | - } |
200 | | - } |
201 | | - return received; |
| 204 | + throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME); |
202 | 205 | } |
203 | | - return n; |
| 206 | + return received; |
204 | 207 | } |
205 | 208 |
|
206 | 209 |
|
|
0 commit comments