source: xplra/src/plugin/src/xplra/ServerThread.cc@ 39:44eda5bbbdfb

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

Implemented a plugin reload command

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