1/* 2 * Copyright (c) 2011-2015, 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#include "RemoteProcessorServer.h" 31#include <iostream> 32#include <memory> 33#include <assert.h> 34#include <string.h> 35#include "RequestMessage.h" 36#include "AnswerMessage.h" 37#include "RemoteCommandHandler.h" 38#include "Socket.h" 39 40using std::string; 41 42CRemoteProcessorServer::CRemoteProcessorServer(uint16_t uiPort) 43 : _uiPort(uiPort), _io_service(), _acceptor(_io_service), _socket(_io_service) 44{ 45} 46 47CRemoteProcessorServer::~CRemoteProcessorServer() 48{ 49 stop(); 50} 51 52// State 53bool CRemoteProcessorServer::start(string &error) 54{ 55 using namespace asio; 56 57 try { 58 ip::tcp::endpoint endpoint(ip::tcp::v6(), _uiPort); 59 60 _acceptor.open(endpoint.protocol()); 61 62 _acceptor.set_option(ip::tcp::acceptor::reuse_address(true)); 63 _acceptor.set_option(asio::socket_base::linger(true, 0)); 64 _acceptor.set_option(socket_base::enable_connection_aborted(true)); 65 66 _acceptor.bind(endpoint); 67 _acceptor.listen(); 68 } catch (std::exception &e) { 69 error = "Unable to listen on port " + std::to_string(_uiPort) + ": " + e.what(); 70 return false; 71 } 72 73 return true; 74} 75 76bool CRemoteProcessorServer::stop() 77{ 78 _io_service.stop(); 79 80 return true; 81} 82 83void CRemoteProcessorServer::acceptRegister(IRemoteCommandHandler &commandHandler) 84{ 85 auto peerHandler = [this, &commandHandler](asio::error_code ec) { 86 if (ec) { 87 std::cerr << "Accept failed: " << ec.message() << std::endl; 88 return; 89 } 90 91 _socket.set_option(asio::ip::tcp::no_delay(true)); 92 handleNewConnection(commandHandler); 93 94 _socket.close(); 95 96 acceptRegister(commandHandler); 97 }; 98 99 _acceptor.async_accept(_socket, peerHandler); 100} 101 102bool CRemoteProcessorServer::process(IRemoteCommandHandler &commandHandler) 103{ 104 acceptRegister(commandHandler); 105 106 asio::error_code ec; 107 108 _io_service.run(ec); 109 110 if (ec) { 111 std::cerr << "Server failed: " << ec.message() << std::endl; 112 } 113 114 return ec.value() == 0; 115} 116 117// New connection 118void CRemoteProcessorServer::handleNewConnection(IRemoteCommandHandler &commandHandler) 119{ 120 // Process all incoming requests from the client 121 while (true) { 122 123 // Process requests 124 // Create command message 125 CRequestMessage requestMessage; 126 127 string strError; 128 ///// Receive command 129 CRequestMessage::Result res; 130 res = requestMessage.serialize(Socket(_socket), false, strError); 131 132 switch (res) { 133 case CRequestMessage::error: 134 std::cout << "Error while receiving message: " << strError << std::endl; 135 // fall through 136 case CRequestMessage::peerDisconnected: 137 // Consider peer disconnection as normal, no log 138 return; // Bail out 139 case CRequestMessage::success: 140 break; // No error, continue 141 } 142 143 // Actually process the request 144 bool bSuccess; 145 146 string strResult; 147 148 bSuccess = commandHandler.remoteCommandProcess(requestMessage, strResult); 149 150 // Send back answer 151 // Create answer message 152 CAnswerMessage answerMessage(strResult, bSuccess); 153 154 ///// Send answer 155 res = answerMessage.serialize(_socket, true, strError); 156 157 switch (res) { 158 case CRequestMessage::peerDisconnected: 159 // Peer should not disconnect while waiting for an answer 160 // Fall through to log the error and bail out 161 case CRequestMessage::error: 162 std::cout << "Error while receiving message: " << strError << std::endl; 163 return; // Bail out 164 case CRequestMessage::success: 165 break; // No error, continue 166 } 167 } 168} 169