Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Side by Side Diff: extensions/browser/api/cast_channel/cast_socket_framer.cc

Issue 505453002: Create dedicated class for handling wire message formatting and parsing. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed include order Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "extensions/browser/api/cast_channel/cast_socket_framer.h"
6
7 #include <stdlib.h>
8
9 #include "base/numerics/safe_conversions.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/sys_byteorder.h"
12 #include "extensions/browser/api/cast_channel/cast_channel.pb.h"
13
14 namespace extensions {
15 namespace core_api {
16 namespace cast_channel {
17 // Size of a CastSocket header payload.
18 size_t const kHeaderSizeBytes = sizeof(int32);
19 // Maximum byte count for a CastSocket message.
20 size_t const kMaxMessageSizeBytes = 65536;
21
22 MessageFramer::MessageFramer(scoped_refptr<net::GrowableIOBuffer> input_buffer)
23 : input_buffer_(input_buffer), error_(false) {
24 Reset();
25 }
26
27 MessageFramer::~MessageFramer() {
28 }
29
30 MessageFramer::MessageHeader::MessageHeader() : message_size(0) {
31 }
32
33 void MessageFramer::MessageHeader::SetMessageSize(size_t size) {
34 DCHECK_LT(size, static_cast<size_t>(kuint32max));
35 DCHECK_GT(size, 0U);
36 message_size = size;
37 }
38
39 // TODO(mfoltz): Investigate replacing header serialization with base::Pickle,
40 // if bit-for-bit compatible.
41 void MessageFramer::MessageHeader::PrependToString(std::string* str) {
42 MessageHeader output = *this;
43 output.message_size = base::HostToNet32(message_size);
44 size_t header_size = MessageHeader::header_size();
45 scoped_ptr<char, base::FreeDeleter> char_array(
46 static_cast<char*>(malloc(header_size)));
47 memcpy(char_array.get(), &output, header_size);
48 str->insert(0, char_array.get(), header_size);
49 }
50
51 // TODO(mfoltz): Investigate replacing header deserialization with base::Pickle,
52 // if bit-for-bit compatible.
53 void MessageFramer::MessageHeader::Deserialize(char* data,
54 MessageHeader* header) {
55 uint32 message_size;
56 memcpy(&message_size, data, kHeaderSizeBytes);
57 header->message_size =
58 base::checked_cast<size_t>(base::NetToHost32(message_size));
59 }
60
61 // static
62 size_t MessageFramer::MessageHeader::header_size() {
63 return kHeaderSizeBytes;
64 }
65
66 // static
67 size_t MessageFramer::MessageHeader::max_message_size() {
68 return kMaxMessageSizeBytes;
69 }
70
71 std::string MessageFramer::MessageHeader::ToString() {
72 return "{message_size: " + base::UintToString(message_size) + "}";
mark a. foltz 2014/09/02 20:27:38 Needs cast for message_size?
Kevin M 2014/09/02 23:15:35 Done.
73 }
74
75 // static
76 bool MessageFramer::Serialize(const CastMessage& message_proto,
77 std::string* message_data) {
78 DCHECK(message_data);
79 message_proto.SerializeToString(message_data);
80 size_t message_size = message_data->size();
81 if (message_size > kMaxMessageSizeBytes) {
82 message_data->clear();
83 return false;
84 }
85 MessageHeader header;
86 header.SetMessageSize(message_size);
87 header.PrependToString(message_data);
88 return true;
89 }
90
91 size_t MessageFramer::BytesRequested() {
92 size_t bytes_left;
93 switch (current_element_) {
94 case HEADER:
95 bytes_left = kHeaderSizeBytes - message_bytes_received_;
96 DCHECK_LE(bytes_left, kHeaderSizeBytes);
97 VLOG(2) << "Bytes needed for header: " << bytes_left;
98 return bytes_left;
99 case BODY:
100 bytes_left = (body_size_ + kHeaderSizeBytes) - message_bytes_received_;
101 DCHECK_LE(bytes_left, kMaxMessageSizeBytes - kHeaderSizeBytes);
102 VLOG(2) << "Bytes needed for body: " << bytes_left;
103 return bytes_left;
104 default:
105 NOTREACHED() << "Unhandled packet element type.";
106 return 0;
107 }
108 }
109
110 scoped_ptr<CastMessage> MessageFramer::Ingest(size_t num_bytes,
111 size_t* message_length,
112 ChannelError* error) {
113 DCHECK_EQ(base::checked_cast<int32>(message_bytes_received_),
114 input_buffer_->offset());
115 DCHECK(error);
116 DCHECK(message_length);
117 CHECK_LE(num_bytes, BytesRequested());
118
119 if (error_) {
120 *error = CHANNEL_ERROR_INVALID_MESSAGE;
121 return scoped_ptr<CastMessage>();
122 }
123
124 message_bytes_received_ += num_bytes;
125 *error = CHANNEL_ERROR_NONE;
126 *message_length = 0;
127 switch (current_element_) {
128 case HEADER:
129 if (BytesRequested() == 0) {
130 MessageHeader header;
131 MessageHeader::Deserialize(input_buffer_.get()->StartOfBuffer(),
132 &header);
133 if (header.message_size > MessageHeader::max_message_size()) {
134 VLOG(1) << "Error parsing header (message size too large).";
135 *error = CHANNEL_ERROR_INVALID_MESSAGE;
136 error_ = true;
137 return scoped_ptr<CastMessage>();
138 }
139 current_element_ = BODY;
140 body_size_ = header.message_size;
141 }
142 break;
143 case BODY:
144 if (BytesRequested() == 0) {
145 scoped_ptr<CastMessage> parsed_message(new CastMessage);
146 if (!parsed_message->ParseFromArray(
147 input_buffer_->StartOfBuffer() + kHeaderSizeBytes,
148 body_size_)) {
149 VLOG(1) << "Error parsing packet body.";
150 *error = CHANNEL_ERROR_INVALID_MESSAGE;
151 error_ = true;
152 return scoped_ptr<CastMessage>();
153 }
154 *message_length = body_size_;
155 Reset();
156 return parsed_message.Pass();
157 }
158 break;
159 default:
160 NOTREACHED() << "Unhandled packet element type.";
161 return scoped_ptr<CastMessage>();
162 }
163
164 input_buffer_->set_offset(message_bytes_received_);
165 return scoped_ptr<CastMessage>();
166 }
167
168 void MessageFramer::Reset() {
169 current_element_ = HEADER;
170 message_bytes_received_ = 0;
171 body_size_ = 0;
172 input_buffer_->set_offset(0);
173 }
174
175 } // namespace cast_channel
176 } // namespace core_api
177 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698