15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/command.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/safe_strerror_posix.h" 145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/socket.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringPiece; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Command format: 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// <port>:<type> 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Where: 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// <port> is a 5-chars zero-padded ASCII decimal integer 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// matching the target port for the command (e.g. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// '08080' for port 8080) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// <type> is a 3-char zero-padded ASCII decimal integer 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// matching a command::Type value (e.g. 002 for 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ACK). 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The column (:) is used as a separator for easier reading. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kPortStringSize = 5; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kCommandTypeStringSize = 2; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Command string size also includes the ':' separator char. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kCommandStringSize = kPortStringSize + kCommandTypeStringSize + 1; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace forwarder2 { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReadCommand(Socket* socket, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* port_out, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command::Type* command_type_out) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char command_buffer[kCommandStringSize + 1]; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To make logging easier. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_buffer[kCommandStringSize] = '\0'; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_read = socket->ReadNumBytes(command_buffer, kCommandStringSize); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_read != kCommandStringSize) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_read < 0) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Read() error: " << safe_strerror(errno); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (!bytes_read) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Read() error, endpoint was unexpectedly closed."; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Read() error, not enough data received from the socket."; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringPiece port_str(command_buffer, kPortStringSize); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!StringToInt(port_str, port_out)) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Could not parse the command port string: " 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << port_str; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StringPiece command_type_str( 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &command_buffer[kPortStringSize + 1], kCommandTypeStringSize); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int command_type; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!StringToInt(command_type_str, &command_type)) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Could not parse the command type string: " 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << command_type_str; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *command_type_out = static_cast<command::Type>(command_type); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SendCommand(command::Type command, int port, Socket* socket) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[kCommandStringSize + 1]; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len = snprintf(buffer, sizeof(buffer), "%05d:%02d", port, command); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(len, kCommandStringSize); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write the full command minus the leading \0 char. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return socket->WriteNumBytes(buffer, len) == len; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReceivedCommand(command::Type command, Socket* socket) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int port; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command::Type received_command; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadCommand(socket, &port, &received_command)) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return received_command == command; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace forwarder 97