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 12 namespace { 13 14 // 4-byte type used for the message header. 15 typedef 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. 19 const 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. 26 const size_t kMaximumMessageSize = 1024 * 1024; 27 28 // Performs the same task as FileStream::WriteSync(), but ensures that exactly 29 // |buffer_length| bytes are written. Unlike WriteSync(), a partial write may 30 // only occur as a result of end-of-file or fatal error. Returns the number of 31 // bytes written (buffer_length) or an error-code <= 0. 32 // 33 // TODO(lambroslambrou): Add this method to net::FileStream, with unit-tests. 34 // See http://crbug.com/232202. 35 int WriteUntilComplete(net::FileStream* out, 36 const char* buffer, int buffer_length) { 37 int written = 0; 38 while (written < buffer_length) { 39 int result = out->WriteSync(buffer + written, buffer_length - written); 40 if (result <= 0) { 41 return result; 42 } 43 DCHECK_LE(result, buffer_length - written); 44 written += result; 45 } 46 return written; 47 } 48 49 } // namespace 50 51 namespace remoting { 52 53 NativeMessagingWriter::NativeMessagingWriter(base::PlatformFile handle) 54 : write_stream_(handle, base::PLATFORM_FILE_WRITE, NULL), 55 fail_(false) { 56 } 57 58 NativeMessagingWriter::~NativeMessagingWriter() { 59 } 60 61 bool NativeMessagingWriter::WriteMessage(const base::Value& message) { 62 if (fail_) { 63 LOG(ERROR) << "Stream marked as corrupt."; 64 return false; 65 } 66 67 std::string message_json; 68 base::JSONWriter::Write(&message, &message_json); 69 70 CHECK_LE(message_json.length(), kMaximumMessageSize); 71 72 // Cast from size_t to the proper header type. The check above ensures this 73 // won't overflow. 74 MessageLengthType message_length = 75 static_cast<MessageLengthType>(message_json.length()); 76 77 int result = WriteUntilComplete( 78 &write_stream_, reinterpret_cast<char*>(&message_length), 79 kMessageHeaderSize); 80 if (result != kMessageHeaderSize) { 81 LOG(ERROR) << "Failed to send message header, write returned " << result; 82 fail_ = true; 83 return false; 84 } 85 86 // The length check above ensures that the cast won't overflow a signed 87 // 32-bit int. 88 int message_length_as_int = message_length; 89 90 // CHECK needed since data() is undefined on an empty std::string. 91 CHECK(!message_json.empty()); 92 result = WriteUntilComplete(&write_stream_, message_json.data(), 93 message_length_as_int); 94 if (result != message_length_as_int) { 95 LOG(ERROR) << "Failed to send message body, write returned " << result; 96 fail_ = true; 97 return false; 98 } 99 100 return true; 101 } 102 103 } // namespace remoting 104