Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 "components/pairing/proto_decoder.h" | |
| 6 | |
| 7 #include "components/pairing/message_buffer.h" | |
| 8 #include "components/pairing/pairing_api.pb.h" | |
| 9 #include "net/base/io_buffer.h" | |
| 10 | |
| 11 namespace { | |
| 12 enum { | |
| 13 MESSAGE_NONE, | |
| 14 MESSAGE_HOST_STATUS, | |
| 15 MESSAGE_CONFIGURE_HOST, | |
| 16 MESSAGE_PAIR_DEVICES, | |
| 17 MESSAGE_COMPLETE_SETUP, | |
| 18 MESSAGE_ERROR, | |
| 19 NUM_MESSAGES, | |
| 20 }; | |
| 21 } | |
| 22 | |
| 23 namespace pairing_chromeos { | |
| 24 | |
| 25 ProtoDecoder::ProtoDecoder(Observer* observer) | |
| 26 : observer_(observer), | |
| 27 message_buffer_(new MessageBuffer), | |
| 28 next_message_type_(MESSAGE_NONE), | |
| 29 next_message_size_(0) {} | |
|
achuithb
2014/08/11 22:04:31
DCHECK(observer);
Zachary Kuznia
2014/08/11 23:40:29
Done.
| |
| 30 | |
| 31 ProtoDecoder::~ProtoDecoder() {} | |
| 32 | |
| 33 bool ProtoDecoder::DecodeIOBuffer(int size, | |
| 34 scoped_refptr<net::IOBuffer> io_buffer) { | |
| 35 // Update the message buffer. | |
| 36 message_buffer_->AddIOBuffer(io_buffer, size); | |
| 37 | |
| 38 // If there is no current message, the next byte is the message type. | |
| 39 if (next_message_type_ == MESSAGE_NONE) { | |
| 40 if (message_buffer_->AvailableBytes() < (int)sizeof(uint8_t)) { | |
|
achuithb
2014/08/11 22:04:31
Don't need curly braces.
You should use reinterpr
Zachary Kuznia
2014/08/11 23:40:29
I went back and forth on that as well, but this mi
| |
| 41 return true; | |
| 42 } | |
| 43 | |
| 44 uint8_t message_type = MESSAGE_NONE; | |
|
achuithb
2014/08/11 22:04:31
Why not char instead of uint8_t?
Zachary Kuznia
2014/08/11 23:40:29
Unsigned types have less undefined behavior with t
| |
| 45 message_buffer_->ReadBytes(reinterpret_cast<char*>(&message_type), | |
| 46 sizeof(message_type)); | |
| 47 | |
| 48 if (message_type == MESSAGE_NONE || message_type >= NUM_MESSAGES) { | |
| 49 LOG(ERROR) << "Unknown message type received: " << message_type; | |
| 50 return false; | |
| 51 } | |
| 52 next_message_type_ = message_type; | |
| 53 } | |
| 54 | |
| 55 // If the message size isn't set, the next two bytes are the message size. | |
| 56 if (next_message_size_ == 0) { | |
| 57 if (message_buffer_->AvailableBytes() < (int)sizeof(uint16_t)) { | |
|
achuithb
2014/08/11 22:04:30
reinterpret cast, no curly braces, consider changi
Zachary Kuznia
2014/08/11 23:40:29
Changed to static_cast, removed braces.
I conside
| |
| 58 return true; | |
| 59 } | |
| 60 | |
| 61 // The size is sent in network byte order. | |
| 62 uint8_t high_byte = 0; | |
| 63 message_buffer_->ReadBytes(reinterpret_cast<char*>(&high_byte), | |
| 64 sizeof(high_byte)); | |
| 65 uint8_t low_byte = 0; | |
| 66 message_buffer_->ReadBytes(reinterpret_cast<char*>(&low_byte), | |
| 67 sizeof(low_byte)); | |
| 68 | |
| 69 next_message_size_ = (high_byte << 8) + low_byte; | |
|
achuithb
2014/08/11 22:04:31
It feels like hte proto libraries should help us w
Zachary Kuznia
2014/08/11 23:40:29
See comment at line 190
| |
| 70 } | |
| 71 | |
| 72 // If the whole proto buffer is not yet available, return early. | |
| 73 if (message_buffer_->AvailableBytes() < next_message_size_) { | |
|
achuithb
2014/08/11 22:04:30
No curly braces.
Zachary Kuznia
2014/08/11 23:40:29
Done.
| |
| 74 return true; | |
| 75 } | |
| 76 | |
| 77 std::vector<char> buffer(next_message_size_); | |
| 78 message_buffer_->ReadBytes(&buffer[0], next_message_size_); | |
| 79 | |
| 80 switch (next_message_type_) { | |
| 81 case MESSAGE_HOST_STATUS: { | |
| 82 pairing_api::HostStatus message; | |
| 83 message.ParseFromArray(&buffer[0], buffer.size()); | |
| 84 observer_->OnHostStatusMessage(message); | |
| 85 } | |
| 86 break; | |
| 87 case MESSAGE_CONFIGURE_HOST: { | |
| 88 pairing_api::ConfigureHost message; | |
| 89 message.ParseFromArray(&buffer[0], buffer.size()); | |
| 90 observer_->OnConfigureHostMessage(message); | |
| 91 } | |
| 92 break; | |
| 93 case MESSAGE_PAIR_DEVICES: { | |
| 94 pairing_api::PairDevices message; | |
| 95 message.ParseFromArray(&buffer[0], buffer.size()); | |
| 96 observer_->OnPairDevicesMessage(message); | |
| 97 } | |
| 98 break; | |
| 99 case MESSAGE_COMPLETE_SETUP: { | |
| 100 pairing_api::CompleteSetup message; | |
| 101 message.ParseFromArray(&buffer[0], buffer.size()); | |
| 102 observer_->OnCompleteSetupMessage(message); | |
| 103 } | |
| 104 break; | |
| 105 case MESSAGE_ERROR: { | |
| 106 pairing_api::Error message; | |
| 107 message.ParseFromArray(&buffer[0], buffer.size()); | |
| 108 observer_->OnErrorMessage(message); | |
| 109 } | |
| 110 break; | |
| 111 | |
| 112 default: | |
| 113 NOTREACHED(); | |
| 114 break; | |
| 115 } | |
| 116 | |
| 117 // Reset the message data. | |
| 118 next_message_type_ = MESSAGE_NONE; | |
| 119 next_message_size_ = 0; | |
| 120 | |
| 121 return true; | |
| 122 } | |
| 123 | |
| 124 scoped_refptr<net::IOBuffer> ProtoDecoder::SendHostStatus( | |
| 125 const pairing_api::HostStatus& message, int* size) { | |
| 126 std::string serialized_proto; | |
| 127 if (!message.SerializeToString(&serialized_proto)) { | |
|
achuithb
2014/08/11 22:04:31
Shouldn't this be a DCHECK?
Here and everywhere b
Zachary Kuznia
2014/08/11 23:40:29
I avoid putting a function call in any kind of ass
| |
| 128 NOTREACHED(); | |
| 129 } | |
| 130 | |
| 131 return SendMessage(MESSAGE_HOST_STATUS, serialized_proto, size); | |
| 132 } | |
| 133 | |
| 134 scoped_refptr<net::IOBuffer> ProtoDecoder::SendConfigureHost( | |
| 135 const pairing_api::ConfigureHost& message, int* size) { | |
| 136 std::string serialized_proto; | |
| 137 if (!message.SerializeToString(&serialized_proto)) { | |
| 138 NOTREACHED(); | |
| 139 } | |
| 140 | |
| 141 return SendMessage(MESSAGE_CONFIGURE_HOST, serialized_proto, size); | |
| 142 } | |
| 143 | |
| 144 scoped_refptr<net::IOBuffer> ProtoDecoder::SendPairDevices( | |
| 145 const pairing_api::PairDevices& message, int* size) { | |
| 146 std::string serialized_proto; | |
| 147 if (!message.SerializeToString(&serialized_proto)) { | |
| 148 NOTREACHED(); | |
| 149 } | |
| 150 | |
| 151 return SendMessage(MESSAGE_PAIR_DEVICES, serialized_proto, size); | |
| 152 } | |
| 153 | |
| 154 scoped_refptr<net::IOBuffer> ProtoDecoder::SendCompleteSetup( | |
| 155 const pairing_api::CompleteSetup& message, int* size) { | |
| 156 std::string serialized_proto; | |
| 157 if (!message.SerializeToString(&serialized_proto)) { | |
| 158 NOTREACHED(); | |
| 159 } | |
| 160 | |
| 161 return SendMessage(MESSAGE_COMPLETE_SETUP, serialized_proto, size); | |
| 162 } | |
| 163 | |
| 164 scoped_refptr<net::IOBuffer> ProtoDecoder::SendError( | |
| 165 const pairing_api::Error& message, int* size) { | |
| 166 std::string serialized_proto; | |
| 167 if (!message.SerializeToString(&serialized_proto)) { | |
| 168 NOTREACHED(); | |
| 169 } | |
| 170 | |
| 171 return SendMessage(MESSAGE_ERROR, serialized_proto, size); | |
| 172 } | |
| 173 | |
| 174 scoped_refptr<net::IOBuffer> ProtoDecoder::SendMessage( | |
| 175 uint8_t message_type, | |
| 176 const std::string& message, | |
| 177 int* size) { | |
|
achuithb
2014/08/11 22:04:31
Should this be size_t? You're doing an implicit co
Zachary Kuznia
2014/08/11 23:40:29
The BluetoothSocket function deals in IOBuffer and
| |
| 178 uint16_t message_size = message.size(); | |
| 179 | |
| 180 *size = sizeof(message_type) + sizeof(message_size) + message.size(); | |
| 181 scoped_refptr<net::IOBuffer> io_buffer(new net::IOBuffer(*size)); | |
| 182 | |
| 183 // Write the message type. | |
| 184 int offset = 0; | |
| 185 memcpy(&io_buffer->data()[offset], &message_type, sizeof(message_type)); | |
| 186 offset += sizeof(message_type); | |
| 187 | |
| 188 // Network byte order. | |
| 189 // Write the high byte of the size. | |
| 190 uint8_t data = (message_size >> 8) & 0xFF; | |
|
achuithb
2014/08/11 22:04:31
Is there no way of getting protobufs to do this wo
Zachary Kuznia
2014/08/11 23:40:29
The other call sites I've seen in Chrome serialize
| |
| 191 memcpy(&io_buffer->data()[offset], &data, sizeof(data)); | |
| 192 offset += sizeof(data); | |
| 193 // Write the low byte of the size. | |
| 194 data = message_size & 0xFF; | |
| 195 memcpy(&io_buffer->data()[offset], &data, sizeof(data)); | |
| 196 offset += sizeof(data); | |
| 197 | |
| 198 // Write the actual message. | |
| 199 memcpy(&io_buffer->data()[offset], message.data(), message.size()); | |
| 200 | |
| 201 return io_buffer; | |
| 202 } | |
| 203 | |
| 204 } // namespace pairing_chromeos | |
| OLD | NEW |