[M73 Dev][EFL] Disable VizDisplayCompositor for EFL port
[platform/framework/web/chromium-efl.git] / components / cast_channel / cast_framer.cc
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 "components/cast_channel/cast_framer.h"
6
7 #include <stdlib.h>
8
9 #include <limits>
10
11 #include "base/memory/free_deleter.h"
12 #include "base/numerics/safe_conversions.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/sys_byteorder.h"
15 #include "components/cast_channel/proto/cast_channel.pb.h"
16
17 namespace cast_channel {
18 MessageFramer::MessageFramer(scoped_refptr<net::GrowableIOBuffer> input_buffer)
19     : input_buffer_(input_buffer), error_(false) {
20   Reset();
21 }
22
23 MessageFramer::~MessageFramer() {}
24
25 MessageFramer::MessageHeader::MessageHeader() : message_size(0) {}
26
27 void MessageFramer::MessageHeader::SetMessageSize(size_t size) {
28   DCHECK_LT(size, static_cast<size_t>(std::numeric_limits<uint32_t>::max()));
29   DCHECK_GT(size, 0U);
30   message_size = size;
31 }
32
33 // TODO(mfoltz): Investigate replacing header serialization with base::Pickle,
34 // if bit-for-bit compatible.
35 void MessageFramer::MessageHeader::PrependToString(std::string* str) {
36   MessageHeader output = *this;
37   output.message_size = base::HostToNet32(message_size);
38   size_t header_size = MessageHeader::header_size();
39   std::unique_ptr<char, base::FreeDeleter> char_array(
40       static_cast<char*>(malloc(header_size)));
41   memcpy(char_array.get(), &output, header_size);
42   str->insert(0, char_array.get(), header_size);
43 }
44
45 // TODO(mfoltz): Investigate replacing header deserialization with base::Pickle,
46 // if bit-for-bit compatible.
47 void MessageFramer::MessageHeader::Deserialize(char* data,
48                                                MessageHeader* header) {
49   uint32_t message_size;
50   memcpy(&message_size, data, header_size());
51   header->message_size =
52       base::checked_cast<size_t>(base::NetToHost32(message_size));
53 }
54
55 // static
56 size_t MessageFramer::MessageHeader::header_size() {
57   return sizeof(uint32_t);
58 }
59
60 // static
61 size_t MessageFramer::MessageHeader::max_body_size() {
62   return 65536;
63 }
64
65 // static
66 size_t MessageFramer::MessageHeader::max_message_size() {
67   return header_size() + max_body_size();
68 }
69
70 std::string MessageFramer::MessageHeader::ToString() {
71   return "{message_size: " +
72          base::UintToString(static_cast<uint32_t>(message_size)) + "}";
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 > MessageHeader::max_body_size()) {
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   if (error_) {
94     return 0;
95   }
96
97   switch (current_element_) {
98     case HEADER:
99       bytes_left = MessageHeader::header_size() - message_bytes_received_;
100       DCHECK_LE(bytes_left, MessageHeader::header_size());
101       VLOG(2) << "Bytes needed for header: " << bytes_left;
102       return bytes_left;
103     case BODY:
104       bytes_left =
105           (body_size_ + MessageHeader::header_size()) - message_bytes_received_;
106       DCHECK_LE(bytes_left, MessageHeader::max_body_size());
107       VLOG(2) << "Bytes needed for body: " << bytes_left;
108       return bytes_left;
109     default:
110       NOTREACHED() << "Unhandled packet element type.";
111       return 0;
112   }
113 }
114
115 std::unique_ptr<CastMessage> MessageFramer::Ingest(size_t num_bytes,
116                                                    size_t* message_length,
117                                                    ChannelError* error) {
118   DCHECK(error);
119   DCHECK(message_length);
120   if (error_) {
121     *error = ChannelError::INVALID_MESSAGE;
122     return nullptr;
123   }
124
125   DCHECK_EQ(base::checked_cast<int32_t>(message_bytes_received_),
126             input_buffer_->offset());
127   CHECK_LE(num_bytes, BytesRequested());
128   message_bytes_received_ += num_bytes;
129   *error = ChannelError::NONE;
130   *message_length = 0;
131   switch (current_element_) {
132     case HEADER:
133       if (BytesRequested() == 0) {
134         MessageHeader header;
135         MessageHeader::Deserialize(input_buffer_->StartOfBuffer(), &header);
136         if (header.message_size > MessageHeader::max_body_size()) {
137           VLOG(1) << "Error parsing header (message size too large).";
138           *error = ChannelError::INVALID_MESSAGE;
139           error_ = true;
140           return nullptr;
141         }
142         current_element_ = BODY;
143         body_size_ = header.message_size;
144       }
145       break;
146     case BODY:
147       if (BytesRequested() == 0) {
148         std::unique_ptr<CastMessage> parsed_message(new CastMessage);
149         if (!parsed_message->ParseFromArray(
150                 input_buffer_->StartOfBuffer() + MessageHeader::header_size(),
151                 body_size_)) {
152           VLOG(1) << "Error parsing packet body.";
153           *error = ChannelError::INVALID_MESSAGE;
154           error_ = true;
155           return nullptr;
156         }
157         *message_length = body_size_;
158         Reset();
159         return parsed_message;
160       }
161       break;
162     default:
163       NOTREACHED() << "Unhandled packet element type.";
164       return nullptr;
165   }
166
167   input_buffer_->set_offset(message_bytes_received_);
168   return nullptr;
169 }
170
171 void MessageFramer::Reset() {
172   current_element_ = HEADER;
173   message_bytes_received_ = 0;
174   body_size_ = 0;
175   input_buffer_->set_offset(0);
176 }
177
178 }  // namespace cast_channel