Home | History | Annotate | Download | only in forwarder2
      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