source: xplra/src/plugin/src/xplra/ServerThread.cc@ 35:9451e75788ea

Last change on this file since 35:9451e75788ea was 13:42fd631176b7, checked in by István Váradi <ivaradi@…>, 11 years ago

Reorganized code to be able to handle the client library as a normal libtool library

File size: 11.2 KB
Line 
1// Copyright (c) 2013 by István Váradi
2
3// This file is part of XPLRA, a remote-access plugin for X-Plane
4
5// Redistribution and use in source and binary forms, with or without
6// modification, 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// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13
14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
25// The views and conclusions contained in the software and documentation are those
26// of the authors and should not be interpreted as representing official policies,
27// either expressed or implied, of the FreeBSD Project.
28
29//------------------------------------------------------------------------------
30
31#include "ServerThread.h"
32
33#include "RequestQueue.h"
34#include "Protocol.h"
35#include "GetDataRefTask.h"
36#include "SetDataRefTask.h"
37#include "TaskRequest.h"
38#include "GetMultiDataRefRequest.h"
39#include "SetMultiDataRefRequest.h"
40
41#include <hu/varadiistvan/xplcommon/Util.h>
42
43#include <cstdio>
44
45//------------------------------------------------------------------------------
46
47using xplra::ServerThread;
48
49using hu::varadiistvan::scpl::io::LocalAcceptor;
50using hu::varadiistvan::scpl::Mutex;
51using hu::varadiistvan::xplcommon::Util;
52
53using std::string;
54
55//------------------------------------------------------------------------------
56
57Mutex ServerThread::instancesMutex;
58
59ServerThread::instances_t ServerThread::instances;
60
61//------------------------------------------------------------------------------
62
63void ServerThread::quitAll()
64{
65 instancesMutex.lock();
66 for(instances_t::iterator i = instances.begin(); i!=instances.end(); ++i) {
67 (*i)->quit();
68 }
69 instancesMutex.unlock();
70}
71
72//------------------------------------------------------------------------------
73
74ServerThread::ServerThread(RequestQueue& requestQueue, LocalAcceptor& acceptor) :
75 Thread(true),
76 requestQueue(requestQueue),
77 bufferedStream(acceptor.getSocket(&waiter)),
78 stream(*bufferedStream),
79 nextGetMultiRequestID(1),
80 nextSetMultiRequestID(1)
81{
82 instancesMutex.lock();
83 instances.insert(this);
84 instancesMutex.unlock();
85}
86
87//------------------------------------------------------------------------------
88
89ServerThread::~ServerThread()
90{
91 delete bufferedStream;
92
93 for(getMultiRequests_t::iterator i = getMultiRequests.begin();
94 i!=getMultiRequests.end(); ++i)
95 {
96 delete i->second;
97 }
98
99 for(setMultiRequests_t::iterator i = setMultiRequests.begin();
100 i!=setMultiRequests.end(); ++i)
101 {
102 delete i->second;
103 }
104
105 instancesMutex.lock();
106 instances.erase(this);
107 instancesMutex.unlock();
108}
109
110//------------------------------------------------------------------------------
111
112void ServerThread::quit()
113{
114 stream.interrupt();
115}
116
117//------------------------------------------------------------------------------
118
119void ServerThread::run()
120{
121 Util::debug("hu.varadiistvan.xplra.ServerThread[%p]::run\n", this);
122 while(stream) {
123 uint8_t command = stream.readU8();
124 if (!stream) continue;
125
126 // Util::debug("hu.varadiistvan.xplra.ServerThread[%p]::run: command=0x%02x\n",
127 // this, command);
128
129 if (command==Protocol::COMMAND_GET_SINGLE) {
130 if (!handleGetSingle()) break;
131 } else if (command==Protocol::COMMAND_SET_SINGLE) {
132 if (!handleSetSingle()) break;
133 } else if (command==Protocol::COMMAND_GET_MULTI) {
134 if (!handleGetMulti()) break;
135 } else if (command==Protocol::COMMAND_SET_MULTI) {
136 if (!handleSetMulti()) break;
137 } else if (command==Protocol::COMMAND_REGISTER_GET_MULTI) {
138 if (!handleRegisterGetMulti()) break;
139 } else if (command==Protocol::COMMAND_UNREGISTER_GET_MULTI) {
140 if (!handleUnregisterGetMulti()) break;
141 } else if (command==Protocol::COMMAND_EXECUTE_GET_MULTI) {
142 if (!handleExecuteGetMulti()) break;
143 } else if (command==Protocol::COMMAND_REGISTER_SET_MULTI) {
144 if (!handleRegisterSetMulti()) break;
145 } else if (command==Protocol::COMMAND_UNREGISTER_SET_MULTI) {
146 if (!handleUnregisterSetMulti()) break;
147 } else if (command==Protocol::COMMAND_EXECUTE_SET_MULTI) {
148 if (!handleExecuteSetMulti()) break;
149 } else {
150 stream.writeU8(Protocol::RESULT_INVALID_COMMAND);
151 }
152 stream.flush();
153 }
154
155 Util::debug("hu.varadiistvan.xplra.ServerThread[%p]::run: quitting\n", this);
156}
157
158//------------------------------------------------------------------------------
159
160bool ServerThread::handleGetSingle()
161{
162 uint8_t result = Protocol::RESULT_OK;
163 GetDataRefTask* task = GetDataRefTask::create(result, stream);
164
165 if (!stream) {
166 return false;
167 } else if (task==0) {
168 stream.writeU8(result);
169 return true;
170 }
171
172 TaskRequest request(task);
173 if (!requestQueue.execute(&request)) return false;
174
175 if (task->isValid()) {
176 stream.writeU8(Protocol::RESULT_OK);
177 task->writeValue(stream);
178 } else {
179 stream.writeU8(Protocol::RESULT_UNKNOWN_DATAREF);
180 }
181
182 return true;
183}
184
185//------------------------------------------------------------------------------
186
187bool ServerThread::handleSetSingle()
188{
189 uint8_t result = Protocol::RESULT_OK;
190 SetDataRefTask* task = SetDataRefTask::create(result, stream);
191
192 if (!stream) {
193 return false;
194 } else if (task==0) {
195 stream.writeU8(result);
196 return true;
197 }
198
199 task->readValue(stream);
200 if (!stream) {
201 delete task;
202 return false;
203 }
204
205 TaskRequest request(task);
206 if (!requestQueue.execute(&request)) return false;
207
208 stream.writeU8(task->isValid() ? Protocol::RESULT_OK :
209 Protocol::RESULT_UNKNOWN_DATAREF);
210 return true;
211}
212
213//------------------------------------------------------------------------------
214
215bool ServerThread::handleGetMulti()
216{
217 uint8_t result = Protocol::RESULT_OK;
218 GetMultiDataRefRequest* request =
219 new GetMultiDataRefRequest(result, stream);
220 if (result!=Protocol::RESULT_OK || !stream) {
221 delete request;
222 stream.writeU8(result);
223 return stream;
224 }
225
226 bool isOK = requestQueue.execute(request);
227
228 if (isOK) {
229 request->writeResult(stream);
230 }
231
232 delete request;
233
234 return isOK;
235}
236
237//------------------------------------------------------------------------------
238
239bool ServerThread::handleSetMulti()
240{
241 uint8_t result = Protocol::RESULT_OK;
242 SetMultiDataRefRequest* request =
243 new SetMultiDataRefRequest(result, stream, true);
244 if (result!=Protocol::RESULT_OK || !stream) {
245 delete request;
246 stream.writeU8(result);
247 return stream;
248 }
249
250 bool isOK = requestQueue.execute(request);
251
252 if (isOK) {
253 request->writeResult(stream);
254 }
255
256 delete request;
257
258 return isOK;
259}
260
261//------------------------------------------------------------------------------
262
263bool ServerThread::handleRegisterGetMulti()
264{
265 uint8_t result = Protocol::RESULT_OK;
266 GetMultiDataRefRequest* request =
267 new GetMultiDataRefRequest(result, stream);
268 if (result!=Protocol::RESULT_OK || !stream) {
269 delete request;
270 stream.writeU8(result);
271 return stream;
272 }
273
274 size_t id = nextGetMultiRequestID++;
275 getMultiRequests[id] = request;
276
277 stream.writeU8(Protocol::RESULT_OK);
278 stream.writeU32(id);
279
280 return true;
281}
282
283//------------------------------------------------------------------------------
284
285bool ServerThread::handleUnregisterGetMulti()
286{
287 uint32_t id = stream.readU32();
288 if (!stream) return false;
289
290 getMultiRequests_t::iterator i = getMultiRequests.find(id);
291 if (i==getMultiRequests.end()) {
292 stream.writeU8(Protocol::RESULT_INVALID_ID);
293 } else {
294 GetMultiDataRefRequest* request = i->second;
295 getMultiRequests.erase(i);
296 delete request;
297 stream.writeU8(Protocol::RESULT_OK);
298 }
299
300 return true;
301}
302
303//------------------------------------------------------------------------------
304
305bool ServerThread::handleExecuteGetMulti()
306{
307 uint32_t id = stream.readU32();
308 if (!stream) return false;
309
310 getMultiRequests_t::iterator i = getMultiRequests.find(id);
311 if (i==getMultiRequests.end()) {
312 stream.writeU8(Protocol::RESULT_INVALID_ID);
313 } else {
314 GetMultiDataRefRequest* request = i->second;
315 if (!requestQueue.execute(request)) return false;
316 request->writeResult(stream);
317 }
318
319 return true;
320}
321
322//------------------------------------------------------------------------------
323
324bool ServerThread::handleRegisterSetMulti()
325{
326 uint8_t result = Protocol::RESULT_OK;
327 SetMultiDataRefRequest* request =
328 new SetMultiDataRefRequest(result, stream, false);
329 if (result!=Protocol::RESULT_OK || !stream) {
330 delete request;
331 stream.writeU8(result);
332 return stream;
333 }
334
335 size_t id = nextSetMultiRequestID++;
336 setMultiRequests[id] = request;
337
338 stream.writeU8(Protocol::RESULT_OK);
339 stream.writeU32(id);
340
341 return true;
342}
343
344//------------------------------------------------------------------------------
345
346bool ServerThread::handleUnregisterSetMulti()
347{
348 uint32_t id = stream.readU32();
349 if (!stream) return false;
350
351 setMultiRequests_t::iterator i = setMultiRequests.find(id);
352 if (i==setMultiRequests.end()) {
353 stream.writeU8(Protocol::RESULT_INVALID_ID);
354 } else {
355 SetMultiDataRefRequest* request = i->second;
356 setMultiRequests.erase(i);
357 delete request;
358 stream.writeU8(Protocol::RESULT_OK);
359 }
360
361 return true;
362}
363
364//------------------------------------------------------------------------------
365
366bool ServerThread::handleExecuteSetMulti()
367{
368 uint32_t id = stream.readU32();
369 if (!stream) return false;
370
371 setMultiRequests_t::iterator i = setMultiRequests.find(id);
372 if (i==setMultiRequests.end()) {
373 stream.writeU8(Protocol::RESULT_INVALID_ID);
374 } else {
375 SetMultiDataRefRequest* request = i->second;
376 request->readValues(stream);
377 if (!stream || !requestQueue.execute(request)) return false;
378 request->writeResult(stream);
379 }
380
381 return true;
382}
383
384//------------------------------------------------------------------------------
385
386// Local Variables:
387// mode: C++
388// c-basic-offset: 4
389// indent-tabs-mode: nil
390// End:
Note: See TracBrowser for help on using the repository browser.