Chromium Code Reviews| Index: components/proximity_auth/wire_message.cc |
| diff --git a/components/proximity_auth/wire_message.cc b/components/proximity_auth/wire_message.cc |
| index b6b57705c200b9bdf2924e6b8b6ff1529f9cd452..b7db7789aeb02aff912d09ce042b3be153a9eb85 100644 |
| --- a/components/proximity_auth/wire_message.cc |
| +++ b/components/proximity_auth/wire_message.cc |
| @@ -4,26 +4,114 @@ |
| #include "components/proximity_auth/wire_message.h" |
| +#include "base/base64.h" |
| +#include "base/json/json_reader.h" |
| +#include "base/logging.h" |
| +#include "base/macros.h" |
| +#include "base/values.h" |
| + |
| +// The wire messages have a simple format: |
| +// [ message version ] [ body length ] [ JSON body ] |
|
Tim Song
2014/09/12 00:25:21
Mention that the JSON object has the data and perm
Ilya Sherman
2014/09/12 01:24:26
Done.
|
| +// 1 byte 2 bytes body length |
| + |
| namespace proximity_auth { |
| +namespace { |
| -WireMessage::~WireMessage() { |
| +// The length of the message header, in bytes. |
| +const size_t kHeaderLength = 3; |
| + |
| +// The protocol version of the message format. |
| +const int kExpectedMessageFormatVersion = 3; |
| + |
| +const char kPayloadKey[] = "payload"; |
| +const char kPermitIdKey[] = "permit_id"; |
| + |
| +// Parses the |serialized_message|'s header. Returns |true| iff the message has |
| +// a valid header, is complete, and is well-formed according to the header. Sets |
| +// |is_incomplete_message| to true iff the message does not have enough data to |
| +// parse the header, or if the message length encoded in the message header |
| +// exceeds the size of the |serialized_message|. |
| +bool ParseHeader(const std::string& serialized_message, |
| + bool* is_incomplete_message) { |
| + *is_incomplete_message = false; |
| + if (serialized_message.size() < kHeaderLength) { |
| + *is_incomplete_message = true; |
| + return false; |
| + } |
| + |
| + COMPILE_ASSERT(kHeaderLength > 2, header_length_too_small); |
| + size_t version = serialized_message[0]; |
| + if (version != kExpectedMessageFormatVersion) { |
| + VLOG(1) << "Error: Invalid message version. Got " << version |
| + << ", expected " << kExpectedMessageFormatVersion; |
| + return false; |
| + } |
| + |
| + size_t expected_body_length = |
| + (static_cast<size_t>(serialized_message[1]) << 8) | |
| + static_cast<size_t>(serialized_message[2]); |
|
Tim Song
2014/09/12 00:25:21
nit: alignment
Ilya Sherman
2014/09/12 01:24:26
How would you like me to change the alignment?
Tim Song
2014/09/12 01:38:21
nudge it right one character.
Ilya Sherman
2014/09/12 17:36:10
Hmm, that would make it appear to be within the pa
Tim Song
2014/09/12 23:54:25
Yeah, I see your point. Maybe add a left shift zer
Ilya Sherman
2014/09/15 22:25:13
Done.
|
| + size_t expected_message_length = kHeaderLength + expected_body_length; |
| + if (serialized_message.size() < expected_message_length) { |
| + *is_incomplete_message = true; |
| + return false; |
| + } |
| + if (serialized_message.size() != expected_message_length) { |
| + VLOG(1) << "Error: Invalid message length. Got " |
| + << serialized_message.size() << ", expected " |
| + << expected_message_length; |
| + return false; |
| + } |
| + |
| + return true; |
| } |
| -// static |
| -bool WireMessage::IsCompleteMessage(const std::string& serialized_message) { |
| - // TODO(isherman): Implement. |
| - return false; |
| +} // namespace |
| + |
| +WireMessage::~WireMessage() { |
| } |
| // static |
| scoped_ptr<WireMessage> WireMessage::Deserialize( |
| - const std::string& serialized_message) { |
| - // TODO(isherman): Implement. |
| - return scoped_ptr<WireMessage>(); |
| + const std::string& serialized_message, |
| + bool* is_incomplete_message) { |
| + if (!ParseHeader(serialized_message, is_incomplete_message)) |
| + return scoped_ptr<WireMessage>(); |
| + |
| + scoped_ptr<base::Value> body_value( |
| + base::JSONReader::Read(serialized_message.substr(kHeaderLength))); |
| + if (!body_value || !body_value->IsType(base::Value::TYPE_DICTIONARY)) { |
| + VLOG(1) << "Error: Unable to parse message as JSON."; |
| + return scoped_ptr<WireMessage>(); |
| + } |
| + |
| + base::DictionaryValue* body; |
| + bool success = body_value->GetAsDictionary(&body); |
| + DCHECK(success); |
| + |
| + std::string permit_id, payload_base64; |
| + if (!body->GetString(kPermitIdKey, &permit_id) || permit_id.empty()) { |
|
Tim Song
2014/09/12 00:25:21
The permit_id is optional. It's fine if the messag
Ilya Sherman
2014/09/12 01:24:26
Done.
|
| + VLOG(1) << "Error: Missing permit id."; |
| + return scoped_ptr<WireMessage>(); |
| + } |
| + if (!body->GetString(kPayloadKey, &payload_base64) || |
| + payload_base64.empty()) { |
| + VLOG(1) << "Error: Missing payload."; |
| + return scoped_ptr<WireMessage>(); |
| + } |
| + |
| + std::string payload; |
| + if (!base::Base64Decode(payload_base64, &payload)) { |
| + VLOG(1) << "Error: Invalid base64 encoding for payload."; |
| + return scoped_ptr<WireMessage>(); |
| + } |
| + |
| + return scoped_ptr<WireMessage>(new WireMessage(permit_id, payload)); |
| } |
| -WireMessage::WireMessage() { |
| - // TODO(isherman): Implement. |
| +WireMessage::WireMessage(const std::string& permit_id, |
| + const std::string& payload) |
| + : permit_id_(permit_id), |
| + payload_(payload) { |
| } |
| } // namespace proximity_auth |