source: xplra/src/plugin/src/xplra/ServerThread.cc@ 44:f5222044879c

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

Created the Globals class

File size: 13.0 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 (*i)->quit();
72 }
73 instancesMutex.unlock();
74}
75
76//------------------------------------------------------------------------------
77
78ServerThread::ServerThread(ListenThread& listenThread,
79 RequestQueue& requestQueue, LocalAcceptor& acceptor) :
80 Thread(true),
81 listenThread(listenThread),
82 requestQueue(requestQueue),
83 bufferedStream(acceptor.getSocket(&waiter)),
84 stream(*bufferedStream),
85 nextGetMultiRequestID(1),
86 nextSetMultiRequestID(1)
87{
88 instancesMutex.lock();
89 instances.insert(this);
90 instancesMutex.unlock();
91}
92
93//------------------------------------------------------------------------------
94
95ServerThread::~ServerThread()
96{
97 delete bufferedStream;
98
99 for(getMultiRequests_t::iterator i = getMultiRequests.begin();
100 i!=getMultiRequests.end(); ++i)
101 {
102 delete i->second;
103 }
104
105 for(setMultiRequests_t::iterator i = setMultiRequests.begin();
106 i!=setMultiRequests.end(); ++i)
107 {
108 delete i->second;
109 }
110
111 instancesMutex.lock();
112 instances.erase(this);
113 instancesMutex.unlock();
114}
115
116//------------------------------------------------------------------------------
117
118void ServerThread::quit()
119{
120 stream.interrupt();
121}
122
123//------------------------------------------------------------------------------
124
125void ServerThread::run()
126{
127 Util::debug("hu.varadiistvan.xplra.ServerThread[%p]::run\n", this);
128 while(stream) {
129 uint8_t command = stream.readU8();
130 if (!stream) continue;
131
132 // Util::debug("hu.varadiistvan.xplra.ServerThread[%p]::run: command=0x%02x\n",
133 // this, command);
134
135 if (command==Protocol::COMMAND_GET_SINGLE) {
136 if (!handleGetSingle()) break;
137 } else if (command==Protocol::COMMAND_SET_SINGLE) {
138 if (!handleSetSingle()) break;
139 } else if (command==Protocol::COMMAND_GET_MULTI) {
140 if (!handleGetMulti()) break;
141 } else if (command==Protocol::COMMAND_SET_MULTI) {
142 if (!handleSetMulti()) break;
143 } else if (command==Protocol::COMMAND_REGISTER_GET_MULTI) {
144 if (!handleRegisterGetMulti()) break;
145 } else if (command==Protocol::COMMAND_UNREGISTER_GET_MULTI) {
146 if (!handleUnregisterGetMulti()) break;
147 } else if (command==Protocol::COMMAND_EXECUTE_GET_MULTI) {
148 if (!handleExecuteGetMulti()) break;
149 } else if (command==Protocol::COMMAND_REGISTER_SET_MULTI) {
150 if (!handleRegisterSetMulti()) break;
151 } else if (command==Protocol::COMMAND_UNREGISTER_SET_MULTI) {
152 if (!handleUnregisterSetMulti()) break;
153 } else if (command==Protocol::COMMAND_EXECUTE_SET_MULTI) {
154 if (!handleExecuteSetMulti()) break;
155 } else if (command==Protocol::COMMAND_GET_VERSIONS) {
156 if (!handleGetVersions()) break;
157 } else if (command==Protocol::COMMAND_RELOAD_PLUGINS) {
158 if (!handleReloadPlugins()) break;
159 } else if (command==Protocol::COMMAND_SHOW_MESSAGE) {
160 if (!handleShowMessage()) break;
161 } else {
162 stream.writeU8(Protocol::RESULT_INVALID_COMMAND);
163 }
164 stream.flush();
165 }
166
167 Util::debug("hu.varadiistvan.xplra.ServerThread[%p]::run: quitting\n", this);
168}
169
170//------------------------------------------------------------------------------
171
172bool ServerThread::handleGetSingle()
173{
174 uint8_t result = Protocol::RESULT_OK;
175 GetDataRefTask* task = GetDataRefTask::create(result, stream);
176
177 if (!stream) {
178 return false;
179 } else if (task==0) {
180 stream.writeU8(result);
181 return true;
182 }
183
184 TaskRequest request(task);
185 if (!requestQueue.execute(&request)) return false;
186
187 if (task->isValid()) {
188 stream.writeU8(Protocol::RESULT_OK);
189 task->writeValue(stream);
190 } else {
191 stream.writeU8(Protocol::RESULT_UNKNOWN_DATAREF);
192 }
193
194 return true;
195}
196
197//------------------------------------------------------------------------------
198
199bool ServerThread::handleSetSingle()
200{
201 uint8_t result = Protocol::RESULT_OK;
202 SetDataRefTask* task = SetDataRefTask::create(result, stream);
203
204 if (!stream) {
205 return false;
206 } else if (task==0) {
207 stream.writeU8(result);
208 return true;
209 }
210
211 task->readValue(stream);
212 if (!stream) {
213 delete task;
214 return false;
215 }
216
217 TaskRequest request(task);
218 if (!requestQueue.execute(&request)) return false;
219
220 stream.writeU8(task->isValid() ? Protocol::RESULT_OK :
221 Protocol::RESULT_UNKNOWN_DATAREF);
222 return true;
223}
224
225//------------------------------------------------------------------------------
226
227bool ServerThread::handleGetMulti()
228{
229 uint8_t result = Protocol::RESULT_OK;
230 GetMultiDataRefRequest* request =
231 new GetMultiDataRefRequest(result, stream);
232 if (result!=Protocol::RESULT_OK || !stream) {
233 delete request;
234 stream.writeU8(result);
235 return stream;
236 }
237
238 bool isOK = requestQueue.execute(request);
239
240 if (isOK) {
241 request->writeResult(stream);
242 }
243
244 delete request;
245
246 return isOK;
247}
248
249//------------------------------------------------------------------------------
250
251bool ServerThread::handleSetMulti()
252{
253 uint8_t result = Protocol::RESULT_OK;
254 SetMultiDataRefRequest* request =
255 new SetMultiDataRefRequest(result, stream, true);
256 if (result!=Protocol::RESULT_OK || !stream) {
257 delete request;
258 stream.writeU8(result);
259 return stream;
260 }
261
262 bool isOK = requestQueue.execute(request);
263
264 if (isOK) {
265 request->writeResult(stream);
266 }
267
268 delete request;
269
270 return isOK;
271}
272
273//------------------------------------------------------------------------------
274
275bool ServerThread::handleRegisterGetMulti()
276{
277 uint8_t result = Protocol::RESULT_OK;
278 GetMultiDataRefRequest* request =
279 new GetMultiDataRefRequest(result, stream);
280 if (result!=Protocol::RESULT_OK || !stream) {
281 delete request;
282 stream.writeU8(result);
283 return stream;
284 }
285
286 size_t id = nextGetMultiRequestID++;
287 getMultiRequests[id] = request;
288
289 stream.writeU8(Protocol::RESULT_OK);
290 stream.writeU32(id);
291
292 return true;
293}
294
295//------------------------------------------------------------------------------
296
297bool ServerThread::handleUnregisterGetMulti()
298{
299 uint32_t id = stream.readU32();
300 if (!stream) return false;
301
302 getMultiRequests_t::iterator i = getMultiRequests.find(id);
303 if (i==getMultiRequests.end()) {
304 stream.writeU8(Protocol::RESULT_INVALID_ID);
305 } else {
306 GetMultiDataRefRequest* request = i->second;
307 getMultiRequests.erase(i);
308 delete request;
309 stream.writeU8(Protocol::RESULT_OK);
310 }
311
312 return true;
313}
314
315//------------------------------------------------------------------------------
316
317bool ServerThread::handleExecuteGetMulti()
318{
319 uint32_t id = stream.readU32();
320 if (!stream) return false;
321
322 getMultiRequests_t::iterator i = getMultiRequests.find(id);
323 if (i==getMultiRequests.end()) {
324 stream.writeU8(Protocol::RESULT_INVALID_ID);
325 } else {
326 GetMultiDataRefRequest* request = i->second;
327 if (!requestQueue.execute(request)) return false;
328 request->writeResult(stream);
329 }
330
331 return true;
332}
333
334//------------------------------------------------------------------------------
335
336bool ServerThread::handleRegisterSetMulti()
337{
338 uint8_t result = Protocol::RESULT_OK;
339 SetMultiDataRefRequest* request =
340 new SetMultiDataRefRequest(result, stream, false);
341 if (result!=Protocol::RESULT_OK || !stream) {
342 delete request;
343 stream.writeU8(result);
344 return stream;
345 }
346
347 size_t id = nextSetMultiRequestID++;
348 setMultiRequests[id] = request;
349
350 stream.writeU8(Protocol::RESULT_OK);
351 stream.writeU32(id);
352
353 return true;
354}
355
356//------------------------------------------------------------------------------
357
358bool ServerThread::handleUnregisterSetMulti()
359{
360 uint32_t id = stream.readU32();
361 if (!stream) return false;
362
363 setMultiRequests_t::iterator i = setMultiRequests.find(id);
364 if (i==setMultiRequests.end()) {
365 stream.writeU8(Protocol::RESULT_INVALID_ID);
366 } else {
367 SetMultiDataRefRequest* request = i->second;
368 setMultiRequests.erase(i);
369 delete request;
370 stream.writeU8(Protocol::RESULT_OK);
371 }
372
373 return true;
374}
375
376//------------------------------------------------------------------------------
377
378bool ServerThread::handleExecuteSetMulti()
379{
380 uint32_t id = stream.readU32();
381 if (!stream) return false;
382
383 setMultiRequests_t::iterator i = setMultiRequests.find(id);
384 if (i==setMultiRequests.end()) {
385 stream.writeU8(Protocol::RESULT_INVALID_ID);
386 } else {
387 SetMultiDataRefRequest* request = i->second;
388 request->readValues(stream);
389 if (!stream || !requestQueue.execute(request)) return false;
390 request->writeResult(stream);
391 }
392
393 return true;
394}
395
396//------------------------------------------------------------------------------
397
398bool ServerThread::handleGetVersions()
399{
400 int xplaneVersion = 0;
401 int xplmVersion = 0;
402
403 listenThread.getGlobals().getVersions(xplaneVersion, xplmVersion);
404
405 stream.writeU8(Protocol::RESULT_OK);
406 stream.writeS32(xplaneVersion);
407 stream.writeS32(xplmVersion);
408 stream.writeS32(Protocol::version);
409
410 return true;
411}
412
413//------------------------------------------------------------------------------
414
415bool ServerThread::handleReloadPlugins()
416{
417 ReloadPluginsRequest request;
418 if (!requestQueue.execute(&request)) return false;
419
420 stream.writeU8(Protocol::RESULT_OK);
421
422 return true;
423}
424
425//------------------------------------------------------------------------------
426
427bool ServerThread::handleShowMessage()
428{
429 string message = stream.readString();
430 float duration = stream.readFloat();
431 if (!stream) return false;
432
433 if (duration>Protocol::MAX_MESSAGE_DURATION) {
434 stream.writeU8(Protocol::RESULT_INVALID_DURATION);
435 } else {
436 MessageRequest request(listenThread.getGlobals().getMessageWindow(),
437 message, duration);
438 if (!requestQueue.execute(&request)) return false;
439
440 stream.writeU8(Protocol::RESULT_OK);
441 }
442
443 return true;
444}
445
446//------------------------------------------------------------------------------
447
448// Local Variables:
449// mode: C++
450// c-basic-offset: 4
451// indent-tabs-mode: nil
452// End:
Note: See TracBrowser for help on using the repository browser.