OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/websockets/websocket_basic_stream.h" | 5 #include "net/websockets/websocket_basic_stream.h" |
6 | 6 |
7 #include <stdint.h> | |
Adam Rice
2015/10/13 08:32:51
I prefer to have a space between the C includes an
wtc
2015/10/13 17:12:17
The Style Guide's recommendation changed in this r
Adam Rice
2015/10/13 17:21:49
Understood. Request withdrawn.
| |
7 #include <algorithm> | 8 #include <algorithm> |
8 #include <limits> | 9 #include <limits> |
9 #include <string> | 10 #include <string> |
10 #include <vector> | 11 #include <vector> |
11 | 12 |
12 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
eroman
2015/10/12 21:24:55
It may be possible to remove basictypes.h in some
Adam Rice
2015/10/13 08:32:51
I am happy to have it removed in a separate CL (as
wtc
2015/10/13 17:12:17
Yes, we should take the opportunity to find out if
eroman
2015/10/13 18:34:26
This is certainly nice work to do, and can probabl
tfarina
2015/10/13 18:44:32
I talked with Kim Gräsman from iwyu back in March
eroman
2015/10/13 18:59:12
Thanks for the update! That is too bad, it sounded
| |
13 #include "base/bind.h" | 14 #include "base/bind.h" |
14 #include "base/logging.h" | 15 #include "base/logging.h" |
15 #include "base/numerics/safe_conversions.h" | 16 #include "base/numerics/safe_conversions.h" |
16 #include "net/base/io_buffer.h" | 17 #include "net/base/io_buffer.h" |
17 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
18 #include "net/socket/client_socket_handle.h" | 19 #include "net/socket/client_socket_handle.h" |
19 #include "net/websockets/websocket_errors.h" | 20 #include "net/websockets/websocket_errors.h" |
20 #include "net/websockets/websocket_frame.h" | 21 #include "net/websockets/websocket_frame.h" |
21 #include "net/websockets/websocket_frame_parser.h" | 22 #include "net/websockets/websocket_frame_parser.h" |
22 | 23 |
23 namespace net { | 24 namespace net { |
24 | 25 |
25 namespace { | 26 namespace { |
26 | 27 |
27 // This uses type uint64 to match the definition of | 28 // This uses type uint64_t to match the definition of |
28 // WebSocketFrameHeader::payload_length in websocket_frame.h. | 29 // WebSocketFrameHeader::payload_length in websocket_frame.h. |
29 const uint64 kMaxControlFramePayload = 125; | 30 const uint64_t kMaxControlFramePayload = 125; |
30 | 31 |
31 // The number of bytes to attempt to read at a time. | 32 // The number of bytes to attempt to read at a time. |
32 // TODO(ricea): See if there is a better number or algorithm to fulfill our | 33 // TODO(ricea): See if there is a better number or algorithm to fulfill our |
33 // requirements: | 34 // requirements: |
34 // 1. We would like to use minimal memory on low-bandwidth or idle connections | 35 // 1. We would like to use minimal memory on low-bandwidth or idle connections |
35 // 2. We would like to read as close to line speed as possible on | 36 // 2. We would like to read as close to line speed as possible on |
36 // high-bandwidth connections | 37 // high-bandwidth connections |
37 // 3. We can't afford to cause jank on the IO thread by copying large buffers | 38 // 3. We can't afford to cause jank on the IO thread by copying large buffers |
38 // around | 39 // around |
39 // 4. We would like to hit any sweet-spots that might exist in terms of network | 40 // 4. We would like to hit any sweet-spots that might exist in terms of network |
40 // packet sizes / encryption block sizes / IPC alignment issues, etc. | 41 // packet sizes / encryption block sizes / IPC alignment issues, etc. |
41 const int kReadBufferSize = 32 * 1024; | 42 const int kReadBufferSize = 32 * 1024; |
42 | 43 |
43 typedef ScopedVector<WebSocketFrame>::const_iterator WebSocketFrameIterator; | 44 typedef ScopedVector<WebSocketFrame>::const_iterator WebSocketFrameIterator; |
44 | 45 |
45 // Returns the total serialized size of |frames|. This function assumes that | 46 // Returns the total serialized size of |frames|. This function assumes that |
46 // |frames| will be serialized with mask field. This function forces the | 47 // |frames| will be serialized with mask field. This function forces the |
47 // masked bit of the frames on. | 48 // masked bit of the frames on. |
48 int CalculateSerializedSizeAndTurnOnMaskBit( | 49 int CalculateSerializedSizeAndTurnOnMaskBit( |
49 ScopedVector<WebSocketFrame>* frames) { | 50 ScopedVector<WebSocketFrame>* frames) { |
50 const uint64 kMaximumTotalSize = std::numeric_limits<int>::max(); | 51 const uint64_t kMaximumTotalSize = std::numeric_limits<int>::max(); |
51 | 52 |
52 uint64 total_size = 0; | 53 uint64_t total_size = 0; |
53 for (WebSocketFrameIterator it = frames->begin(); it != frames->end(); ++it) { | 54 for (WebSocketFrameIterator it = frames->begin(); it != frames->end(); ++it) { |
54 WebSocketFrame* frame = *it; | 55 WebSocketFrame* frame = *it; |
55 // Force the masked bit on. | 56 // Force the masked bit on. |
56 frame->header.masked = true; | 57 frame->header.masked = true; |
57 // We enforce flow control so the renderer should never be able to force us | 58 // We enforce flow control so the renderer should never be able to force us |
58 // to cache anywhere near 2GB of frames. | 59 // to cache anywhere near 2GB of frames. |
59 uint64 frame_size = frame->header.payload_length + | 60 uint64_t frame_size = frame->header.payload_length + |
60 GetWebSocketFrameHeaderSize(frame->header); | 61 GetWebSocketFrameHeaderSize(frame->header); |
61 CHECK_LE(frame_size, kMaximumTotalSize - total_size) | 62 CHECK_LE(frame_size, kMaximumTotalSize - total_size) |
62 << "Aborting to prevent overflow"; | 63 << "Aborting to prevent overflow"; |
63 total_size += frame_size; | 64 total_size += frame_size; |
64 } | 65 } |
65 return static_cast<int>(total_size); | 66 return static_cast<int>(total_size); |
66 } | 67 } |
67 | 68 |
68 } // namespace | 69 } // namespace |
69 | 70 |
70 WebSocketBasicStream::WebSocketBasicStream( | 71 WebSocketBasicStream::WebSocketBasicStream( |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
150 WebSocketMaskingKey mask = generate_websocket_masking_key_(); | 151 WebSocketMaskingKey mask = generate_websocket_masking_key_(); |
151 int result = | 152 int result = |
152 WriteWebSocketFrameHeader(frame->header, &mask, dest, remaining_size); | 153 WriteWebSocketFrameHeader(frame->header, &mask, dest, remaining_size); |
153 DCHECK_NE(ERR_INVALID_ARGUMENT, result) | 154 DCHECK_NE(ERR_INVALID_ARGUMENT, result) |
154 << "WriteWebSocketFrameHeader() says that " << remaining_size | 155 << "WriteWebSocketFrameHeader() says that " << remaining_size |
155 << " is not enough to write the header in. This should not happen."; | 156 << " is not enough to write the header in. This should not happen."; |
156 CHECK_GE(result, 0) << "Potentially security-critical check failed"; | 157 CHECK_GE(result, 0) << "Potentially security-critical check failed"; |
157 dest += result; | 158 dest += result; |
158 remaining_size -= result; | 159 remaining_size -= result; |
159 | 160 |
160 CHECK_LE(frame->header.payload_length, static_cast<uint64>(remaining_size)); | 161 CHECK_LE(frame->header.payload_length, |
162 static_cast<uint64_t>(remaining_size)); | |
161 const int frame_size = static_cast<int>(frame->header.payload_length); | 163 const int frame_size = static_cast<int>(frame->header.payload_length); |
162 if (frame_size > 0) { | 164 if (frame_size > 0) { |
163 const char* const frame_data = frame->data->data(); | 165 const char* const frame_data = frame->data->data(); |
164 std::copy(frame_data, frame_data + frame_size, dest); | 166 std::copy(frame_data, frame_data + frame_size, dest); |
165 MaskWebSocketFramePayload(mask, 0, dest, frame_size); | 167 MaskWebSocketFramePayload(mask, 0, dest, frame_size); |
166 dest += frame_size; | 168 dest += frame_size; |
167 remaining_size -= frame_size; | 169 remaining_size -= frame_size; |
168 } | 170 } |
169 } | 171 } |
170 DCHECK_EQ(0, remaining_size) << "Buffer size calculation was wrong; " | 172 DCHECK_EQ(0, remaining_size) << "Buffer size calculation was wrong; " |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
342 DCHECK(is_final_chunk); | 344 DCHECK(is_final_chunk); |
343 *frame = CreateFrame(is_final_chunk, body); | 345 *frame = CreateFrame(is_final_chunk, body); |
344 return OK; | 346 return OK; |
345 } | 347 } |
346 } | 348 } |
347 | 349 |
348 // Apply basic sanity checks to the |payload_length| field from the frame | 350 // Apply basic sanity checks to the |payload_length| field from the frame |
349 // header. A check for exact equality can only be used when the whole frame | 351 // header. A check for exact equality can only be used when the whole frame |
350 // arrives in one chunk. | 352 // arrives in one chunk. |
351 DCHECK_GE(current_frame_header_->payload_length, | 353 DCHECK_GE(current_frame_header_->payload_length, |
352 base::checked_cast<uint64>(chunk_size)); | 354 base::checked_cast<uint64_t>(chunk_size)); |
353 DCHECK(!is_first_chunk || !is_final_chunk || | 355 DCHECK(!is_first_chunk || !is_final_chunk || |
354 current_frame_header_->payload_length == | 356 current_frame_header_->payload_length == |
355 base::checked_cast<uint64>(chunk_size)); | 357 base::checked_cast<uint64_t>(chunk_size)); |
356 | 358 |
357 // Convert the chunk to a complete frame. | 359 // Convert the chunk to a complete frame. |
358 *frame = CreateFrame(is_final_chunk, data_buffer); | 360 *frame = CreateFrame(is_final_chunk, data_buffer); |
359 return OK; | 361 return OK; |
360 } | 362 } |
361 | 363 |
362 scoped_ptr<WebSocketFrame> WebSocketBasicStream::CreateFrame( | 364 scoped_ptr<WebSocketFrame> WebSocketBasicStream::CreateFrame( |
363 bool is_final_chunk, | 365 bool is_final_chunk, |
364 const scoped_refptr<IOBufferWithSize>& data) { | 366 const scoped_refptr<IOBufferWithSize>& data) { |
365 scoped_ptr<WebSocketFrame> result_frame; | 367 scoped_ptr<WebSocketFrame> result_frame; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
415 const CompletionCallback& callback, | 417 const CompletionCallback& callback, |
416 int result) { | 418 int result) { |
417 result = HandleReadResult(result, frames); | 419 result = HandleReadResult(result, frames); |
418 if (result == ERR_IO_PENDING) | 420 if (result == ERR_IO_PENDING) |
419 result = ReadFrames(frames, callback); | 421 result = ReadFrames(frames, callback); |
420 if (result != ERR_IO_PENDING) | 422 if (result != ERR_IO_PENDING) |
421 callback.Run(result); | 423 callback.Run(result); |
422 } | 424 } |
423 | 425 |
424 } // namespace net | 426 } // namespace net |
OLD | NEW |