source: xplra/src/plugin/src/xplra/ServerThread.cc@ 46:e57735492bf8

Last change on this file since 46:e57735492bf8 was 46:e57735492bf8, checked in by István Váradi <ivaradi@…>, 11 years ago

Fixed the shutdown sequence and removed some unnecessary printouts

File size: 14.9 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 "ListenThread.h"
34#include "RequestQueue.h"
35#include "Protocol.h"
36#include "GetDataRefTask.h"
37#include "SetDataRefTask.h"
38#include "TaskRequest.h"
39#include "GetMultiDataRefRequest.h"
40#include "SetMultiDataRefRequest.h"
41#include "ReloadPluginsRequest.h"
42#include "MessageRequest.h"
43#include "Globals.h"
44
45#include <hu/varadiistvan/xplcommon/Util.h>
46
47#include <cstdio>
48
49//------------------------------------------------------------------------------
50
51using xplra::ServerThread;
52
53using hu::varadiistvan::scpl::io::LocalAcceptor;
54using hu::varadiistvan::scpl::Mutex;
55using hu::varadiistvan::xplcommon::Util;
56
57using std::string;
58
59//------------------------------------------------------------------------------
60
61Mutex ServerThread::instancesMutex;
62
63ServerThread::instances_t ServerThread::instances;
64
65//------------------------------------------------------------------------------
66
67void ServerThread::quitAll()
68{
69 instancesMutex.lock();
70 for(instances_t::iterator i = instances.begin(); i!=instances.end(); ++i) {
71 ServerThread* thread = *i;
72 thread->quit();
73 thread->join();
74 delete thread;
75 }
76 instances.clear();
77 instancesMutex.unlock();
78}
79
80//------------------------------------------------------------------------------
81
82inline bool ServerThread::destroyHotkeys()
83{
84 if (hotkeys!=0) {
85 listenThread.getGlobals().getHotkeyHandler().unregisterHotkeys(hotkeys);
86 delete hotkeys; hotkeys = 0;
87 return true;
88 } else {
89 return false;
90 }
91}
92
93//------------------------------------------------------------------------------
94
95ServerThread::ServerThread(ListenThread& listenThread,
96 RequestQueue& requestQueue, LocalAcceptor& acceptor) :
97 listenThread(listenThread),
98 requestQueue(requestQueue),
99 bufferedStream(acceptor.getSocket(&waiter)),
100 stream(*bufferedStream),
101 nextGetMultiRequestID(1),
102 nextSetMultiRequestID(1),
103 hotkeys(0)
104{
105 instancesMutex.lock();
106 instances.insert(this);
107 instancesMutex.unlock();
108}
109
110//------------------------------------------------------------------------------
111
112ServerThread::~ServerThread()
113{
114 delete bufferedStream;
115
116 for(getMultiRequests_t::iterator i = getMultiRequests.begin();
117 i!=getMultiRequests.end(); ++i)
118 {
119 delete i->second;
120 }
121
122 for(setMultiRequests_t::iterator i = setMultiRequests.begin();
123 i!=setMultiRequests.end(); ++i)
124 {
125 delete i->second;
126 }
127}
128
129//------------------------------------------------------------------------------
130
131void ServerThread::quit()
132{
133 stream.interrupt();
134}
135
136//------------------------------------------------------------------------------
137
138void ServerThread::run()
139{
140 Util::debug("hu.varadiistvan.xplra.ServerThread[%p]::run\n", this);
141 while(stream) {
142 uint8_t command = stream.readU8();
143 if (!stream) continue;
144
145 // Util::debug("hu.varadiistvan.xplra.ServerThread[%p]::run: command=0x%02x\n",
146 // this, command);
147
148 if (command==Protocol::COMMAND_GET_SINGLE) {
149 if (!handleGetSingle()) break;
150 } else if (command==Protocol::COMMAND_SET_SINGLE) {
151 if (!handleSetSingle()) break;
152 } else if (command==Protocol::COMMAND_GET_MULTI) {
153 if (!handleGetMulti()) break;
154 } else if (command==Protocol::COMMAND_SET_MULTI) {
155 if (!handleSetMulti()) break;
156 } else if (command==Protocol::COMMAND_REGISTER_GET_MULTI) {
157 if (!handleRegisterGetMulti()) break;
158 } else if (command==Protocol::COMMAND_UNREGISTER_GET_MULTI) {
159 if (!handleUnregisterGetMulti()) break;
160 } else if (command==Protocol::COMMAND_EXECUTE_GET_MULTI) {
161 if (!handleExecuteGetMulti()) break;
162 } else if (command==Protocol::COMMAND_REGISTER_SET_MULTI) {
163 if (!handleRegisterSetMulti()) break;
164 } else if (command==Protocol::COMMAND_UNREGISTER_SET_MULTI) {
165 if (!handleUnregisterSetMulti()) break;
166 } else if (command==Protocol::COMMAND_EXECUTE_SET_MULTI) {
167 if (!handleExecuteSetMulti()) break;
168 } else if (command==Protocol::COMMAND_GET_VERSIONS) {
169 if (!handleGetVersions()) break;
170 } else if (command==Protocol::COMMAND_RELOAD_PLUGINS) {
171 if (!handleReloadPlugins()) break;
172 } else if (command==Protocol::COMMAND_SHOW_MESSAGE) {
173 if (!handleShowMessage()) break;
174 } else if (command==Protocol::COMMAND_REGISTER_HOTKEYS) {
175 if (!handleRegisterHotkeys()) break;
176 } else if (command==Protocol::COMMAND_QUERY_HOTKEYS) {
177 if (!handleQueryHotkeys()) break;
178 } else if (command==Protocol::COMMAND_UNREGISTER_HOTKEYS) {
179 if (!handleUnregisterHotkeys()) break;
180 } else {
181 stream.writeU8(Protocol::RESULT_INVALID_COMMAND);
182 }
183 stream.flush();
184 }
185
186 destroyHotkeys();
187
188 Util::debug("hu.varadiistvan.xplra.ServerThread[%p]::run: quitting\n", this);
189}
190
191//------------------------------------------------------------------------------
192
193bool ServerThread::handleGetSingle()
194{
195 uint8_t result = Protocol::RESULT_OK;
196 GetDataRefTask* task = GetDataRefTask::create(result, stream);
197
198 if (!stream) {
199 return false;
200 } else if (task==0) {
201 stream.writeU8(result);
202 return true;
203 }
204
205 TaskRequest request(task);
206 if (!requestQueue.execute(&request)) return false;
207
208 if (task->isValid()) {
209 stream.writeU8(Protocol::RESULT_OK);
210 task->writeValue(stream);
211 } else {
212 stream.writeU8(Protocol::RESULT_UNKNOWN_DATAREF);
213 }
214
215 return true;
216}
217
218//------------------------------------------------------------------------------
219
220bool ServerThread::handleSetSingle()
221{
222 uint8_t result = Protocol::RESULT_OK;
223 SetDataRefTask* task = SetDataRefTask::create(result, stream);
224
225 if (!stream) {
226 return false;
227 } else if (task==0) {
228 stream.writeU8(result);
229 return true;
230 }
231
232 task->readValue(stream);
233 if (!stream) {
234 delete task;
235 return false;
236 }
237
238 TaskRequest request(task);
239 if (!requestQueue.execute(&request)) return false;
240
241 stream.writeU8(task->isValid() ? Protocol::RESULT_OK :
242 Protocol::RESULT_UNKNOWN_DATAREF);
243 return true;
244}
245
246//------------------------------------------------------------------------------
247
248bool ServerThread::handleGetMulti()
249{
250 uint8_t result = Protocol::RESULT_OK;
251 GetMultiDataRefRequest* request =
252 new GetMultiDataRefRequest(result, stream);
253 if (result!=Protocol::RESULT_OK || !stream) {
254 delete request;
255 stream.writeU8(result);
256 return stream;
257 }
258
259 bool isOK = requestQueue.execute(request);
260
261 if (isOK) {
262 request->writeResult(stream);
263 }
264
265 delete request;
266
267 return isOK;
268}
269
270//------------------------------------------------------------------------------
271
272bool ServerThread::handleSetMulti()
273{
274 uint8_t result = Protocol::RESULT_OK;
275 SetMultiDataRefRequest* request =
276 new SetMultiDataRefRequest(result, stream, true);
277 if (result!=Protocol::RESULT_OK || !stream) {
278 delete request;
279 stream.writeU8(result);
280 return stream;
281 }
282
283 bool isOK = requestQueue.execute(request);
284
285 if (isOK) {
286 request->writeResult(stream);
287 }
288
289 delete request;
290
291 return isOK;
292}
293
294//------------------------------------------------------------------------------
295
296bool ServerThread::handleRegisterGetMulti()
297{
298 uint8_t result = Protocol::RESULT_OK;
299 GetMultiDataRefRequest* request =
300 new GetMultiDataRefRequest(result, stream);
301 if (result!=Protocol::RESULT_OK || !stream) {
302 delete request;
303 stream.writeU8(result);
304 return stream;
305 }
306
307 size_t id = nextGetMultiRequestID++;
308 getMultiRequests[id] = request;
309
310 stream.writeU8(Protocol::RESULT_OK);
311 stream.writeU32(id);
312
313 return true;
314}
315
316//------------------------------------------------------------------------------
317
318bool ServerThread::handleUnregisterGetMulti()
319{
320 uint32_t id = stream.readU32();
321 if (!stream) return false;
322
323 getMultiRequests_t::iterator i = getMultiRequests.find(id);
324 if (i==getMultiRequests.end()) {
325 stream.writeU8(Protocol::RESULT_INVALID_ID);
326 } else {
327 GetMultiDataRefRequest* request = i->second;
328 getMultiRequests.erase(i);
329 delete request;
330 stream.writeU8(Protocol::RESULT_OK);
331 }
332
333 return true;
334}
335
336//------------------------------------------------------------------------------
337
338bool ServerThread::handleExecuteGetMulti()
339{
340 uint32_t id = stream.readU32();
341 if (!stream) return false;
342
343 getMultiRequests_t::iterator i = getMultiRequests.find(id);
344 if (i==getMultiRequests.end()) {
345 stream.writeU8(Protocol::RESULT_INVALID_ID);
346 } else {
347 GetMultiDataRefRequest* request = i->second;
348 if (!requestQueue.execute(request)) return false;
349 request->writeResult(stream);
350 }
351
352 return true;
353}
354
355//------------------------------------------------------------------------------
356
357bool ServerThread::handleRegisterSetMulti()
358{
359 uint8_t result = Protocol::RESULT_OK;
360 SetMultiDataRefRequest* request =
361 new SetMultiDataRefRequest(result, stream, false);
362 if (result!=Protocol::RESULT_OK || !stream) {
363 delete request;
364 stream.writeU8(result);
365 return stream;
366 }
367
368 size_t id = nextSetMultiRequestID++;
369 setMultiRequests[id] = request;
370
371 stream.writeU8(Protocol::RESULT_OK);
372 stream.writeU32(id);
373
374 return true;
375}
376
377//------------------------------------------------------------------------------
378
379bool ServerThread::handleUnregisterSetMulti()
380{
381 uint32_t id = stream.readU32();
382 if (!stream) return false;
383
384 setMultiRequests_t::iterator i = setMultiRequests.find(id);
385 if (i==setMultiRequests.end()) {
386 stream.writeU8(Protocol::RESULT_INVALID_ID);
387 } else {
388 SetMultiDataRefRequest* request = i->second;
389 setMultiRequests.erase(i);
390 delete request;
391 stream.writeU8(Protocol::RESULT_OK);
392 }
393
394 return true;
395}
396
397//------------------------------------------------------------------------------
398
399bool ServerThread::handleExecuteSetMulti()
400{
401 uint32_t id = stream.readU32();
402 if (!stream) return false;
403
404 setMultiRequests_t::iterator i = setMultiRequests.find(id);
405 if (i==setMultiRequests.end()) {
406 stream.writeU8(Protocol::RESULT_INVALID_ID);
407 } else {
408 SetMultiDataRefRequest* request = i->second;
409 request->readValues(stream);
410 if (!stream || !requestQueue.execute(request)) return false;
411 request->writeResult(stream);
412 }
413
414 return true;
415}
416
417//------------------------------------------------------------------------------
418
419bool ServerThread::handleGetVersions()
420{
421 int xplaneVersion = 0;
422 int xplmVersion = 0;
423
424 listenThread.getGlobals().getVersions(xplaneVersion, xplmVersion);
425
426 stream.writeU8(Protocol::RESULT_OK);
427 stream.writeS32(xplaneVersion);
428 stream.writeS32(xplmVersion);
429 stream.writeS32(Protocol::version);
430
431 return true;
432}
433
434//------------------------------------------------------------------------------
435
436bool ServerThread::handleReloadPlugins()
437{
438 ReloadPluginsRequest request;
439 if (!requestQueue.execute(&request)) return false;
440
441 stream.writeU8(Protocol::RESULT_OK);
442
443 return true;
444}
445
446//------------------------------------------------------------------------------
447
448bool ServerThread::handleShowMessage()
449{
450 string message = stream.readString();
451 float duration = stream.readFloat();
452 if (!stream) return false;
453
454 if (duration>Protocol::MAX_MESSAGE_DURATION) {
455 stream.writeU8(Protocol::RESULT_INVALID_DURATION);
456 } else {
457 MessageRequest request(listenThread.getGlobals().getMessageWindow(),
458 message, duration);
459 if (!requestQueue.execute(&request)) return false;
460
461 stream.writeU8(Protocol::RESULT_OK);
462 }
463
464 return true;
465}
466
467//------------------------------------------------------------------------------
468
469bool ServerThread::handleRegisterHotkeys()
470{
471 size_t numHotkeys = stream.readU32();
472 if (!stream) return false;
473
474 if (numHotkeys>Protocol::MAX_HOTKEY_COUNT) {
475 stream.writeU8(Protocol::RESULT_INVALID_LENGTH);
476 } else {
477 HotkeyHandler::Hotkeys* newHotkeys =
478 new HotkeyHandler::Hotkeys(numHotkeys, stream);
479 if (newHotkeys->isValid()) {
480 destroyHotkeys();
481 hotkeys = newHotkeys;
482 listenThread.getGlobals().getHotkeyHandler().registerHotkeys(hotkeys);
483 stream.writeU8(Protocol::RESULT_OK);
484 } else {
485 delete newHotkeys;
486 return false;
487 }
488 }
489
490 return true;
491}
492
493//------------------------------------------------------------------------------
494
495bool ServerThread::handleQueryHotkeys()
496{
497 stream.writeU8(Protocol::RESULT_OK);
498 if (hotkeys==0) {
499 stream.writeU32(0);
500 } else {
501 hotkeys->writePressed(stream);
502 }
503 return true;
504}
505
506//------------------------------------------------------------------------------
507
508bool ServerThread::handleUnregisterHotkeys()
509{
510 destroyHotkeys();
511 stream.writeU8(Protocol::RESULT_OK);
512 return true;
513}
514
515//------------------------------------------------------------------------------
516
517// Local Variables:
518// mode: C++
519// c-basic-offset: 4
520// indent-tabs-mode: nil
521// End:
Note: See TracBrowser for help on using the repository browser.