1 /******************************************************************************\
2 * Copyright (c) 2004-2020
3 *
4 * Author(s):
5 * Volker Fischer
6 *
7 ******************************************************************************
8 *
9 * This program is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License as published by the Free Software
11 * Foundation; either version 2 of the License, or (at your option) any later
12 * version.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 *
23 \******************************************************************************/
24
25 /*
26 Protocol message definition
27 ---------------------------
28
29 - All messages received need to be acknowledged by an acknowledge packet (except
30 of connection less messages)
31
32
33
34 MAIN FRAME
35 ----------
36
37 +-------------+------------+------------+------------------+ ...
38 | 2 bytes TAG | 2 bytes ID | 1 byte cnt | 2 bytes length n | ...
39 +-------------+------------+------------+------------------+ ...
40 ... --------------+-------------+
41 ... n bytes data | 2 bytes CRC |
42 ... --------------+-------------+
43
44 - TAG is an all zero bit word to identify protocol messages
45 - message ID defined by the defines PROTMESSID_x
46 - cnt: counter which is increment for each message and wraps around at 255
47 - length n in bytes of the data
48 - actual data, dependent on message type
49 - 16 bits CRC, calculated over the entire message and is transmitted inverted
50 Generator polynom: G_16(x) = x^16 + x^12 + x^5 + 1, initial state: all ones
51
52
53
54 SPLIT MESSAGE CONTAINER
55 -----------------------
56
57 +------------+------------------------+------------------+--------------+
58 | 2 bytes ID | 1 byte number of parts | 1 byte split cnt | n bytes data |
59 +------------+------------------------+------------------+--------------+
60
61 - ID is the message ID of the message being split
62 - number of parts - total number of parts comprising the whole message
63 - split cnt - number within number total for this part of the message
64 - data - subset of the data part of the original message being split
65
66
67
68 MESSAGES (with connection)
69 --------------------------
70
71 - PROTMESSID_ACKN: Acknowledgement message
72
73 +------------------------------------------+
74 | 2 bytes ID of message to be acknowledged |
75 +------------------------------------------+
76
77 note: the cnt value is the same as of the message to be acknowledged
78
79
80 - PROTMESSID_JITT_BUF_SIZE: Jitter buffer size
81
82 +--------------------------+
83 | 2 bytes number of blocks |
84 +--------------------------+
85
86
87 - PROTMESSID_REQ_JITT_BUF_SIZE: Request jitter buffer size
88
89 note: does not have any data -> n = 0
90
91
92 - PROTMESSID_CLIENT_ID: Sends the current client ID to the client
93
94 +---------------------------------+
95 | 1 byte channel ID of the client |
96 +---------------------------------+
97
98
99 - PROTMESSID_CHANNEL_GAIN: Gain of channel
100
101 +-------------------+--------------+
102 | 1 byte channel ID | 2 bytes gain |
103 +-------------------+--------------+
104
105
106 - PROTMESSID_CHANNEL_PAN: Gain of channel
107
108 +-------------------+-----------------+
109 | 1 byte channel ID | 2 bytes panning |
110 +-------------------+-----------------+
111
112
113 - PROTMESSID_MUTE_STATE_CHANGED: Mute state of your signal at another client has changed
114
115 +-------------------+-----------------+
116 | 1 byte channel ID | 1 byte is muted |
117 +-------------------+-----------------+
118
119
120 - PROTMESSID_CONN_CLIENTS_LIST: Information about connected clients
121
122 for each connected client append following data:
123
124 +-------------------+-----------------+--------------------+ ...
125 | 1 byte channel ID | 2 bytes country | 4 bytes instrument | ...
126 +-------------------+-----------------+--------------------+ ...
127 ... --------------------+--------------------------------------+ ...
128 ... 1 byte skill level | 4 bytes zero (used to be IP address) | ...
129 ... --------------------+--------------------------------------+ ...
130 ... ------------------+---------------------------+
131 ... 2 bytes number n | n bytes UTF-8 string name |
132 ... ------------------+---------------------------+
133 ... ------------------+---------------------------+
134 ... 2 bytes number n | n bytes UTF-8 string city |
135 ... ------------------+---------------------------+
136
137
138 - PROTMESSID_REQ_CONN_CLIENTS_LIST: Request connected clients list
139
140 note: does not have any data -> n = 0
141
142
143 - PROTMESSID_CHANNEL_INFOS: Information about the channel
144
145 +-----------------+--------------------+ ...
146 | 2 bytes country | 4 bytes instrument | ...
147 +-----------------+--------------------+ ...
148 ... --------------------+ ...
149 ... 1 byte skill level | ...
150 ... --------------------+ ...
151 ... ------------------+---------------------------+ ...
152 ... 2 bytes number n | n bytes UTF-8 string name | ...
153 ... ------------------+---------------------------+ ...
154 ... ------------------+---------------------------+
155 ... 2 bytes number n | n bytes UTF-8 string city |
156 ... ------------------+---------------------------+
157
158
159 - PROTMESSID_REQ_CHANNEL_INFOS: Request infos of the channel
160
161 note: does not have any data -> n = 0
162
163
164 - PROTMESSID_CHAT_TEXT: Chat text
165
166 +------------------+----------------------+
167 | 2 bytes number n | n bytes UTF-8 string |
168 +------------------+----------------------+
169
170 - "UTF-8 string": the chat message (plain text from client to server;
171 HTML from server to client)
172
173
174 - PROTMESSID_NETW_TRANSPORT_PROPS: Properties for network transport
175
176 +------------------------+-------------------------+-----------------+ ...
177 | 4 bytes base netw size | 2 bytes block size fact | 1 byte num chan | ...
178 +------------------------+-------------------------+-----------------+ ...
179 ... ------------------+-----------------------+ ...
180 ... 4 bytes sam rate | 2 bytes audiocod type | ...
181 ... ------------------+-----------------------+ ...
182 ... ---------------+----------------------+
183 ... 2 bytes flags | 4 bytes audiocod arg |
184 ... ---------------+----------------------+
185
186 - "base netw size": length of the base network packet (frame) in bytes
187 - "block size fact": block size factor
188 - "num chan": number of channels of the audio signal, e.g. "2" is
189 stereo
190 - "sam rate": sample rate of the audio stream
191 - "audiocod type": audio coding type, the following types are supported:
192 - 0: none, no audio coding applied
193 - 1: CELT
194 - 2: OPUS
195 - 3: OPUS64
196 - "flags": flags indicating network properties:
197 - 0: none
198 - 1: WITH_COUNTER (a packet counter is added to the audio packet)
199 - "audiocod arg": argument for the audio coder, if not used this value
200 shall be set to 0
201
202
203 - PROTMESSID_REQ_NETW_TRANSPORT_PROPS: Request properties for network transport
204
205 note: does not have any data -> n = 0
206
207
208 - PROTMESSID_REQ_SPLIT_MESS_SUPPORT: Request split message support
209
210 note: does not have any data -> n = 0
211
212
213 - PROTMESSID_SPLIT_MESS_SUPPORTED: Split messages are supported
214
215 note: does not have any data -> n = 0
216
217
218 - PROTMESSID_LICENCE_REQUIRED: Licence required to connect to the server
219
220 +---------------------+
221 | 1 byte licence type |
222 +---------------------+
223
224
225 - PROTMESSID_VERSION_AND_OS: Version number and operating system
226
227 +-------------------------+------------------+------------------------------+
228 | 1 byte operating system | 2 bytes number n | n bytes UTF-8 string version |
229 +-------------------------+------------------+------------------------------+
230
231
232 // #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
233 - PROTMESSID_OPUS_SUPPORTED: Informs that OPUS codec is supported
234
235 note: does not have any data -> n = 0
236
237
238 - PROTMESSID_RECORDER_STATE: notifies of changes in the server jam recorder state
239
240 +--------------+
241 | 1 byte state |
242 +--------------+
243
244 state is a value from the enum ERecorderState:
245 - 0 undefined (not used by protocol messages)
246 - tbc
247
248
249 CONNECTION LESS MESSAGES
250 ------------------------
251
252 - PROTMESSID_CLM_PING_MS: Connection less ping message (for measuring the ping
253 time)
254
255 +-----------------------------+
256 | 4 bytes transmit time in ms |
257 +-----------------------------+
258
259
260 - PROTMESSID_CLM_PING_MS_WITHNUMCLIENTS: Connection less ping message (for
261 measuring the ping time) with the
262 info about the current number of
263 connected clients
264
265 +-----------------------------+---------------------------------+
266 | 4 bytes transmit time in ms | 1 byte number connected clients |
267 +-----------------------------+---------------------------------+
268
269
270 - PROTMESSID_CLM_SERVER_FULL: Connection less server full message
271
272 note: does not have any data -> n = 0
273
274
275 - PROTMESSID_CLM_REGISTER_SERVER: Register a server, providing server
276 information
277
278 +------------------------------+ ...
279 | 2 bytes server internal port | ...
280 +------------------------------+ ...
281 ... -----------------+----------------------------------+ ...
282 ... 2 bytes country | 1 byte maximum connected clients | ...
283 ... -----------------+----------------------------------+ ...
284 ... ---------------------+ ...
285 ... 1 byte is permanent | ...
286 ... ---------------------+ ...
287 ... ------------------+----------------------------------+ ...
288 ... 2 bytes number n | n bytes UTF-8 string server name | ...
289 ... ------------------+----------------------------------+ ...
290 ... ------------------+----------------------------------------------+ ...
291 ... 2 bytes number n | n bytes UTF-8 string server internal address | ...
292 ... ------------------+----------------------------------------------+ ...
293 ... ------------------+---------------------------+
294 ... 2 bytes number n | n bytes UTF-8 string city |
295 ... ------------------+---------------------------+
296
297 - "country" is according to "Common Locale Data Repository" which is used in
298 the QLocale class
299 - "maximum connected clients" is the maximum number of clients which can
300 be connected to the server at the same time
301 - "is permanent" is a flag which indicates if the server is permanent
302 online or not. If this value is any value <> 0 indicates that the server
303 is permanent online.
304 - "server internal address" represents the IPv4 address as a dotted quad to
305 be used by clients with the same external IP address as the server.
306 NOTE: In the PROTMESSID_CLM_SERVER_LIST list, this field will be empty
307 as only the initial IP address should be used by the client. Where
308 necessary, that value will contain the server internal address.
309 When running a directory server and a slave server behind the same NAT,
310 this field is used the other way round: It will contain the public
311 IP in this case which will be served to clients from the Internet.
312
313
314 - PROTMESSID_CLM_REGISTER_SERVER_EX: Register a server, providing extended server
315 information
316
317 +--------------------------------+-------------------------------+
318 | PROTMESSID_CLM_REGISTER_SERVER | PROTMESSID_CLM_VERSION_AND_OS |
319 +--------------------------------+-------------------------------+
320
321
322 - PROTMESSID_CLM_UNREGISTER_SERVER: Unregister a server
323
324 note: does not have any data -> n = 0
325
326
327 - PROTMESSID_CLM_SERVER_LIST: Server list message
328
329 for each registered server append following data:
330
331 +--------------------+--------------------------------+
332 | 4 bytes IP address | PROTMESSID_CLM_REGISTER_SERVER |
333 +--------------------+--------------------------------+
334
335 - "PROTMESSID_CLM_REGISTER_SERVER" means that exactly the same message body
336 of the PROTMESSID_CLM_REGISTER_SERVER message is used
337
338
339 - PROTMESSID_CLM_RED_SERVER_LIST: Reduced server list message (to have less UDP fragmentation)
340
341 for each registered server append following data:
342
343 +--------------------+------------------------------+ ...
344 | 4 bytes IP address | 2 bytes server internal port | ...
345 +--------------------+------------------------------+ ...
346 ... -----------------+----------------------------------+
347 ... 1 byte number n | n bytes UTF-8 string server name |
348 ... -----------------+----------------------------------+
349
350
351 - PROTMESSID_CLM_REQ_SERVER_LIST: Request server list
352
353 note: does not have any data -> n = 0
354
355
356 - PROTMESSID_CLM_SEND_EMPTY_MESSAGE: Send "empty message" message
357
358 +--------------------+--------------+
359 | 4 bytes IP address | 2 bytes port |
360 +--------------------+--------------+
361
362
363 - PROTMESSID_CLM_DISCONNECTION: Disconnect message
364
365 note: does not have any data -> n = 0
366
367
368 - PROTMESSID_CLM_VERSION_AND_OS: Version number and operating system
369
370 +-------------------------+------------------+------------------------------+
371 | 1 byte operating system | 2 bytes number n | n bytes UTF-8 string version |
372 +-------------------------+------------------+------------------------------+
373
374
375 - PROTMESSID_CLM_REQ_VERSION_AND_OS: Request version number and operating system
376
377 note: does not have any data -> n = 0
378
379
380 - PROTMESSID_CLM_CONN_CLIENTS_LIST: Information about connected clients
381
382 for each connected client append the PROTMESSID_CONN_CLIENTS_LIST:
383
384 +------------------------------+------------------------------+ ...
385 | PROTMESSID_CONN_CLIENTS_LIST | PROTMESSID_CONN_CLIENTS_LIST | ...
386 +------------------------------+------------------------------+ ...
387
388
389 - PROTMESSID_CLM_REQ_CONN_CLIENTS_LIST: Request the connected clients list
390
391 note: does not have any data -> n = 0
392
393
394 - PROTMESSID_CLM_CHANNEL_LEVEL_LIST: The channel level list
395
396 +----------------------------------+
397 | ( ( n + 1 ) / 2 ) * 4 bit values |
398 +----------------------------------+
399
400 n is number of connected clients
401
402 the values are the maximum channel levels for a client frame converted
403 to the range of CLevelMeter in 4 bits, two entries per byte
404 with the earlier channel in the lower half of the byte
405
406 where an odd number of clients is connected, there will be four unused
407 upper bits in the final byte, containing 0xF (which is out of range)
408
409 the server may compute the message when any client has used
410 PROTMESSID_CLM_REQ_CHANNEL_LEVEL_LIST to opt in
411
412 the server should issue the message only to a client that has used
413 PROTMESSID_CLM_REQ_CHANNEL_LEVEL_LIST to opt in
414
415
416 - PROTMESSID_CLM_REGISTER_SERVER_RESP: result of registration request
417
418 +---------------+
419 | 1 byte status |
420 +---------------+
421
422 - "status":
423 Values of ESvrRegResult:
424 0 - success
425 1 - failed due to directory server list being full
426 2 - your server version is too old
427 3 - registration requirements not fulfilled
428
429 Note: the directory server may send this message in response to a
430 PROTMESSID_CLM_REGISTER_SERVER request.
431 Where not received, the registering server may only retry up to
432 five times for one registration request at 500ms intervals.
433 Beyond this, it should "ping" every 15 minutes
434 (standard re-registration timeout).
435 */
436
437 #include "protocol.h"
438
439 /* Implementation *************************************************************/
CProtocol()440 CProtocol::CProtocol()
441 {
442 // allocate worst case memory for split part messages
443 vecbySplitMessageStorage.Init ( MAX_SIZE_BYTES_NETW_BUF );
444
445 Reset();
446
447 // Connections -------------------------------------------------------------
448 QObject::connect ( &TimerSendMess, &QTimer::timeout, this, &CProtocol::OnTimerSendMess );
449 }
450
Reset()451 void CProtocol::Reset()
452 {
453 QMutexLocker locker ( &Mutex );
454
455 // prepare internal variables for initial protocol transfer
456 iCounter = 0;
457 iOldRecID = PROTMESSID_ILLEGAL;
458 iOldRecCnt = 0;
459 iSplitMessageCnt = 0;
460 iSplitMessageDataIndex = 0;
461 bSplitMessageSupported = false; // compatilibity to old versions
462
463 // delete complete "send message queue"
464 SendMessQueue.clear();
465 }
466
EnqueueMessage(CVector<uint8_t> & vecMessage,const int iCnt,const int iID)467 void CProtocol::EnqueueMessage ( CVector<uint8_t>& vecMessage, const int iCnt, const int iID )
468 {
469 bool bListWasEmpty;
470
471 Mutex.lock();
472 {
473 // check if list is empty so that we have to initiate a send process
474 bListWasEmpty = SendMessQueue.empty();
475
476 // create send message object for the queue
477 CSendMessage SendMessageObj ( vecMessage, iCnt, iID );
478
479 // we want to have a FIFO: we add at the end and take from the beginning
480 SendMessQueue.push_back ( SendMessageObj );
481 }
482 Mutex.unlock();
483
484 // if list was empty, initiate send process
485 if ( bListWasEmpty )
486 {
487 SendMessage();
488 }
489 }
490
SendMessage()491 void CProtocol::SendMessage()
492 {
493 CVector<uint8_t> vecMessage;
494 bool bSendMess = false;
495
496 Mutex.lock();
497 {
498 // we have to check that list is not empty, since in another thread the
499 // last element of the list might have been erased
500 if ( !SendMessQueue.empty() )
501 {
502 vecMessage.Init ( SendMessQueue.front().vecMessage.Size() );
503 vecMessage = SendMessQueue.front().vecMessage;
504
505 // start time-out timer if not active
506 if ( !TimerSendMess.isActive() )
507 {
508 TimerSendMess.start ( SEND_MESS_TIMEOUT_MS );
509 }
510
511 bSendMess = true;
512 }
513 else
514 {
515 // no message to send, stop timer
516 TimerSendMess.stop();
517 }
518 }
519 Mutex.unlock();
520
521 if ( bSendMess )
522 {
523 // send message
524 emit MessReadyForSending ( vecMessage );
525 }
526 }
527
CreateAndSendMessage(const int iID,const CVector<uint8_t> & vecData)528 void CProtocol::CreateAndSendMessage ( const int iID, const CVector<uint8_t>& vecData )
529 {
530 CVector<uint8_t> vecNewMessage;
531 int iCurCounter;
532 const int iDataLen = vecData.Size();
533
534 // check if message has to be split because it is too large
535 if ( bSplitMessageSupported && ( iDataLen > MESS_SPLIT_PART_SIZE_BYTES ) )
536 {
537 CVector<uint8_t> vecNewSplitMessage;
538 int iStartIndexInData = 0; // init index
539
540 // calculate the number of split parts
541 const int iNumParts = static_cast<int> ( std::ceil ( static_cast<double> ( iDataLen ) / MESS_SPLIT_PART_SIZE_BYTES ) );
542
543 for ( int iSplitCnt = 0; iSplitCnt < iNumParts; iSplitCnt++ )
544 {
545 // the split part size may be smaller for the last part
546 int iCurPartSize = MESS_SPLIT_PART_SIZE_BYTES;
547
548 if ( iDataLen - iStartIndexInData < MESS_SPLIT_PART_SIZE_BYTES )
549 {
550 iCurPartSize = iDataLen - iStartIndexInData;
551 }
552
553 GenSplitMessageContainer ( vecNewSplitMessage, iID, iNumParts, iSplitCnt, vecData, iStartIndexInData, iCurPartSize );
554
555 // increment the start index of the source data by the last part size
556 iStartIndexInData += iCurPartSize;
557
558 Mutex.lock();
559 {
560 // store current counter value
561 iCurCounter = iCounter;
562
563 // increase counter (wraps around automatically)
564 iCounter++;
565 }
566 Mutex.unlock();
567
568 // build complete message
569 GenMessageFrame ( vecNewMessage, iCurCounter, PROTMESSID_SPECIAL_SPLIT_MESSAGE, vecNewSplitMessage );
570
571 // enqueue message
572 EnqueueMessage ( vecNewMessage, iCurCounter, PROTMESSID_SPECIAL_SPLIT_MESSAGE );
573 }
574 }
575 else
576 {
577 Mutex.lock();
578 {
579 // store current counter value
580 iCurCounter = iCounter;
581
582 // increase counter (wraps around automatically)
583 iCounter++;
584 }
585 Mutex.unlock();
586
587 // build complete message
588 GenMessageFrame ( vecNewMessage, iCurCounter, iID, vecData );
589
590 // enqueue message
591 EnqueueMessage ( vecNewMessage, iCurCounter, iID );
592 }
593 }
594
CreateAndImmSendAcknMess(const int & iID,const int & iCnt)595 void CProtocol::CreateAndImmSendAcknMess ( const int& iID, const int& iCnt )
596 {
597 CVector<uint8_t> vecAcknMessage;
598 CVector<uint8_t> vecData ( 2 ); // 2 bytes of data
599 int iPos = 0; // init position pointer
600
601 // build data vector
602 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iID ), 2 );
603
604 // build complete message
605 GenMessageFrame ( vecAcknMessage, iCnt, PROTMESSID_ACKN, vecData );
606
607 // immediately send acknowledge message
608 emit MessReadyForSending ( vecAcknMessage );
609 }
610
CreateAndImmSendConLessMessage(const int iID,const CVector<uint8_t> & vecData,const CHostAddress & InetAddr)611 void CProtocol::CreateAndImmSendConLessMessage ( const int iID, const CVector<uint8_t>& vecData, const CHostAddress& InetAddr )
612 {
613 CVector<uint8_t> vecNewMessage;
614
615 // build complete message (counter per definition=0 for connection less
616 // messages)
617 GenMessageFrame ( vecNewMessage, 0, iID, vecData );
618
619 // immediately send message
620 emit CLMessReadyForSending ( InetAddr, vecNewMessage );
621 }
622
ParseMessageBody(const CVector<uint8_t> & vecbyMesBodyData,const int iRecCounter,const int iRecID)623 void CProtocol::ParseMessageBody ( const CVector<uint8_t>& vecbyMesBodyData, const int iRecCounter, const int iRecID )
624 {
625 // clang-format off
626 /*
627 // TEST channel implementation: randomly delete protocol messages (50 % loss)
628 if ( rand() < ( RAND_MAX / 2 ) ) return false;
629 */
630 // clang-format on
631
632 // In case we received a message and returned an answer but our answer
633 // did not make it to the receiver, he will resend his message. We check
634 // here if the message is the same as the old one, and if this is the
635 // case, just resend our old answer again
636 if ( ( iOldRecID == iRecID ) && ( iOldRecCnt == iRecCounter ) )
637 {
638 // acknowledgments are not acknowledged
639 if ( iRecID != PROTMESSID_ACKN )
640 {
641 // resend acknowledgement
642 CreateAndImmSendAcknMess ( iRecID, iRecCounter );
643 }
644 }
645 else
646 {
647 // special treatment for acknowledge messages
648 if ( iRecID == PROTMESSID_ACKN )
649 {
650 // check size
651 if ( vecbyMesBodyData.Size() != 2 )
652 {
653 return;
654 }
655
656 // extract data from stream and emit signal for received value
657 bool bSendNextMess = false;
658 int iPos = 0;
659 const int iData = static_cast<int> ( GetValFromStream ( vecbyMesBodyData, iPos, 2 ) );
660
661 Mutex.lock();
662 {
663 // check if this is the correct acknowledgment
664 if ( !SendMessQueue.empty() )
665 {
666 if ( ( SendMessQueue.front().iCnt == iRecCounter ) && ( SendMessQueue.front().iID == iData ) )
667 {
668 // message acknowledged, remove from queue
669 SendMessQueue.pop_front();
670
671 // send next message in queue
672 bSendNextMess = true;
673 }
674 }
675 }
676 Mutex.unlock();
677
678 if ( bSendNextMess )
679 {
680 SendMessage();
681 }
682 }
683 else
684 {
685 CVector<uint8_t> vecbyMesBodyDataSplitMess;
686 int iRecIDModified = iRecID;
687 bool bEvaluateMessage = false;
688
689 // check for special ID first
690 if ( iRecID == PROTMESSID_SPECIAL_SPLIT_MESSAGE )
691 {
692 // Split message management ------------------------------------
693 int iOriginalID;
694 int iReceivedNumParts;
695 int iReceivedSplitCnt;
696 int iCurPartSize;
697
698 if ( !ParseSplitMessageContainer ( vecbyMesBodyData,
699 vecbySplitMessageStorage,
700 iSplitMessageDataIndex,
701 iOriginalID,
702 iReceivedNumParts,
703 iReceivedSplitCnt,
704 iCurPartSize ) )
705 {
706 // consistency checks
707 if ( ( iSplitMessageCnt != iReceivedSplitCnt ) || ( iSplitMessageCnt >= iReceivedNumParts ) ||
708 ( iSplitMessageCnt >= MAX_NUM_MESS_SPLIT_PARTS ) )
709 {
710 // in case of an error we reset the split message counter
711 iSplitMessageCnt = 0;
712 iSplitMessageDataIndex = 0;
713 }
714 else
715 {
716 // update counter and message data index since we have received a valid new part
717 iSplitMessageCnt++;
718 iSplitMessageDataIndex += iCurPartSize;
719
720 // check if the split part messages was completely received
721 if ( iSplitMessageCnt == iReceivedNumParts )
722 {
723 // the split message is completely received, copy data for parsing
724 vecbyMesBodyDataSplitMess.Init ( iSplitMessageDataIndex );
725
726 std::copy ( vecbySplitMessageStorage.begin(),
727 vecbySplitMessageStorage.begin() + iSplitMessageDataIndex,
728 vecbyMesBodyDataSplitMess.begin() );
729
730 // the received ID is still PROTMESSID_SPECIAL_SPLIT_MESSAGE, set it to
731 // the ID of the original reconstructed split message now
732 iRecIDModified = iOriginalID;
733
734 // the complete split message was reconstructed, reset the counter for
735 // the next split message
736 iSplitMessageCnt = 0;
737 iSplitMessageDataIndex = 0;
738 bEvaluateMessage = true;
739 }
740 }
741 }
742 }
743 else
744 {
745 // a non-split message was received, reset split message counter and directly evaluate message
746 iSplitMessageCnt = 0;
747 iSplitMessageDataIndex = 0;
748 bEvaluateMessage = true;
749 }
750
751 if ( bEvaluateMessage )
752 {
753 // use a reference to either the original data vector or the reconstructed
754 // split message to avoid unnecessary copying
755 const CVector<uint8_t>& vecbyMesBodyDataRef =
756 ( iRecID == PROTMESSID_SPECIAL_SPLIT_MESSAGE ) ? vecbyMesBodyDataSplitMess : vecbyMesBodyData;
757
758 // check which type of message we received and do action
759 switch ( iRecIDModified )
760 {
761 case PROTMESSID_JITT_BUF_SIZE:
762 EvaluateJitBufMes ( vecbyMesBodyDataRef );
763 break;
764
765 case PROTMESSID_REQ_JITT_BUF_SIZE:
766 EvaluateReqJitBufMes();
767 break;
768
769 case PROTMESSID_CLIENT_ID:
770 EvaluateClientIDMes ( vecbyMesBodyDataRef );
771 break;
772
773 case PROTMESSID_CHANNEL_GAIN:
774 EvaluateChanGainMes ( vecbyMesBodyDataRef );
775 break;
776
777 case PROTMESSID_CHANNEL_PAN:
778 EvaluateChanPanMes ( vecbyMesBodyDataRef );
779 break;
780
781 case PROTMESSID_MUTE_STATE_CHANGED:
782 EvaluateMuteStateHasChangedMes ( vecbyMesBodyDataRef );
783 break;
784
785 case PROTMESSID_CONN_CLIENTS_LIST:
786 EvaluateConClientListMes ( vecbyMesBodyDataRef );
787 break;
788
789 case PROTMESSID_REQ_CONN_CLIENTS_LIST:
790 EvaluateReqConnClientsList();
791 break;
792
793 case PROTMESSID_CHANNEL_INFOS:
794 EvaluateChanInfoMes ( vecbyMesBodyDataRef );
795 break;
796
797 case PROTMESSID_REQ_CHANNEL_INFOS:
798 EvaluateReqChanInfoMes();
799 break;
800
801 case PROTMESSID_CHAT_TEXT:
802 EvaluateChatTextMes ( vecbyMesBodyDataRef );
803 break;
804
805 case PROTMESSID_NETW_TRANSPORT_PROPS:
806 EvaluateNetwTranspPropsMes ( vecbyMesBodyDataRef );
807 break;
808
809 case PROTMESSID_REQ_NETW_TRANSPORT_PROPS:
810 EvaluateReqNetwTranspPropsMes();
811 break;
812
813 case PROTMESSID_REQ_SPLIT_MESS_SUPPORT:
814 EvaluateReqSplitMessSupportMes();
815 break;
816
817 case PROTMESSID_SPLIT_MESS_SUPPORTED:
818 EvaluateSplitMessSupportedMes();
819 break;
820
821 case PROTMESSID_LICENCE_REQUIRED:
822 EvaluateLicenceRequiredMes ( vecbyMesBodyDataRef );
823 break;
824
825 case PROTMESSID_VERSION_AND_OS:
826 EvaluateVersionAndOSMes ( vecbyMesBodyDataRef );
827 break;
828
829 case PROTMESSID_RECORDER_STATE:
830 EvaluateRecorderStateMes ( vecbyMesBodyDataRef );
831 break;
832 }
833 }
834
835 // immediately send acknowledge message
836 CreateAndImmSendAcknMess ( iRecID, iRecCounter );
837
838 // save current message ID and counter to find out if message
839 // was resent
840 iOldRecID = iRecID;
841 iOldRecCnt = iRecCounter;
842 }
843 }
844 }
845
ParseConnectionLessMessageBody(const CVector<uint8_t> & vecbyMesBodyData,const int iRecID,const CHostAddress & InetAddr)846 void CProtocol::ParseConnectionLessMessageBody ( const CVector<uint8_t>& vecbyMesBodyData, const int iRecID, const CHostAddress& InetAddr )
847 {
848 // clang-format off
849 /*
850 // TEST channel implementation: randomly delete protocol messages (50 % loss)
851 if ( rand() < ( RAND_MAX / 2 ) ) return false;
852 */
853 // clang-format on
854
855 // check which type of message we received and do action
856 switch ( iRecID )
857 {
858 case PROTMESSID_CLM_PING_MS:
859 EvaluateCLPingMes ( InetAddr, vecbyMesBodyData );
860 break;
861
862 case PROTMESSID_CLM_PING_MS_WITHNUMCLIENTS:
863 EvaluateCLPingWithNumClientsMes ( InetAddr, vecbyMesBodyData );
864 break;
865
866 case PROTMESSID_CLM_SERVER_FULL:
867 EvaluateCLServerFullMes();
868 break;
869
870 case PROTMESSID_CLM_SERVER_LIST:
871 EvaluateCLServerListMes ( InetAddr, vecbyMesBodyData );
872 break;
873
874 case PROTMESSID_CLM_RED_SERVER_LIST:
875 EvaluateCLRedServerListMes ( InetAddr, vecbyMesBodyData );
876 break;
877
878 case PROTMESSID_CLM_REQ_SERVER_LIST:
879 EvaluateCLReqServerListMes ( InetAddr );
880 break;
881
882 case PROTMESSID_CLM_SEND_EMPTY_MESSAGE:
883 EvaluateCLSendEmptyMesMes ( vecbyMesBodyData );
884 break;
885
886 case PROTMESSID_CLM_REGISTER_SERVER:
887 EvaluateCLRegisterServerMes ( InetAddr, vecbyMesBodyData );
888 break;
889
890 case PROTMESSID_CLM_REGISTER_SERVER_EX:
891 EvaluateCLRegisterServerExMes ( InetAddr, vecbyMesBodyData );
892 break;
893
894 case PROTMESSID_CLM_UNREGISTER_SERVER:
895 EvaluateCLUnregisterServerMes ( InetAddr );
896 break;
897
898 case PROTMESSID_CLM_DISCONNECTION:
899 EvaluateCLDisconnectionMes ( InetAddr );
900 break;
901
902 case PROTMESSID_CLM_VERSION_AND_OS:
903 EvaluateCLVersionAndOSMes ( InetAddr, vecbyMesBodyData );
904 break;
905
906 case PROTMESSID_CLM_REQ_VERSION_AND_OS:
907 EvaluateCLReqVersionAndOSMes ( InetAddr );
908 break;
909
910 case PROTMESSID_CLM_CONN_CLIENTS_LIST:
911 EvaluateCLConnClientsListMes ( InetAddr, vecbyMesBodyData );
912 break;
913
914 case PROTMESSID_CLM_REQ_CONN_CLIENTS_LIST:
915 EvaluateCLReqConnClientsListMes ( InetAddr );
916 break;
917
918 case PROTMESSID_CLM_CHANNEL_LEVEL_LIST:
919 EvaluateCLChannelLevelListMes ( InetAddr, vecbyMesBodyData );
920 break;
921
922 case PROTMESSID_CLM_REGISTER_SERVER_RESP:
923 EvaluateCLRegisterServerResp ( InetAddr, vecbyMesBodyData );
924 break;
925 }
926 }
927
928 /******************************************************************************\
929 * Access functions for creating and parsing messages *
930 \******************************************************************************/
CreateJitBufMes(const int iJitBufSize)931 void CProtocol::CreateJitBufMes ( const int iJitBufSize )
932 {
933 CVector<uint8_t> vecData ( 2 ); // 2 bytes of data
934 int iPos = 0; // init position pointer
935
936 // build data vector
937 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iJitBufSize ), 2 );
938
939 CreateAndSendMessage ( PROTMESSID_JITT_BUF_SIZE, vecData );
940 }
941
EvaluateJitBufMes(const CVector<uint8_t> & vecData)942 bool CProtocol::EvaluateJitBufMes ( const CVector<uint8_t>& vecData )
943 {
944 int iPos = 0; // init position pointer
945
946 // check size
947 if ( vecData.Size() != 2 )
948 {
949 return true; // return error code
950 }
951
952 // extract jitter buffer size
953 const int iData = static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
954
955 if ( ( ( iData < MIN_NET_BUF_SIZE_NUM_BL ) || ( iData > MAX_NET_BUF_SIZE_NUM_BL ) ) && ( iData != AUTO_NET_BUF_SIZE_FOR_PROTOCOL ) )
956 {
957 return true; // return error code
958 }
959
960 // invoke message action
961 emit ChangeJittBufSize ( iData );
962
963 return false; // no error
964 }
965
CreateReqJitBufMes()966 void CProtocol::CreateReqJitBufMes() { CreateAndSendMessage ( PROTMESSID_REQ_JITT_BUF_SIZE, CVector<uint8_t> ( 0 ) ); }
967
EvaluateReqJitBufMes()968 bool CProtocol::EvaluateReqJitBufMes()
969 {
970 // invoke message action
971 emit ReqJittBufSize();
972
973 return false; // no error
974 }
975
CreateClientIDMes(const int iChanID)976 void CProtocol::CreateClientIDMes ( const int iChanID )
977 {
978 CVector<uint8_t> vecData ( 1 ); // 1 byte of data
979 int iPos = 0; // init position pointer
980
981 // build data vector
982 // channel ID
983 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iChanID ), 1 );
984
985 CreateAndSendMessage ( PROTMESSID_CLIENT_ID, vecData );
986 }
987
EvaluateClientIDMes(const CVector<uint8_t> & vecData)988 bool CProtocol::EvaluateClientIDMes ( const CVector<uint8_t>& vecData )
989 {
990 int iPos = 0; // init position pointer
991
992 // check size
993 if ( vecData.Size() != 1 )
994 {
995 return true; // return error code
996 }
997
998 // channel ID
999 const int iCurID = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
1000
1001 // invoke message action
1002 emit ClientIDReceived ( iCurID );
1003
1004 return false; // no error
1005 }
1006
CreateChanGainMes(const int iChanID,const float fGain)1007 void CProtocol::CreateChanGainMes ( const int iChanID, const float fGain )
1008 {
1009 CVector<uint8_t> vecData ( 3 ); // 3 bytes of data
1010 int iPos = 0; // init position pointer
1011
1012 // build data vector
1013 // channel ID
1014 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iChanID ), 1 );
1015
1016 // actual gain, we convert from double with range 0..1 to integer
1017 const int iCurGain = static_cast<int> ( fGain * ( 1 << 15 ) );
1018
1019 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iCurGain ), 2 );
1020
1021 CreateAndSendMessage ( PROTMESSID_CHANNEL_GAIN, vecData );
1022 }
1023
EvaluateChanGainMes(const CVector<uint8_t> & vecData)1024 bool CProtocol::EvaluateChanGainMes ( const CVector<uint8_t>& vecData )
1025 {
1026 int iPos = 0; // init position pointer
1027
1028 // check size
1029 if ( vecData.Size() != 3 )
1030 {
1031 return true; // return error code
1032 }
1033
1034 // channel ID
1035 const int iCurID = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
1036
1037 // gain (read integer value)
1038 const int iData = static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
1039
1040 // we convert the gain from integer to double with range 0..1
1041 const float fNewGain = static_cast<float> ( iData ) / ( 1 << 15 );
1042
1043 // invoke message action
1044 emit ChangeChanGain ( iCurID, fNewGain );
1045
1046 return false; // no error
1047 }
1048
CreateChanPanMes(const int iChanID,const float fPan)1049 void CProtocol::CreateChanPanMes ( const int iChanID, const float fPan )
1050 {
1051 CVector<uint8_t> vecData ( 3 ); // 3 bytes of data
1052 int iPos = 0; // init position pointer
1053
1054 // build data vector
1055 // channel ID
1056 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iChanID ), 1 );
1057
1058 // actual pan, we convert from double with range 0..1 to integer
1059 const int iCurPan = static_cast<int> ( fPan * ( 1 << 15 ) );
1060
1061 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iCurPan ), 2 );
1062
1063 CreateAndSendMessage ( PROTMESSID_CHANNEL_PAN, vecData );
1064 }
1065
EvaluateChanPanMes(const CVector<uint8_t> & vecData)1066 bool CProtocol::EvaluateChanPanMes ( const CVector<uint8_t>& vecData )
1067 {
1068 int iPos = 0; // init position pointer
1069
1070 // check size
1071 if ( vecData.Size() != 3 )
1072 {
1073 return true; // return error code
1074 }
1075
1076 // channel ID
1077 const int iCurID = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
1078
1079 // pan (read integer value)
1080 const int iData = static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
1081
1082 // we convert the pan from integer to double with range 0..1
1083 const float fNewPan = static_cast<float> ( iData ) / ( 1 << 15 );
1084
1085 // invoke message action
1086 emit ChangeChanPan ( iCurID, fNewPan );
1087
1088 return false; // no error
1089 }
1090
CreateMuteStateHasChangedMes(const int iChanID,const bool bIsMuted)1091 void CProtocol::CreateMuteStateHasChangedMes ( const int iChanID, const bool bIsMuted )
1092 {
1093 CVector<uint8_t> vecData ( 2 ); // 2 bytes of data
1094 int iPos = 0; // init position pointer
1095
1096 // build data vector
1097 // channel ID
1098 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iChanID ), 1 );
1099
1100 // mute state
1101 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( bIsMuted ), 1 );
1102
1103 CreateAndSendMessage ( PROTMESSID_MUTE_STATE_CHANGED, vecData );
1104 }
1105
EvaluateMuteStateHasChangedMes(const CVector<uint8_t> & vecData)1106 bool CProtocol::EvaluateMuteStateHasChangedMes ( const CVector<uint8_t>& vecData )
1107 {
1108 int iPos = 0; // init position pointer
1109
1110 // check size
1111 if ( vecData.Size() != 2 )
1112 {
1113 return true; // return error code
1114 }
1115
1116 // channel ID
1117 const int iCurID = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
1118
1119 // mute state
1120 const bool bIsMuted = static_cast<bool> ( GetValFromStream ( vecData, iPos, 1 ) );
1121
1122 // invoke message action
1123 emit MuteStateHasChangedReceived ( iCurID, bIsMuted );
1124
1125 return false; // no error
1126 }
1127
CreateConClientListMes(const CVector<CChannelInfo> & vecChanInfo)1128 void CProtocol::CreateConClientListMes ( const CVector<CChannelInfo>& vecChanInfo )
1129 {
1130 const int iNumClients = vecChanInfo.Size();
1131
1132 // build data vector
1133 CVector<uint8_t> vecData ( 0 );
1134 int iPos = 0; // init position pointer
1135
1136 for ( int i = 0; i < iNumClients; i++ )
1137 {
1138 // convert strings to utf-8
1139 const QByteArray strUTF8Name = vecChanInfo[i].strName.toUtf8();
1140 const QByteArray strUTF8City = vecChanInfo[i].strCity.toUtf8();
1141
1142 // size of current list entry
1143 const int iCurListEntrLen = 1 + // chan ID
1144 2 + // country
1145 4 + // instrument
1146 1 + // skill level
1147 4 + // IP address
1148 2 + strUTF8Name.size() + // utf-8 str. size / str.
1149 2 + strUTF8City.size(); // utf-8 str. size / str.
1150
1151 // make space for new data
1152 vecData.Enlarge ( iCurListEntrLen );
1153
1154 // channel ID (1 byte)
1155 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecChanInfo[i].iChanID ), 1 );
1156
1157 // country (2 bytes)
1158 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecChanInfo[i].eCountry ), 2 );
1159
1160 // instrument (4 bytes)
1161 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecChanInfo[i].iInstrument ), 4 );
1162
1163 // skill level (1 byte)
1164 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecChanInfo[i].eSkillLevel ), 1 );
1165
1166 // used to be IP address before #316 (4 bytes)
1167 PutValOnStream ( vecData, iPos, 0, 4 );
1168
1169 // name
1170 PutStringUTF8OnStream ( vecData, iPos, strUTF8Name );
1171
1172 // city
1173 PutStringUTF8OnStream ( vecData, iPos, strUTF8City );
1174 }
1175
1176 CreateAndSendMessage ( PROTMESSID_CONN_CLIENTS_LIST, vecData );
1177 }
1178
EvaluateConClientListMes(const CVector<uint8_t> & vecData)1179 bool CProtocol::EvaluateConClientListMes ( const CVector<uint8_t>& vecData )
1180 {
1181 int iPos = 0; // init position pointer
1182 const int iDataLen = vecData.Size();
1183 CVector<CChannelInfo> vecChanInfo ( 0 );
1184
1185 while ( iPos < iDataLen )
1186 {
1187 // check size (the next 12 bytes)
1188 if ( ( iDataLen - iPos ) < 12 )
1189 {
1190 return true; // return error code
1191 }
1192
1193 // channel ID (1 byte)
1194 const int iChanID = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
1195
1196 // country (2 bytes)
1197 const QLocale::Country eCountry = static_cast<QLocale::Country> ( GetValFromStream ( vecData, iPos, 2 ) );
1198
1199 // instrument (4 bytes)
1200 const int iInstrument = static_cast<int> ( GetValFromStream ( vecData, iPos, 4 ) );
1201
1202 // skill level (1 byte)
1203 const ESkillLevel eSkillLevel = static_cast<ESkillLevel> ( GetValFromStream ( vecData, iPos, 1 ) );
1204
1205 // used to be IP address, zero since #316 (4 bytes)
1206 iPos += 4;
1207
1208 // name
1209 QString strCurName;
1210 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_FADER_TAG, strCurName ) )
1211 {
1212 return true; // return error code
1213 }
1214
1215 // city
1216 QString strCurCity;
1217 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_SERVER_CITY, strCurCity ) )
1218 {
1219 return true; // return error code
1220 }
1221
1222 // add channel information to vector
1223 vecChanInfo.Add ( CChannelInfo ( iChanID, strCurName, eCountry, strCurCity, iInstrument, eSkillLevel ) );
1224 }
1225
1226 // check size: all data is read, the position must now be at the end
1227 if ( iPos != iDataLen )
1228 {
1229 return true; // return error code
1230 }
1231
1232 // invoke message action
1233 emit ConClientListMesReceived ( vecChanInfo );
1234
1235 return false; // no error
1236 }
1237
CreateReqConnClientsList()1238 void CProtocol::CreateReqConnClientsList() { CreateAndSendMessage ( PROTMESSID_REQ_CONN_CLIENTS_LIST, CVector<uint8_t> ( 0 ) ); }
1239
EvaluateReqConnClientsList()1240 bool CProtocol::EvaluateReqConnClientsList()
1241 {
1242 // invoke message action
1243 emit ReqConnClientsList();
1244
1245 return false; // no error
1246 }
1247
CreateChanInfoMes(const CChannelCoreInfo ChanInfo)1248 void CProtocol::CreateChanInfoMes ( const CChannelCoreInfo ChanInfo )
1249 {
1250 int iPos = 0; // init position pointer
1251
1252 // convert strings to utf-8
1253 const QByteArray strUTF8Name = ChanInfo.strName.toUtf8();
1254 const QByteArray strUTF8City = ChanInfo.strCity.toUtf8();
1255
1256 // size of current list entry
1257 const int iEntrLen = 2 + // country
1258 4 + // instrument
1259 1 + // skill level
1260 2 + strUTF8Name.size() + // utf-8 str. size / str.
1261 2 + strUTF8City.size(); // utf-8 str. size / str.
1262
1263 // build data vector
1264 CVector<uint8_t> vecData ( iEntrLen );
1265
1266 // country (2 bytes)
1267 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( ChanInfo.eCountry ), 2 );
1268
1269 // instrument (4 bytes)
1270 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( ChanInfo.iInstrument ), 4 );
1271
1272 // skill level (1 byte)
1273 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( ChanInfo.eSkillLevel ), 1 );
1274
1275 // name
1276 PutStringUTF8OnStream ( vecData, iPos, strUTF8Name );
1277
1278 // city
1279 PutStringUTF8OnStream ( vecData, iPos, strUTF8City );
1280
1281 CreateAndSendMessage ( PROTMESSID_CHANNEL_INFOS, vecData );
1282 }
1283
EvaluateChanInfoMes(const CVector<uint8_t> & vecData)1284 bool CProtocol::EvaluateChanInfoMes ( const CVector<uint8_t>& vecData )
1285 {
1286 int iPos = 0; // init position pointer
1287 const int iDataLen = vecData.Size();
1288 CChannelCoreInfo ChanInfo;
1289
1290 // check size (the first 7 bytes)
1291 if ( iDataLen < 7 )
1292 {
1293 return true; // return error code
1294 }
1295
1296 // country (2 bytes)
1297 ChanInfo.eCountry = static_cast<QLocale::Country> ( GetValFromStream ( vecData, iPos, 2 ) );
1298
1299 // instrument (4 bytes)
1300 ChanInfo.iInstrument = static_cast<int> ( GetValFromStream ( vecData, iPos, 4 ) );
1301
1302 // skill level (1 byte)
1303 ChanInfo.eSkillLevel = static_cast<ESkillLevel> ( GetValFromStream ( vecData, iPos, 1 ) );
1304
1305 // name
1306 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_FADER_TAG, ChanInfo.strName ) )
1307 {
1308 return true; // return error code
1309 }
1310
1311 // city
1312 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_SERVER_CITY, ChanInfo.strCity ) )
1313 {
1314 return true; // return error code
1315 }
1316
1317 // check size: all data is read, the position must now be at the end
1318 if ( iPos != iDataLen )
1319 {
1320 return true; // return error code
1321 }
1322
1323 // invoke message action
1324 emit ChangeChanInfo ( ChanInfo );
1325
1326 return false; // no error
1327 }
1328
CreateReqChanInfoMes()1329 void CProtocol::CreateReqChanInfoMes() { CreateAndSendMessage ( PROTMESSID_REQ_CHANNEL_INFOS, CVector<uint8_t> ( 0 ) ); }
1330
EvaluateReqChanInfoMes()1331 bool CProtocol::EvaluateReqChanInfoMes()
1332 {
1333 // invoke message action
1334 emit ReqChanInfo();
1335
1336 return false; // no error
1337 }
1338
CreateChatTextMes(const QString strChatText)1339 void CProtocol::CreateChatTextMes ( const QString strChatText )
1340 {
1341 int iPos = 0; // init position pointer
1342
1343 // convert chat text string to utf-8
1344 const QByteArray strUTF8ChatText = strChatText.toUtf8();
1345
1346 const int iStrUTF8Len = strUTF8ChatText.size(); // get utf-8 str. size / string
1347
1348 // size of message body
1349 const int iEntrLen = 2 + iStrUTF8Len; // utf-8 str. size / string
1350
1351 // build data vector
1352 CVector<uint8_t> vecData ( iEntrLen );
1353
1354 // chat text
1355 PutStringUTF8OnStream ( vecData, iPos, strUTF8ChatText );
1356
1357 CreateAndSendMessage ( PROTMESSID_CHAT_TEXT, vecData );
1358 }
1359
EvaluateChatTextMes(const CVector<uint8_t> & vecData)1360 bool CProtocol::EvaluateChatTextMes ( const CVector<uint8_t>& vecData )
1361 {
1362 int iPos = 0; // init position pointer
1363
1364 // chat text
1365 QString strChatText;
1366 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_CHAT_TEXT_PLUS_HTML, strChatText ) )
1367 {
1368 return true; // return error code
1369 }
1370
1371 // check size: all data is read, the position must now be at the end
1372 if ( iPos != vecData.Size() )
1373 {
1374 return true; // return error code
1375 }
1376
1377 // invoke message action
1378 emit ChatTextReceived ( strChatText );
1379
1380 return false; // no error
1381 }
1382
CreateNetwTranspPropsMes(const CNetworkTransportProps & NetTrProps)1383 void CProtocol::CreateNetwTranspPropsMes ( const CNetworkTransportProps& NetTrProps )
1384 {
1385 int iPos = 0; // init position pointer
1386
1387 // size of current message body
1388 const int iEntrLen = 4 + // netw size
1389 2 + // block size fact
1390 1 + // num chan
1391 4 + // sam rate
1392 2 + // audiocod type
1393 2 + // version
1394 4; // audiocod arg
1395
1396 // build data vector
1397 CVector<uint8_t> vecData ( iEntrLen );
1398
1399 // length of the base network packet (frame) in bytes (4 bytes)
1400 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( NetTrProps.iBaseNetworkPacketSize ), 4 );
1401
1402 // block size factor (2 bytes)
1403 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( NetTrProps.iBlockSizeFact ), 2 );
1404
1405 // number of channels of the audio signal, e.g. "2" is stereo (1 byte)
1406 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( NetTrProps.iNumAudioChannels ), 1 );
1407
1408 // sample rate of the audio stream (4 bytes)
1409 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( NetTrProps.iSampleRate ), 4 );
1410
1411 // audio coding type (2 bytes)
1412 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( NetTrProps.eAudioCodingType ), 2 );
1413
1414 // flags (2 bytes)
1415 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( NetTrProps.eFlags ), 2 );
1416
1417 // argument for the audio coder (4 bytes)
1418 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( NetTrProps.iAudioCodingArg ), 4 );
1419
1420 CreateAndSendMessage ( PROTMESSID_NETW_TRANSPORT_PROPS, vecData );
1421 }
1422
EvaluateNetwTranspPropsMes(const CVector<uint8_t> & vecData)1423 bool CProtocol::EvaluateNetwTranspPropsMes ( const CVector<uint8_t>& vecData )
1424 {
1425 int iPos = 0; // init position pointer
1426 CNetworkTransportProps ReceivedNetwTranspProps;
1427
1428 // size of current message body
1429 const int iEntrLen = 4 + // netw size
1430 2 + // block size fact
1431 1 + // num chan
1432 4 + // sam rate
1433 2 + // audiocod type
1434 2 + // flags
1435 4; // audiocod arg
1436
1437 // check size
1438 if ( vecData.Size() != iEntrLen )
1439 {
1440 return true; // return error code
1441 }
1442
1443 // length of the base network packet (frame) in bytes (4 bytes)
1444 ReceivedNetwTranspProps.iBaseNetworkPacketSize = static_cast<uint32_t> ( GetValFromStream ( vecData, iPos, 4 ) );
1445
1446 // at least CELT_MINIMUM_NUM_BYTES bytes are required for the CELC codec
1447 if ( ( ReceivedNetwTranspProps.iBaseNetworkPacketSize < CELT_MINIMUM_NUM_BYTES ) ||
1448 ( ReceivedNetwTranspProps.iBaseNetworkPacketSize > MAX_SIZE_BYTES_NETW_BUF ) )
1449 {
1450 return true; // return error code
1451 }
1452
1453 // block size factor (2 bytes)
1454 ReceivedNetwTranspProps.iBlockSizeFact = static_cast<uint16_t> ( GetValFromStream ( vecData, iPos, 2 ) );
1455
1456 if ( ( ReceivedNetwTranspProps.iBlockSizeFact != FRAME_SIZE_FACTOR_PREFERRED ) &&
1457 ( ReceivedNetwTranspProps.iBlockSizeFact != FRAME_SIZE_FACTOR_DEFAULT ) &&
1458 ( ReceivedNetwTranspProps.iBlockSizeFact != FRAME_SIZE_FACTOR_SAFE ) )
1459 {
1460 return true; // return error code
1461 }
1462
1463 // number of channels of the audio signal, only mono (1 channel) or
1464 // stereo (2 channels) allowed (1 byte)
1465 ReceivedNetwTranspProps.iNumAudioChannels = static_cast<uint32_t> ( GetValFromStream ( vecData, iPos, 1 ) );
1466
1467 if ( ( ReceivedNetwTranspProps.iNumAudioChannels != 1 ) && ( ReceivedNetwTranspProps.iNumAudioChannels != 2 ) )
1468 {
1469 return true; // return error code
1470 }
1471
1472 // sample rate of the audio stream (4 bytes)
1473 ReceivedNetwTranspProps.iSampleRate = static_cast<uint32_t> ( GetValFromStream ( vecData, iPos, 4 ) );
1474
1475 // audio coding type (2 bytes) with error check
1476 const int iRecCodingType = static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
1477
1478 // note that CT_NONE is not a valid setting but only used for server
1479 // initialization
1480 if ( ( iRecCodingType != CT_CELT ) && ( iRecCodingType != CT_OPUS ) && ( iRecCodingType != CT_OPUS64 ) )
1481 {
1482 return true;
1483 }
1484
1485 ReceivedNetwTranspProps.eAudioCodingType = static_cast<EAudComprType> ( iRecCodingType );
1486
1487 // flags (2 bytes)
1488 ReceivedNetwTranspProps.eFlags = static_cast<ENetwFlags> ( GetValFromStream ( vecData, iPos, 2 ) );
1489
1490 // argument for the audio coder (4 bytes)
1491 ReceivedNetwTranspProps.iAudioCodingArg = static_cast<int32_t> ( GetValFromStream ( vecData, iPos, 4 ) );
1492
1493 // invoke message action
1494 emit NetTranspPropsReceived ( ReceivedNetwTranspProps );
1495
1496 return false; // no error
1497 }
1498
CreateReqNetwTranspPropsMes()1499 void CProtocol::CreateReqNetwTranspPropsMes() { CreateAndSendMessage ( PROTMESSID_REQ_NETW_TRANSPORT_PROPS, CVector<uint8_t> ( 0 ) ); }
1500
EvaluateReqNetwTranspPropsMes()1501 bool CProtocol::EvaluateReqNetwTranspPropsMes()
1502 {
1503 // invoke message action
1504 emit ReqNetTranspProps();
1505
1506 return false; // no error
1507 }
1508
CreateReqSplitMessSupportMes()1509 void CProtocol::CreateReqSplitMessSupportMes() { CreateAndSendMessage ( PROTMESSID_REQ_SPLIT_MESS_SUPPORT, CVector<uint8_t> ( 0 ) ); }
1510
EvaluateReqSplitMessSupportMes()1511 bool CProtocol::EvaluateReqSplitMessSupportMes()
1512 {
1513 // invoke message action
1514 emit ReqSplitMessSupport();
1515
1516 return false; // no error
1517 }
1518
CreateSplitMessSupportedMes()1519 void CProtocol::CreateSplitMessSupportedMes() { CreateAndSendMessage ( PROTMESSID_SPLIT_MESS_SUPPORTED, CVector<uint8_t> ( 0 ) ); }
1520
EvaluateSplitMessSupportedMes()1521 bool CProtocol::EvaluateSplitMessSupportedMes()
1522 {
1523 // invoke message action
1524 emit SplitMessSupported();
1525
1526 return false; // no error
1527 }
1528
CreateLicenceRequiredMes(const ELicenceType eLicenceType)1529 void CProtocol::CreateLicenceRequiredMes ( const ELicenceType eLicenceType )
1530 {
1531 CVector<uint8_t> vecData ( 1 ); // 1 bytes of data
1532 int iPos = 0; // init position pointer
1533
1534 // build data vector
1535 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( eLicenceType ), 1 );
1536
1537 CreateAndSendMessage ( PROTMESSID_LICENCE_REQUIRED, vecData );
1538 }
1539
EvaluateLicenceRequiredMes(const CVector<uint8_t> & vecData)1540 bool CProtocol::EvaluateLicenceRequiredMes ( const CVector<uint8_t>& vecData )
1541 {
1542 int iPos = 0; // init position pointer
1543
1544 // check size
1545 if ( vecData.Size() != 1 )
1546 {
1547 return true; // return error code
1548 }
1549
1550 // extract licence type
1551 const ELicenceType eLicenceType = static_cast<ELicenceType> ( GetValFromStream ( vecData, iPos, 1 ) );
1552
1553 if ( ( eLicenceType != LT_CREATIVECOMMONS ) && ( eLicenceType != LT_NO_LICENCE ) )
1554 {
1555 return true; // return error code
1556 }
1557
1558 // invoke message action
1559 emit LicenceRequired ( eLicenceType );
1560
1561 return false; // no error
1562 }
1563
CreateOpusSupportedMes()1564 void CProtocol::CreateOpusSupportedMes() { CreateAndSendMessage ( PROTMESSID_OPUS_SUPPORTED, CVector<uint8_t> ( 0 ) ); }
1565
1566 // TODO needed for compatibility to old servers >= 3.4.6 and <= 3.5.12
CreateReqChannelLevelListMes()1567 void CProtocol::CreateReqChannelLevelListMes()
1568 {
1569 CVector<uint8_t> vecData ( 1 ); // 1 byte of data
1570 int iPos = 0; // init position pointer
1571
1572 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( true ), 1 );
1573
1574 CreateAndSendMessage ( PROTMESSID_REQ_CHANNEL_LEVEL_LIST, vecData );
1575 }
1576
CreateVersionAndOSMes()1577 void CProtocol::CreateVersionAndOSMes()
1578 {
1579 int iPos = 0; // init position pointer
1580
1581 // get the version number string
1582 const QString strVerion = VERSION;
1583
1584 // convert version string to utf-8
1585 const QByteArray strUTF8Version = strVerion.toUtf8();
1586
1587 // size of current message body
1588 const int iEntrLen = 1 + // operating system
1589 2 + strUTF8Version.size(); // version utf-8 str. size / string
1590
1591 // build data vector
1592 CVector<uint8_t> vecData ( iEntrLen );
1593
1594 // operating system (1 byte)
1595 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( COSUtil::GetOperatingSystem() ), 1 );
1596
1597 // version
1598 PutStringUTF8OnStream ( vecData, iPos, strUTF8Version );
1599
1600 CreateAndSendMessage ( PROTMESSID_VERSION_AND_OS, vecData );
1601 }
1602
EvaluateVersionAndOSMes(const CVector<uint8_t> & vecData)1603 bool CProtocol::EvaluateVersionAndOSMes ( const CVector<uint8_t>& vecData )
1604 {
1605 int iPos = 0; // init position pointer
1606 const int iDataLen = vecData.Size();
1607
1608 // check size (the first 1 byte)
1609 if ( iDataLen < 1 )
1610 {
1611 return true; // return error code
1612 }
1613
1614 // operating system (1 byte)
1615 const COSUtil::EOpSystemType eOSType = static_cast<COSUtil::EOpSystemType> ( GetValFromStream ( vecData, iPos, 1 ) );
1616
1617 // version text
1618 QString strVersion;
1619 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_VERSION_TEXT, strVersion ) )
1620 {
1621 return true; // return error code
1622 }
1623
1624 // check size: all data is read, the position must now be at the end
1625 if ( iPos != iDataLen )
1626 {
1627 return true; // return error code
1628 }
1629
1630 // invoke message action
1631 emit VersionAndOSReceived ( eOSType, strVersion );
1632
1633 return false; // no error
1634 }
1635
CreateRecorderStateMes(const ERecorderState eRecorderState)1636 void CProtocol::CreateRecorderStateMes ( const ERecorderState eRecorderState )
1637 {
1638 CVector<uint8_t> vecData ( 1 ); // 1 byte of data
1639 int iPos = 0; // init position pointer
1640
1641 // build data vector
1642 // server jam recorder state (1 byte)
1643 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( eRecorderState ), 1 );
1644
1645 CreateAndSendMessage ( PROTMESSID_RECORDER_STATE, vecData );
1646 }
1647
EvaluateRecorderStateMes(const CVector<uint8_t> & vecData)1648 bool CProtocol::EvaluateRecorderStateMes ( const CVector<uint8_t>& vecData )
1649 {
1650 int iPos = 0; // init position pointer
1651
1652 // check size
1653 if ( vecData.Size() != 1 )
1654 {
1655 return true; // return error code
1656 }
1657
1658 // server jam recorder state (1 byte)
1659 const int iRecorderState = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
1660
1661 // note that RS_UNDEFINED is only internally used
1662 if ( ( iRecorderState != RS_NOT_INITIALISED ) && ( iRecorderState != RS_NOT_ENABLED ) && ( iRecorderState != RS_RECORDING ) )
1663 {
1664 return true;
1665 }
1666
1667 // invoke message action
1668 emit RecorderStateReceived ( static_cast<ERecorderState> ( iRecorderState ) );
1669
1670 return false; // no error
1671 }
1672
1673 // Connection less messages ----------------------------------------------------
CreateCLPingMes(const CHostAddress & InetAddr,const int iMs)1674 void CProtocol::CreateCLPingMes ( const CHostAddress& InetAddr, const int iMs )
1675 {
1676 int iPos = 0; // init position pointer
1677
1678 // build data vector (4 bytes long)
1679 CVector<uint8_t> vecData ( 4 );
1680
1681 // transmit time (4 bytes)
1682 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iMs ), 4 );
1683
1684 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_PING_MS, vecData, InetAddr );
1685 }
1686
EvaluateCLPingMes(const CHostAddress & InetAddr,const CVector<uint8_t> & vecData)1687 bool CProtocol::EvaluateCLPingMes ( const CHostAddress& InetAddr, const CVector<uint8_t>& vecData )
1688 {
1689 int iPos = 0; // init position pointer
1690
1691 // check size
1692 if ( vecData.Size() != 4 )
1693 {
1694 return true; // return error code
1695 }
1696
1697 // invoke message action
1698 emit CLPingReceived ( InetAddr, static_cast<int> ( GetValFromStream ( vecData, iPos, 4 ) ) );
1699
1700 return false; // no error
1701 }
1702
CreateCLPingWithNumClientsMes(const CHostAddress & InetAddr,const int iMs,const int iNumClients)1703 void CProtocol::CreateCLPingWithNumClientsMes ( const CHostAddress& InetAddr, const int iMs, const int iNumClients )
1704 {
1705 int iPos = 0; // init position pointer
1706
1707 // build data vector (5 bytes long)
1708 CVector<uint8_t> vecData ( 5 );
1709
1710 // transmit time (4 bytes)
1711 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iMs ), 4 );
1712
1713 // current number of connected clients (1 byte)
1714 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iNumClients ), 1 );
1715
1716 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_PING_MS_WITHNUMCLIENTS, vecData, InetAddr );
1717 }
1718
EvaluateCLPingWithNumClientsMes(const CHostAddress & InetAddr,const CVector<uint8_t> & vecData)1719 bool CProtocol::EvaluateCLPingWithNumClientsMes ( const CHostAddress& InetAddr, const CVector<uint8_t>& vecData )
1720 {
1721 int iPos = 0; // init position pointer
1722
1723 // check size
1724 if ( vecData.Size() != 5 )
1725 {
1726 return true; // return error code
1727 }
1728
1729 // transmit time
1730 const int iCurMs = static_cast<int> ( GetValFromStream ( vecData, iPos, 4 ) );
1731
1732 // current number of connected clients
1733 const int iCurNumClients = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
1734
1735 // invoke message action
1736 emit CLPingWithNumClientsReceived ( InetAddr, iCurMs, iCurNumClients );
1737
1738 return false; // no error
1739 }
1740
CreateCLServerFullMes(const CHostAddress & InetAddr)1741 void CProtocol::CreateCLServerFullMes ( const CHostAddress& InetAddr )
1742 {
1743 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_SERVER_FULL, CVector<uint8_t> ( 0 ), InetAddr );
1744 }
1745
EvaluateCLServerFullMes()1746 bool CProtocol::EvaluateCLServerFullMes()
1747 {
1748 // invoke message action
1749 emit ServerFullMesReceived();
1750
1751 return false; // no error
1752 }
1753
CreateCLRegisterServerMes(const CHostAddress & InetAddr,const CHostAddress & LInetAddr,const CServerCoreInfo & ServerInfo)1754 void CProtocol::CreateCLRegisterServerMes ( const CHostAddress& InetAddr, const CHostAddress& LInetAddr, const CServerCoreInfo& ServerInfo )
1755 {
1756 int iPos = 0; // init position pointer
1757
1758 // convert server info strings to utf-8
1759 const QByteArray strUTF8LInetAddr = LInetAddr.InetAddr.toString().toUtf8();
1760 const QByteArray strUTF8Name = ServerInfo.strName.toUtf8();
1761 const QByteArray strUTF8City = ServerInfo.strCity.toUtf8();
1762
1763 // size of current message body
1764 const int iEntrLen = 2 + // server internal port number
1765 2 + // country
1766 1 + // maximum number of connected clients
1767 1 + // is permanent flag
1768 2 + strUTF8Name.size() + // name utf-8 str. size / str.
1769 2 + strUTF8LInetAddr.size() + // server internal address utf-8 str. size / str.
1770 2 + strUTF8City.size(); // city utf-8 str. size / str.
1771
1772 // build data vector
1773 CVector<uint8_t> vecData ( iEntrLen );
1774
1775 // port number (2 bytes)
1776 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( LInetAddr.iPort ), 2 );
1777
1778 // country (2 bytes)
1779 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( ServerInfo.eCountry ), 2 );
1780
1781 // maximum number of connected clients (1 byte)
1782 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( ServerInfo.iMaxNumClients ), 1 );
1783
1784 // "is permanent" flag (1 byte)
1785 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( ServerInfo.bPermanentOnline ), 1 );
1786
1787 // name
1788 PutStringUTF8OnStream ( vecData, iPos, strUTF8Name );
1789
1790 // server internal address (formerly unused topic)
1791 PutStringUTF8OnStream ( vecData, iPos, strUTF8LInetAddr );
1792
1793 // city
1794 PutStringUTF8OnStream ( vecData, iPos, strUTF8City );
1795
1796 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_REGISTER_SERVER, vecData, InetAddr );
1797 }
1798
EvaluateCLRegisterServerMes(const CHostAddress & InetAddr,const CVector<uint8_t> & vecData)1799 bool CProtocol::EvaluateCLRegisterServerMes ( const CHostAddress& InetAddr, const CVector<uint8_t>& vecData )
1800 {
1801 int iPos = 0; // init position pointer
1802 const int iDataLen = vecData.Size();
1803 QString sLocHost; // temp string for server internal address
1804 CHostAddress LInetAddr;
1805 CServerCoreInfo RecServerInfo;
1806
1807 // check size (the first 6 bytes)
1808 if ( iDataLen < 6 )
1809 {
1810 return true; // return error code
1811 }
1812
1813 // port number (2 bytes)
1814 LInetAddr.iPort = static_cast<quint16> ( GetValFromStream ( vecData, iPos, 2 ) );
1815
1816 // country (2 bytes)
1817 RecServerInfo.eCountry = static_cast<QLocale::Country> ( GetValFromStream ( vecData, iPos, 2 ) );
1818
1819 // maximum number of connected clients (1 byte)
1820 RecServerInfo.iMaxNumClients = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
1821
1822 // "is permanent" flag (1 byte)
1823 RecServerInfo.bPermanentOnline = static_cast<bool> ( GetValFromStream ( vecData, iPos, 1 ) );
1824
1825 // server name
1826 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_SERVER_NAME, RecServerInfo.strName ) )
1827 {
1828 return true; // return error code
1829 }
1830
1831 // server internal address
1832 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_IP_ADDRESS, sLocHost ) )
1833 {
1834 return true; // return error code
1835 }
1836
1837 if ( sLocHost.isEmpty() )
1838 {
1839 // old server, empty "topic", register as local host
1840 LInetAddr.InetAddr.setAddress ( QHostAddress::LocalHost );
1841 }
1842 else if ( !LInetAddr.InetAddr.setAddress ( sLocHost ) )
1843 {
1844 return true; // return error code
1845 }
1846
1847 // server city
1848 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_SERVER_CITY, RecServerInfo.strCity ) )
1849 {
1850 return true; // return error code
1851 }
1852
1853 // check size: all data is read, the position must now be at the end
1854 if ( iPos != iDataLen )
1855 {
1856 return true; // return error code
1857 }
1858
1859 // invoke message action
1860 emit CLRegisterServerReceived ( InetAddr, LInetAddr, RecServerInfo );
1861
1862 return false; // no error
1863 }
1864
CreateCLRegisterServerExMes(const CHostAddress & InetAddr,const CHostAddress & LInetAddr,const CServerCoreInfo & ServerInfo)1865 void CProtocol::CreateCLRegisterServerExMes ( const CHostAddress& InetAddr, const CHostAddress& LInetAddr, const CServerCoreInfo& ServerInfo )
1866 {
1867 int iPos = 0; // init position pointer
1868
1869 // convert server info strings to utf-8
1870 const QByteArray strUTF8LInetAddr = LInetAddr.InetAddr.toString().toUtf8();
1871 const QByteArray strUTF8Name = ServerInfo.strName.toUtf8();
1872 const QByteArray strUTF8City = ServerInfo.strCity.toUtf8();
1873 const QByteArray strUTF8Version = QString ( VERSION ).toUtf8();
1874
1875 // size of current message body
1876 const int iEntrLen = 2 + // server internal port number
1877 2 + // country
1878 1 + // maximum number of connected clients
1879 1 + // is permanent flag
1880 2 + strUTF8Name.size() + // name utf-8 str. size / str.
1881 2 + strUTF8LInetAddr.size() + // server internal address utf-8 str. size / str.
1882 2 + strUTF8City.size() + // city utf-8 str. size / str.
1883 1 + // operating system
1884 2 + strUTF8Version.size(); // version utf-8 str. size / str.
1885
1886 // build data vector
1887 CVector<uint8_t> vecData ( iEntrLen );
1888
1889 // port number (2 bytes)
1890 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( LInetAddr.iPort ), 2 );
1891
1892 // country (2 bytes)
1893 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( ServerInfo.eCountry ), 2 );
1894
1895 // maximum number of connected clients (1 byte)
1896 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( ServerInfo.iMaxNumClients ), 1 );
1897
1898 // "is permanent" flag (1 byte)
1899 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( ServerInfo.bPermanentOnline ), 1 );
1900
1901 // name
1902 PutStringUTF8OnStream ( vecData, iPos, strUTF8Name );
1903
1904 // server internal address (formerly unused topic)
1905 PutStringUTF8OnStream ( vecData, iPos, strUTF8LInetAddr );
1906
1907 // city
1908 PutStringUTF8OnStream ( vecData, iPos, strUTF8City );
1909
1910 // operating system (1 byte)
1911 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( COSUtil::GetOperatingSystem() ), 1 );
1912
1913 // version
1914 PutStringUTF8OnStream ( vecData, iPos, strUTF8Version );
1915
1916 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_REGISTER_SERVER_EX, vecData, InetAddr );
1917 }
1918
EvaluateCLRegisterServerExMes(const CHostAddress & InetAddr,const CVector<uint8_t> & vecData)1919 bool CProtocol::EvaluateCLRegisterServerExMes ( const CHostAddress& InetAddr, const CVector<uint8_t>& vecData )
1920 {
1921 int iPos = 0; // init position pointer
1922 const int iDataLen = vecData.Size();
1923 QString sLocHost; // temp string for server internal address
1924 CHostAddress LInetAddr;
1925 CServerCoreInfo RecServerInfo;
1926
1927 // check size (the first 6 bytes)
1928 if ( iDataLen < 6 )
1929 {
1930 return true; // return error code
1931 }
1932
1933 // port number (2 bytes)
1934 LInetAddr.iPort = static_cast<quint16> ( GetValFromStream ( vecData, iPos, 2 ) );
1935
1936 // country (2 bytes)
1937 RecServerInfo.eCountry = static_cast<QLocale::Country> ( GetValFromStream ( vecData, iPos, 2 ) );
1938
1939 // maximum number of connected clients (1 byte)
1940 RecServerInfo.iMaxNumClients = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
1941
1942 // "is permanent" flag (1 byte)
1943 RecServerInfo.bPermanentOnline = static_cast<bool> ( GetValFromStream ( vecData, iPos, 1 ) );
1944
1945 // server name
1946 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_SERVER_NAME, RecServerInfo.strName ) )
1947 {
1948 return true; // return error code
1949 }
1950
1951 // server internal address
1952 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_IP_ADDRESS, sLocHost ) )
1953 {
1954 return true; // return error code
1955 }
1956
1957 if ( sLocHost.isEmpty() )
1958 {
1959 // old server, empty "topic", register as local host
1960 LInetAddr.InetAddr.setAddress ( QHostAddress::LocalHost );
1961 }
1962 else if ( !LInetAddr.InetAddr.setAddress ( sLocHost ) )
1963 {
1964 return true; // return error code
1965 }
1966
1967 // server city
1968 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_SERVER_CITY, RecServerInfo.strCity ) )
1969 {
1970 return true; // return error code
1971 }
1972
1973 // check size (the next 1 byte)
1974 if ( iDataLen < iPos + 1 )
1975 {
1976 return true; // return error code
1977 }
1978
1979 // operating system (1 byte)
1980 const COSUtil::EOpSystemType eOSType = static_cast<COSUtil::EOpSystemType> ( GetValFromStream ( vecData, iPos, 1 ) );
1981
1982 // version text
1983 QString strVersion;
1984 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_VERSION_TEXT, strVersion ) )
1985 {
1986 return true; // return error code
1987 }
1988
1989 // check size: all data is read, the position must now be at the end
1990 if ( iPos != iDataLen )
1991 {
1992 return true; // return error code
1993 }
1994
1995 // invoke message action
1996 emit CLRegisterServerExReceived ( InetAddr, LInetAddr, RecServerInfo, eOSType, strVersion );
1997
1998 return false; // no error
1999 }
2000
CreateCLUnregisterServerMes(const CHostAddress & InetAddr)2001 void CProtocol::CreateCLUnregisterServerMes ( const CHostAddress& InetAddr )
2002 {
2003 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_UNREGISTER_SERVER, CVector<uint8_t> ( 0 ), InetAddr );
2004 }
2005
EvaluateCLUnregisterServerMes(const CHostAddress & InetAddr)2006 bool CProtocol::EvaluateCLUnregisterServerMes ( const CHostAddress& InetAddr )
2007 {
2008 // invoke message action
2009 emit CLUnregisterServerReceived ( InetAddr );
2010
2011 return false; // no error
2012 }
2013
CreateCLServerListMes(const CHostAddress & InetAddr,const CVector<CServerInfo> vecServerInfo)2014 void CProtocol::CreateCLServerListMes ( const CHostAddress& InetAddr, const CVector<CServerInfo> vecServerInfo )
2015 {
2016 const int iNumServers = vecServerInfo.Size();
2017
2018 // build data vector
2019 CVector<uint8_t> vecData ( 0 );
2020 int iPos = 0; // init position pointer
2021
2022 for ( int i = 0; i < iNumServers; i++ )
2023 {
2024 // convert server list strings to utf-8
2025 const QByteArray strUTF8Name = vecServerInfo[i].strName.toUtf8();
2026 const QByteArray strUTF8Empty = QString ( "" ).toUtf8();
2027 const QByteArray strUTF8City = vecServerInfo[i].strCity.toUtf8();
2028
2029 // size of current list entry
2030 const int iCurListEntrLen = 4 + // IP address
2031 2 + // port number
2032 2 + // country
2033 1 + // maximum number of connected clients
2034 1 + // is permanent flag
2035 2 + strUTF8Name.size() + // name utf-8 str. size / str.
2036 2 + // empty string
2037 2 + strUTF8City.size(); // city utf-8 str. size / str.
2038
2039 // make space for new data
2040 vecData.Enlarge ( iCurListEntrLen );
2041
2042 // IP address (4 bytes)
2043 // note the Server List manager has put the internal details in HostAddr where required
2044 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].HostAddr.InetAddr.toIPv4Address() ), 4 );
2045
2046 // port number (2 bytes)
2047 // note the Server List manager has put the internal details in HostAddr where required
2048 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].HostAddr.iPort ), 2 );
2049
2050 // country (2 bytes)
2051 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].eCountry ), 2 );
2052
2053 // maximum number of connected clients (1 byte)
2054 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].iMaxNumClients ), 1 );
2055
2056 // "is permanent" flag (1 byte)
2057 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].bPermanentOnline ), 1 );
2058
2059 // name
2060 PutStringUTF8OnStream ( vecData, iPos, strUTF8Name );
2061
2062 // empty string
2063 PutStringUTF8OnStream ( vecData, iPos, strUTF8Empty );
2064
2065 // city
2066 PutStringUTF8OnStream ( vecData, iPos, strUTF8City );
2067 }
2068
2069 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_SERVER_LIST, vecData, InetAddr );
2070 }
2071
EvaluateCLServerListMes(const CHostAddress & InetAddr,const CVector<uint8_t> & vecData)2072 bool CProtocol::EvaluateCLServerListMes ( const CHostAddress& InetAddr, const CVector<uint8_t>& vecData )
2073 {
2074 int iPos = 0; // init position pointer
2075 const int iDataLen = vecData.Size();
2076 CVector<CServerInfo> vecServerInfo ( 0 );
2077
2078 while ( iPos < iDataLen )
2079 {
2080 // check size (the next 10 bytes)
2081 if ( ( iDataLen - iPos ) < 10 )
2082 {
2083 return true; // return error code
2084 }
2085
2086 // IP address (4 bytes)
2087 const quint32 iIpAddr = static_cast<quint32> ( GetValFromStream ( vecData, iPos, 4 ) );
2088
2089 // port number (2 bytes)
2090 const quint16 iPort = static_cast<quint16> ( GetValFromStream ( vecData, iPos, 2 ) );
2091
2092 // country (2 bytes)
2093 const QLocale::Country eCountry = static_cast<QLocale::Country> ( GetValFromStream ( vecData, iPos, 2 ) );
2094
2095 // maximum number of connected clients (1 byte)
2096 const int iMaxNumClients = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
2097
2098 // "is permanent" flag (1 byte)
2099 const bool bPermanentOnline = static_cast<bool> ( GetValFromStream ( vecData, iPos, 1 ) );
2100
2101 // server name
2102 QString strName;
2103 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_SERVER_NAME, strName ) )
2104 {
2105 return true; // return error code
2106 }
2107
2108 // empty
2109 QString strEmpty;
2110 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_IP_ADDRESS, strEmpty ) )
2111 {
2112 return true; // return error code
2113 }
2114
2115 // server city
2116 QString strCity;
2117 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_SERVER_CITY, strCity ) )
2118 {
2119 return true; // return error code
2120 }
2121
2122 // add server information to vector
2123 vecServerInfo.Add ( CServerInfo ( CHostAddress ( QHostAddress ( iIpAddr ), iPort ),
2124 CHostAddress ( QHostAddress ( iIpAddr ), iPort ),
2125 strName,
2126 eCountry,
2127 strCity,
2128 iMaxNumClients,
2129 bPermanentOnline ) );
2130 }
2131
2132 // check size: all data is read, the position must now be at the end
2133 if ( iPos != iDataLen )
2134 {
2135 return true; // return error code
2136 }
2137
2138 // invoke message action
2139 emit CLServerListReceived ( InetAddr, vecServerInfo );
2140
2141 return false; // no error
2142 }
2143
CreateCLRedServerListMes(const CHostAddress & InetAddr,const CVector<CServerInfo> vecServerInfo)2144 void CProtocol::CreateCLRedServerListMes ( const CHostAddress& InetAddr, const CVector<CServerInfo> vecServerInfo )
2145 {
2146 const int iNumServers = vecServerInfo.Size();
2147
2148 // build data vector
2149 CVector<uint8_t> vecData ( 0 );
2150 int iPos = 0; // init position pointer
2151
2152 for ( int i = 0; i < iNumServers; i++ )
2153 {
2154 // convert server list strings to utf-8
2155 const QByteArray strUTF8Name = vecServerInfo[i].strName.toUtf8();
2156
2157 // size of current list entry
2158 const int iCurListEntrLen = 4 + // IP address
2159 2 + // port number
2160 1 + strUTF8Name.size(); // name utf-8 str. size / str.
2161
2162 // make space for new data
2163 vecData.Enlarge ( iCurListEntrLen );
2164
2165 // IP address (4 bytes)
2166 // note the Server List manager has put the internal details in HostAddr where required
2167 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].HostAddr.InetAddr.toIPv4Address() ), 4 );
2168
2169 // port number (2 bytes)
2170 // note the Server List manager has put the internal details in HostAddr where required
2171 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecServerInfo[i].HostAddr.iPort ), 2 );
2172
2173 // name (note that the string length indicator is 1 in this special case)
2174 PutStringUTF8OnStream ( vecData, iPos, strUTF8Name, 1 );
2175 }
2176
2177 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_RED_SERVER_LIST, vecData, InetAddr );
2178 }
2179
EvaluateCLRedServerListMes(const CHostAddress & InetAddr,const CVector<uint8_t> & vecData)2180 bool CProtocol::EvaluateCLRedServerListMes ( const CHostAddress& InetAddr, const CVector<uint8_t>& vecData )
2181 {
2182 int iPos = 0; // init position pointer
2183 const int iDataLen = vecData.Size();
2184 CVector<CServerInfo> vecServerInfo ( 0 );
2185
2186 while ( iPos < iDataLen )
2187 {
2188 // check size (the next 6 bytes)
2189 if ( ( iDataLen - iPos ) < 6 )
2190 {
2191 return true; // return error code
2192 }
2193
2194 // IP address (4 bytes)
2195 const quint32 iIpAddr = static_cast<quint32> ( GetValFromStream ( vecData, iPos, 4 ) );
2196
2197 // port number (2 bytes)
2198 const quint16 iPort = static_cast<quint16> ( GetValFromStream ( vecData, iPos, 2 ) );
2199
2200 // server name (note that the string length indicator is 1 in this special case)
2201 QString strName;
2202 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_SERVER_NAME, strName, 1 ) )
2203 {
2204 return true; // return error code
2205 }
2206
2207 // add server information to vector
2208 vecServerInfo.Add ( CServerInfo ( CHostAddress ( QHostAddress ( iIpAddr ), iPort ),
2209 CHostAddress ( QHostAddress ( iIpAddr ), iPort ),
2210 strName,
2211 QLocale::AnyCountry, // set to any country since the information is not transmitted
2212 "", // empty city name since the information is not transmitted
2213 0, // per definition: if max. num. client is zero, we ignore the value in the server list
2214 false ) ); // assume not permanent since the information is not transmitted
2215 }
2216
2217 // check size: all data is read, the position must now be at the end
2218 if ( iPos != iDataLen )
2219 {
2220 return true; // return error code
2221 }
2222
2223 // invoke message action
2224 emit CLRedServerListReceived ( InetAddr, vecServerInfo );
2225
2226 return false; // no error
2227 }
2228
CreateCLReqServerListMes(const CHostAddress & InetAddr)2229 void CProtocol::CreateCLReqServerListMes ( const CHostAddress& InetAddr )
2230 {
2231 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_REQ_SERVER_LIST, CVector<uint8_t> ( 0 ), InetAddr );
2232 }
2233
EvaluateCLReqServerListMes(const CHostAddress & InetAddr)2234 bool CProtocol::EvaluateCLReqServerListMes ( const CHostAddress& InetAddr )
2235 {
2236 // invoke message action
2237 emit CLReqServerList ( InetAddr );
2238
2239 return false; // no error
2240 }
2241
CreateCLSendEmptyMesMes(const CHostAddress & InetAddr,const CHostAddress & TargetInetAddr)2242 void CProtocol::CreateCLSendEmptyMesMes ( const CHostAddress& InetAddr, const CHostAddress& TargetInetAddr )
2243 {
2244 int iPos = 0; // init position pointer
2245
2246 // build data vector (6 bytes long)
2247 CVector<uint8_t> vecData ( 6 );
2248
2249 // IP address (4 bytes)
2250 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( TargetInetAddr.InetAddr.toIPv4Address() ), 4 );
2251
2252 // port number (2 bytes)
2253 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( TargetInetAddr.iPort ), 2 );
2254
2255 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_SEND_EMPTY_MESSAGE, vecData, InetAddr );
2256 }
2257
EvaluateCLSendEmptyMesMes(const CVector<uint8_t> & vecData)2258 bool CProtocol::EvaluateCLSendEmptyMesMes ( const CVector<uint8_t>& vecData )
2259 {
2260 int iPos = 0; // init position pointer
2261
2262 // check size
2263 if ( vecData.Size() != 6 )
2264 {
2265 return true; // return error code
2266 }
2267
2268 // IP address (4 bytes)
2269 const quint32 iIpAddr = static_cast<int> ( GetValFromStream ( vecData, iPos, 4 ) );
2270
2271 // port number (2 bytes)
2272 const quint16 iPort = static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
2273
2274 // invoke message action
2275 emit CLSendEmptyMes ( CHostAddress ( QHostAddress ( iIpAddr ), iPort ) );
2276
2277 return false; // no error
2278 }
2279
CreateCLEmptyMes(const CHostAddress & InetAddr)2280 void CProtocol::CreateCLEmptyMes ( const CHostAddress& InetAddr )
2281 {
2282 // special message: for this message there exist no Evaluate
2283 // function
2284 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_EMPTY_MESSAGE, CVector<uint8_t> ( 0 ), InetAddr );
2285 }
2286
CreateCLDisconnection(const CHostAddress & InetAddr)2287 void CProtocol::CreateCLDisconnection ( const CHostAddress& InetAddr )
2288 {
2289 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_DISCONNECTION, CVector<uint8_t> ( 0 ), InetAddr );
2290 }
2291
EvaluateCLDisconnectionMes(const CHostAddress & InetAddr)2292 bool CProtocol::EvaluateCLDisconnectionMes ( const CHostAddress& InetAddr )
2293 {
2294 // invoke message action
2295 emit CLDisconnection ( InetAddr );
2296
2297 return false; // no error
2298 }
2299
CreateCLVersionAndOSMes(const CHostAddress & InetAddr)2300 void CProtocol::CreateCLVersionAndOSMes ( const CHostAddress& InetAddr )
2301 {
2302 int iPos = 0; // init position pointer
2303
2304 // get the version number string
2305 const QString strVerion = VERSION;
2306
2307 // convert version string to utf-8
2308 const QByteArray strUTF8Version = strVerion.toUtf8();
2309
2310 // size of current message body
2311 const int iEntrLen = 1 + // operating system
2312 2 + strUTF8Version.size(); // version utf-8 str. size / str.
2313
2314 // build data vector
2315 CVector<uint8_t> vecData ( iEntrLen );
2316
2317 // operating system (1 byte)
2318 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( COSUtil::GetOperatingSystem() ), 1 );
2319
2320 // version
2321 PutStringUTF8OnStream ( vecData, iPos, strUTF8Version );
2322
2323 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_VERSION_AND_OS, vecData, InetAddr );
2324 }
2325
EvaluateCLVersionAndOSMes(const CHostAddress & InetAddr,const CVector<uint8_t> & vecData)2326 bool CProtocol::EvaluateCLVersionAndOSMes ( const CHostAddress& InetAddr, const CVector<uint8_t>& vecData )
2327 {
2328 int iPos = 0; // init position pointer
2329 const int iDataLen = vecData.Size();
2330
2331 // check size (the first 1 byte)
2332 if ( iDataLen < 1 )
2333 {
2334 return true; // return error code
2335 }
2336
2337 // operating system (1 byte)
2338 const COSUtil::EOpSystemType eOSType = static_cast<COSUtil::EOpSystemType> ( GetValFromStream ( vecData, iPos, 1 ) );
2339
2340 // version text
2341 QString strVersion;
2342 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_VERSION_TEXT, strVersion ) )
2343 {
2344 return true; // return error code
2345 }
2346
2347 // check size: all data is read, the position must now be at the end
2348 if ( iPos != iDataLen )
2349 {
2350 return true; // return error code
2351 }
2352
2353 // invoke message action
2354 emit CLVersionAndOSReceived ( InetAddr, eOSType, strVersion );
2355
2356 return false; // no error
2357 }
2358
CreateCLReqVersionAndOSMes(const CHostAddress & InetAddr)2359 void CProtocol::CreateCLReqVersionAndOSMes ( const CHostAddress& InetAddr )
2360 {
2361 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_REQ_VERSION_AND_OS, CVector<uint8_t> ( 0 ), InetAddr );
2362 }
2363
EvaluateCLReqVersionAndOSMes(const CHostAddress & InetAddr)2364 bool CProtocol::EvaluateCLReqVersionAndOSMes ( const CHostAddress& InetAddr )
2365 {
2366 // invoke message action
2367 emit CLReqVersionAndOS ( InetAddr );
2368
2369 return false; // no error
2370 }
2371
CreateCLConnClientsListMes(const CHostAddress & InetAddr,const CVector<CChannelInfo> & vecChanInfo)2372 void CProtocol::CreateCLConnClientsListMes ( const CHostAddress& InetAddr, const CVector<CChannelInfo>& vecChanInfo )
2373 {
2374 const int iNumClients = vecChanInfo.Size();
2375
2376 // build data vector
2377 CVector<uint8_t> vecData ( 0 );
2378 int iPos = 0; // init position pointer
2379
2380 for ( int i = 0; i < iNumClients; i++ )
2381 {
2382 // convert strings to utf-8
2383 const QByteArray strUTF8Name = vecChanInfo[i].strName.toUtf8();
2384 const QByteArray strUTF8City = vecChanInfo[i].strCity.toUtf8();
2385
2386 // size of current list entry
2387 const int iCurListEntrLen = 1 + // chan ID
2388 2 + // country
2389 4 + // instrument
2390 1 + // skill level
2391 4 + // IP address
2392 2 + strUTF8Name.size() + // utf-8 str. size / str.
2393 2 + strUTF8City.size(); // utf-8 str. size / str.
2394
2395 // make space for new data
2396 vecData.Enlarge ( iCurListEntrLen );
2397
2398 // channel ID (1 byte)
2399 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecChanInfo[i].iChanID ), 1 );
2400
2401 // country (2 bytes)
2402 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecChanInfo[i].eCountry ), 2 );
2403
2404 // instrument (4 bytes)
2405 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecChanInfo[i].iInstrument ), 4 );
2406
2407 // skill level (1 byte)
2408 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( vecChanInfo[i].eSkillLevel ), 1 );
2409
2410 // used to be IP address before #316 (4 bytes)
2411 PutValOnStream ( vecData, iPos, 0, 4 );
2412
2413 // name
2414 PutStringUTF8OnStream ( vecData, iPos, strUTF8Name );
2415
2416 // city
2417 PutStringUTF8OnStream ( vecData, iPos, strUTF8City );
2418 }
2419
2420 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_CONN_CLIENTS_LIST, vecData, InetAddr );
2421 }
2422
EvaluateCLConnClientsListMes(const CHostAddress & InetAddr,const CVector<uint8_t> & vecData)2423 bool CProtocol::EvaluateCLConnClientsListMes ( const CHostAddress& InetAddr, const CVector<uint8_t>& vecData )
2424 {
2425 int iPos = 0; // init position pointer
2426 const int iDataLen = vecData.Size();
2427 CVector<CChannelInfo> vecChanInfo ( 0 );
2428
2429 while ( iPos < iDataLen )
2430 {
2431 // check size (the next 12 bytes)
2432 if ( ( iDataLen - iPos ) < 12 )
2433 {
2434 return true; // return error code
2435 }
2436
2437 // channel ID (1 byte)
2438 const int iChanID = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
2439
2440 // country (2 bytes)
2441 const QLocale::Country eCountry = static_cast<QLocale::Country> ( GetValFromStream ( vecData, iPos, 2 ) );
2442
2443 // instrument (4 bytes)
2444 const int iInstrument = static_cast<int> ( GetValFromStream ( vecData, iPos, 4 ) );
2445
2446 // skill level (1 byte)
2447 const ESkillLevel eSkillLevel = static_cast<ESkillLevel> ( GetValFromStream ( vecData, iPos, 1 ) );
2448
2449 // used to be IP address, zero since #316 (4 bytes)
2450 iPos += 4;
2451
2452 // name
2453 QString strCurName;
2454 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_FADER_TAG, strCurName ) )
2455 {
2456 return true; // return error code
2457 }
2458
2459 // city
2460 QString strCurCity;
2461 if ( GetStringFromStream ( vecData, iPos, MAX_LEN_SERVER_CITY, strCurCity ) )
2462 {
2463 return true; // return error code
2464 }
2465
2466 // add channel information to vector
2467 vecChanInfo.Add ( CChannelInfo ( iChanID, strCurName, eCountry, strCurCity, iInstrument, eSkillLevel ) );
2468 }
2469
2470 // check size: all data is read, the position must now be at the end
2471 if ( iPos != iDataLen )
2472 {
2473 return true; // return error code
2474 }
2475
2476 // invoke message action
2477 emit CLConnClientsListMesReceived ( InetAddr, vecChanInfo );
2478
2479 return false; // no error
2480 }
2481
CreateCLReqConnClientsListMes(const CHostAddress & InetAddr)2482 void CProtocol::CreateCLReqConnClientsListMes ( const CHostAddress& InetAddr )
2483 {
2484 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_REQ_CONN_CLIENTS_LIST, CVector<uint8_t> ( 0 ), InetAddr );
2485 }
2486
EvaluateCLReqConnClientsListMes(const CHostAddress & InetAddr)2487 bool CProtocol::EvaluateCLReqConnClientsListMes ( const CHostAddress& InetAddr )
2488 {
2489 // invoke message action
2490 emit CLReqConnClientsList ( InetAddr );
2491
2492 return false; // no error
2493 }
2494
CreateCLChannelLevelListMes(const CHostAddress & InetAddr,const CVector<uint16_t> & vecLevelList,const int iNumClients)2495 void CProtocol::CreateCLChannelLevelListMes ( const CHostAddress& InetAddr, const CVector<uint16_t>& vecLevelList, const int iNumClients )
2496 {
2497 // This must be a multiple of bytes at four bits per client
2498 const int iNumBytes = ( iNumClients + 1 ) / 2;
2499 CVector<uint8_t> vecData ( iNumBytes );
2500 int iPos = 0; // init position pointer
2501
2502 for ( int i = 0, j = 0; i < iNumClients; i += 2 /* pack two per byte */, j++ )
2503 {
2504 uint16_t levelLo = vecLevelList[i] & 0x0F;
2505 uint16_t levelHi = ( i + 1 < iNumClients ) ? vecLevelList[i + 1] & 0x0F : 0x0F;
2506 uint8_t byte = static_cast<uint8_t> ( levelLo | ( levelHi << 4 ) );
2507
2508 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( byte ), 1 );
2509 }
2510
2511 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_CHANNEL_LEVEL_LIST, vecData, InetAddr );
2512 }
2513
EvaluateCLChannelLevelListMes(const CHostAddress & InetAddr,const CVector<uint8_t> & vecData)2514 bool CProtocol::EvaluateCLChannelLevelListMes ( const CHostAddress& InetAddr, const CVector<uint8_t>& vecData )
2515 {
2516 int iPos = 0; // init position pointer
2517 const int iDataLen = vecData.Size(); // four bits per channel, 2 channels per byte
2518 // may have one too many entries, last being 0xF
2519 int iVecLen = iDataLen * 2; // one ushort per channel
2520
2521 if ( iVecLen > MAX_NUM_CHANNELS )
2522 {
2523 return true; // return error code
2524 }
2525
2526 CVector<uint16_t> vecLevelList ( iVecLen );
2527
2528 for ( int i = 0, j = 0; i < iDataLen; i++, j += 2 )
2529 {
2530 uint8_t byte = static_cast<uint8_t> ( GetValFromStream ( vecData, iPos, 1 ) );
2531 uint16_t levelLo = byte & 0x0F;
2532 uint16_t levelHi = ( byte >> 4 ) & 0x0F;
2533
2534 vecLevelList[j] = levelLo;
2535
2536 if ( levelHi != 0x0F )
2537 {
2538 vecLevelList[j + 1] = levelHi;
2539 }
2540 else
2541 {
2542 vecLevelList.resize ( iVecLen - 1 );
2543 break;
2544 }
2545 }
2546
2547 // invoke message action
2548 emit CLChannelLevelListReceived ( InetAddr, vecLevelList );
2549
2550 return false; // no error
2551 }
2552
CreateCLRegisterServerResp(const CHostAddress & InetAddr,const ESvrRegResult eResult)2553 void CProtocol::CreateCLRegisterServerResp ( const CHostAddress& InetAddr, const ESvrRegResult eResult )
2554 {
2555 int iPos = 0; // init position pointer
2556 CVector<uint8_t> vecData ( 1 );
2557
2558 PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( eResult ), 1 );
2559
2560 CreateAndImmSendConLessMessage ( PROTMESSID_CLM_REGISTER_SERVER_RESP, vecData, InetAddr );
2561 }
2562
EvaluateCLRegisterServerResp(const CHostAddress & InetAddr,const CVector<uint8_t> & vecData)2563 bool CProtocol::EvaluateCLRegisterServerResp ( const CHostAddress& InetAddr, const CVector<uint8_t>& vecData )
2564 {
2565 int iPos = 0; // init position pointer
2566 const int iDataLen = vecData.Size();
2567
2568 if ( iDataLen != 1 )
2569 {
2570 return true;
2571 }
2572
2573 // server registration result (1 byte)
2574 const int iSvrRegResult = static_cast<int> ( GetValFromStream ( vecData, iPos, 1 ) );
2575
2576 if ( ( iSvrRegResult != SRR_REGISTERED ) && ( iSvrRegResult != SRR_CENTRAL_SVR_FULL ) && ( iSvrRegResult != SRR_VERSION_TOO_OLD ) &&
2577 ( iSvrRegResult != SRR_NOT_FULFILL_REQIREMENTS ) )
2578 {
2579 return true;
2580 }
2581
2582 // invoke message action
2583 emit CLRegisterServerResp ( InetAddr, static_cast<ESvrRegResult> ( iSvrRegResult ) );
2584
2585 return false; // no error
2586 }
2587
2588 /******************************************************************************\
2589 * Message generation and parsing *
2590 \******************************************************************************/
ParseMessageFrame(const CVector<uint8_t> & vecbyData,const int iNumBytesIn,CVector<uint8_t> & vecbyMesBodyData,int & iCnt,int & iID)2591 bool CProtocol::ParseMessageFrame ( const CVector<uint8_t>& vecbyData,
2592 const int iNumBytesIn,
2593 CVector<uint8_t>& vecbyMesBodyData,
2594 int& iCnt,
2595 int& iID )
2596 {
2597 int i;
2598 int iCurPos;
2599
2600 // vector must be at least "MESS_LEN_WITHOUT_DATA_BYTE" bytes long
2601 if ( iNumBytesIn < MESS_LEN_WITHOUT_DATA_BYTE )
2602 {
2603 return true; // return error code
2604 }
2605
2606 // Decode header -----------------------------------------------------------
2607 iCurPos = 0; // start from beginning
2608
2609 // 2 bytes TAG
2610 const int iTag = static_cast<int> ( GetValFromStream ( vecbyData, iCurPos, 2 ) );
2611
2612 // check if tag is correct
2613 if ( iTag != 0 )
2614 {
2615 return true; // return error code
2616 }
2617
2618 // 2 bytes ID
2619 iID = static_cast<int> ( GetValFromStream ( vecbyData, iCurPos, 2 ) );
2620
2621 // 1 byte cnt
2622 iCnt = static_cast<int> ( GetValFromStream ( vecbyData, iCurPos, 1 ) );
2623
2624 // 2 bytes length
2625 const int iLenBy = static_cast<int> ( GetValFromStream ( vecbyData, iCurPos, 2 ) );
2626
2627 // make sure the length is correct
2628 if ( iLenBy != iNumBytesIn - MESS_LEN_WITHOUT_DATA_BYTE )
2629 {
2630 return true; // return error code
2631 }
2632
2633 // Now check CRC -----------------------------------------------------------
2634 CCRC CRCObj;
2635
2636 const int iLenCRCCalc = MESS_HEADER_LENGTH_BYTE + iLenBy;
2637
2638 iCurPos = 0; // start from the beginning
2639
2640 for ( i = 0; i < iLenCRCCalc; i++ )
2641 {
2642 CRCObj.AddByte ( static_cast<uint8_t> ( GetValFromStream ( vecbyData, iCurPos, 1 ) ) );
2643 }
2644
2645 if ( CRCObj.GetCRC() != GetValFromStream ( vecbyData, iCurPos, 2 ) )
2646 {
2647 return true; // return error code
2648 }
2649
2650 // Extract actual data -----------------------------------------------------
2651
2652 // clang-format off
2653 // TODO this memory allocation is done in the real time thread but should be
2654 // done in the low priority protocol management thread
2655 // clang-format on
2656
2657 vecbyMesBodyData.Init ( iLenBy );
2658
2659 iCurPos = MESS_HEADER_LENGTH_BYTE; // start from beginning of data
2660
2661 for ( i = 0; i < iLenBy; i++ )
2662 {
2663 vecbyMesBodyData[i] = static_cast<uint8_t> ( GetValFromStream ( vecbyData, iCurPos, 1 ) );
2664 }
2665
2666 return false; // no error
2667 }
2668
ParseSplitMessageContainer(const CVector<uint8_t> & vecbyData,CVector<uint8_t> & vecbyMesBodyData,const int iSplitMessageDataIndex,int & iID,int & iNumParts,int & iSplitCnt,int & iCurPartSize)2669 bool CProtocol::ParseSplitMessageContainer ( const CVector<uint8_t>& vecbyData,
2670 CVector<uint8_t>& vecbyMesBodyData,
2671 const int iSplitMessageDataIndex,
2672 int& iID,
2673 int& iNumParts,
2674 int& iSplitCnt,
2675 int& iCurPartSize )
2676 {
2677 int iPos = 0; // init position pointer
2678 const int iDataLen = vecbyData.Size();
2679
2680 // check size (the first 4 bytes)
2681 if ( iDataLen < 4 )
2682 {
2683 return true; // return error code
2684 }
2685
2686 // 2 bytes ID
2687 iID = static_cast<int> ( GetValFromStream ( vecbyData, iPos, 2 ) );
2688
2689 // 1 byte number of parts
2690 iNumParts = static_cast<int> ( GetValFromStream ( vecbyData, iPos, 1 ) );
2691
2692 // 1 byte split cnt
2693 iSplitCnt = static_cast<int> ( GetValFromStream ( vecbyData, iPos, 1 ) );
2694
2695 // Extract actual data -----------------------------------------------------
2696 iCurPartSize = iDataLen - 4;
2697
2698 // the memory must be allocated outside this function -> check the size
2699 if ( vecbyMesBodyData.Size() < iSplitMessageDataIndex + iCurPartSize )
2700 {
2701 return true; // return error code
2702 }
2703
2704 for ( int i = 0; i < iCurPartSize; i++ )
2705 {
2706 vecbyMesBodyData[iSplitMessageDataIndex + i] = static_cast<uint8_t> ( GetValFromStream ( vecbyData, iPos, 1 ) );
2707 }
2708
2709 return false; // no error
2710 }
2711
GetValFromStream(const CVector<uint8_t> & vecIn,int & iPos,const int iNumOfBytes)2712 uint32_t CProtocol::GetValFromStream ( const CVector<uint8_t>& vecIn, int& iPos, const int iNumOfBytes )
2713 {
2714 /*
2715 note: iPos is automatically incremented in this function
2716 */
2717 // 4 bytes maximum since we return uint32
2718 Q_ASSERT ( ( iNumOfBytes > 0 ) && ( iNumOfBytes <= 4 ) );
2719 Q_ASSERT ( vecIn.Size() >= iPos + iNumOfBytes );
2720
2721 uint32_t iRet = 0;
2722
2723 for ( int i = 0; i < iNumOfBytes; i++ )
2724 {
2725 iRet |= vecIn[iPos] << ( i * 8 /* size of byte */ );
2726 iPos++;
2727 }
2728
2729 return iRet;
2730 }
2731
GetStringFromStream(const CVector<uint8_t> & vecIn,int & iPos,const int iMaxStringLen,QString & strOut,const int iNumberOfBytsLen)2732 bool CProtocol::GetStringFromStream ( const CVector<uint8_t>& vecIn, int& iPos, const int iMaxStringLen, QString& strOut, const int iNumberOfBytsLen )
2733 {
2734 /*
2735 note: iPos is automatically incremented in this function
2736 */
2737 const int iInLen = vecIn.Size();
2738
2739 // check if at least iNumberOfBytsLen bytes are available
2740 if ( ( iInLen - iPos ) < iNumberOfBytsLen )
2741 {
2742 return true; // return error code
2743 }
2744
2745 // number of bytes for utf-8 string (1 or 2 bytes)
2746 const int iStrUTF8Len = static_cast<int> ( GetValFromStream ( vecIn, iPos, iNumberOfBytsLen ) );
2747
2748 // (note that iPos was incremented by 2 in the above code!)
2749 if ( ( iInLen - iPos ) < iStrUTF8Len )
2750 {
2751 return true; // return error code
2752 }
2753
2754 // string (n bytes)
2755 QByteArray sStringUTF8;
2756
2757 for ( int i = 0; i < iStrUTF8Len; i++ )
2758 {
2759 // byte-by-byte copying of the string data
2760 sStringUTF8.append ( static_cast<char> ( GetValFromStream ( vecIn, iPos, 1 ) ) );
2761 }
2762
2763 // convert utf-8 byte array in the return string
2764 strOut = QString::fromUtf8 ( sStringUTF8 );
2765
2766 // check length of actual string
2767 if ( strOut.size() > iMaxStringLen )
2768 {
2769 return true; // return error code
2770 }
2771
2772 return false; // no error
2773 }
2774
GenMessageFrame(CVector<uint8_t> & vecOut,const int iCnt,const int iID,const CVector<uint8_t> & vecData)2775 void CProtocol::GenMessageFrame ( CVector<uint8_t>& vecOut, const int iCnt, const int iID, const CVector<uint8_t>& vecData )
2776 {
2777 int i;
2778
2779 // query length of data vector
2780 const int iDataLenByte = vecData.Size();
2781
2782 // total length of message
2783 const int iTotLenByte = MESS_LEN_WITHOUT_DATA_BYTE + iDataLenByte;
2784
2785 // init message vector
2786 vecOut.Init ( iTotLenByte );
2787
2788 // Encode header -----------------------------------------------------------
2789 int iCurPos = 0; // init position pointer
2790
2791 // 2 bytes TAG (all zero bits)
2792 PutValOnStream ( vecOut, iCurPos, static_cast<uint32_t> ( 0 ), 2 );
2793
2794 // 2 bytes ID
2795 PutValOnStream ( vecOut, iCurPos, static_cast<uint32_t> ( iID ), 2 );
2796
2797 // 1 byte cnt
2798 PutValOnStream ( vecOut, iCurPos, static_cast<uint32_t> ( iCnt ), 1 );
2799
2800 // 2 bytes length
2801 PutValOnStream ( vecOut, iCurPos, static_cast<uint32_t> ( iDataLenByte ), 2 );
2802
2803 // encode data -----
2804 for ( i = 0; i < iDataLenByte; i++ )
2805 {
2806 PutValOnStream ( vecOut, iCurPos, static_cast<uint32_t> ( vecData[i] ), 1 );
2807 }
2808
2809 // Encode CRC --------------------------------------------------------------
2810 CCRC CRCObj;
2811
2812 iCurPos = 0; // start from beginning
2813
2814 const int iLenCRCCalc = MESS_HEADER_LENGTH_BYTE + iDataLenByte;
2815
2816 for ( i = 0; i < iLenCRCCalc; i++ )
2817 {
2818 CRCObj.AddByte ( static_cast<uint8_t> ( GetValFromStream ( vecOut, iCurPos, 1 ) ) );
2819 }
2820
2821 PutValOnStream ( vecOut, iCurPos, static_cast<uint32_t> ( CRCObj.GetCRC() ), 2 );
2822 }
2823
GenSplitMessageContainer(CVector<uint8_t> & vecOut,const int iID,const int iNumParts,const int iSplitCnt,const CVector<uint8_t> & vecData,const int iStartIndexInData,const int iLengthOfDataPart)2824 void CProtocol::GenSplitMessageContainer ( CVector<uint8_t>& vecOut,
2825 const int iID,
2826 const int iNumParts,
2827 const int iSplitCnt,
2828 const CVector<uint8_t>& vecData,
2829 const int iStartIndexInData,
2830 const int iLengthOfDataPart )
2831 {
2832 int iPos = 0; // init position pointer
2833
2834 // total length of message
2835 const int iTotLenByte = 4 + iLengthOfDataPart;
2836
2837 // init message vector
2838 vecOut.Init ( iTotLenByte );
2839
2840 // 2 bytes ID
2841 PutValOnStream ( vecOut, iPos, static_cast<uint32_t> ( iID ), 2 );
2842
2843 // 1 byte number of parts
2844 PutValOnStream ( vecOut, iPos, static_cast<uint32_t> ( iNumParts ), 1 );
2845
2846 // 1 byte split cnt
2847 PutValOnStream ( vecOut, iPos, static_cast<uint32_t> ( iSplitCnt ), 1 );
2848
2849 // data
2850 for ( int i = 0; i < iLengthOfDataPart; i++ )
2851 {
2852 PutValOnStream ( vecOut, iPos, static_cast<uint32_t> ( vecData[iStartIndexInData + i] ), 1 );
2853 }
2854 }
2855
PutValOnStream(CVector<uint8_t> & vecIn,int & iPos,const uint32_t iVal,const int iNumOfBytes)2856 void CProtocol::PutValOnStream ( CVector<uint8_t>& vecIn, int& iPos, const uint32_t iVal, const int iNumOfBytes )
2857 {
2858 /*
2859 note: iPos is automatically incremented in this function
2860 */
2861 // 4 bytes maximum since we use uint32
2862 Q_ASSERT ( ( iNumOfBytes > 0 ) && ( iNumOfBytes <= 4 ) );
2863 Q_ASSERT ( vecIn.Size() >= iPos + iNumOfBytes );
2864
2865 for ( int i = 0; i < iNumOfBytes; i++ )
2866 {
2867 vecIn[iPos] = ( iVal >> ( i * 8 /* size of byte */ ) ) & 255 /* 11111111 */;
2868 iPos++;
2869 }
2870 }
2871
PutStringUTF8OnStream(CVector<uint8_t> & vecIn,int & iPos,const QByteArray & sStringUTF8,const int iNumberOfBytsLen)2872 void CProtocol::PutStringUTF8OnStream ( CVector<uint8_t>& vecIn, int& iPos, const QByteArray& sStringUTF8, const int iNumberOfBytsLen )
2873 {
2874 // get the utf-8 string size
2875 const int iStrUTF8Len = sStringUTF8.size();
2876
2877 // number of bytes for utf-8 string (iNumberOfBytsLen bytes)
2878 PutValOnStream ( vecIn, iPos, static_cast<uint32_t> ( iStrUTF8Len ), iNumberOfBytsLen );
2879
2880 // actual utf-8 string (n bytes)
2881 for ( int j = 0; j < iStrUTF8Len; j++ )
2882 {
2883 // byte-by-byte copying of the utf-8 string data
2884 PutValOnStream ( vecIn, iPos, static_cast<uint32_t> ( sStringUTF8[j] ), 1 );
2885 }
2886 }
2887