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
3// found in the LICENSE file.
4
5#include "remoting/host/native_messaging/native_messaging_writer.h"
6
7#include <string>
8
9#include "base/basictypes.h"
10#include "base/json/json_writer.h"
11
12namespace {
13
14// 4-byte type used for the message header.
15typedef uint32 MessageLengthType;
16
17// Defined as an int, for passing to APIs that take an int, to avoid
18// signed/unsigned warnings about implicit cast.
19const int kMessageHeaderSize = sizeof(MessageLengthType);
20
21// Limit the size of sent messages, since Chrome will not accept messages
22// larger than 1MB, and this helps deal with the problem of integer overflow
23// when passing sizes to net::FileStream APIs that take |int| parameters.
24// This is defined as size_t (unsigned type) so it can be compared with the
25// result of std::string::length() without compiler warnings.
26const size_t kMaximumMessageSize = 1024 * 1024;
27
28}  // namespace
29
30namespace remoting {
31
32NativeMessagingWriter::NativeMessagingWriter(base::File file)
33    : write_stream_(file.Pass()),
34      fail_(false) {
35}
36
37NativeMessagingWriter::~NativeMessagingWriter() {
38}
39
40bool NativeMessagingWriter::WriteMessage(const base::Value& message) {
41  if (fail_) {
42    LOG(ERROR) << "Stream marked as corrupt.";
43    return false;
44  }
45
46  std::string message_json;
47  base::JSONWriter::Write(&message, &message_json);
48
49  CHECK_LE(message_json.length(), kMaximumMessageSize);
50
51  // Cast from size_t to the proper header type. The check above ensures this
52  // won't overflow.
53  MessageLengthType message_length =
54      static_cast<MessageLengthType>(message_json.length());
55
56  int result = write_stream_.WriteAtCurrentPos(
57      reinterpret_cast<char*>(&message_length), kMessageHeaderSize);
58  if (result != kMessageHeaderSize) {
59    LOG(ERROR) << "Failed to send message header, write returned " << result;
60    fail_ = true;
61    return false;
62  }
63
64  // The length check above ensures that the cast won't overflow a signed
65  // 32-bit int.
66  int message_length_as_int = message_length;
67
68  // CHECK needed since data() is undefined on an empty std::string.
69  CHECK(!message_json.empty());
70  result = write_stream_.WriteAtCurrentPos(message_json.data(),
71                                           message_length_as_int);
72  if (result != message_length_as_int) {
73    LOG(ERROR) << "Failed to send message body, write returned " << result;
74    fail_ = true;
75    return false;
76  }
77
78  return true;
79}
80
81}  // namespace remoting
82