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
40 using std::string;
41
CRemoteProcessorServer(uint16_t uiPort)42 CRemoteProcessorServer::CRemoteProcessorServer(uint16_t uiPort)
43 : _uiPort(uiPort), _io_service(), _acceptor(_io_service), _socket(_io_service)
44 {
45 }
46
~CRemoteProcessorServer()47 CRemoteProcessorServer::~CRemoteProcessorServer()
48 {
49 stop();
50 }
51
52 // State
start(string & error)53 bool 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
stop()76 bool CRemoteProcessorServer::stop()
77 {
78 _io_service.stop();
79
80 return true;
81 }
82
acceptRegister(IRemoteCommandHandler & commandHandler)83 void 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
process(IRemoteCommandHandler & commandHandler)102 bool 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
handleNewConnection(IRemoteCommandHandler & commandHandler)118 void 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