• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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