#include "remoting/host/security_key/security_key_message_writer_impl.h"
#include <cstdint>
#include <string>
#include <utility>
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "remoting/host/security_key/security_key_message.h"
namespace remoting {
SecurityKeyMessageWriterImpl::SecurityKeyMessageWriterImpl(
base::File output_file)
: output_stream_(std::move(output_file)) {}
SecurityKeyMessageWriterImpl::~SecurityKeyMessageWriterImpl() = default;
bool SecurityKeyMessageWriterImpl::WriteMessage(
SecurityKeyMessageType message_type) {
return WriteMessageWithPayload(message_type, std::string());
}
bool SecurityKeyMessageWriterImpl::WriteMessageWithPayload(
SecurityKeyMessageType message_type,
const std::string& message_payload) {
if (write_failed_ || !output_stream_.IsValid()) {
return false;
}
int message_payload_size_bytes = message_payload.size();
uint32_t total_message_size_bytes =
SecurityKeyMessage::kMessageTypeSizeBytes + message_payload_size_bytes;
CHECK(SecurityKeyMessage::IsValidMessageSize(total_message_size_bytes));
if (!WriteBytesToOutput(reinterpret_cast<char*>(&total_message_size_bytes),
SecurityKeyMessage::kHeaderSizeBytes)) {
LOG(ERROR) << "Failed to send message header.";
return false;
}
if (!WriteBytesToOutput(reinterpret_cast<char*>(&message_type),
SecurityKeyMessage::kMessageTypeSizeBytes)) {
LOG(ERROR) << "Failed to send message type.";
return false;
}
if (!message_payload.empty()) {
if (!WriteBytesToOutput(message_payload.data(),
message_payload_size_bytes)) {
LOG(ERROR) << "Failed to send message payload.";
return false;
}
}
return true;
}
bool SecurityKeyMessageWriterImpl::WriteBytesToOutput(const char* message,
int bytes_to_write) {
DCHECK(message);
DCHECK_GT(bytes_to_write, 0);
int result =
UNSAFE_TODO(output_stream_.WriteAtCurrentPos(message, bytes_to_write));
if (result != bytes_to_write) {
LOG(ERROR) << "Failed to write all bytes to output stream. bytes written: "
<< result << ", file error: "
<< base::File::ErrorToString(output_stream_.error_details());
write_failed_ = true;
return false;
}
return true;
}
}