1 /* 2 * Copyright (c) 2011-2014, Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation and/or 13 * other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors 16 * may be used to endorse or promote products derived from this software without 17 * specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <asio.hpp> 32 33 #include <iostream> 34 #include <string> 35 #include <cstring> 36 #include <stdlib.h> 37 #include "RequestMessage.h" 38 #include "AnswerMessage.h" 39 #include "Socket.h" 40 #include "convert.hpp" 41 42 using namespace std; 43 44 bool sendAndDisplayCommand(asio::generic::stream_protocol::socket &socket, 45 CRequestMessage &requestMessage) 46 { 47 string strError; 48 49 if (requestMessage.serialize(Socket(socket), true, strError) != CRequestMessage::success) { 50 51 cerr << "Unable to send command to target: " << strError << endl; 52 return false; 53 } 54 55 ///// Get answer 56 CAnswerMessage answerMessage; 57 if (answerMessage.serialize(Socket(socket), false, strError) != CRequestMessage::success) { 58 59 cerr << "Unable to received answer from target: " << strError << endl; 60 return false; 61 } 62 63 // Success? 64 if (!answerMessage.success()) { 65 66 // Display error answer 67 cerr << answerMessage.getAnswer() << endl; 68 return false; 69 } 70 71 // Display success answer 72 cout << answerMessage.getAnswer() << endl; 73 74 return true; 75 } 76 77 int usage(const std::string &command, const std::string &error) 78 { 79 if (not error.empty()) { 80 cerr << error << endl; 81 } 82 cerr << "Usage: " << endl; 83 cerr << "Send a single command:" << endl; 84 cerr << "\t" << command 85 << " <hostname port|<protocol>://<host:port|port_name>> <command> [argument[s]]" << endl; 86 87 return 1; 88 } 89 90 // <hostname port|path> command [argument[s]] 91 // or 92 // <hostname port|path> < commands 93 int main(int argc, char *argv[]) 94 { 95 int commandPos; 96 97 // Enough args? 98 if (argc < 3) { 99 return usage(argv[0], "Missing arguments"); 100 } 101 asio::io_service io_service; 102 asio::generic::stream_protocol::socket connectionSocket(io_service); 103 104 bool isInet = false; 105 string port; 106 string host; 107 try { 108 // backward compatibility: tcp port only refered by its value 109 uint16_t testConverter; 110 if (convertTo({argv[2]}, testConverter)) { 111 isInet = true; 112 port = argv[2]; 113 host = argv[1]; 114 if (argc <= 3) { 115 return usage(argv[0], "Missing arguments"); 116 } 117 commandPos = 3; 118 } else { 119 commandPos = 2; 120 string endPortArg{argv[1]}; 121 std::string protocol; 122 123 const std::string tcpProtocol{"tcp"}; 124 const std::string unixProtocol{"unix"}; 125 const std::vector<std::string> supportedProtocols{ tcpProtocol, unixProtocol }; 126 const std::string protocolDelimiter{"://"}; 127 128 size_t protocolDelPos = endPortArg.find(protocolDelimiter); 129 if (protocolDelPos == std::string::npos) { 130 return usage(argv[0], "Invalid socket endpoint, missing " + protocolDelimiter); 131 } 132 protocol = endPortArg.substr(0, protocolDelPos); 133 134 if (std::find(begin(supportedProtocols), end(supportedProtocols), protocol) == 135 end(supportedProtocols)) { 136 return usage(argv[0], "Invalid socket protocol " + protocol); 137 } 138 isInet = (endPortArg.find(tcpProtocol) != std::string::npos); 139 if (isInet) { 140 size_t portDelPos = endPortArg.find(':', protocolDelPos + protocolDelimiter.size()); 141 if (portDelPos == std::string::npos) { 142 return usage(argv[0], "Invalid tcp endpoint" + endPortArg); 143 } 144 host = endPortArg.substr(protocolDelPos + protocolDelimiter.size(), 145 portDelPos - (protocolDelPos + protocolDelimiter.size())); 146 port = endPortArg.substr(portDelPos + 1); 147 } else { 148 port = endPortArg.substr(protocolDelPos + protocolDelimiter.size()); 149 } 150 } 151 if (isInet) { 152 asio::ip::tcp::resolver resolver(io_service); 153 asio::ip::tcp::socket tcpSocket(io_service); 154 155 asio::connect(tcpSocket, resolver.resolve(asio::ip::tcp::resolver::query(host, port))); 156 connectionSocket = std::move(tcpSocket); 157 } else { 158 asio::generic::stream_protocol::socket socket(io_service); 159 asio::generic::stream_protocol::endpoint endpoint = 160 asio::local::stream_protocol::endpoint(port); 161 socket.connect(endpoint); 162 connectionSocket = std::move(socket); 163 } 164 165 } catch (const asio::system_error &e) { 166 string endpoint; 167 168 if (isInet) { 169 endpoint = string("tcp://") + host + ":" + port; 170 } else { /* other supported protocols */ 171 endpoint = argv[1]; 172 } 173 cerr << "Connection to '" << endpoint << "' failed: " << e.what() << endl; 174 return 1; 175 } 176 177 // Create command message 178 CRequestMessage requestMessage(argv[commandPos]); 179 180 // Add arguments 181 for (int arg = commandPos + 1; arg < argc; arg++) { 182 183 requestMessage.addArgument(argv[arg]); 184 } 185 186 if (!sendAndDisplayCommand(connectionSocket, requestMessage)) { 187 return 1; 188 } 189 190 // Program status 191 return 0; 192 } 193