source: xplra/src/plugin/src/xplra/ServerThread.cc@ 36:29e3b676c0c2

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

Added a new command to query the versions

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