source: xplra/src/plugin/src/xplra/ServerThread.cc@ 38:128b9ced9779

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

Added basic support for showing a message

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