source: xplra/src/plugin/src/xplra/ServerThread.cc@ 81:f28f1b8f3ef7

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

Added a command to save the current situation

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