1 // Copyright (c) 2012 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 "tools/android/forwarder2/command.h" 6 7 #include <errno.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 12 #include "base/logging.h" 13 #include "base/safe_strerror_posix.h" 14 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_piece.h" 16 #include "tools/android/forwarder2/socket.h" 17 18 using base::StringPiece; 19 20 namespace { 21 22 23 // Command format: 24 // <port>:<type> 25 // 26 // Where: 27 // <port> is a 5-chars zero-padded ASCII decimal integer 28 // matching the target port for the command (e.g. 29 // '08080' for port 8080) 30 // <type> is a 3-char zero-padded ASCII decimal integer 31 // matching a command::Type value (e.g. 002 for 32 // ACK). 33 // The column (:) is used as a separator for easier reading. 34 const int kPortStringSize = 5; 35 const int kCommandTypeStringSize = 2; 36 // Command string size also includes the ':' separator char. 37 const int kCommandStringSize = kPortStringSize + kCommandTypeStringSize + 1; 38 39 } // namespace 40 41 namespace forwarder2 { 42 43 bool ReadCommand(Socket* socket, 44 int* port_out, 45 command::Type* command_type_out) { 46 char command_buffer[kCommandStringSize + 1]; 47 // To make logging easier. 48 command_buffer[kCommandStringSize] = '\0'; 49 50 int bytes_read = socket->ReadNumBytes(command_buffer, kCommandStringSize); 51 if (bytes_read != kCommandStringSize) { 52 if (bytes_read < 0) 53 LOG(ERROR) << "Read() error: " << safe_strerror(errno); 54 else if (!bytes_read) 55 LOG(ERROR) << "Read() error, endpoint was unexpectedly closed."; 56 else 57 LOG(ERROR) << "Read() error, not enough data received from the socket."; 58 return false; 59 } 60 61 StringPiece port_str(command_buffer, kPortStringSize); 62 if (!StringToInt(port_str, port_out)) { 63 LOG(ERROR) << "Could not parse the command port string: " 64 << port_str; 65 return false; 66 } 67 68 StringPiece command_type_str( 69 &command_buffer[kPortStringSize + 1], kCommandTypeStringSize); 70 int command_type; 71 if (!StringToInt(command_type_str, &command_type)) { 72 LOG(ERROR) << "Could not parse the command type string: " 73 << command_type_str; 74 return false; 75 } 76 *command_type_out = static_cast<command::Type>(command_type); 77 return true; 78 } 79 80 bool SendCommand(command::Type command, int port, Socket* socket) { 81 char buffer[kCommandStringSize + 1]; 82 int len = snprintf(buffer, sizeof(buffer), "%05d:%02d", port, command); 83 CHECK_EQ(len, kCommandStringSize); 84 // Write the full command minus the leading \0 char. 85 return socket->WriteNumBytes(buffer, len) == len; 86 } 87 88 bool ReceivedCommand(command::Type command, Socket* socket) { 89 int port; 90 command::Type received_command; 91 if (!ReadCommand(socket, &port, &received_command)) 92 return false; 93 return received_command == command; 94 } 95 96 } // namespace forwarder 97