From 23d79c5f855b155be7bc8450bb0333a2f8f835ad Mon Sep 17 00:00:00 2001 From: Volker Fischer Date: Mon, 25 Apr 2011 10:51:57 +0000 Subject: [PATCH] the number of connected clients are now not managed with the server list but by the connection less ping time message --- src/client.cpp | 13 +- src/client.h | 654 ++++---- src/connectdlg.cpp | 26 +- src/connectdlg.h | 7 +- src/llconclientdlg.cpp | 17 +- src/llconclientdlg.h | 4 +- src/protocol.cpp | 3494 ++++++++++++++++++++-------------------- src/protocol.h | 527 +++--- src/server.cpp | 17 + src/server.h | 599 +++---- src/serverlist.cpp | 2 - src/serverlist.h | 308 ++-- src/util.h | 9 - 13 files changed, 2878 insertions(+), 2799 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 9c28d07b..d78968fe 100755 --- a/src/client.cpp +++ b/src/client.cpp @@ -114,8 +114,9 @@ CClient::CClient ( const quint16 iPortNumber ) : SIGNAL ( CLServerListReceived ( CHostAddress, CVector ) ), SIGNAL ( CLServerListReceived ( CHostAddress, CVector ) ) ); - QObject::connect ( &ConnLessProtocol, SIGNAL ( CLPingReceived ( CHostAddress, int ) ), - this, SLOT ( OnCLPingReceived ( CHostAddress, int ) ) ); + QObject::connect ( &ConnLessProtocol, + SIGNAL ( CLPingWithNumClientsReceived ( CHostAddress, int, int ) ), + this, SLOT ( OnCLPingWithNumClientsReceived ( CHostAddress, int, int ) ) ); QObject::connect ( &Sound, SIGNAL ( ReinitRequest() ), this, SLOT ( OnSndCrdReinitRequest() ) ); @@ -162,13 +163,17 @@ void CClient::OnReceivePingMessage ( int iMs ) } } -void CClient::OnCLPingReceived ( CHostAddress InetAddr, int iMs ) +void CClient::OnCLPingWithNumClientsReceived ( CHostAddress InetAddr, + int iMs, + int iNumClients ) { // take care of wrap arounds (if wrapping, do not use result) const int iCurDiff = EvaluatePingMessage ( iMs ); if ( iCurDiff >= 0 ) { - emit CLPingTimeReceived ( InetAddr, iCurDiff ); + emit CLPingTimeWithNumClientsReceived ( InetAddr, + iCurDiff, + iNumClients ); } } diff --git a/src/client.h b/src/client.h index 16937604..64d65549 100755 --- a/src/client.h +++ b/src/client.h @@ -1,325 +1,329 @@ -/******************************************************************************\ - * Copyright (c) 2004-2011 - * - * Author(s): - * Volker Fischer - * - ****************************************************************************** - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -\******************************************************************************/ - -#if !defined ( CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_ ) -#define CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_ - -#include -#include -#include -#include -#include -#include -#include "celt.h" -#include "global.h" -#include "socket.h" -#include "channel.h" -#include "util.h" -#include "buffer.h" -#ifdef LLCON_VST_PLUGIN -# include "vstsound.h" -#else -# ifdef _WIN32 -# include "../windows/sound.h" -# else -# if defined ( __APPLE__ ) || defined ( __MACOSX ) -# include "../mac/sound.h" -# else -# include "../linux/sound.h" -# include -# include -# include -# endif -# endif -#endif - - -/* Definitions ****************************************************************/ -// audio in fader range -#define AUD_FADER_IN_MIN 0 -#define AUD_FADER_IN_MAX 100 -#define AUD_FADER_IN_MIDDLE ( AUD_FADER_IN_MAX / 2 ) - -// audio reverberation range -#define AUD_REVERB_MAX 100 - -// CELT number of coded bytes per audio packet -// 24: mono low/normal quality 156 kbsp (128) / 114 kbps (256) -// 44: mono high quality 216 kbps (128) / 174 kbps (256) -#define CELT_NUM_BYTES_MONO_NORMAL_QUALITY 24 -#define CELT_NUM_BYTES_MONO_HIGH_QUALITY 44 - -// 46: stereo low/normal quality 222 kbsp (128) / 180 kbps (256) -// 70: stereo high quality 294 kbps (128) / 252 kbps (256) -#define CELT_NUM_BYTES_STEREO_NORMAL_QUALITY 46 -#define CELT_NUM_BYTES_STEREO_HIGH_QUALITY 70 - - -/* Classes ********************************************************************/ -class CClient : public QObject -{ - Q_OBJECT - -public: - CClient ( const quint16 iPortNumber ); - - void Start(); - void Stop(); - bool IsRunning() { return Sound.IsRunning(); } - bool SetServerAddr ( QString strNAddr ); - double MicLevelL() { return SignalLevelMeter.MicLevelLeft(); } - double MicLevelR() { return SignalLevelMeter.MicLevelRight(); } - bool IsConnected() { return Channel.IsConnected(); } - - double GetTimingStdDev() { return CycleTimeVariance.GetStdDev(); } - - bool GetOpenChatOnNewMessage() const { return bOpenChatOnNewMessage; } - void SetOpenChatOnNewMessage ( const bool bNV ) { bOpenChatOnNewMessage = bNV; } - - EGUIDesign GetGUIDesign() const { return eGUIDesign; } - void SetGUIDesign ( const EGUIDesign bNGD ) { eGUIDesign = bNGD; } - - bool GetCELTHighQuality() const { return bCeltDoHighQuality; } - void SetCELTHighQuality ( const bool bNCeltHighQualityFlag ); - - bool GetUseStereo() const { return bUseStereo; } - void SetUseStereo ( const bool bNUseStereo ); - - int GetAudioInFader() const { return iAudioInFader; } - void SetAudioInFader ( const int iNV ) { iAudioInFader = iNV; } - - int GetReverbLevel() const { return iReverbLevel; } - void SetReverbLevel ( const int iNL ) { iReverbLevel = iNL; } - - bool IsReverbOnLeftChan() const { return bReverbOnLeftChan; } - void SetReverbOnLeftChan ( const bool bIL ) - { - bReverbOnLeftChan = bIL; - AudioReverbL.Clear(); - AudioReverbR.Clear(); - } - - void SetDoAutoSockBufSize ( const bool bValue ) { bDoAutoSockBufSize = bValue; } - bool GetDoAutoSockBufSize() const { return bDoAutoSockBufSize; } - void SetSockBufNumFrames ( const int iNumBlocks ) - { - // only change parameter if new parameter is different from current one - if ( Channel.GetSockBufNumFrames() != iNumBlocks ) - { - // set the new socket size (number of frames) - if ( !Channel.SetSockBufNumFrames ( iNumBlocks ) ) - { - // if setting of socket buffer size was successful, - // tell the server that size has changed - Channel.CreateJitBufMes ( iNumBlocks ); - } - } - } - int GetSockBufNumFrames() { return Channel.GetSockBufNumFrames(); } - - int GetUploadRateKbps() { return Channel.GetUploadRateKbps(); } - - // sound card device selection - int GetSndCrdNumDev() { return Sound.GetNumDev(); } - QString GetSndCrdDeviceName ( const int iDiD ) - { return Sound.GetDeviceName ( iDiD ); } - - QString SetSndCrdDev ( const int iNewDev ); - int GetSndCrdDev() { return Sound.GetDev(); } - void OpenSndCrdDriverSetup() { Sound.OpenDriverSetup(); } - - // sound card channel selection - int GetSndCrdNumInputChannels() { return Sound.GetNumInputChannels(); } - QString GetSndCrdInputChannelName ( const int iDiD ) { return Sound.GetInputChannelName ( iDiD ); } - void SetSndCrdLeftInputChannel ( const int iNewChan ); - void SetSndCrdRightInputChannel ( const int iNewChan ); - int GetSndCrdLeftInputChannel() { return Sound.GetLeftInputChannel(); } - int GetSndCrdRightInputChannel() { return Sound.GetRightInputChannel(); } - - int GetSndCrdNumOutputChannels() { return Sound.GetNumOutputChannels(); } - QString GetSndCrdOutputChannelName ( const int iDiD ) { return Sound.GetOutputChannelName ( iDiD ); } - void SetSndCrdLeftOutputChannel ( const int iNewChan ); - void SetSndCrdRightOutputChannel ( const int iNewChan ); - int GetSndCrdLeftOutputChannel() { return Sound.GetLeftOutputChannel(); } - int GetSndCrdRightOutputChannel() { return Sound.GetRightOutputChannel(); } - - void SetSndCrdPrefFrameSizeFactor ( const int iNewFactor ); - int GetSndCrdPrefFrameSizeFactor() - { return iSndCrdPrefFrameSizeFactor; } - - int GetSndCrdActualMonoBlSize() - { - // the actual sound card mono block size depends on whether a - // sound card conversion buffer is used or not - if ( bSndCrdConversionBufferRequired ) - { - return iSndCardMonoBlockSizeSamConvBuff; - } - else - { - return iMonoBlockSizeSam; - } - } - int GetSystemMonoBlSize() { return iMonoBlockSizeSam; } - int GetSndCrdConvBufAdditionalDelayMonoBlSize() - { - if ( bSndCrdConversionBufferRequired ) - { - // by introducing the conversion buffer we also introduce additional - // delay which equals the "internal" mono buffer size - return iMonoBlockSizeSam; - } - else - { - return 0; - } - } - - bool GetFraSiFactPrefSupported() { return bFraSiFactPrefSupported; } - bool GetFraSiFactDefSupported() { return bFraSiFactDefSupported; } - bool GetFraSiFactSafeSupported() { return bFraSiFactSafeSupported; } - - void SetRemoteChanGain ( const int iId, const double dGain ) - { Channel.SetRemoteChanGain ( iId, dGain ); } - - void SetRemoteName() { Channel.SetRemoteName ( strName ); } - - void CreateChatTextMes ( const QString& strChatText ) - { Channel.CreateChatTextMes ( strChatText ); } - - void CreatePingMes() - { Channel.CreatePingMes ( PreparePingMessage() ); } - - void CreateCLPingMes ( const CHostAddress& InetAddr ) - { ConnLessProtocol.CreateCLPingMes ( InetAddr, PreparePingMessage() ); } - - void CreateCLReqServerListMes ( const CHostAddress& InetAddr ) - { ConnLessProtocol.CreateCLReqServerListMes ( InetAddr ); } - - int EstimatedOverallDelay ( const int iPingTimeMs ); - - CChannel* GetChannel() { return &Channel; } - - // settings - CVector vstrIPAddress; - QString strName; - -#ifdef LLCON_VST_PLUGIN - // VST version must have direct access to sound object - CSound* GetSound() { return &Sound; } -#endif - -protected: - // callback function must be static, otherwise it does not work - static void AudioCallback ( CVector& psData, void* arg ); - - void Init(); - void ProcessSndCrdAudioData ( CVector& vecsStereoSndCrd ); - void ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ); - void UpdateSocketBufferSize(); - - int PreparePingMessage(); - int EvaluatePingMessage ( const int iMs ); - - // only one channel is needed for client application - CChannel Channel; - CProtocol ConnLessProtocol; - bool bDoAutoSockBufSize; - - // audio encoder/decoder - CELTMode* CeltModeMono; - CELTEncoder* CeltEncoderMono; - CELTDecoder* CeltDecoderMono; - CELTMode* CeltModeStereo; - CELTEncoder* CeltEncoderStereo; - CELTDecoder* CeltDecoderStereo; - int iCeltNumCodedBytes; - bool bCeltDoHighQuality; - bool bUseStereo; - CVector vecCeltData; - - CSocket Socket; - CSound Sound; - CStereoSignalLevelMeter SignalLevelMeter; - - CVector vecbyNetwData; - - int iAudioInFader; - bool bReverbOnLeftChan; - int iReverbLevel; - CAudioReverb AudioReverbL; - CAudioReverb AudioReverbR; - - int iSndCrdPrefFrameSizeFactor; - int iSndCrdFrameSizeFactor; - - bool bSndCrdConversionBufferRequired; - int iSndCardMonoBlockSizeSamConvBuff; - CBufferBase SndCrdConversionBufferIn; - CBufferBase SndCrdConversionBufferOut; - CVector vecDataConvBuf; - - bool bFraSiFactPrefSupported; - bool bFraSiFactDefSupported; - bool bFraSiFactSafeSupported; - - int iMonoBlockSizeSam; - int iStereoBlockSizeSam; - - bool bOpenChatOnNewMessage; - EGUIDesign eGUIDesign; - - CVector vecsAudioSndCrdMono; - CVector vecdAudioStereo; - CVector vecsNetwork; - - // for ping measurement - CPreciseTime PreciseTime; - - CCycleTimeVariance CycleTimeVariance; - -public slots: - void OnSendProtMessage ( CVector vecMessage ); - void OnReqJittBufSize() { Channel.CreateJitBufMes ( Channel.GetSockBufNumFrames() ); } - void OnReqChanName() { Channel.SetRemoteName ( strName ); } - void OnNewConnection(); - void OnReceivePingMessage ( int iMs ); - - void OnSendCLProtMessage ( CHostAddress InetAddr, CVector vecMessage ); - void OnCLPingReceived ( CHostAddress InetAddr, int iMs ); - - void OnSndCrdReinitRequest(); - -signals: - void ConClientListMesReceived ( CVector vecChanInfo ); - void ChatTextReceived ( QString strChatText ); - void PingTimeReceived ( int iPingTime ); - void CLServerListReceived ( CHostAddress InetAddr, - CVector vecServerInfo ); - void CLPingTimeReceived ( CHostAddress InetAddr, int iPingTime ); - void Disconnected(); - void Stopped(); -}; - -#endif /* !defined ( CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_ ) */ +/******************************************************************************\ + * Copyright (c) 2004-2011 + * + * Author(s): + * Volker Fischer + * + ****************************************************************************** + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +\******************************************************************************/ + +#if !defined ( CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_ ) +#define CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include "celt.h" +#include "global.h" +#include "socket.h" +#include "channel.h" +#include "util.h" +#include "buffer.h" +#ifdef LLCON_VST_PLUGIN +# include "vstsound.h" +#else +# ifdef _WIN32 +# include "../windows/sound.h" +# else +# if defined ( __APPLE__ ) || defined ( __MACOSX ) +# include "../mac/sound.h" +# else +# include "../linux/sound.h" +# include +# include +# include +# endif +# endif +#endif + + +/* Definitions ****************************************************************/ +// audio in fader range +#define AUD_FADER_IN_MIN 0 +#define AUD_FADER_IN_MAX 100 +#define AUD_FADER_IN_MIDDLE ( AUD_FADER_IN_MAX / 2 ) + +// audio reverberation range +#define AUD_REVERB_MAX 100 + +// CELT number of coded bytes per audio packet +// 24: mono low/normal quality 156 kbsp (128) / 114 kbps (256) +// 44: mono high quality 216 kbps (128) / 174 kbps (256) +#define CELT_NUM_BYTES_MONO_NORMAL_QUALITY 24 +#define CELT_NUM_BYTES_MONO_HIGH_QUALITY 44 + +// 46: stereo low/normal quality 222 kbsp (128) / 180 kbps (256) +// 70: stereo high quality 294 kbps (128) / 252 kbps (256) +#define CELT_NUM_BYTES_STEREO_NORMAL_QUALITY 46 +#define CELT_NUM_BYTES_STEREO_HIGH_QUALITY 70 + + +/* Classes ********************************************************************/ +class CClient : public QObject +{ + Q_OBJECT + +public: + CClient ( const quint16 iPortNumber ); + + void Start(); + void Stop(); + bool IsRunning() { return Sound.IsRunning(); } + bool SetServerAddr ( QString strNAddr ); + double MicLevelL() { return SignalLevelMeter.MicLevelLeft(); } + double MicLevelR() { return SignalLevelMeter.MicLevelRight(); } + bool IsConnected() { return Channel.IsConnected(); } + + double GetTimingStdDev() { return CycleTimeVariance.GetStdDev(); } + + bool GetOpenChatOnNewMessage() const { return bOpenChatOnNewMessage; } + void SetOpenChatOnNewMessage ( const bool bNV ) { bOpenChatOnNewMessage = bNV; } + + EGUIDesign GetGUIDesign() const { return eGUIDesign; } + void SetGUIDesign ( const EGUIDesign bNGD ) { eGUIDesign = bNGD; } + + bool GetCELTHighQuality() const { return bCeltDoHighQuality; } + void SetCELTHighQuality ( const bool bNCeltHighQualityFlag ); + + bool GetUseStereo() const { return bUseStereo; } + void SetUseStereo ( const bool bNUseStereo ); + + int GetAudioInFader() const { return iAudioInFader; } + void SetAudioInFader ( const int iNV ) { iAudioInFader = iNV; } + + int GetReverbLevel() const { return iReverbLevel; } + void SetReverbLevel ( const int iNL ) { iReverbLevel = iNL; } + + bool IsReverbOnLeftChan() const { return bReverbOnLeftChan; } + void SetReverbOnLeftChan ( const bool bIL ) + { + bReverbOnLeftChan = bIL; + AudioReverbL.Clear(); + AudioReverbR.Clear(); + } + + void SetDoAutoSockBufSize ( const bool bValue ) { bDoAutoSockBufSize = bValue; } + bool GetDoAutoSockBufSize() const { return bDoAutoSockBufSize; } + void SetSockBufNumFrames ( const int iNumBlocks ) + { + // only change parameter if new parameter is different from current one + if ( Channel.GetSockBufNumFrames() != iNumBlocks ) + { + // set the new socket size (number of frames) + if ( !Channel.SetSockBufNumFrames ( iNumBlocks ) ) + { + // if setting of socket buffer size was successful, + // tell the server that size has changed + Channel.CreateJitBufMes ( iNumBlocks ); + } + } + } + int GetSockBufNumFrames() { return Channel.GetSockBufNumFrames(); } + + int GetUploadRateKbps() { return Channel.GetUploadRateKbps(); } + + // sound card device selection + int GetSndCrdNumDev() { return Sound.GetNumDev(); } + QString GetSndCrdDeviceName ( const int iDiD ) + { return Sound.GetDeviceName ( iDiD ); } + + QString SetSndCrdDev ( const int iNewDev ); + int GetSndCrdDev() { return Sound.GetDev(); } + void OpenSndCrdDriverSetup() { Sound.OpenDriverSetup(); } + + // sound card channel selection + int GetSndCrdNumInputChannels() { return Sound.GetNumInputChannels(); } + QString GetSndCrdInputChannelName ( const int iDiD ) { return Sound.GetInputChannelName ( iDiD ); } + void SetSndCrdLeftInputChannel ( const int iNewChan ); + void SetSndCrdRightInputChannel ( const int iNewChan ); + int GetSndCrdLeftInputChannel() { return Sound.GetLeftInputChannel(); } + int GetSndCrdRightInputChannel() { return Sound.GetRightInputChannel(); } + + int GetSndCrdNumOutputChannels() { return Sound.GetNumOutputChannels(); } + QString GetSndCrdOutputChannelName ( const int iDiD ) { return Sound.GetOutputChannelName ( iDiD ); } + void SetSndCrdLeftOutputChannel ( const int iNewChan ); + void SetSndCrdRightOutputChannel ( const int iNewChan ); + int GetSndCrdLeftOutputChannel() { return Sound.GetLeftOutputChannel(); } + int GetSndCrdRightOutputChannel() { return Sound.GetRightOutputChannel(); } + + void SetSndCrdPrefFrameSizeFactor ( const int iNewFactor ); + int GetSndCrdPrefFrameSizeFactor() + { return iSndCrdPrefFrameSizeFactor; } + + int GetSndCrdActualMonoBlSize() + { + // the actual sound card mono block size depends on whether a + // sound card conversion buffer is used or not + if ( bSndCrdConversionBufferRequired ) + { + return iSndCardMonoBlockSizeSamConvBuff; + } + else + { + return iMonoBlockSizeSam; + } + } + int GetSystemMonoBlSize() { return iMonoBlockSizeSam; } + int GetSndCrdConvBufAdditionalDelayMonoBlSize() + { + if ( bSndCrdConversionBufferRequired ) + { + // by introducing the conversion buffer we also introduce additional + // delay which equals the "internal" mono buffer size + return iMonoBlockSizeSam; + } + else + { + return 0; + } + } + + bool GetFraSiFactPrefSupported() { return bFraSiFactPrefSupported; } + bool GetFraSiFactDefSupported() { return bFraSiFactDefSupported; } + bool GetFraSiFactSafeSupported() { return bFraSiFactSafeSupported; } + + void SetRemoteChanGain ( const int iId, const double dGain ) + { Channel.SetRemoteChanGain ( iId, dGain ); } + + void SetRemoteName() { Channel.SetRemoteName ( strName ); } + + void CreateChatTextMes ( const QString& strChatText ) + { Channel.CreateChatTextMes ( strChatText ); } + + void CreatePingMes() + { Channel.CreatePingMes ( PreparePingMessage() ); } + + void CreateCLPingMes ( const CHostAddress& InetAddr ) + { ConnLessProtocol.CreateCLPingMes ( InetAddr, PreparePingMessage() ); } + + void CreateCLReqServerListMes ( const CHostAddress& InetAddr ) + { ConnLessProtocol.CreateCLReqServerListMes ( InetAddr ); } + + int EstimatedOverallDelay ( const int iPingTimeMs ); + + CChannel* GetChannel() { return &Channel; } + + // settings + CVector vstrIPAddress; + QString strName; + +#ifdef LLCON_VST_PLUGIN + // VST version must have direct access to sound object + CSound* GetSound() { return &Sound; } +#endif + +protected: + // callback function must be static, otherwise it does not work + static void AudioCallback ( CVector& psData, void* arg ); + + void Init(); + void ProcessSndCrdAudioData ( CVector& vecsStereoSndCrd ); + void ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ); + void UpdateSocketBufferSize(); + + int PreparePingMessage(); + int EvaluatePingMessage ( const int iMs ); + + // only one channel is needed for client application + CChannel Channel; + CProtocol ConnLessProtocol; + bool bDoAutoSockBufSize; + + // audio encoder/decoder + CELTMode* CeltModeMono; + CELTEncoder* CeltEncoderMono; + CELTDecoder* CeltDecoderMono; + CELTMode* CeltModeStereo; + CELTEncoder* CeltEncoderStereo; + CELTDecoder* CeltDecoderStereo; + int iCeltNumCodedBytes; + bool bCeltDoHighQuality; + bool bUseStereo; + CVector vecCeltData; + + CSocket Socket; + CSound Sound; + CStereoSignalLevelMeter SignalLevelMeter; + + CVector vecbyNetwData; + + int iAudioInFader; + bool bReverbOnLeftChan; + int iReverbLevel; + CAudioReverb AudioReverbL; + CAudioReverb AudioReverbR; + + int iSndCrdPrefFrameSizeFactor; + int iSndCrdFrameSizeFactor; + + bool bSndCrdConversionBufferRequired; + int iSndCardMonoBlockSizeSamConvBuff; + CBufferBase SndCrdConversionBufferIn; + CBufferBase SndCrdConversionBufferOut; + CVector vecDataConvBuf; + + bool bFraSiFactPrefSupported; + bool bFraSiFactDefSupported; + bool bFraSiFactSafeSupported; + + int iMonoBlockSizeSam; + int iStereoBlockSizeSam; + + bool bOpenChatOnNewMessage; + EGUIDesign eGUIDesign; + + CVector vecsAudioSndCrdMono; + CVector vecdAudioStereo; + CVector vecsNetwork; + + // for ping measurement + CPreciseTime PreciseTime; + + CCycleTimeVariance CycleTimeVariance; + +public slots: + void OnSendProtMessage ( CVector vecMessage ); + void OnReqJittBufSize() { Channel.CreateJitBufMes ( Channel.GetSockBufNumFrames() ); } + void OnReqChanName() { Channel.SetRemoteName ( strName ); } + void OnNewConnection(); + void OnReceivePingMessage ( int iMs ); + + void OnSendCLProtMessage ( CHostAddress InetAddr, CVector vecMessage ); + void OnCLPingWithNumClientsReceived ( CHostAddress InetAddr, + int iMs, + int iNumClients ); + + void OnSndCrdReinitRequest(); + +signals: + void ConClientListMesReceived ( CVector vecChanInfo ); + void ChatTextReceived ( QString strChatText ); + void PingTimeReceived ( int iPingTime ); + void CLServerListReceived ( CHostAddress InetAddr, + CVector vecServerInfo ); + void CLPingTimeWithNumClientsReceived ( CHostAddress InetAddr, + int iPingTime, + int iNumClients ); + void Disconnected(); + void Stopped(); +}; + +#endif /* !defined ( CLIENT_HOIHGE76GEKJH98_3_43445KJIUHF1912__INCLUDED_ ) */ diff --git a/src/connectdlg.cpp b/src/connectdlg.cpp index 324d3e3d..d61e05b2 100755 --- a/src/connectdlg.cpp +++ b/src/connectdlg.cpp @@ -234,13 +234,16 @@ void CConnectDlg::SetServerList ( const CHostAddress& InetAddr, CurPingTimeFont.setBold ( true ); pNewListViewItem->setFont ( 1, CurPingTimeFont ); - // number of clients - pNewListViewItem->setText ( 2, - QString().setNum ( vecServerInfo[iIdx].iNumClients ) ); + // server location (city and country) + QString strLocation = vecServerInfo[iIdx].strCity; + if ( !strLocation.isEmpty() ) + { + strLocation += ", "; + } + strLocation += + QLocale::countryToString ( vecServerInfo[iIdx].eCountry ); - // server country - pNewListViewItem->setText ( 3, - QLocale::countryToString ( vecServerInfo[iIdx].eCountry ) ); + pNewListViewItem->setText ( 3, strLocation ); // store host address pNewListViewItem->setData ( 0, Qt::UserRole, @@ -294,9 +297,10 @@ void CConnectDlg::OnTimerPing() } } -void CConnectDlg::SetPingTimeResult ( CHostAddress& InetAddr, - const int iPingTime, - const int iPingTimeLEDColor ) +void CConnectDlg::SetPingTimeAndNumClientsResult ( CHostAddress& InetAddr, + const int iPingTime, + const int iPingTimeLEDColor, + const int iNumClients ) { // apply the received ping time to the correct server list entry const int iServerListLen = ListViewServers->topLevelItemCount(); @@ -332,6 +336,10 @@ void CConnectDlg::SetPingTimeResult ( CHostAddress& InetAddr, ListViewServers->topLevelItem ( iIdx )-> setText ( 1, QString().setNum ( iPingTime ) + " ms" ); + // update number of clients text + ListViewServers->topLevelItem ( iIdx )-> + setText ( 2, QString().setNum ( iNumClients ) ); + // a ping time was received, set item to visible ListViewServers->topLevelItem ( iIdx )->setHidden ( false ); } diff --git a/src/connectdlg.h b/src/connectdlg.h index 0ebc181a..1aa7a73d 100755 --- a/src/connectdlg.h +++ b/src/connectdlg.h @@ -61,9 +61,10 @@ public: void LoadStoredServers ( const CVector& vstrNewIPAddresses ); - void SetPingTimeResult ( CHostAddress& InetAddr, - const int iPingTime, - const int iPingTimeLEDColor ); + void SetPingTimeAndNumClientsResult ( CHostAddress& InetAddr, + const int iPingTime, + const int iPingTimeLEDColor, + const int iNumClients ); bool GetStateOK() const { return bStateOK; } bool GetServerListItemWasChosen() const { return bServerListItemWasChosen; } diff --git a/src/llconclientdlg.cpp b/src/llconclientdlg.cpp index c8cf1cfc..81396b39 100755 --- a/src/llconclientdlg.cpp +++ b/src/llconclientdlg.cpp @@ -389,8 +389,9 @@ CLlconClientDlg::CLlconClientDlg ( CClient* pNCliP, SIGNAL ( CLServerListReceived ( CHostAddress, CVector ) ), this, SLOT ( OnCLServerListReceived ( CHostAddress, CVector ) ) ); - QObject::connect ( pClient, SIGNAL ( CLPingTimeReceived ( CHostAddress, int ) ), - this, SLOT ( OnCLPingTimeResult ( CHostAddress, int ) ) ); + QObject::connect ( pClient, + SIGNAL ( CLPingTimeWithNumClientsReceived ( CHostAddress, int, int ) ), + this, SLOT ( OnCLPingTimeWithNumClientsReceived ( CHostAddress, int, int ) ) ); QObject::connect ( &ClientSettingsDlg, SIGNAL ( GUIDesignChanged() ), this, SLOT ( OnGUIDesignChanged() ) ); @@ -698,8 +699,9 @@ void CLlconClientDlg::OnPingTimeResult ( int iPingTime ) LEDDelay->SetLight ( iOverallDelayLEDColor ); } -void CLlconClientDlg::OnCLPingTimeResult ( CHostAddress InetAddr, - int iPingTime ) +void CLlconClientDlg::OnCLPingTimeWithNumClientsReceived ( CHostAddress InetAddr, + int iPingTime, + int iNumClients ) { // color definition: <= 25 ms green, <= 50 ms yellow, otherwise red int iPingTimeLEDColor; @@ -720,9 +722,10 @@ void CLlconClientDlg::OnCLPingTimeResult ( CHostAddress InetAddr, } // update connection dialog server list - ConnectDlg.SetPingTimeResult ( InetAddr, - iPingTime, - iPingTimeLEDColor ); + ConnectDlg.SetPingTimeAndNumClientsResult ( InetAddr, + iPingTime, + iPingTimeLEDColor, + iNumClients ); } void CLlconClientDlg::ConnectDisconnect ( const bool bDoStart ) diff --git a/src/llconclientdlg.h b/src/llconclientdlg.h index ec63110f..b5b239f6 100755 --- a/src/llconclientdlg.h +++ b/src/llconclientdlg.h @@ -115,7 +115,9 @@ public slots: void OnTimerPing(); void OnPingTimeResult ( int iPingTime ); - void OnCLPingTimeResult ( CHostAddress InetAddr, int iPingTime ); + void OnCLPingTimeWithNumClientsReceived ( CHostAddress InetAddr, + int iPingTime, + int iNumClients ); void OnOpenGeneralSettings(); void OnOpenChatDialog() diff --git a/src/protocol.cpp b/src/protocol.cpp index bef7a75d..41b335b6 100755 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -1,1727 +1,1767 @@ -/******************************************************************************\ - * Copyright (c) 2004-2011 - * - * Author(s): - * Volker Fischer - * - -Protocol message definition ---------------------------- - -- All messages received need to be acknowledged by an acknowledge packet (except - of connection less messages) - - - -MAIN FRAME ----------- - - +-------------+------------+------------+------------------+ ... - | 2 bytes TAG | 2 bytes ID | 1 byte cnt | 2 bytes length n | ... - +-------------+------------+------------+------------------+ ... - ... --------------+-------------+ - ... n bytes data | 2 bytes CRC | - ... --------------+-------------+ - -- TAG is an all zero bit word to identify protocol messages -- message ID defined by the defines PROTMESSID_x -- cnt: counter which is increment for each message and wraps around at 255 -- length n in bytes of the data -- actual data, dependent on message type -- 16 bits CRC, calculating over the entire message, is transmitted inverted - Generator polynom: G_16(x) = x^16 + x^12 + x^5 + 1, initial state: all ones - - - -MESSAGES --------- - -- PROTMESSID_ACKN: Acknowledgement message - - +-----------------------------------+ - | 2 bytes ID of message to be ackn. | - +-----------------------------------+ - - note: the cnt value is the same as of the message to be acknowledged - - -- PROTMESSID_JITT_BUF_SIZE: Jitter buffer size - - +--------------------------+ - | 2 bytes number of blocks | - +--------------------------+ - - -- PROTMESSID_REQ_JITT_BUF_SIZE: Request jitter buffer size - - note: does not have any data -> n = 0 - - -- PROTMESSID_CHANNEL_GAIN: Gain of channel - - +-------------------+--------------+ - | 1 byte channel ID | 2 bytes gain | - +-------------------+--------------+ - - -- PROTMESSID_CONN_CLIENTS_LIST: IP number and name of connected clients - - for each connected client append following data: - - +-------------------+--------------------+------------------+ ... - | 1 byte channel ID | 4 bytes IP address | 2 bytes number n | ... - +-------------------+--------------------+------------------+ ... - ... ----------------------+ - ... n bytes UTF-8 string | - ... ----------------------+ - - -- PROTMESSID_REQ_CONN_CLIENTS_LIST: Request connected clients list - - note: does not have any data -> n = 0 - - -- PROTMESSID_CHANNEL_NAME: Name of channel - - for each connected client append following data: - - +------------------+----------------------+ - | 2 bytes number n | n bytes UTF-8 string | - +------------------+----------------------+ - - -- PROTMESSID_REQ_CHANNEL_NAME: Request name of channel - - note: does not have any data -> n = 0 - - -- PROTMESSID_CHAT_TEXT: Chat text - - +------------------+----------------------+ - | 2 bytes number n | n bytes UTF-8 string | - +------------------+----------------------+ - - -- PROTMESSID_PING_MS: Ping message (for measuring the ping time) - - +-----------------------------+ - | 4 bytes transmit time in ms | - +-----------------------------+ - - -- PROTMESSID_NETW_TRANSPORT_PROPS: Properties for network transport - - +------------------------+-------------------------+-----------------+ ... - | 4 bytes base netw size | 2 bytes block size fact | 1 byte num chan | ... - +------------------------+-------------------------+-----------------+ ... - ... ------------------+-----------------------+ ... - ... 4 bytes sam rate | 2 bytes audiocod type | ... - ... ------------------+-----------------------+ ... - ... -----------------+----------------------+ - ... 2 bytes version | 4 bytes audiocod arg | - ... -----------------+----------------------+ - - - "base netw size": length of the base network packet (frame) in bytes - - "block size fact": block size factor - - "num chan": number of channels of the audio signal, e.g. "2" is - stereo - - "sam rate": sample rate of the audio stream - - "audiocod type": audio coding type, the following types are supported: - - 0: none, no audio coding applied - - 1: CELT - - "version": version of the audio coder, if not used this value - shall be set to 0 - - "audiocod arg": argument for the audio coder, if not used this value - shall be set to 0 - - -- PROTMESSID_REQ_NETW_TRANSPORT_PROPS: Request properties for network transport - - note: does not have any data -> n = 0 - - -- PROTMESSID_DISCONNECTION: Disconnect message - - note: does not have any data -> n = 0 - - - -CONNECTION LESS MESSAGES ------------------------- - -- PROTMESSID_CLM_PING_MS: Connection less ping message (for measuring the ping - time) - - note: same definition as PROTMESSID_PING_MS - - -- PROTMESSID_SERVER_FULL: Connection less server full message - - note: does not have any data -> n = 0 - - -- PROTMESSID_CLM_REGISTER_SERVER: Register a server, providing server - information - - +-----------------+---------------------------------+ ... - | 2 bytes country | 1 byte number connected clients | ... - +-----------------+---------------------------------+ ... - ... ---------------------------------+---------------------+ ... - ... 1 byte maximum connected clients | 1 byte is permanent | ... - ... ---------------------------------+---------------------+ ... - ... -----------------+----------------------------------+ ... - ... 2 bytes number n | n bytes UTF-8 string server name | ... - ... -----------------+----------------------------------+ ... - ... -----------------+----------------------------+ ... - ... 2 bytes number n | n bytes UTF-8 string topic | ... - ... -----------------+----------------------------+ ... - ... -----------------+---------------------------+ - ... 2 bytes number n | n bytes UTF-8 string city | - ... -----------------+---------------------------+ - - - "country" is according to "Common Locale Data Repository" which is used in - the QLocale class - - "connected clients" is the current number of connected clients - - "maximum connected clients" is the maximum number of clients which can - be connected to the server at the same time - - "is permanent" is a flag which indicates if the server is permanent - online or not. If this value is any value <> 0 indicates that the server - is permanent online. - - -- PROTMESSID_CLM_SERVER_LIST: Server list message - - for each registered server append following data: - - +--------------------+--------------+--------------------------------+ - | 4 bytes IP address | 2 bytes port | PROTMESSID_CLM_REGISTER_SERVER | - +--------------------+--------------+--------------------------------+ - - - "PROTMESSID_CLM_REGISTER_SERVER" means that exactly the same message body - of the PROTMESSID_CLM_REGISTER_SERVER message is used - - -- PROTMESSID_CLM_REQ_SERVER_LIST: Request server list - - note: does not have any data -> n = 0 - - -- PROTMESSID_CLM_SEND_EMPTY_MESSAGE: Send "empty message" message - - +--------------------+--------------+ - | 4 bytes IP address | 2 bytes port | - +--------------------+--------------+ - - - ****************************************************************************** - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -\******************************************************************************/ - -#include "protocol.h" - - -/* Implementation *************************************************************/ -CProtocol::CProtocol() -{ - Reset(); - - - // Connections ------------------------------------------------------------- - QObject::connect ( &TimerSendMess, SIGNAL ( timeout() ), - this, SLOT ( OnTimerSendMess() ) ); -} - -void CProtocol::Reset() -{ - QMutexLocker locker ( &Mutex ); - - // prepare internal variables for initial protocol transfer - iCounter = 0; - iOldRecID = PROTMESSID_ILLEGAL; - iOldRecCnt = 0; - - // delete complete "send message queue" - SendMessQueue.clear(); -} - -void CProtocol::EnqueueMessage ( CVector& vecMessage, - const int iCnt, - const int iID ) -{ - bool bListWasEmpty; - - Mutex.lock(); - { - // check if list is empty so that we have to initiate a send process - bListWasEmpty = SendMessQueue.empty(); - - // create send message object for the queue - CSendMessage SendMessageObj ( vecMessage, iCnt, iID ); - - // we want to have a FIFO: we add at the end and take from the beginning - SendMessQueue.push_back ( SendMessageObj ); - } - Mutex.unlock(); - - // if list was empty, initiate send process - if ( bListWasEmpty ) - { - SendMessage(); - } -} - -void CProtocol::SendMessage() -{ - CVector vecMessage; - bool bSendMess = false; - - Mutex.lock(); - { - // we have to check that list is not empty, since in another thread the - // last element of the list might have been erased - if ( !SendMessQueue.empty() ) - { - vecMessage.Init ( SendMessQueue.front().vecMessage.Size() ); - vecMessage = SendMessQueue.front().vecMessage; - - bSendMess = true; - } - } - Mutex.unlock(); - - if ( bSendMess ) - { - // send message - emit MessReadyForSending ( vecMessage ); - - // start time-out timer if not active - if ( !TimerSendMess.isActive() ) - { - TimerSendMess.start ( SEND_MESS_TIMEOUT_MS ); - } - } - else - { - // no message to send, stop timer - TimerSendMess.stop(); - } -} - -void CProtocol::CreateAndSendMessage ( const int iID, - const CVector& vecData ) -{ - CVector vecNewMessage; - int iCurCounter; - - Mutex.lock(); - { - // store current counter value - iCurCounter = iCounter; - - // increase counter (wraps around automatically) - iCounter++; - } - Mutex.unlock(); - - // build complete message - GenMessageFrame ( vecNewMessage, iCurCounter, iID, vecData ); - - // enqueue message - EnqueueMessage ( vecNewMessage, iCurCounter, iID ); -} - -void CProtocol::CreateAndImmSendAcknMess ( const int& iID, - const int& iCnt ) -{ - CVector vecAcknMessage; - CVector vecData ( 2 ); // 2 bytes of data - int iPos = 0; // init position pointer - - // build data vector - PutValOnStream ( vecData, iPos, static_cast ( iID ), 2 ); - - // build complete message - GenMessageFrame ( vecAcknMessage, iCnt, PROTMESSID_ACKN, vecData ); - - // immediately send acknowledge message - emit MessReadyForSending ( vecAcknMessage ); -} - -void CProtocol::CreateAndImmSendConLessMessage ( const int iID, - const CVector& vecData, - const CHostAddress& InetAddr ) -{ - CVector vecNewMessage; - - // build complete message (counter per definition=0 for connection less - // messages) - GenMessageFrame ( vecNewMessage, 0, iID, vecData ); - - // immediately send message - emit CLMessReadyForSending ( InetAddr, vecNewMessage ); -} - -bool CProtocol::IsProtocolMessage ( const CVector& vecbyData, - const int iNumBytes ) -{ -/* - just check if this is a protocol message but do not act on message -*/ - int iRecCounter, iRecID; - CVector vecData; - - return !ParseMessageFrame ( vecbyData, - iNumBytes, - iRecCounter, - iRecID, - vecData ); -} - -bool CProtocol::ParseMessage ( const CVector& vecbyData, - const int iNumBytes ) -{ -/* - return code: false -> ok; true -> error -*/ - bool bRet = false; - bool bSendNextMess; - int iRecCounter, iRecID; - CVector vecData; - - if ( !ParseMessageFrame ( vecbyData, iNumBytes, iRecCounter, iRecID, vecData ) ) - { - -/* -// TEST channel implementation: randomly delete protocol messages (50 % loss) -if ( rand() < ( RAND_MAX / 2 ) ) return false; -*/ - - // in case this is a connection less message, we do not process it here - if ( IsConnectionLessMessageID ( iRecID ) ) - { - - -// TODO fire signal so that an other class can process this type of message - - - // return function without issuing an error code (since it is a - // regular message but will just not processed here) - return false; - } - - // In case we received a message and returned an answer but our answer - // did not make it to the receiver, he will resend his message. We check - // here if the message is the same as the old one, and if this is the - // case, just resend our old answer again - if ( ( iOldRecID == iRecID ) && ( iOldRecCnt == iRecCounter ) ) - { - // acknowledgments are not acknowledged - if ( iRecID != PROTMESSID_ACKN ) - { - // resend acknowledgement - CreateAndImmSendAcknMess ( iRecID, iRecCounter ); - } - } - else - { - // special treatment for acknowledge messages - if ( iRecID == PROTMESSID_ACKN ) - { - // extract data from stream and emit signal for received value - int iPos = 0; - const int iData = - static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); - - Mutex.lock(); - { - // check if this is the correct acknowledgment - bSendNextMess = false; - if ( !SendMessQueue.empty() ) - { - if ( ( SendMessQueue.front().iCnt == iRecCounter ) && - ( SendMessQueue.front().iID == iData ) ) - { - // message acknowledged, remove from queue - SendMessQueue.pop_front(); - - // send next message in queue - bSendNextMess = true; - } - } - } - Mutex.unlock(); - - if ( bSendNextMess ) - { - SendMessage(); - } - } - else - { - // check which type of message we received and do action - switch ( iRecID ) - { - case PROTMESSID_JITT_BUF_SIZE: - bRet = EvaluateJitBufMes ( vecData ); - break; - - case PROTMESSID_REQ_JITT_BUF_SIZE: - bRet = EvaluateReqJitBufMes(); - break; - - case PROTMESSID_CHANNEL_GAIN: - bRet = EvaluateChanGainMes ( vecData ); - break; - - case PROTMESSID_CONN_CLIENTS_LIST: - bRet = EvaluateConClientListMes ( vecData ); - break; - - case PROTMESSID_REQ_CONN_CLIENTS_LIST: - bRet = EvaluateReqConnClientsList(); - break; - - case PROTMESSID_CHANNEL_NAME: - bRet = EvaluateChanNameMes ( vecData ); - break; - - case PROTMESSID_REQ_CHANNEL_NAME: - bRet = EvaluateReqChanNameMes(); - break; - - case PROTMESSID_CHAT_TEXT: - bRet = EvaluateChatTextMes ( vecData ); - break; - - case PROTMESSID_PING_MS: - bRet = EvaluatePingMes ( vecData ); - break; - - case PROTMESSID_NETW_TRANSPORT_PROPS: - bRet = EvaluateNetwTranspPropsMes ( vecData ); - break; - - case PROTMESSID_REQ_NETW_TRANSPORT_PROPS: - bRet = EvaluateReqNetwTranspPropsMes(); - break; - - case PROTMESSID_DISCONNECTION: - bRet = EvaluateDisconnectionMes(); - break; - } - - // immediately send acknowledge message - CreateAndImmSendAcknMess ( iRecID, iRecCounter ); - - // save current message ID and counter to find out if message - // was resent - iOldRecID = iRecID; - iOldRecCnt = iRecCounter; - } - } - } - else - { - bRet = true; // return error code - } - - return bRet; -} - -bool CProtocol::ParseConnectionLessMessage ( const CVector& vecbyData, - const int iNumBytes, - const CHostAddress& InetAddr ) -{ -/* - return code: false -> ok; true -> error -*/ - bool bRet = false; - int iRecCounter, iRecID; - CVector vecData; - - if ( !ParseMessageFrame ( vecbyData, iNumBytes, iRecCounter, iRecID, vecData ) ) - { - if ( IsConnectionLessMessageID ( iRecID ) ) - { - // check which type of message we received and do action - switch ( iRecID ) - { - case PROTMESSID_CLM_PING_MS: - bRet = EvaluateCLPingMes ( InetAddr, vecData ); - break; - - case PROTMESSID_CLM_SERVER_FULL: - bRet = EvaluateCLServerFullMes(); - break; - - case PROTMESSID_CLM_SERVER_LIST: - bRet = EvaluateCLServerListMes ( InetAddr, vecData ); - break; - - case PROTMESSID_CLM_REQ_SERVER_LIST: - bRet = EvaluateCLReqServerListMes ( InetAddr ); - break; - - case PROTMESSID_CLM_SEND_EMPTY_MESSAGE: - bRet = EvaluateCLSendEmptyMesMes ( vecData ); - break; - - case PROTMESSID_CLM_REGISTER_SERVER: - bRet = EvaluateCLRegisterServerMes ( InetAddr, vecData ); - break; - } - } - else - { - bRet = true; // return error code - } - } - else - { - bRet = true; // return error code - } - - return bRet; -} - - -/******************************************************************************\ -* Access-functions for creating and parsing messages * -\******************************************************************************/ -void CProtocol::CreateJitBufMes ( const int iJitBufSize ) -{ - CVector vecData ( 2 ); // 2 bytes of data - int iPos = 0; // init position pointer - - // build data vector - PutValOnStream ( vecData, iPos, static_cast ( iJitBufSize ), 2 ); - - CreateAndSendMessage ( PROTMESSID_JITT_BUF_SIZE, vecData ); -} - -bool CProtocol::EvaluateJitBufMes ( const CVector& vecData ) -{ - int iPos = 0; // init position pointer - - // check size - if ( vecData.Size() != 2 ) - { - return true; // return error code - } - - // extract jitter buffer size - const int iData = - static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); - - if ( ( iData < MIN_NET_BUF_SIZE_NUM_BL ) || - ( iData > MAX_NET_BUF_SIZE_NUM_BL ) ) - { - return true; // return error code - } - - // invoke message action - emit ChangeJittBufSize ( iData ); - - return false; // no error -} - -void CProtocol::CreateReqJitBufMes() -{ - CreateAndSendMessage ( PROTMESSID_REQ_JITT_BUF_SIZE, - CVector ( 0 ) ); -} - -bool CProtocol::EvaluateReqJitBufMes() -{ - // invoke message action - emit ReqJittBufSize(); - - return false; // no error -} - -void CProtocol::CreateChanGainMes ( const int iChanID, const double dGain ) -{ - CVector vecData ( 3 ); // 3 bytes of data - int iPos = 0; // init position pointer - - // build data vector - // channel ID - PutValOnStream ( vecData, iPos, static_cast ( iChanID ), 1 ); - - // actual gain, we convert from double with range 0..1 to integer - const int iCurGain = static_cast ( dGain * ( 1 << 15 ) ); - - PutValOnStream ( vecData, iPos, static_cast ( iCurGain ), 2 ); - - CreateAndSendMessage ( PROTMESSID_CHANNEL_GAIN, vecData ); -} - -bool CProtocol::EvaluateChanGainMes ( const CVector& vecData ) -{ - int iPos = 0; // init position pointer - - // check size - if ( vecData.Size() != 3 ) - { - return true; // return error code - } - - // channel ID - const int iCurID = - static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); - - // gain (read integer value) - const int iData = - static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); - - // we convert the gain from integer to double with range 0..1 - const double dNewGain = static_cast ( iData ) / ( 1 << 15 ); - - // invoke message action - emit ChangeChanGain ( iCurID, dNewGain ); - - return false; // no error -} - -void CProtocol::CreateConClientListMes ( const CVector& vecChanInfo ) -{ - const int iNumClients = vecChanInfo.Size(); - - // build data vector - CVector vecData ( 0 ); - int iPos = 0; // init position pointer - - for ( int i = 0; i < iNumClients; i++ ) - { - // current string size - const int iCurStrLen = vecChanInfo[i].strName.size(); - - // size of current list entry - const int iCurListEntrLen = - 1 /* chan ID */ + 4 /* IP addr. */ + 2 /* str. size */ + iCurStrLen; - - // make space for new data - vecData.Enlarge ( iCurListEntrLen ); - - // channel ID - PutValOnStream ( vecData, iPos, - static_cast ( vecChanInfo[i].iChanID ), 1 ); - - // IP address (4 bytes) - PutValOnStream ( vecData, iPos, - static_cast ( vecChanInfo[i].iIpAddr ), 4 ); - - // name string - PutStringOnStream ( vecData, iPos, vecChanInfo[i].strName ); - } - - CreateAndSendMessage ( PROTMESSID_CONN_CLIENTS_LIST, vecData ); -} - -bool CProtocol::EvaluateConClientListMes ( const CVector& vecData ) -{ - int iPos = 0; // init position pointer - const int iDataLen = vecData.Size(); - CVector vecChanInfo ( 0 ); - - while ( iPos < iDataLen ) - { - // check size (the next 5 bytes) - if ( ( iDataLen - iPos ) < 5 ) - { - return true; // return error code - } - - // channel ID (1 byte) - const int iChanID = - static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); - - // IP address (4 bytes) - const int iIpAddr = - static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); - - // name - QString strCurStr; - if ( GetStringFromStream ( vecData, - iPos, - MAX_LEN_FADER_TAG, - strCurStr ) ) - { - return true; // return error code - } - - // add channel information to vector - vecChanInfo.Add ( CChannelShortInfo ( iChanID, iIpAddr, strCurStr ) ); - } - - // check size: all data is read, the position must now be at the end - if ( iPos != iDataLen ) - { - return true; // return error code - } - - // invoke message action - emit ConClientListMesReceived ( vecChanInfo ); - - return false; // no error -} - -void CProtocol::CreateReqConnClientsList() -{ - CreateAndSendMessage ( PROTMESSID_REQ_CONN_CLIENTS_LIST, CVector ( 0 ) ); -} - -bool CProtocol::EvaluateReqConnClientsList() -{ - // invoke message action - emit ReqConnClientsList(); - - return false; // no error -} - -void CProtocol::CreateChanNameMes ( const QString strName ) -{ - int iPos = 0; // init position pointer - const int iStrLen = strName.size(); // get string size - - // size of current list entry - const int iEntrLen = 2 /* string size */ + iStrLen; - - // build data vector - CVector vecData ( iEntrLen ); - - // name string - PutStringOnStream ( vecData, iPos, strName ); - - CreateAndSendMessage ( PROTMESSID_CHANNEL_NAME, vecData ); -} - -bool CProtocol::EvaluateChanNameMes ( const CVector& vecData ) -{ - int iPos = 0; // init position pointer - - // channel name - QString strName; - if ( GetStringFromStream ( vecData, - iPos, - MAX_LEN_FADER_TAG, - strName ) ) - { - return true; // return error code - } - - // check size: all data is read, the position must now be at the end - if ( iPos != vecData.Size() ) - { - return true; // return error code - } - - // invoke message action - emit ChangeChanName ( strName ); - - return false; // no error -} - -void CProtocol::CreateReqChanNameMes() -{ - CreateAndSendMessage ( PROTMESSID_REQ_CHANNEL_NAME, CVector ( 0 ) ); -} - -bool CProtocol::EvaluateReqChanNameMes() -{ - // invoke message action - emit ReqChanName(); - - return false; // no error -} - -void CProtocol::CreateChatTextMes ( const QString strChatText ) -{ - int iPos = 0; // init position pointer - const int iStrLen = strChatText.size(); // get string size - - // size of message body - const int iEntrLen = 2 /* string size */ + iStrLen; - - // build data vector - CVector vecData ( iEntrLen ); - - // chat text - PutStringOnStream ( vecData, iPos, strChatText ); - - CreateAndSendMessage ( PROTMESSID_CHAT_TEXT, vecData ); -} - -bool CProtocol::EvaluateChatTextMes ( const CVector& vecData ) -{ - int iPos = 0; // init position pointer - - // chat text - QString strChatText; - if ( GetStringFromStream ( vecData, - iPos, - MAX_LEN_CHAT_TEXT_PLUS_HTML, - strChatText ) ) - { - return true; // return error code - } - - // check size: all data is read, the position must now be at the end - if ( iPos != vecData.Size() ) - { - return true; // return error code - } - - // invoke message action - emit ChatTextReceived ( strChatText ); - - return false; // no error -} - -void CProtocol::CreatePingMes ( const int iMs ) -{ - int iPos = 0; // init position pointer - - // build data vector (4 bytes long) - CVector vecData ( 4 ); - - // transmit time (4 bytes) - PutValOnStream ( vecData, iPos, static_cast ( iMs ), 4 ); - - CreateAndSendMessage ( PROTMESSID_PING_MS, vecData ); -} - -bool CProtocol::EvaluatePingMes ( const CVector& vecData ) -{ - int iPos = 0; // init position pointer - - // check size - if ( vecData.Size() != 4 ) - { - return true; // return error code - } - - // invoke message action - emit PingReceived ( static_cast ( GetValFromStream ( vecData, iPos, 4 ) ) ); - - return false; // no error -} - -void CProtocol::CreateNetwTranspPropsMes ( const CNetworkTransportProps& NetTrProps ) -{ - int iPos = 0; // init position pointer - - // size of current message body - const int iEntrLen = - 4 /* netw size */ + - 2 /* block size fact */ + - 1 /* num chan */ + - 4 /* sam rate */ + - 2 /* audiocod type */ + - 2 /* version */ + - 4 /* audiocod arg */; - - // build data vector - CVector vecData ( iEntrLen ); - - // length of the base network packet (frame) in bytes (4 bytes) - PutValOnStream ( vecData, iPos, - static_cast ( NetTrProps.iBaseNetworkPacketSize ), 4 ); - - // block size factor (2 bytes) - PutValOnStream ( vecData, iPos, - static_cast ( NetTrProps.iBlockSizeFact ), 2 ); - - // number of channels of the audio signal, e.g. "2" is stereo (1 byte) - PutValOnStream ( vecData, iPos, - static_cast ( NetTrProps.iNumAudioChannels ), 1 ); - - // sample rate of the audio stream (4 bytes) - PutValOnStream ( vecData, iPos, - static_cast ( NetTrProps.iSampleRate ), 4 ); - - // audio coding type (2 bytes) - PutValOnStream ( vecData, iPos, - static_cast ( NetTrProps.eAudioCodingType ), 2 ); - - // version (2 bytes) - PutValOnStream ( vecData, iPos, - static_cast ( NetTrProps.iVersion ), 2 ); - - // argument for the audio coder (4 bytes) - PutValOnStream ( vecData, iPos, - static_cast ( NetTrProps.iAudioCodingArg ), 4 ); - - CreateAndSendMessage ( PROTMESSID_NETW_TRANSPORT_PROPS, vecData ); -} - -bool CProtocol::EvaluateNetwTranspPropsMes ( const CVector& vecData ) -{ - int iPos = 0; // init position pointer - CNetworkTransportProps ReceivedNetwTranspProps; - - // size of current message body - const int iEntrLen = - 4 /* netw size */ + - 2 /* block size fact */ + - 1 /* num chan */ + - 4 /* sam rate */ + - 2 /* audiocod type */ + - 2 /* version */ + - 4 /* audiocod arg */; - - // check size - if ( vecData.Size() != iEntrLen ) - { - return true; // return error code - } - - // length of the base network packet (frame) in bytes (4 bytes) - ReceivedNetwTranspProps.iBaseNetworkPacketSize = - static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); - - if ( ( ReceivedNetwTranspProps.iBaseNetworkPacketSize < 1 ) || - ( ReceivedNetwTranspProps.iBaseNetworkPacketSize > MAX_SIZE_BYTES_NETW_BUF ) ) - { - return true; // return error code - } - - // block size factor (2 bytes) - ReceivedNetwTranspProps.iBlockSizeFact = - static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); - - if ( ( ReceivedNetwTranspProps.iBlockSizeFact != FRAME_SIZE_FACTOR_PREFERRED ) && - ( ReceivedNetwTranspProps.iBlockSizeFact != FRAME_SIZE_FACTOR_DEFAULT ) && - ( ReceivedNetwTranspProps.iBlockSizeFact != FRAME_SIZE_FACTOR_SAFE ) ) - { - return true; // return error code - } - - // number of channels of the audio signal, only mono (1 channel) or - // stereo (2 channels) allowed (1 byte) - ReceivedNetwTranspProps.iNumAudioChannels = - static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); - - if ( ( ReceivedNetwTranspProps.iNumAudioChannels != 1 ) && - ( ReceivedNetwTranspProps.iNumAudioChannels != 2 ) ) - { - return true; // return error code - } - - // sample rate of the audio stream (4 bytes) - ReceivedNetwTranspProps.iSampleRate = - static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); - - // audio coding type (2 bytes) with error check - const int iRecCodingType = - static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); - - if ( ( iRecCodingType != CT_NONE ) && - ( iRecCodingType != CT_CELT ) ) - { - return true; - } - - ReceivedNetwTranspProps.eAudioCodingType = - static_cast ( iRecCodingType ); - - // version (2 bytes) - ReceivedNetwTranspProps.iVersion = - static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); - - // argument for the audio coder (4 bytes) - ReceivedNetwTranspProps.iAudioCodingArg = - static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); - - // invoke message action - emit NetTranspPropsReceived ( ReceivedNetwTranspProps ); - - return false; // no error -} - -void CProtocol::CreateReqNetwTranspPropsMes() -{ - CreateAndSendMessage ( PROTMESSID_REQ_NETW_TRANSPORT_PROPS, - CVector ( 0 ) ); -} - -bool CProtocol::EvaluateReqNetwTranspPropsMes() -{ - // invoke message action - emit ReqNetTranspProps(); - - return false; // no error -} - -void CProtocol::CreateAndImmSendDisconnectionMes() -{ - CVector vecDisconMessage; - int iCurCounter; - - Mutex.lock(); - { - // store current counter value - iCurCounter = iCounter; - - // increase counter (wraps around automatically) - iCounter++; - } - Mutex.unlock(); - - // build complete message - GenMessageFrame ( vecDisconMessage, iCurCounter, - PROTMESSID_DISCONNECTION, CVector ( 0 ) ); - - // immediately send acknowledge message - emit MessReadyForSending ( vecDisconMessage ); -} - -bool CProtocol::EvaluateDisconnectionMes() -{ - // invoke message action - emit Disconnection(); - - return false; // no error -} - - -// Connection less messages ---------------------------------------------------- -void CProtocol::CreateCLPingMes ( const CHostAddress& InetAddr, const int iMs ) -{ - int iPos = 0; // init position pointer - - // build data vector (4 bytes long) - CVector vecData ( 4 ); - - // transmit time (4 bytes) - PutValOnStream ( vecData, iPos, static_cast ( iMs ), 4 ); - - CreateAndImmSendConLessMessage ( PROTMESSID_CLM_PING_MS, - vecData, - InetAddr ); -} - -bool CProtocol::EvaluateCLPingMes ( const CHostAddress& InetAddr, - const CVector& vecData ) -{ - int iPos = 0; // init position pointer - - // check size - if ( vecData.Size() != 4 ) - { - return true; // return error code - } - - // invoke message action - emit CLPingReceived ( InetAddr, - static_cast ( GetValFromStream ( vecData, iPos, 4 ) ) ); - - return false; // no error -} - -void CProtocol::CreateCLServerFullMes ( const CHostAddress& InetAddr ) -{ - CreateAndImmSendConLessMessage ( PROTMESSID_CLM_SERVER_FULL, - CVector ( 0 ), - InetAddr ); -} - -bool CProtocol::EvaluateCLServerFullMes() -{ - // invoke message action - emit ServerFullMesReceived(); - - return false; // no error -} - -void CProtocol::CreateCLRegisterServerMes ( const CHostAddress& InetAddr, - const CServerCoreInfo& ServerInfo ) -{ - int iPos = 0; // init position pointer - - // size of current message body - const int iEntrLen = - 2 /* country */ + - 1 /* number of connected clients */ + - 1 /* maximum number of connected clients */ + - 1 /* is permanent flag */ + - 2 /* name string size */ + ServerInfo.strName.size() + - 2 /* topic string size */ + ServerInfo.strTopic.size() + - 2 /* city string size */ + ServerInfo.strCity.size(); - - // build data vector - CVector vecData ( iEntrLen ); - - // country (2 bytes) - PutValOnStream ( vecData, iPos, - static_cast ( ServerInfo.eCountry ), 2 ); - - // number of connected clients (1 byte) - PutValOnStream ( vecData, iPos, - static_cast ( ServerInfo.iNumClients ), 1 ); - - // maximum number of connected clients (1 byte) - PutValOnStream ( vecData, iPos, - static_cast ( ServerInfo.iMaxNumClients ), 1 ); - - // "is permanent" flag (1 byte) - PutValOnStream ( vecData, iPos, - static_cast ( ServerInfo.bPermanentOnline ), 1 ); - - // name - PutStringOnStream ( vecData, iPos, ServerInfo.strName ); - - // topic - PutStringOnStream ( vecData, iPos, ServerInfo.strTopic ); - - // city - PutStringOnStream ( vecData, iPos, ServerInfo.strCity ); - - CreateAndImmSendConLessMessage ( PROTMESSID_CLM_REGISTER_SERVER, - vecData, - InetAddr ); -} - -bool CProtocol::EvaluateCLRegisterServerMes ( const CHostAddress& InetAddr, - const CVector& vecData ) -{ - int iPos = 0; // init position pointer - const int iDataLen = vecData.Size(); - CServerCoreInfo RecServerInfo; - - // check size (the first 5 bytes) - if ( iDataLen < 5 ) - { - return true; // return error code - } - - // country (2 bytes) - RecServerInfo.eCountry = - static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); - - // number of connected clients (1 byte) - RecServerInfo.iNumClients = - static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); - - // maximum number of connected clients (1 byte) - RecServerInfo.iMaxNumClients = - static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); - - // "is permanent" flag (1 byte) - RecServerInfo.bPermanentOnline = - static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); - - // server name - if ( GetStringFromStream ( vecData, - iPos, - MAX_LEN_SERVER_NAME, - RecServerInfo.strName ) ) - { - return true; // return error code - } - - // server topic - if ( GetStringFromStream ( vecData, - iPos, - MAX_LEN_SERVER_TOPIC, - RecServerInfo.strTopic ) ) - { - return true; // return error code - } - - // server city - if ( GetStringFromStream ( vecData, - iPos, - MAX_LEN_SERVER_CITY, - RecServerInfo.strCity ) ) - { - return true; // return error code - } - - // check size: all data is read, the position must now be at the end - if ( iPos != iDataLen ) - { - return true; // return error code - } - - // invoke message action - emit CLRegisterServerReceived ( InetAddr, RecServerInfo ); - - return false; // no error -} - - -void CProtocol::CreateCLServerListMes ( const CHostAddress& InetAddr, - const CVector vecServerInfo ) -{ - const int iNumServers = vecServerInfo.Size(); - - // build data vector - CVector vecData ( 0 ); - int iPos = 0; // init position pointer - - for ( int i = 0; i < iNumServers; i++ ) - { - // size of current list entry - const int iCurListEntrLen = - 4 /* IP address */ + - 2 /* port number */ + - 2 /* country */ + - 1 /* number of connected clients */ + - 1 /* maximum number of connected clients */ + - 1 /* is permanent flag */ + - 2 /* name string size */ + vecServerInfo[i].strName.size() + - 2 /* topic string size */ + vecServerInfo[i].strTopic.size() + - 2 /* city string size */ + vecServerInfo[i].strCity.size(); - - // make space for new data - vecData.Enlarge ( iCurListEntrLen ); - - // IP address (4 bytes) - PutValOnStream ( vecData, iPos, static_cast ( - vecServerInfo[i].HostAddr.InetAddr.toIPv4Address() ), 4 ); - - // port number (2 bytes) - PutValOnStream ( vecData, iPos, - static_cast ( vecServerInfo[i].HostAddr.iPort ), 2 ); - - // country (2 bytes) - PutValOnStream ( vecData, iPos, - static_cast ( vecServerInfo[i].eCountry ), 2 ); - - // number of connected clients (1 byte) - PutValOnStream ( vecData, iPos, - static_cast ( vecServerInfo[i].iNumClients ), 1 ); - - // maximum number of connected clients (1 byte) - PutValOnStream ( vecData, iPos, - static_cast ( vecServerInfo[i].iMaxNumClients ), 1 ); - - // "is permanent" flag (1 byte) - PutValOnStream ( vecData, iPos, - static_cast ( vecServerInfo[i].bPermanentOnline ), 1 ); - - // name - PutStringOnStream ( vecData, iPos, vecServerInfo[i].strName ); - - // topic - PutStringOnStream ( vecData, iPos, vecServerInfo[i].strTopic ); - - // city - PutStringOnStream ( vecData, iPos, vecServerInfo[i].strCity ); - } - - CreateAndImmSendConLessMessage ( PROTMESSID_CLM_SERVER_LIST, - vecData, - InetAddr ); -} - -bool CProtocol::EvaluateCLServerListMes ( const CHostAddress& InetAddr, - const CVector& vecData ) -{ - int iPos = 0; // init position pointer - const int iDataLen = vecData.Size(); - CVector vecServerInfo ( 0 ); - - while ( iPos < iDataLen ) - { - // check size (the next 11 bytes) - if ( ( iDataLen - iPos ) < 11 ) - { - return true; // return error code - } - - // IP address (4 bytes) - const quint32 iIpAddr = - static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); - - // port number (2 bytes) - const quint16 iPort = - static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); - - // country (2 bytes) - const QLocale::Country eCountry = - static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); - - // number of connected clients (1 byte) - const int iNumClients = - static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); - - // maximum number of connected clients (1 byte) - const int iMaxNumClients = - static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); - - // "is permanent" flag (1 byte) - const bool bPermanentOnline = - static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); - - // server name - QString strName; - if ( GetStringFromStream ( vecData, - iPos, - MAX_LEN_SERVER_NAME, - strName ) ) - { - return true; // return error code - } - - // server topic - QString strTopic; - if ( GetStringFromStream ( vecData, - iPos, - MAX_LEN_SERVER_TOPIC, - strTopic ) ) - { - return true; // return error code - } - - // server city - QString strCity; - if ( GetStringFromStream ( vecData, - iPos, - MAX_LEN_SERVER_CITY, - strCity ) ) - { - return true; // return error code - } - - // add server information to vector - vecServerInfo.Add ( - CServerInfo ( CHostAddress ( QHostAddress ( iIpAddr ), iPort ), - strName, - strTopic, - eCountry, - strCity, - iNumClients, - iMaxNumClients, - bPermanentOnline ) ); - } - - // check size: all data is read, the position must now be at the end - if ( iPos != iDataLen ) - { - return true; // return error code - } - - // invoke message action - emit CLServerListReceived ( InetAddr, vecServerInfo ); - - return false; // no error -} - -void CProtocol::CreateCLReqServerListMes ( const CHostAddress& InetAddr ) -{ - CreateAndImmSendConLessMessage ( PROTMESSID_CLM_REQ_SERVER_LIST, - CVector ( 0 ), - InetAddr ); -} - -bool CProtocol::EvaluateCLReqServerListMes ( const CHostAddress& InetAddr ) -{ - // invoke message action - emit CLReqServerList ( InetAddr ); - - return false; // no error -} - -void CProtocol::CreateCLSendEmptyMesMes ( const CHostAddress& InetAddr, - const CHostAddress& TargetInetAddr ) -{ - int iPos = 0; // init position pointer - - // build data vector (6 bytes long) - CVector vecData ( 6 ); - - // IP address (4 bytes) - PutValOnStream ( vecData, iPos, static_cast ( - TargetInetAddr.InetAddr.toIPv4Address() ), 4 ); - - // port number (2 bytes) - PutValOnStream ( vecData, iPos, - static_cast ( TargetInetAddr.iPort ), 2 ); - - CreateAndImmSendConLessMessage ( PROTMESSID_CLM_SEND_EMPTY_MESSAGE, - vecData, - InetAddr ); -} - -bool CProtocol::EvaluateCLSendEmptyMesMes ( const CVector& vecData ) -{ - int iPos = 0; // init position pointer - - // check size - if ( vecData.Size() != 6 ) - { - return true; // return error code - } - - // IP address (4 bytes) - const quint32 iIpAddr = - static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); - - // port number (2 bytes) - const quint16 iPort = - static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); - - // invoke message action - emit CLSendEmptyMes ( CHostAddress ( QHostAddress ( iIpAddr ), iPort ) ); - - return false; // no error -} - -void CProtocol::CreateCLEmptyMes ( const CHostAddress& InetAddr ) -{ - CreateAndImmSendConLessMessage ( PROTMESSID_CLM_EMPTY_MESSAGE, - CVector ( 0 ), - InetAddr ); -} - - -/******************************************************************************\ -* Message generation and parsing * -\******************************************************************************/ -bool CProtocol::ParseMessageFrame ( const CVector& vecIn, - const int iNumBytesIn, - int& iCnt, - int& iID, - CVector& vecData ) -{ - int i; - int iLenBy; - int iCurPos; - - // vector must be at least "MESS_LEN_WITHOUT_DATA_BYTE" bytes long - if ( iNumBytesIn < MESS_LEN_WITHOUT_DATA_BYTE ) - { - return true; // return error code - } - - - // Decode header ----------------------------------------------------------- - iCurPos = 0; // start from beginning - - // 2 bytes TAG - const int iTag = static_cast ( GetValFromStream ( vecIn, iCurPos, 2 ) ); - - // check if tag is correct - if ( iTag != 0 ) - { - return true; // return error code - } - - // 2 bytes ID - iID = static_cast ( GetValFromStream ( vecIn, iCurPos, 2 ) ); - - // 1 byte cnt - iCnt = static_cast ( GetValFromStream ( vecIn, iCurPos, 1 ) ); - - // 2 bytes length - iLenBy = static_cast ( GetValFromStream ( vecIn, iCurPos, 2 ) ); - - // make sure the length is correct - if ( iLenBy != iNumBytesIn - MESS_LEN_WITHOUT_DATA_BYTE ) - { - return true; // return error code - } - - - // Now check CRC ----------------------------------------------------------- - CCRC CRCObj; - const int iLenCRCCalc = MESS_HEADER_LENGTH_BYTE + iLenBy; - - iCurPos = 0; // start from the beginning - for ( i = 0; i < iLenCRCCalc; i++ ) - { - CRCObj.AddByte ( static_cast ( - GetValFromStream ( vecIn, iCurPos, 1 ) ) ); - } - - if ( CRCObj.GetCRC () != GetValFromStream ( vecIn, iCurPos, 2 ) ) - { - return true; // return error code - } - - - // Extract actual data ----------------------------------------------------- - vecData.Init ( iLenBy ); - iCurPos = MESS_HEADER_LENGTH_BYTE; // start from beginning of data - for ( i = 0; i < iLenBy; i++ ) - { - vecData[i] = static_cast ( - GetValFromStream ( vecIn, iCurPos, 1 ) ); - } - - return false; // no error -} - -uint32_t CProtocol::GetValFromStream ( const CVector& vecIn, - int& iPos, - const int iNumOfBytes ) -{ -/* - note: iPos is automatically incremented in this function -*/ - // 4 bytes maximum since we return uint32 - Q_ASSERT ( ( iNumOfBytes > 0 ) && ( iNumOfBytes <= 4 ) ); - Q_ASSERT ( vecIn.Size() >= iPos + iNumOfBytes ); - - uint32_t iRet = 0; - for ( int i = 0; i < iNumOfBytes; i++ ) - { - iRet |= vecIn[iPos] << ( i * 8 /* size of byte */ ); - iPos++; - } - - return iRet; -} - -bool CProtocol::GetStringFromStream ( const CVector& vecIn, - int& iPos, - const int iMaxStringLen, - QString& strOut ) -{ -/* - note: iPos is automatically incremented in this function -*/ - // check if at least two bytes are available - const int iInLen = vecIn.Size(); - if ( ( iInLen - iPos ) < 2 ) - { - return true; // return error code - } - - // number of bytes for string (2 bytes) - const int iStrLen = - static_cast ( GetValFromStream ( vecIn, iPos, 2 ) ); - - if ( ( ( iInLen - iPos ) < iStrLen ) || - ( iStrLen > iMaxStringLen ) ) - { - return true; // return error code - } - - // string (n bytes) - strOut = ""; - for ( int i = 0; i < iStrLen; i++ ) - { - // byte-by-byte copying of the string data - int iData = static_cast ( GetValFromStream ( vecIn, iPos, 1 ) ); - strOut += QString ( (char*) &iData ); - } - - return false; // no error -} - -void CProtocol::GenMessageFrame ( CVector& vecOut, - const int iCnt, - const int iID, - const CVector& vecData ) -{ - int i; - - // query length of data vector - const int iDataLenByte = vecData.Size(); - - // total length of message - const int iTotLenByte = MESS_LEN_WITHOUT_DATA_BYTE + iDataLenByte; - - // init message vector - vecOut.Init ( iTotLenByte ); - - - // Encode header ----------------------------------------------------------- - int iCurPos = 0; // init position pointer - - // 2 bytes TAG (all zero bits) - PutValOnStream ( vecOut, iCurPos, - static_cast ( 0 ), 2 ); - - // 2 bytes ID - PutValOnStream ( vecOut, iCurPos, - static_cast ( iID ), 2 ); - - // 1 byte cnt - PutValOnStream ( vecOut, iCurPos, - static_cast ( iCnt ), 1 ); - - // 2 bytes length - PutValOnStream ( vecOut, iCurPos, - static_cast ( iDataLenByte ), 2 ); - - // encode data ----- - for ( i = 0; i < iDataLenByte; i++ ) - { - PutValOnStream ( vecOut, iCurPos, - static_cast ( vecData[i] ), 1 ); - } - - - // Encode CRC -------------------------------------------------------------- - CCRC CRCObj; - iCurPos = 0; // start from beginning - - const int iLenCRCCalc = MESS_HEADER_LENGTH_BYTE + iDataLenByte; - for ( i = 0; i < iLenCRCCalc; i++ ) - { - CRCObj.AddByte ( static_cast ( - GetValFromStream ( vecOut, iCurPos, 1 ) ) ); - } - - PutValOnStream ( vecOut, iCurPos, - static_cast ( CRCObj.GetCRC() ), 2 ); -} - -void CProtocol::PutValOnStream ( CVector& vecIn, - int& iPos, - const uint32_t iVal, - const int iNumOfBytes ) -{ -/* - note: iPos is automatically incremented in this function -*/ - // 4 bytes maximum since we use uint32 - Q_ASSERT ( ( iNumOfBytes > 0 ) && ( iNumOfBytes <= 4 ) ); - Q_ASSERT ( vecIn.Size() >= iPos + iNumOfBytes ); - - for ( int i = 0; i < iNumOfBytes; i++ ) - { - vecIn[iPos] = - ( iVal >> ( i * 8 /* size of byte */ ) ) & 255 /* 11111111 */; - - iPos++; - } -} - -void CProtocol::PutStringOnStream ( CVector& vecIn, - int& iPos, - const QString& sString ) -{ - // get the string size - const int iStrLen = sString.size(); - - // number of bytes for string (2 bytes) - PutValOnStream ( vecIn, iPos, - static_cast ( iStrLen ), 2 ); - - // actual string (n bytes) - for ( int j = 0; j < iStrLen; j++ ) - { - // byte-by-byte copying of the string data - PutValOnStream ( vecIn, iPos, - static_cast ( sString[j].toAscii() ), 1 ); - } -} +/******************************************************************************\ + * Copyright (c) 2004-2011 + * + * Author(s): + * Volker Fischer + * + +Protocol message definition +--------------------------- + +- All messages received need to be acknowledged by an acknowledge packet (except + of connection less messages) + + + +MAIN FRAME +---------- + + +-------------+------------+------------+------------------+ ... + | 2 bytes TAG | 2 bytes ID | 1 byte cnt | 2 bytes length n | ... + +-------------+------------+------------+------------------+ ... + ... --------------+-------------+ + ... n bytes data | 2 bytes CRC | + ... --------------+-------------+ + +- TAG is an all zero bit word to identify protocol messages +- message ID defined by the defines PROTMESSID_x +- cnt: counter which is increment for each message and wraps around at 255 +- length n in bytes of the data +- actual data, dependent on message type +- 16 bits CRC, calculating over the entire message, is transmitted inverted + Generator polynom: G_16(x) = x^16 + x^12 + x^5 + 1, initial state: all ones + + + +MESSAGES +-------- + +- PROTMESSID_ACKN: Acknowledgement message + + +-----------------------------------+ + | 2 bytes ID of message to be ackn. | + +-----------------------------------+ + + note: the cnt value is the same as of the message to be acknowledged + + +- PROTMESSID_JITT_BUF_SIZE: Jitter buffer size + + +--------------------------+ + | 2 bytes number of blocks | + +--------------------------+ + + +- PROTMESSID_REQ_JITT_BUF_SIZE: Request jitter buffer size + + note: does not have any data -> n = 0 + + +- PROTMESSID_CHANNEL_GAIN: Gain of channel + + +-------------------+--------------+ + | 1 byte channel ID | 2 bytes gain | + +-------------------+--------------+ + + +- PROTMESSID_CONN_CLIENTS_LIST: IP number and name of connected clients + + for each connected client append following data: + + +-------------------+--------------------+------------------+ ... + | 1 byte channel ID | 4 bytes IP address | 2 bytes number n | ... + +-------------------+--------------------+------------------+ ... + ... ----------------------+ + ... n bytes UTF-8 string | + ... ----------------------+ + + +- PROTMESSID_REQ_CONN_CLIENTS_LIST: Request connected clients list + + note: does not have any data -> n = 0 + + +- PROTMESSID_CHANNEL_NAME: Name of channel + + for each connected client append following data: + + +------------------+----------------------+ + | 2 bytes number n | n bytes UTF-8 string | + +------------------+----------------------+ + + +- PROTMESSID_REQ_CHANNEL_NAME: Request name of channel + + note: does not have any data -> n = 0 + + +- PROTMESSID_CHAT_TEXT: Chat text + + +------------------+----------------------+ + | 2 bytes number n | n bytes UTF-8 string | + +------------------+----------------------+ + + +- PROTMESSID_PING_MS: Ping message (for measuring the ping time) + + +-----------------------------+ + | 4 bytes transmit time in ms | + +-----------------------------+ + + +- PROTMESSID_NETW_TRANSPORT_PROPS: Properties for network transport + + +------------------------+-------------------------+-----------------+ ... + | 4 bytes base netw size | 2 bytes block size fact | 1 byte num chan | ... + +------------------------+-------------------------+-----------------+ ... + ... ------------------+-----------------------+ ... + ... 4 bytes sam rate | 2 bytes audiocod type | ... + ... ------------------+-----------------------+ ... + ... -----------------+----------------------+ + ... 2 bytes version | 4 bytes audiocod arg | + ... -----------------+----------------------+ + + - "base netw size": length of the base network packet (frame) in bytes + - "block size fact": block size factor + - "num chan": number of channels of the audio signal, e.g. "2" is + stereo + - "sam rate": sample rate of the audio stream + - "audiocod type": audio coding type, the following types are supported: + - 0: none, no audio coding applied + - 1: CELT + - "version": version of the audio coder, if not used this value + shall be set to 0 + - "audiocod arg": argument for the audio coder, if not used this value + shall be set to 0 + + +- PROTMESSID_REQ_NETW_TRANSPORT_PROPS: Request properties for network transport + + note: does not have any data -> n = 0 + + +- PROTMESSID_DISCONNECTION: Disconnect message + + note: does not have any data -> n = 0 + + + +CONNECTION LESS MESSAGES +------------------------ + +- PROTMESSID_CLM_PING_MS: Connection less ping message (for measuring the ping + time) + + note: same definition as PROTMESSID_PING_MS + + + +- PROTMESSID_CLM_PING_MS_WITHNUMCLIENTS: Connection less ping message (for + measuring the ping time) with the + info about the current number of + connected clients + + +-----------------------------+---------------------------------+ + | 4 bytes transmit time in ms | 1 byte number connected clients | + +-----------------------------+---------------------------------+ + + +- PROTMESSID_SERVER_FULL: Connection less server full message + + note: does not have any data -> n = 0 + + +- PROTMESSID_CLM_REGISTER_SERVER: Register a server, providing server + information + + +-----------------+----------------------------------+ ... + | 2 bytes country | 1 byte maximum connected clients | ... + +-----------------+----------------------------------+ ... + ... ---------------------+------------------+ ... + ... 1 byte is permanent | 2 bytes number n | ... + ... ---------------------+------------------+ ... + ... ----------------------------------+ ... + ... n bytes UTF-8 string server name | ... + ... ----------------------------------+ ... + ... ------------------+----------------------------+ ... + ... 2 bytes number n | n bytes UTF-8 string topic | ... + ... ------------------+----------------------------+ ... + ... ------------------+---------------------------+ + ... 2 bytes number n | n bytes UTF-8 string city | + ... ------------------+---------------------------+ + + - "maximum connected clients" is the maximum number of clients which can + be connected to the server at the same time + - "is permanent" is a flag which indicates if the server is permanent + online or not. If this value is any value <> 0 indicates that the server + is permanent online. + - "country" is according to "Common Locale Data Repository" which is used in + the QLocale class + + +- PROTMESSID_CLM_SERVER_LIST: Server list message + + for each registered server append following data: + + +--------------------+--------------+--------------------------------+ + | 4 bytes IP address | 2 bytes port | PROTMESSID_CLM_REGISTER_SERVER | + +--------------------+--------------+--------------------------------+ + + - "PROTMESSID_CLM_REGISTER_SERVER" means that exactly the same message body + of the PROTMESSID_CLM_REGISTER_SERVER message is used + + +- PROTMESSID_CLM_REQ_SERVER_LIST: Request server list + + note: does not have any data -> n = 0 + + +- PROTMESSID_CLM_SEND_EMPTY_MESSAGE: Send "empty message" message + + +--------------------+--------------+ + | 4 bytes IP address | 2 bytes port | + +--------------------+--------------+ + + + ****************************************************************************** + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +\******************************************************************************/ + +#include "protocol.h" + + +/* Implementation *************************************************************/ +CProtocol::CProtocol() +{ + Reset(); + + + // Connections ------------------------------------------------------------- + QObject::connect ( &TimerSendMess, SIGNAL ( timeout() ), + this, SLOT ( OnTimerSendMess() ) ); +} + +void CProtocol::Reset() +{ + QMutexLocker locker ( &Mutex ); + + // prepare internal variables for initial protocol transfer + iCounter = 0; + iOldRecID = PROTMESSID_ILLEGAL; + iOldRecCnt = 0; + + // delete complete "send message queue" + SendMessQueue.clear(); +} + +void CProtocol::EnqueueMessage ( CVector& vecMessage, + const int iCnt, + const int iID ) +{ + bool bListWasEmpty; + + Mutex.lock(); + { + // check if list is empty so that we have to initiate a send process + bListWasEmpty = SendMessQueue.empty(); + + // create send message object for the queue + CSendMessage SendMessageObj ( vecMessage, iCnt, iID ); + + // we want to have a FIFO: we add at the end and take from the beginning + SendMessQueue.push_back ( SendMessageObj ); + } + Mutex.unlock(); + + // if list was empty, initiate send process + if ( bListWasEmpty ) + { + SendMessage(); + } +} + +void CProtocol::SendMessage() +{ + CVector vecMessage; + bool bSendMess = false; + + Mutex.lock(); + { + // we have to check that list is not empty, since in another thread the + // last element of the list might have been erased + if ( !SendMessQueue.empty() ) + { + vecMessage.Init ( SendMessQueue.front().vecMessage.Size() ); + vecMessage = SendMessQueue.front().vecMessage; + + bSendMess = true; + } + } + Mutex.unlock(); + + if ( bSendMess ) + { + // send message + emit MessReadyForSending ( vecMessage ); + + // start time-out timer if not active + if ( !TimerSendMess.isActive() ) + { + TimerSendMess.start ( SEND_MESS_TIMEOUT_MS ); + } + } + else + { + // no message to send, stop timer + TimerSendMess.stop(); + } +} + +void CProtocol::CreateAndSendMessage ( const int iID, + const CVector& vecData ) +{ + CVector vecNewMessage; + int iCurCounter; + + Mutex.lock(); + { + // store current counter value + iCurCounter = iCounter; + + // increase counter (wraps around automatically) + iCounter++; + } + Mutex.unlock(); + + // build complete message + GenMessageFrame ( vecNewMessage, iCurCounter, iID, vecData ); + + // enqueue message + EnqueueMessage ( vecNewMessage, iCurCounter, iID ); +} + +void CProtocol::CreateAndImmSendAcknMess ( const int& iID, + const int& iCnt ) +{ + CVector vecAcknMessage; + CVector vecData ( 2 ); // 2 bytes of data + int iPos = 0; // init position pointer + + // build data vector + PutValOnStream ( vecData, iPos, static_cast ( iID ), 2 ); + + // build complete message + GenMessageFrame ( vecAcknMessage, iCnt, PROTMESSID_ACKN, vecData ); + + // immediately send acknowledge message + emit MessReadyForSending ( vecAcknMessage ); +} + +void CProtocol::CreateAndImmSendConLessMessage ( const int iID, + const CVector& vecData, + const CHostAddress& InetAddr ) +{ + CVector vecNewMessage; + + // build complete message (counter per definition=0 for connection less + // messages) + GenMessageFrame ( vecNewMessage, 0, iID, vecData ); + + // immediately send message + emit CLMessReadyForSending ( InetAddr, vecNewMessage ); +} + +bool CProtocol::IsProtocolMessage ( const CVector& vecbyData, + const int iNumBytes ) +{ +/* + just check if this is a protocol message but do not act on message +*/ + int iRecCounter, iRecID; + CVector vecData; + + return !ParseMessageFrame ( vecbyData, + iNumBytes, + iRecCounter, + iRecID, + vecData ); +} + +bool CProtocol::ParseMessage ( const CVector& vecbyData, + const int iNumBytes ) +{ +/* + return code: false -> ok; true -> error +*/ + bool bRet = false; + bool bSendNextMess; + int iRecCounter, iRecID; + CVector vecData; + + if ( !ParseMessageFrame ( vecbyData, iNumBytes, iRecCounter, iRecID, vecData ) ) + { + +/* +// TEST channel implementation: randomly delete protocol messages (50 % loss) +if ( rand() < ( RAND_MAX / 2 ) ) return false; +*/ + + // in case this is a connection less message, we do not process it here + if ( IsConnectionLessMessageID ( iRecID ) ) + { + + +// TODO fire signal so that an other class can process this type of message + + + // return function without issuing an error code (since it is a + // regular message but will just not processed here) + return false; + } + + // In case we received a message and returned an answer but our answer + // did not make it to the receiver, he will resend his message. We check + // here if the message is the same as the old one, and if this is the + // case, just resend our old answer again + if ( ( iOldRecID == iRecID ) && ( iOldRecCnt == iRecCounter ) ) + { + // acknowledgments are not acknowledged + if ( iRecID != PROTMESSID_ACKN ) + { + // resend acknowledgement + CreateAndImmSendAcknMess ( iRecID, iRecCounter ); + } + } + else + { + // special treatment for acknowledge messages + if ( iRecID == PROTMESSID_ACKN ) + { + // extract data from stream and emit signal for received value + int iPos = 0; + const int iData = + static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); + + Mutex.lock(); + { + // check if this is the correct acknowledgment + bSendNextMess = false; + if ( !SendMessQueue.empty() ) + { + if ( ( SendMessQueue.front().iCnt == iRecCounter ) && + ( SendMessQueue.front().iID == iData ) ) + { + // message acknowledged, remove from queue + SendMessQueue.pop_front(); + + // send next message in queue + bSendNextMess = true; + } + } + } + Mutex.unlock(); + + if ( bSendNextMess ) + { + SendMessage(); + } + } + else + { + // check which type of message we received and do action + switch ( iRecID ) + { + case PROTMESSID_JITT_BUF_SIZE: + bRet = EvaluateJitBufMes ( vecData ); + break; + + case PROTMESSID_REQ_JITT_BUF_SIZE: + bRet = EvaluateReqJitBufMes(); + break; + + case PROTMESSID_CHANNEL_GAIN: + bRet = EvaluateChanGainMes ( vecData ); + break; + + case PROTMESSID_CONN_CLIENTS_LIST: + bRet = EvaluateConClientListMes ( vecData ); + break; + + case PROTMESSID_REQ_CONN_CLIENTS_LIST: + bRet = EvaluateReqConnClientsList(); + break; + + case PROTMESSID_CHANNEL_NAME: + bRet = EvaluateChanNameMes ( vecData ); + break; + + case PROTMESSID_REQ_CHANNEL_NAME: + bRet = EvaluateReqChanNameMes(); + break; + + case PROTMESSID_CHAT_TEXT: + bRet = EvaluateChatTextMes ( vecData ); + break; + + case PROTMESSID_PING_MS: + bRet = EvaluatePingMes ( vecData ); + break; + + case PROTMESSID_NETW_TRANSPORT_PROPS: + bRet = EvaluateNetwTranspPropsMes ( vecData ); + break; + + case PROTMESSID_REQ_NETW_TRANSPORT_PROPS: + bRet = EvaluateReqNetwTranspPropsMes(); + break; + + case PROTMESSID_DISCONNECTION: + bRet = EvaluateDisconnectionMes(); + break; + } + + // immediately send acknowledge message + CreateAndImmSendAcknMess ( iRecID, iRecCounter ); + + // save current message ID and counter to find out if message + // was resent + iOldRecID = iRecID; + iOldRecCnt = iRecCounter; + } + } + } + else + { + bRet = true; // return error code + } + + return bRet; +} + +bool CProtocol::ParseConnectionLessMessage ( const CVector& vecbyData, + const int iNumBytes, + const CHostAddress& InetAddr ) +{ +/* + return code: false -> ok; true -> error +*/ + bool bRet = false; + int iRecCounter, iRecID; + CVector vecData; + + if ( !ParseMessageFrame ( vecbyData, iNumBytes, iRecCounter, iRecID, vecData ) ) + { + if ( IsConnectionLessMessageID ( iRecID ) ) + { + // check which type of message we received and do action + switch ( iRecID ) + { + case PROTMESSID_CLM_PING_MS: + bRet = EvaluateCLPingMes ( InetAddr, vecData ); + break; + + case PROTMESSID_CLM_PING_MS_WITHNUMCLIENTS: + bRet = EvaluateCLPingWithNumClientsMes ( InetAddr, vecData ); + break; + + case PROTMESSID_CLM_SERVER_FULL: + bRet = EvaluateCLServerFullMes(); + break; + + case PROTMESSID_CLM_SERVER_LIST: + bRet = EvaluateCLServerListMes ( InetAddr, vecData ); + break; + + case PROTMESSID_CLM_REQ_SERVER_LIST: + bRet = EvaluateCLReqServerListMes ( InetAddr ); + break; + + case PROTMESSID_CLM_SEND_EMPTY_MESSAGE: + bRet = EvaluateCLSendEmptyMesMes ( vecData ); + break; + + case PROTMESSID_CLM_REGISTER_SERVER: + bRet = EvaluateCLRegisterServerMes ( InetAddr, vecData ); + break; + } + } + else + { + bRet = true; // return error code + } + } + else + { + bRet = true; // return error code + } + + return bRet; +} + + +/******************************************************************************\ +* Access-functions for creating and parsing messages * +\******************************************************************************/ +void CProtocol::CreateJitBufMes ( const int iJitBufSize ) +{ + CVector vecData ( 2 ); // 2 bytes of data + int iPos = 0; // init position pointer + + // build data vector + PutValOnStream ( vecData, iPos, static_cast ( iJitBufSize ), 2 ); + + CreateAndSendMessage ( PROTMESSID_JITT_BUF_SIZE, vecData ); +} + +bool CProtocol::EvaluateJitBufMes ( const CVector& vecData ) +{ + int iPos = 0; // init position pointer + + // check size + if ( vecData.Size() != 2 ) + { + return true; // return error code + } + + // extract jitter buffer size + const int iData = + static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); + + if ( ( iData < MIN_NET_BUF_SIZE_NUM_BL ) || + ( iData > MAX_NET_BUF_SIZE_NUM_BL ) ) + { + return true; // return error code + } + + // invoke message action + emit ChangeJittBufSize ( iData ); + + return false; // no error +} + +void CProtocol::CreateReqJitBufMes() +{ + CreateAndSendMessage ( PROTMESSID_REQ_JITT_BUF_SIZE, + CVector ( 0 ) ); +} + +bool CProtocol::EvaluateReqJitBufMes() +{ + // invoke message action + emit ReqJittBufSize(); + + return false; // no error +} + +void CProtocol::CreateChanGainMes ( const int iChanID, const double dGain ) +{ + CVector vecData ( 3 ); // 3 bytes of data + int iPos = 0; // init position pointer + + // build data vector + // channel ID + PutValOnStream ( vecData, iPos, static_cast ( iChanID ), 1 ); + + // actual gain, we convert from double with range 0..1 to integer + const int iCurGain = static_cast ( dGain * ( 1 << 15 ) ); + + PutValOnStream ( vecData, iPos, static_cast ( iCurGain ), 2 ); + + CreateAndSendMessage ( PROTMESSID_CHANNEL_GAIN, vecData ); +} + +bool CProtocol::EvaluateChanGainMes ( const CVector& vecData ) +{ + int iPos = 0; // init position pointer + + // check size + if ( vecData.Size() != 3 ) + { + return true; // return error code + } + + // channel ID + const int iCurID = + static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); + + // gain (read integer value) + const int iData = + static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); + + // we convert the gain from integer to double with range 0..1 + const double dNewGain = static_cast ( iData ) / ( 1 << 15 ); + + // invoke message action + emit ChangeChanGain ( iCurID, dNewGain ); + + return false; // no error +} + +void CProtocol::CreateConClientListMes ( const CVector& vecChanInfo ) +{ + const int iNumClients = vecChanInfo.Size(); + + // build data vector + CVector vecData ( 0 ); + int iPos = 0; // init position pointer + + for ( int i = 0; i < iNumClients; i++ ) + { + // current string size + const int iCurStrLen = vecChanInfo[i].strName.size(); + + // size of current list entry + const int iCurListEntrLen = + 1 /* chan ID */ + 4 /* IP addr. */ + 2 /* str. size */ + iCurStrLen; + + // make space for new data + vecData.Enlarge ( iCurListEntrLen ); + + // channel ID + PutValOnStream ( vecData, iPos, + static_cast ( vecChanInfo[i].iChanID ), 1 ); + + // IP address (4 bytes) + PutValOnStream ( vecData, iPos, + static_cast ( vecChanInfo[i].iIpAddr ), 4 ); + + // name string + PutStringOnStream ( vecData, iPos, vecChanInfo[i].strName ); + } + + CreateAndSendMessage ( PROTMESSID_CONN_CLIENTS_LIST, vecData ); +} + +bool CProtocol::EvaluateConClientListMes ( const CVector& vecData ) +{ + int iPos = 0; // init position pointer + const int iDataLen = vecData.Size(); + CVector vecChanInfo ( 0 ); + + while ( iPos < iDataLen ) + { + // check size (the next 5 bytes) + if ( ( iDataLen - iPos ) < 5 ) + { + return true; // return error code + } + + // channel ID (1 byte) + const int iChanID = + static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); + + // IP address (4 bytes) + const int iIpAddr = + static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); + + // name + QString strCurStr; + if ( GetStringFromStream ( vecData, + iPos, + MAX_LEN_FADER_TAG, + strCurStr ) ) + { + return true; // return error code + } + + // add channel information to vector + vecChanInfo.Add ( CChannelShortInfo ( iChanID, iIpAddr, strCurStr ) ); + } + + // check size: all data is read, the position must now be at the end + if ( iPos != iDataLen ) + { + return true; // return error code + } + + // invoke message action + emit ConClientListMesReceived ( vecChanInfo ); + + return false; // no error +} + +void CProtocol::CreateReqConnClientsList() +{ + CreateAndSendMessage ( PROTMESSID_REQ_CONN_CLIENTS_LIST, CVector ( 0 ) ); +} + +bool CProtocol::EvaluateReqConnClientsList() +{ + // invoke message action + emit ReqConnClientsList(); + + return false; // no error +} + +void CProtocol::CreateChanNameMes ( const QString strName ) +{ + int iPos = 0; // init position pointer + const int iStrLen = strName.size(); // get string size + + // size of current list entry + const int iEntrLen = 2 /* string size */ + iStrLen; + + // build data vector + CVector vecData ( iEntrLen ); + + // name string + PutStringOnStream ( vecData, iPos, strName ); + + CreateAndSendMessage ( PROTMESSID_CHANNEL_NAME, vecData ); +} + +bool CProtocol::EvaluateChanNameMes ( const CVector& vecData ) +{ + int iPos = 0; // init position pointer + + // channel name + QString strName; + if ( GetStringFromStream ( vecData, + iPos, + MAX_LEN_FADER_TAG, + strName ) ) + { + return true; // return error code + } + + // check size: all data is read, the position must now be at the end + if ( iPos != vecData.Size() ) + { + return true; // return error code + } + + // invoke message action + emit ChangeChanName ( strName ); + + return false; // no error +} + +void CProtocol::CreateReqChanNameMes() +{ + CreateAndSendMessage ( PROTMESSID_REQ_CHANNEL_NAME, CVector ( 0 ) ); +} + +bool CProtocol::EvaluateReqChanNameMes() +{ + // invoke message action + emit ReqChanName(); + + return false; // no error +} + +void CProtocol::CreateChatTextMes ( const QString strChatText ) +{ + int iPos = 0; // init position pointer + const int iStrLen = strChatText.size(); // get string size + + // size of message body + const int iEntrLen = 2 /* string size */ + iStrLen; + + // build data vector + CVector vecData ( iEntrLen ); + + // chat text + PutStringOnStream ( vecData, iPos, strChatText ); + + CreateAndSendMessage ( PROTMESSID_CHAT_TEXT, vecData ); +} + +bool CProtocol::EvaluateChatTextMes ( const CVector& vecData ) +{ + int iPos = 0; // init position pointer + + // chat text + QString strChatText; + if ( GetStringFromStream ( vecData, + iPos, + MAX_LEN_CHAT_TEXT_PLUS_HTML, + strChatText ) ) + { + return true; // return error code + } + + // check size: all data is read, the position must now be at the end + if ( iPos != vecData.Size() ) + { + return true; // return error code + } + + // invoke message action + emit ChatTextReceived ( strChatText ); + + return false; // no error +} + +void CProtocol::CreatePingMes ( const int iMs ) +{ + int iPos = 0; // init position pointer + + // build data vector (4 bytes long) + CVector vecData ( 4 ); + + // transmit time (4 bytes) + PutValOnStream ( vecData, iPos, static_cast ( iMs ), 4 ); + + CreateAndSendMessage ( PROTMESSID_PING_MS, vecData ); +} + +bool CProtocol::EvaluatePingMes ( const CVector& vecData ) +{ + int iPos = 0; // init position pointer + + // check size + if ( vecData.Size() != 4 ) + { + return true; // return error code + } + + // invoke message action + emit PingReceived ( static_cast ( GetValFromStream ( vecData, iPos, 4 ) ) ); + + return false; // no error +} + +void CProtocol::CreateNetwTranspPropsMes ( const CNetworkTransportProps& NetTrProps ) +{ + int iPos = 0; // init position pointer + + // size of current message body + const int iEntrLen = + 4 /* netw size */ + + 2 /* block size fact */ + + 1 /* num chan */ + + 4 /* sam rate */ + + 2 /* audiocod type */ + + 2 /* version */ + + 4 /* audiocod arg */; + + // build data vector + CVector vecData ( iEntrLen ); + + // length of the base network packet (frame) in bytes (4 bytes) + PutValOnStream ( vecData, iPos, + static_cast ( NetTrProps.iBaseNetworkPacketSize ), 4 ); + + // block size factor (2 bytes) + PutValOnStream ( vecData, iPos, + static_cast ( NetTrProps.iBlockSizeFact ), 2 ); + + // number of channels of the audio signal, e.g. "2" is stereo (1 byte) + PutValOnStream ( vecData, iPos, + static_cast ( NetTrProps.iNumAudioChannels ), 1 ); + + // sample rate of the audio stream (4 bytes) + PutValOnStream ( vecData, iPos, + static_cast ( NetTrProps.iSampleRate ), 4 ); + + // audio coding type (2 bytes) + PutValOnStream ( vecData, iPos, + static_cast ( NetTrProps.eAudioCodingType ), 2 ); + + // version (2 bytes) + PutValOnStream ( vecData, iPos, + static_cast ( NetTrProps.iVersion ), 2 ); + + // argument for the audio coder (4 bytes) + PutValOnStream ( vecData, iPos, + static_cast ( NetTrProps.iAudioCodingArg ), 4 ); + + CreateAndSendMessage ( PROTMESSID_NETW_TRANSPORT_PROPS, vecData ); +} + +bool CProtocol::EvaluateNetwTranspPropsMes ( const CVector& vecData ) +{ + int iPos = 0; // init position pointer + CNetworkTransportProps ReceivedNetwTranspProps; + + // size of current message body + const int iEntrLen = + 4 /* netw size */ + + 2 /* block size fact */ + + 1 /* num chan */ + + 4 /* sam rate */ + + 2 /* audiocod type */ + + 2 /* version */ + + 4 /* audiocod arg */; + + // check size + if ( vecData.Size() != iEntrLen ) + { + return true; // return error code + } + + // length of the base network packet (frame) in bytes (4 bytes) + ReceivedNetwTranspProps.iBaseNetworkPacketSize = + static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); + + if ( ( ReceivedNetwTranspProps.iBaseNetworkPacketSize < 1 ) || + ( ReceivedNetwTranspProps.iBaseNetworkPacketSize > MAX_SIZE_BYTES_NETW_BUF ) ) + { + return true; // return error code + } + + // block size factor (2 bytes) + ReceivedNetwTranspProps.iBlockSizeFact = + static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); + + if ( ( ReceivedNetwTranspProps.iBlockSizeFact != FRAME_SIZE_FACTOR_PREFERRED ) && + ( ReceivedNetwTranspProps.iBlockSizeFact != FRAME_SIZE_FACTOR_DEFAULT ) && + ( ReceivedNetwTranspProps.iBlockSizeFact != FRAME_SIZE_FACTOR_SAFE ) ) + { + return true; // return error code + } + + // number of channels of the audio signal, only mono (1 channel) or + // stereo (2 channels) allowed (1 byte) + ReceivedNetwTranspProps.iNumAudioChannels = + static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); + + if ( ( ReceivedNetwTranspProps.iNumAudioChannels != 1 ) && + ( ReceivedNetwTranspProps.iNumAudioChannels != 2 ) ) + { + return true; // return error code + } + + // sample rate of the audio stream (4 bytes) + ReceivedNetwTranspProps.iSampleRate = + static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); + + // audio coding type (2 bytes) with error check + const int iRecCodingType = + static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); + + if ( ( iRecCodingType != CT_NONE ) && + ( iRecCodingType != CT_CELT ) ) + { + return true; + } + + ReceivedNetwTranspProps.eAudioCodingType = + static_cast ( iRecCodingType ); + + // version (2 bytes) + ReceivedNetwTranspProps.iVersion = + static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); + + // argument for the audio coder (4 bytes) + ReceivedNetwTranspProps.iAudioCodingArg = + static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); + + // invoke message action + emit NetTranspPropsReceived ( ReceivedNetwTranspProps ); + + return false; // no error +} + +void CProtocol::CreateReqNetwTranspPropsMes() +{ + CreateAndSendMessage ( PROTMESSID_REQ_NETW_TRANSPORT_PROPS, + CVector ( 0 ) ); +} + +bool CProtocol::EvaluateReqNetwTranspPropsMes() +{ + // invoke message action + emit ReqNetTranspProps(); + + return false; // no error +} + +void CProtocol::CreateAndImmSendDisconnectionMes() +{ + CVector vecDisconMessage; + int iCurCounter; + + Mutex.lock(); + { + // store current counter value + iCurCounter = iCounter; + + // increase counter (wraps around automatically) + iCounter++; + } + Mutex.unlock(); + + // build complete message + GenMessageFrame ( vecDisconMessage, iCurCounter, + PROTMESSID_DISCONNECTION, CVector ( 0 ) ); + + // immediately send acknowledge message + emit MessReadyForSending ( vecDisconMessage ); +} + +bool CProtocol::EvaluateDisconnectionMes() +{ + // invoke message action + emit Disconnection(); + + return false; // no error +} + + +// Connection less messages ---------------------------------------------------- +void CProtocol::CreateCLPingMes ( const CHostAddress& InetAddr, const int iMs ) +{ + int iPos = 0; // init position pointer + + // build data vector (4 bytes long) + CVector vecData ( 4 ); + + // transmit time (4 bytes) + PutValOnStream ( vecData, iPos, static_cast ( iMs ), 4 ); + + CreateAndImmSendConLessMessage ( PROTMESSID_CLM_PING_MS, + vecData, + InetAddr ); +} + +bool CProtocol::EvaluateCLPingMes ( const CHostAddress& InetAddr, + const CVector& vecData ) +{ + int iPos = 0; // init position pointer + + // check size + if ( vecData.Size() != 4 ) + { + return true; // return error code + } + + // invoke message action + emit CLPingReceived ( InetAddr, + static_cast ( GetValFromStream ( vecData, iPos, 4 ) ) ); + + return false; // no error +} + +void CProtocol::CreateCLPingWithNumClientsMes ( const CHostAddress& InetAddr, + const int iMs, + const int iNumClients ) +{ + int iPos = 0; // init position pointer + + // build data vector (5 bytes long) + CVector vecData ( 5 ); + + // transmit time (4 bytes) + PutValOnStream ( vecData, iPos, static_cast ( iMs ), 4 ); + + // current number of connected clients (1 byte) + PutValOnStream ( vecData, iPos, static_cast ( iNumClients ), 1 ); + + CreateAndImmSendConLessMessage ( PROTMESSID_CLM_PING_MS_WITHNUMCLIENTS, + vecData, + InetAddr ); +} + +bool CProtocol::EvaluateCLPingWithNumClientsMes ( const CHostAddress& InetAddr, + const CVector& vecData ) +{ + int iPos = 0; // init position pointer + + // check size + if ( vecData.Size() != 5 ) + { + return true; // return error code + } + + // transmit time + const int iCurMs = + static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); + + // current number of connected clients + const int iCurNumClients = + static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); + + // invoke message action + emit CLPingWithNumClientsReceived ( InetAddr, iCurMs, iCurNumClients ); + + return false; // no error +} + +void CProtocol::CreateCLServerFullMes ( const CHostAddress& InetAddr ) +{ + CreateAndImmSendConLessMessage ( PROTMESSID_CLM_SERVER_FULL, + CVector ( 0 ), + InetAddr ); +} + +bool CProtocol::EvaluateCLServerFullMes() +{ + // invoke message action + emit ServerFullMesReceived(); + + return false; // no error +} + +void CProtocol::CreateCLRegisterServerMes ( const CHostAddress& InetAddr, + const CServerCoreInfo& ServerInfo ) +{ + int iPos = 0; // init position pointer + + // size of current message body + const int iEntrLen = + 2 /* country */ + + 1 /* maximum number of connected clients */ + + 1 /* is permanent flag */ + + 2 /* name string size */ + ServerInfo.strName.size() + + 2 /* topic string size */ + ServerInfo.strTopic.size() + + 2 /* city string size */ + ServerInfo.strCity.size(); + + // build data vector + CVector vecData ( iEntrLen ); + + // country (2 bytes) + PutValOnStream ( vecData, iPos, + static_cast ( ServerInfo.eCountry ), 2 ); + + // maximum number of connected clients (1 byte) + PutValOnStream ( vecData, iPos, + static_cast ( ServerInfo.iMaxNumClients ), 1 ); + + // "is permanent" flag (1 byte) + PutValOnStream ( vecData, iPos, + static_cast ( ServerInfo.bPermanentOnline ), 1 ); + + // name + PutStringOnStream ( vecData, iPos, ServerInfo.strName ); + + // topic + PutStringOnStream ( vecData, iPos, ServerInfo.strTopic ); + + // city + PutStringOnStream ( vecData, iPos, ServerInfo.strCity ); + + CreateAndImmSendConLessMessage ( PROTMESSID_CLM_REGISTER_SERVER, + vecData, + InetAddr ); +} + +bool CProtocol::EvaluateCLRegisterServerMes ( const CHostAddress& InetAddr, + const CVector& vecData ) +{ + int iPos = 0; // init position pointer + const int iDataLen = vecData.Size(); + CServerCoreInfo RecServerInfo; + + // check size (the first 4 bytes) + if ( iDataLen < 4 ) + { + return true; // return error code + } + + // country (2 bytes) + RecServerInfo.eCountry = + static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); + + // maximum number of connected clients (1 byte) + RecServerInfo.iMaxNumClients = + static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); + + // "is permanent" flag (1 byte) + RecServerInfo.bPermanentOnline = + static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); + + // server name + if ( GetStringFromStream ( vecData, + iPos, + MAX_LEN_SERVER_NAME, + RecServerInfo.strName ) ) + { + return true; // return error code + } + + // server topic + if ( GetStringFromStream ( vecData, + iPos, + MAX_LEN_SERVER_TOPIC, + RecServerInfo.strTopic ) ) + { + return true; // return error code + } + + // server city + if ( GetStringFromStream ( vecData, + iPos, + MAX_LEN_SERVER_CITY, + RecServerInfo.strCity ) ) + { + return true; // return error code + } + + // check size: all data is read, the position must now be at the end + if ( iPos != iDataLen ) + { + return true; // return error code + } + + // invoke message action + emit CLRegisterServerReceived ( InetAddr, RecServerInfo ); + + return false; // no error +} + + +void CProtocol::CreateCLServerListMes ( const CHostAddress& InetAddr, + const CVector vecServerInfo ) +{ + const int iNumServers = vecServerInfo.Size(); + + // build data vector + CVector vecData ( 0 ); + int iPos = 0; // init position pointer + + for ( int i = 0; i < iNumServers; i++ ) + { + // size of current list entry + const int iCurListEntrLen = + 4 /* IP address */ + + 2 /* port number */ + + 2 /* country */ + + 1 /* maximum number of connected clients */ + + 1 /* is permanent flag */ + + 2 /* name string size */ + vecServerInfo[i].strName.size() + + 2 /* topic string size */ + vecServerInfo[i].strTopic.size() + + 2 /* city string size */ + vecServerInfo[i].strCity.size(); + + // make space for new data + vecData.Enlarge ( iCurListEntrLen ); + + // IP address (4 bytes) + PutValOnStream ( vecData, iPos, static_cast ( + vecServerInfo[i].HostAddr.InetAddr.toIPv4Address() ), 4 ); + + // port number (2 bytes) + PutValOnStream ( vecData, iPos, + static_cast ( vecServerInfo[i].HostAddr.iPort ), 2 ); + + // country (2 bytes) + PutValOnStream ( vecData, iPos, + static_cast ( vecServerInfo[i].eCountry ), 2 ); + + // maximum number of connected clients (1 byte) + PutValOnStream ( vecData, iPos, + static_cast ( vecServerInfo[i].iMaxNumClients ), 1 ); + + // "is permanent" flag (1 byte) + PutValOnStream ( vecData, iPos, + static_cast ( vecServerInfo[i].bPermanentOnline ), 1 ); + + // name + PutStringOnStream ( vecData, iPos, vecServerInfo[i].strName ); + + // topic + PutStringOnStream ( vecData, iPos, vecServerInfo[i].strTopic ); + + // city + PutStringOnStream ( vecData, iPos, vecServerInfo[i].strCity ); + } + + CreateAndImmSendConLessMessage ( PROTMESSID_CLM_SERVER_LIST, + vecData, + InetAddr ); +} + +bool CProtocol::EvaluateCLServerListMes ( const CHostAddress& InetAddr, + const CVector& vecData ) +{ + int iPos = 0; // init position pointer + const int iDataLen = vecData.Size(); + CVector vecServerInfo ( 0 ); + + while ( iPos < iDataLen ) + { + // check size (the next 10 bytes) + if ( ( iDataLen - iPos ) < 10 ) + { + return true; // return error code + } + + // IP address (4 bytes) + const quint32 iIpAddr = + static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); + + // port number (2 bytes) + const quint16 iPort = + static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); + + // country (2 bytes) + const QLocale::Country eCountry = + static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); + + // maximum number of connected clients (1 byte) + const int iMaxNumClients = + static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); + + // "is permanent" flag (1 byte) + const bool bPermanentOnline = + static_cast ( GetValFromStream ( vecData, iPos, 1 ) ); + + // server name + QString strName; + if ( GetStringFromStream ( vecData, + iPos, + MAX_LEN_SERVER_NAME, + strName ) ) + { + return true; // return error code + } + + // server topic + QString strTopic; + if ( GetStringFromStream ( vecData, + iPos, + MAX_LEN_SERVER_TOPIC, + strTopic ) ) + { + return true; // return error code + } + + // server city + QString strCity; + if ( GetStringFromStream ( vecData, + iPos, + MAX_LEN_SERVER_CITY, + strCity ) ) + { + return true; // return error code + } + + // add server information to vector + vecServerInfo.Add ( + CServerInfo ( CHostAddress ( QHostAddress ( iIpAddr ), iPort ), + strName, + strTopic, + eCountry, + strCity, + iMaxNumClients, + bPermanentOnline ) ); + } + + // check size: all data is read, the position must now be at the end + if ( iPos != iDataLen ) + { + return true; // return error code + } + + // invoke message action + emit CLServerListReceived ( InetAddr, vecServerInfo ); + + return false; // no error +} + +void CProtocol::CreateCLReqServerListMes ( const CHostAddress& InetAddr ) +{ + CreateAndImmSendConLessMessage ( PROTMESSID_CLM_REQ_SERVER_LIST, + CVector ( 0 ), + InetAddr ); +} + +bool CProtocol::EvaluateCLReqServerListMes ( const CHostAddress& InetAddr ) +{ + // invoke message action + emit CLReqServerList ( InetAddr ); + + return false; // no error +} + +void CProtocol::CreateCLSendEmptyMesMes ( const CHostAddress& InetAddr, + const CHostAddress& TargetInetAddr ) +{ + int iPos = 0; // init position pointer + + // build data vector (6 bytes long) + CVector vecData ( 6 ); + + // IP address (4 bytes) + PutValOnStream ( vecData, iPos, static_cast ( + TargetInetAddr.InetAddr.toIPv4Address() ), 4 ); + + // port number (2 bytes) + PutValOnStream ( vecData, iPos, + static_cast ( TargetInetAddr.iPort ), 2 ); + + CreateAndImmSendConLessMessage ( PROTMESSID_CLM_SEND_EMPTY_MESSAGE, + vecData, + InetAddr ); +} + +bool CProtocol::EvaluateCLSendEmptyMesMes ( const CVector& vecData ) +{ + int iPos = 0; // init position pointer + + // check size + if ( vecData.Size() != 6 ) + { + return true; // return error code + } + + // IP address (4 bytes) + const quint32 iIpAddr = + static_cast ( GetValFromStream ( vecData, iPos, 4 ) ); + + // port number (2 bytes) + const quint16 iPort = + static_cast ( GetValFromStream ( vecData, iPos, 2 ) ); + + // invoke message action + emit CLSendEmptyMes ( CHostAddress ( QHostAddress ( iIpAddr ), iPort ) ); + + return false; // no error +} + +void CProtocol::CreateCLEmptyMes ( const CHostAddress& InetAddr ) +{ + CreateAndImmSendConLessMessage ( PROTMESSID_CLM_EMPTY_MESSAGE, + CVector ( 0 ), + InetAddr ); +} + + +/******************************************************************************\ +* Message generation and parsing * +\******************************************************************************/ +bool CProtocol::ParseMessageFrame ( const CVector& vecIn, + const int iNumBytesIn, + int& iCnt, + int& iID, + CVector& vecData ) +{ + int i; + int iLenBy; + int iCurPos; + + // vector must be at least "MESS_LEN_WITHOUT_DATA_BYTE" bytes long + if ( iNumBytesIn < MESS_LEN_WITHOUT_DATA_BYTE ) + { + return true; // return error code + } + + + // Decode header ----------------------------------------------------------- + iCurPos = 0; // start from beginning + + // 2 bytes TAG + const int iTag = static_cast ( GetValFromStream ( vecIn, iCurPos, 2 ) ); + + // check if tag is correct + if ( iTag != 0 ) + { + return true; // return error code + } + + // 2 bytes ID + iID = static_cast ( GetValFromStream ( vecIn, iCurPos, 2 ) ); + + // 1 byte cnt + iCnt = static_cast ( GetValFromStream ( vecIn, iCurPos, 1 ) ); + + // 2 bytes length + iLenBy = static_cast ( GetValFromStream ( vecIn, iCurPos, 2 ) ); + + // make sure the length is correct + if ( iLenBy != iNumBytesIn - MESS_LEN_WITHOUT_DATA_BYTE ) + { + return true; // return error code + } + + + // Now check CRC ----------------------------------------------------------- + CCRC CRCObj; + const int iLenCRCCalc = MESS_HEADER_LENGTH_BYTE + iLenBy; + + iCurPos = 0; // start from the beginning + for ( i = 0; i < iLenCRCCalc; i++ ) + { + CRCObj.AddByte ( static_cast ( + GetValFromStream ( vecIn, iCurPos, 1 ) ) ); + } + + if ( CRCObj.GetCRC () != GetValFromStream ( vecIn, iCurPos, 2 ) ) + { + return true; // return error code + } + + + // Extract actual data ----------------------------------------------------- + vecData.Init ( iLenBy ); + iCurPos = MESS_HEADER_LENGTH_BYTE; // start from beginning of data + for ( i = 0; i < iLenBy; i++ ) + { + vecData[i] = static_cast ( + GetValFromStream ( vecIn, iCurPos, 1 ) ); + } + + return false; // no error +} + +uint32_t CProtocol::GetValFromStream ( const CVector& vecIn, + int& iPos, + const int iNumOfBytes ) +{ +/* + note: iPos is automatically incremented in this function +*/ + // 4 bytes maximum since we return uint32 + Q_ASSERT ( ( iNumOfBytes > 0 ) && ( iNumOfBytes <= 4 ) ); + Q_ASSERT ( vecIn.Size() >= iPos + iNumOfBytes ); + + uint32_t iRet = 0; + for ( int i = 0; i < iNumOfBytes; i++ ) + { + iRet |= vecIn[iPos] << ( i * 8 /* size of byte */ ); + iPos++; + } + + return iRet; +} + +bool CProtocol::GetStringFromStream ( const CVector& vecIn, + int& iPos, + const int iMaxStringLen, + QString& strOut ) +{ +/* + note: iPos is automatically incremented in this function +*/ + // check if at least two bytes are available + const int iInLen = vecIn.Size(); + if ( ( iInLen - iPos ) < 2 ) + { + return true; // return error code + } + + // number of bytes for string (2 bytes) + const int iStrLen = + static_cast ( GetValFromStream ( vecIn, iPos, 2 ) ); + + if ( ( ( iInLen - iPos ) < iStrLen ) || + ( iStrLen > iMaxStringLen ) ) + { + return true; // return error code + } + + // string (n bytes) + strOut = ""; + for ( int i = 0; i < iStrLen; i++ ) + { + // byte-by-byte copying of the string data + int iData = static_cast ( GetValFromStream ( vecIn, iPos, 1 ) ); + strOut += QString ( (char*) &iData ); + } + + return false; // no error +} + +void CProtocol::GenMessageFrame ( CVector& vecOut, + const int iCnt, + const int iID, + const CVector& vecData ) +{ + int i; + + // query length of data vector + const int iDataLenByte = vecData.Size(); + + // total length of message + const int iTotLenByte = MESS_LEN_WITHOUT_DATA_BYTE + iDataLenByte; + + // init message vector + vecOut.Init ( iTotLenByte ); + + + // Encode header ----------------------------------------------------------- + int iCurPos = 0; // init position pointer + + // 2 bytes TAG (all zero bits) + PutValOnStream ( vecOut, iCurPos, + static_cast ( 0 ), 2 ); + + // 2 bytes ID + PutValOnStream ( vecOut, iCurPos, + static_cast ( iID ), 2 ); + + // 1 byte cnt + PutValOnStream ( vecOut, iCurPos, + static_cast ( iCnt ), 1 ); + + // 2 bytes length + PutValOnStream ( vecOut, iCurPos, + static_cast ( iDataLenByte ), 2 ); + + // encode data ----- + for ( i = 0; i < iDataLenByte; i++ ) + { + PutValOnStream ( vecOut, iCurPos, + static_cast ( vecData[i] ), 1 ); + } + + + // Encode CRC -------------------------------------------------------------- + CCRC CRCObj; + iCurPos = 0; // start from beginning + + const int iLenCRCCalc = MESS_HEADER_LENGTH_BYTE + iDataLenByte; + for ( i = 0; i < iLenCRCCalc; i++ ) + { + CRCObj.AddByte ( static_cast ( + GetValFromStream ( vecOut, iCurPos, 1 ) ) ); + } + + PutValOnStream ( vecOut, iCurPos, + static_cast ( CRCObj.GetCRC() ), 2 ); +} + +void CProtocol::PutValOnStream ( CVector& vecIn, + int& iPos, + const uint32_t iVal, + const int iNumOfBytes ) +{ +/* + note: iPos is automatically incremented in this function +*/ + // 4 bytes maximum since we use uint32 + Q_ASSERT ( ( iNumOfBytes > 0 ) && ( iNumOfBytes <= 4 ) ); + Q_ASSERT ( vecIn.Size() >= iPos + iNumOfBytes ); + + for ( int i = 0; i < iNumOfBytes; i++ ) + { + vecIn[iPos] = + ( iVal >> ( i * 8 /* size of byte */ ) ) & 255 /* 11111111 */; + + iPos++; + } +} + +void CProtocol::PutStringOnStream ( CVector& vecIn, + int& iPos, + const QString& sString ) +{ + // get the string size + const int iStrLen = sString.size(); + + // number of bytes for string (2 bytes) + PutValOnStream ( vecIn, iPos, + static_cast ( iStrLen ), 2 ); + + // actual string (n bytes) + for ( int j = 0; j < iStrLen; j++ ) + { + // byte-by-byte copying of the string data + PutValOnStream ( vecIn, iPos, + static_cast ( sString[j].toAscii() ), 1 ); + } +} diff --git a/src/protocol.h b/src/protocol.h index 571980c5..5ad6f875 100755 --- a/src/protocol.h +++ b/src/protocol.h @@ -1,259 +1,268 @@ -/******************************************************************************\ - * Copyright (c) 2004-2011 - * - * Author(s): - * Volker Fischer - * - ****************************************************************************** - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -\******************************************************************************/ - -#if !defined ( PROTOCOL_H__3B123453_4344_BB2392354455IUHF1912__INCLUDED_ ) -#define PROTOCOL_H__3B123453_4344_BB2392354455IUHF1912__INCLUDED_ - -#include -#include -#include -#include -#include -#include "global.h" -#include "util.h" - - -/* Definitions ****************************************************************/ -// protocol message IDs -#define PROTMESSID_ILLEGAL 0 // illegal ID -#define PROTMESSID_ACKN 1 // acknowledge -#define PROTMESSID_JITT_BUF_SIZE 10 // jitter buffer size -#define PROTMESSID_REQ_JITT_BUF_SIZE 11 // request jitter buffer size -#define PROTMESSID_NET_BLSI_FACTOR 12 // OLD (not used anymore) -#define PROTMESSID_CHANNEL_GAIN 13 // set channel gain for mix -#define PROTMESSID_CONN_CLIENTS_LIST 14 // connected client list -#define PROTMESSID_SERVER_FULL 15 // OLD (not used anymore) -#define PROTMESSID_REQ_CONN_CLIENTS_LIST 16 // request connected client list -#define PROTMESSID_CHANNEL_NAME 17 // set channel name for fader tag -#define PROTMESSID_CHAT_TEXT 18 // contains a chat text -#define PROTMESSID_PING_MS 19 // for measuring ping time -#define PROTMESSID_NETW_TRANSPORT_PROPS 20 // properties for network transport -#define PROTMESSID_REQ_NETW_TRANSPORT_PROPS 21 // request properties for network transport -#define PROTMESSID_DISCONNECTION 22 // disconnection -#define PROTMESSID_REQ_CHANNEL_NAME 23 // request channel name for fader tag - -// message IDs of connection less messages (CLM) -// DEFINITION -> start at 1000, end at 1999, see IsConnectionLessMessageID -#define PROTMESSID_CLM_PING_MS 1001 // for measuring ping time -#define PROTMESSID_CLM_SERVER_FULL 1002 // server full message -#define PROTMESSID_CLM_REGISTER_SERVER 1003 // register server -#define PROTMESSID_CLM_UNREGISTER_SERVER 1004 // unregister server -> TODO -#define PROTMESSID_CLM_SERVER_LIST 1005 // server list -#define PROTMESSID_CLM_REQ_SERVER_LIST 1006 // request server list -#define PROTMESSID_CLM_SEND_EMPTY_MESSAGE 1007 // an empty message shall be send -#define PROTMESSID_CLM_EMPTY_MESSAGE 1008 // empty message - - -// lengths of message as defined in protocol.cpp file -#define MESS_HEADER_LENGTH_BYTE 7 // TAG (2), ID (2), cnt (1), length (2) -#define MESS_LEN_WITHOUT_DATA_BYTE ( MESS_HEADER_LENGTH_BYTE + 2 /* CRC (2) */ ) - -// time out for message re-send if no acknowledgement was received -#define SEND_MESS_TIMEOUT_MS 400 // ms - - -/* Classes ********************************************************************/ -class CProtocol : public QObject -{ - Q_OBJECT - -public: - CProtocol(); - - void Reset(); - - void CreateJitBufMes ( const int iJitBufSize ); - void CreateReqJitBufMes(); - void CreateChanGainMes ( const int iChanID, const double dGain ); - void CreateConClientListMes ( const CVector& vecChanInfo ); - void CreateReqConnClientsList(); - void CreateChanNameMes ( const QString strName ); - void CreateReqChanNameMes(); - void CreateChatTextMes ( const QString strChatText ); - void CreatePingMes ( const int iMs ); - void CreateNetwTranspPropsMes ( const CNetworkTransportProps& NetTrProps ); - void CreateReqNetwTranspPropsMes(); - - void CreateCLPingMes ( const CHostAddress& InetAddr, const int iMs ); - void CreateCLServerFullMes ( const CHostAddress& InetAddr ); - void CreateCLRegisterServerMes ( const CHostAddress& InetAddr, - const CServerCoreInfo& ServerInfo ); - void CreateCLServerListMes ( const CHostAddress& InetAddr, - const CVector vecServerInfo ); - void CreateCLReqServerListMes ( const CHostAddress& InetAddr ); - void CreateCLSendEmptyMesMes ( const CHostAddress& InetAddr, - const CHostAddress& TargetInetAddr ); - void CreateCLEmptyMes ( const CHostAddress& InetAddr ); - - void CreateAndImmSendDisconnectionMes(); - void CreateAndImmSendAcknMess ( const int& iID, - const int& iCnt ); - - bool ParseMessage ( const CVector& vecbyData, - const int iNumBytes ); - - bool ParseConnectionLessMessage ( const CVector& vecbyData, - const int iNumBytes, - const CHostAddress& InetAddr ); - - bool IsProtocolMessage ( const CVector& vecbyData, - const int iNumBytes ); - -protected: - class CSendMessage - { - public: - CSendMessage() : vecMessage ( 0 ), iID ( PROTMESSID_ILLEGAL ), - iCnt ( 0 ) {} - CSendMessage ( const CVector& nMess, const int iNCnt, - const int iNID ) : vecMessage ( nMess ), iID ( iNID ), - iCnt ( iNCnt ) {} - - CSendMessage& operator= ( const CSendMessage& NewSendMess ) - { - vecMessage.Init ( NewSendMess.vecMessage.Size() ); - vecMessage = NewSendMess.vecMessage; - - iID = NewSendMess.iID; - iCnt = NewSendMess.iCnt; - return *this; - } - - CVector vecMessage; - int iID, iCnt; - }; - - void EnqueueMessage ( CVector& vecMessage, - const int iCnt, - const int iID ); - - bool ParseMessageFrame ( const CVector& vecIn, - const int iNumBytesIn, - int& iCnt, - int& iID, - CVector& vecData ); - - void GenMessageFrame ( CVector& vecOut, - const int iCnt, - const int iID, - const CVector& vecData ); - - void PutValOnStream ( CVector& vecIn, - int& iPos, - const uint32_t iVal, - const int iNumOfBytes ); - - void PutStringOnStream ( CVector& vecIn, - int& iPos, - const QString& sString ); - - uint32_t GetValFromStream ( const CVector& vecIn, - int& iPos, - const int iNumOfBytes ); - - bool GetStringFromStream ( const CVector& vecIn, - int& iPos, - const int iMaxStringLen, - QString& strOut ); - - bool IsConnectionLessMessageID ( const int iID ) const - { return (iID >= 1000) & (iID < 2000); } - - void SendMessage(); - - void CreateAndSendMessage ( const int iID, - const CVector& vecData ); - - void CreateAndImmSendConLessMessage ( const int iID, - const CVector& vecData, - const CHostAddress& InetAddr ); - - bool EvaluateJitBufMes ( const CVector& vecData ); - bool EvaluateReqJitBufMes(); - bool EvaluateChanGainMes ( const CVector& vecData ); - bool EvaluateConClientListMes ( const CVector& vecData ); - bool EvaluateReqConnClientsList(); - bool EvaluateChanNameMes ( const CVector& vecData ); - bool EvaluateReqChanNameMes(); - bool EvaluateChatTextMes ( const CVector& vecData ); - bool EvaluatePingMes ( const CVector& vecData ); - bool EvaluateNetwTranspPropsMes ( const CVector& vecData ); - bool EvaluateReqNetwTranspPropsMes(); - bool EvaluateDisconnectionMes(); - - bool EvaluateCLPingMes ( const CHostAddress& InetAddr, - const CVector& vecData ); - bool EvaluateCLServerFullMes(); - bool EvaluateCLRegisterServerMes ( const CHostAddress& InetAddr, - const CVector& vecData ); - bool EvaluateCLServerListMes ( const CHostAddress& InetAddr, - const CVector& vecData ); - bool EvaluateCLReqServerListMes ( const CHostAddress& InetAddr ); - bool EvaluateCLSendEmptyMesMes ( const CVector& vecData ); - - int iOldRecID; - int iOldRecCnt; - - // these two objects must be sequred by a mutex - uint8_t iCounter; - std::list SendMessQueue; - - QTimer TimerSendMess; - QMutex Mutex; - -public slots: - void OnTimerSendMess() { SendMessage(); } - -signals: - // transmitting - void MessReadyForSending ( CVector vecMessage ); - void CLMessReadyForSending ( CHostAddress InetAddr, - CVector vecMessage ); - - // receiving - void ChangeJittBufSize ( int iNewJitBufSize ); - void ReqJittBufSize(); - void ChangeNetwBlSiFact ( int iNewNetwBlSiFact ); - void ChangeChanGain ( int iChanID, double dNewGain ); - void ConClientListMesReceived ( CVector vecChanInfo ); - void ServerFullMesReceived(); - void ReqConnClientsList(); - void ChangeChanName ( QString strName ); - void ReqChanName(); - void ChatTextReceived ( QString strChatText ); - void PingReceived ( int iMs ); - void NetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps ); - void ReqNetTranspProps(); - void Disconnection(); - - void CLPingReceived ( CHostAddress InetAddr, int iMs ); - void CLRegisterServerReceived ( CHostAddress InetAddr, - CServerCoreInfo ServerInfo ); - void CLServerListReceived ( CHostAddress InetAddr, - CVector vecServerInfo ); - void CLReqServerList ( CHostAddress InetAddr ); - void CLSendEmptyMes ( CHostAddress TargetInetAddr ); -}; - -#endif /* !defined ( PROTOCOL_H__3B123453_4344_BB2392354455IUHF1912__INCLUDED_ ) */ +/******************************************************************************\ + * Copyright (c) 2004-2011 + * + * Author(s): + * Volker Fischer + * + ****************************************************************************** + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +\******************************************************************************/ + +#if !defined ( PROTOCOL_H__3B123453_4344_BB2392354455IUHF1912__INCLUDED_ ) +#define PROTOCOL_H__3B123453_4344_BB2392354455IUHF1912__INCLUDED_ + +#include +#include +#include +#include +#include +#include "global.h" +#include "util.h" + + +/* Definitions ****************************************************************/ +// protocol message IDs +#define PROTMESSID_ILLEGAL 0 // illegal ID +#define PROTMESSID_ACKN 1 // acknowledge +#define PROTMESSID_JITT_BUF_SIZE 10 // jitter buffer size +#define PROTMESSID_REQ_JITT_BUF_SIZE 11 // request jitter buffer size +#define PROTMESSID_NET_BLSI_FACTOR 12 // OLD (not used anymore) +#define PROTMESSID_CHANNEL_GAIN 13 // set channel gain for mix +#define PROTMESSID_CONN_CLIENTS_LIST 14 // connected client list +#define PROTMESSID_SERVER_FULL 15 // OLD (not used anymore) +#define PROTMESSID_REQ_CONN_CLIENTS_LIST 16 // request connected client list +#define PROTMESSID_CHANNEL_NAME 17 // set channel name for fader tag +#define PROTMESSID_CHAT_TEXT 18 // contains a chat text +#define PROTMESSID_PING_MS 19 // for measuring ping time +#define PROTMESSID_NETW_TRANSPORT_PROPS 20 // properties for network transport +#define PROTMESSID_REQ_NETW_TRANSPORT_PROPS 21 // request properties for network transport +#define PROTMESSID_DISCONNECTION 22 // disconnection +#define PROTMESSID_REQ_CHANNEL_NAME 23 // request channel name for fader tag + +// message IDs of connection less messages (CLM) +// DEFINITION -> start at 1000, end at 1999, see IsConnectionLessMessageID +#define PROTMESSID_CLM_PING_MS 1001 // for measuring ping time +#define PROTMESSID_CLM_PING_MS_WITHNUMCLIENTS 1002 // for ping time and num. of clients info +#define PROTMESSID_CLM_SERVER_FULL 1003 // server full message +#define PROTMESSID_CLM_REGISTER_SERVER 1004 // register server +#define PROTMESSID_CLM_UNREGISTER_SERVER 1005 // unregister server -> TODO +#define PROTMESSID_CLM_SERVER_LIST 1006 // server list +#define PROTMESSID_CLM_REQ_SERVER_LIST 1007 // request server list +#define PROTMESSID_CLM_SEND_EMPTY_MESSAGE 1008 // an empty message shall be send +#define PROTMESSID_CLM_EMPTY_MESSAGE 1009 // empty message + + +// lengths of message as defined in protocol.cpp file +#define MESS_HEADER_LENGTH_BYTE 7 // TAG (2), ID (2), cnt (1), length (2) +#define MESS_LEN_WITHOUT_DATA_BYTE ( MESS_HEADER_LENGTH_BYTE + 2 /* CRC (2) */ ) + +// time out for message re-send if no acknowledgement was received +#define SEND_MESS_TIMEOUT_MS 400 // ms + + +/* Classes ********************************************************************/ +class CProtocol : public QObject +{ + Q_OBJECT + +public: + CProtocol(); + + void Reset(); + + void CreateJitBufMes ( const int iJitBufSize ); + void CreateReqJitBufMes(); + void CreateChanGainMes ( const int iChanID, const double dGain ); + void CreateConClientListMes ( const CVector& vecChanInfo ); + void CreateReqConnClientsList(); + void CreateChanNameMes ( const QString strName ); + void CreateReqChanNameMes(); + void CreateChatTextMes ( const QString strChatText ); + void CreatePingMes ( const int iMs ); + void CreateNetwTranspPropsMes ( const CNetworkTransportProps& NetTrProps ); + void CreateReqNetwTranspPropsMes(); + + void CreateCLPingMes ( const CHostAddress& InetAddr, const int iMs ); + void CreateCLPingWithNumClientsMes ( const CHostAddress& InetAddr, + const int iMs, + const int iNumClients ); + void CreateCLServerFullMes ( const CHostAddress& InetAddr ); + void CreateCLRegisterServerMes ( const CHostAddress& InetAddr, + const CServerCoreInfo& ServerInfo ); + void CreateCLServerListMes ( const CHostAddress& InetAddr, + const CVector vecServerInfo ); + void CreateCLReqServerListMes ( const CHostAddress& InetAddr ); + void CreateCLSendEmptyMesMes ( const CHostAddress& InetAddr, + const CHostAddress& TargetInetAddr ); + void CreateCLEmptyMes ( const CHostAddress& InetAddr ); + + void CreateAndImmSendDisconnectionMes(); + void CreateAndImmSendAcknMess ( const int& iID, + const int& iCnt ); + + bool ParseMessage ( const CVector& vecbyData, + const int iNumBytes ); + + bool ParseConnectionLessMessage ( const CVector& vecbyData, + const int iNumBytes, + const CHostAddress& InetAddr ); + + bool IsProtocolMessage ( const CVector& vecbyData, + const int iNumBytes ); + +protected: + class CSendMessage + { + public: + CSendMessage() : vecMessage ( 0 ), iID ( PROTMESSID_ILLEGAL ), + iCnt ( 0 ) {} + CSendMessage ( const CVector& nMess, const int iNCnt, + const int iNID ) : vecMessage ( nMess ), iID ( iNID ), + iCnt ( iNCnt ) {} + + CSendMessage& operator= ( const CSendMessage& NewSendMess ) + { + vecMessage.Init ( NewSendMess.vecMessage.Size() ); + vecMessage = NewSendMess.vecMessage; + + iID = NewSendMess.iID; + iCnt = NewSendMess.iCnt; + return *this; + } + + CVector vecMessage; + int iID, iCnt; + }; + + void EnqueueMessage ( CVector& vecMessage, + const int iCnt, + const int iID ); + + bool ParseMessageFrame ( const CVector& vecIn, + const int iNumBytesIn, + int& iCnt, + int& iID, + CVector& vecData ); + + void GenMessageFrame ( CVector& vecOut, + const int iCnt, + const int iID, + const CVector& vecData ); + + void PutValOnStream ( CVector& vecIn, + int& iPos, + const uint32_t iVal, + const int iNumOfBytes ); + + void PutStringOnStream ( CVector& vecIn, + int& iPos, + const QString& sString ); + + uint32_t GetValFromStream ( const CVector& vecIn, + int& iPos, + const int iNumOfBytes ); + + bool GetStringFromStream ( const CVector& vecIn, + int& iPos, + const int iMaxStringLen, + QString& strOut ); + + bool IsConnectionLessMessageID ( const int iID ) const + { return (iID >= 1000) & (iID < 2000); } + + void SendMessage(); + + void CreateAndSendMessage ( const int iID, + const CVector& vecData ); + + void CreateAndImmSendConLessMessage ( const int iID, + const CVector& vecData, + const CHostAddress& InetAddr ); + + bool EvaluateJitBufMes ( const CVector& vecData ); + bool EvaluateReqJitBufMes(); + bool EvaluateChanGainMes ( const CVector& vecData ); + bool EvaluateConClientListMes ( const CVector& vecData ); + bool EvaluateReqConnClientsList(); + bool EvaluateChanNameMes ( const CVector& vecData ); + bool EvaluateReqChanNameMes(); + bool EvaluateChatTextMes ( const CVector& vecData ); + bool EvaluatePingMes ( const CVector& vecData ); + bool EvaluateNetwTranspPropsMes ( const CVector& vecData ); + bool EvaluateReqNetwTranspPropsMes(); + bool EvaluateDisconnectionMes(); + + bool EvaluateCLPingMes ( const CHostAddress& InetAddr, + const CVector& vecData ); + bool EvaluateCLPingWithNumClientsMes ( const CHostAddress& InetAddr, + const CVector& vecData ); + bool EvaluateCLServerFullMes(); + bool EvaluateCLRegisterServerMes ( const CHostAddress& InetAddr, + const CVector& vecData ); + bool EvaluateCLServerListMes ( const CHostAddress& InetAddr, + const CVector& vecData ); + bool EvaluateCLReqServerListMes ( const CHostAddress& InetAddr ); + bool EvaluateCLSendEmptyMesMes ( const CVector& vecData ); + + int iOldRecID; + int iOldRecCnt; + + // these two objects must be sequred by a mutex + uint8_t iCounter; + std::list SendMessQueue; + + QTimer TimerSendMess; + QMutex Mutex; + +public slots: + void OnTimerSendMess() { SendMessage(); } + +signals: + // transmitting + void MessReadyForSending ( CVector vecMessage ); + void CLMessReadyForSending ( CHostAddress InetAddr, + CVector vecMessage ); + + // receiving + void ChangeJittBufSize ( int iNewJitBufSize ); + void ReqJittBufSize(); + void ChangeNetwBlSiFact ( int iNewNetwBlSiFact ); + void ChangeChanGain ( int iChanID, double dNewGain ); + void ConClientListMesReceived ( CVector vecChanInfo ); + void ServerFullMesReceived(); + void ReqConnClientsList(); + void ChangeChanName ( QString strName ); + void ReqChanName(); + void ChatTextReceived ( QString strChatText ); + void PingReceived ( int iMs ); + void NetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps ); + void ReqNetTranspProps(); + void Disconnection(); + + void CLPingReceived ( CHostAddress InetAddr, int iMs ); + void CLPingWithNumClientsReceived ( CHostAddress InetAddr, + int iMs, + int iNumClients ); + void CLRegisterServerReceived ( CHostAddress InetAddr, + CServerCoreInfo ServerInfo ); + void CLServerListReceived ( CHostAddress InetAddr, + CVector vecServerInfo ); + void CLReqServerList ( CHostAddress InetAddr ); + void CLSendEmptyMes ( CHostAddress TargetInetAddr ); +}; + +#endif /* !defined ( PROTOCOL_H__3B123453_4344_BB2392354455IUHF1912__INCLUDED_ ) */ diff --git a/src/server.cpp b/src/server.cpp index f284c8ce..f5ba2e1d 100755 --- a/src/server.cpp +++ b/src/server.cpp @@ -870,6 +870,23 @@ int CServer::GetFreeChan() return INVALID_CHANNEL_ID; } +int CServer::GetNumberOfConnectedClients() +{ + int iNumConnClients = 0; + + // check all possible channels for connection status + for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) + { + if ( vecChannels[i].IsConnected() ) + { + // this channel is connected, increment counter + iNumConnClients += 1; + } + } + + return iNumConnClients; +} + int CServer::CheckAddr ( const CHostAddress& Addr ) { CHostAddress InetAddr; diff --git a/src/server.h b/src/server.h index 42a4a765..3e08db35 100755 --- a/src/server.h +++ b/src/server.h @@ -1,297 +1,302 @@ -/******************************************************************************\ - * Copyright (c) 2004-2011 - * - * Author(s): - * Volker Fischer - * - ****************************************************************************** - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -\******************************************************************************/ - -#if !defined ( SERVER_HOIHGE7LOKIH83JH8_3_43445KJIUHF1912__INCLUDED_ ) -#define SERVER_HOIHGE7LOKIH83JH8_3_43445KJIUHF1912__INCLUDED_ - -#include -#include -#include -#include -#include "celt.h" -#include "global.h" -#include "socket.h" -#include "channel.h" -#include "util.h" -#include "serverlogging.h" -#include "serverlist.h" - - -/* Definitions ****************************************************************/ -// no valid channel number -#define INVALID_CHANNEL_ID ( MAX_NUM_CHANNELS + 1 ) - -// minimum timer precision -#define MIN_TIMER_RESOLUTION_MS 1 // ms - - -/* Classes ********************************************************************/ -#if defined ( __APPLE__ ) || defined ( __MACOSX ) -// using mach timers for Mac -class CHighPrecisionTimer : public QThread -{ - Q_OBJECT - -public: - CHighPrecisionTimer(); - - void Start(); - void Stop(); - bool isActive() { return bRun; } - -protected: - virtual void run(); - - bool bRun; - uint64_t iMachDelay; - uint64_t iNextEnd; - -signals: - void timeout(); -}; -#else -// using QTimer for Windows and Linux -class CHighPrecisionTimer : public QObject -{ - Q_OBJECT - -public: - CHighPrecisionTimer(); - - void Start(); - void Stop(); - bool isActive() const { return Timer.isActive(); } - -protected: - QTimer Timer; - CVector veciTimeOutIntervals; - int iCurPosInVector; - int iIntervalCounter; - -public slots: - void OnTimer(); - -signals: - void timeout(); -}; -#endif - - -class CServer : public QObject -{ - Q_OBJECT - -public: - CServer ( const QString& strLoggingFileName, - const quint16 iPortNumber, - const QString& strHTMLStatusFileName, - const QString& strHistoryFileName, - const QString& strServerNameForHTMLStatusFile, - const QString& strCentralServer ); - - void Start(); - void Stop(); - bool IsRunning() { return HighPrecisionTimer.isActive(); } - - bool GetTimingStdDev ( double& dCurTiStdDev ); - - bool PutData ( const CVector& vecbyRecBuf, - const int iNumBytesRead, - const CHostAddress& HostAdr ); - - void GetConCliParam ( CVector& vecHostAddresses, - CVector& vecsName, - CVector& veciJitBufNumFrames, - CVector& veciNetwFrameSizeFact ); - -protected: - // access functions for actual channels - bool IsConnected ( const int iChanNum ) - { return vecChannels[iChanNum].IsConnected(); } - - void StartStatusHTMLFileWriting ( const QString& strNewFileName, - const QString& strNewServerNameWithPort ); - - int CheckAddr ( const CHostAddress& Addr ); - int GetFreeChan(); - CVector CreateChannelList(); - void CreateAndSendChanListForAllConChannels(); - void CreateAndSendChanListForThisChan ( const int iCurChanID ); - void CreateAndSendChatTextForAllConChannels ( const int iCurChanID, - const QString& strChatText ); - void WriteHTMLChannelList(); - - CVector ProcessData ( const int iCurIndex, - CVector >& vecvecsData, - CVector& vecdGains, - CVector& vecNumAudioChannels ); - - virtual void customEvent ( QEvent* Event ); - - // do not use the vector class since CChannel does not have appropriate - // copy constructor/operator - CChannel vecChannels[MAX_NUM_CHANNELS]; - CProtocol ConnLessProtocol; - QMutex Mutex; - - // audio encoder/decoder - CELTMode* CeltModeMono[MAX_NUM_CHANNELS]; - CELTEncoder* CeltEncoderMono[MAX_NUM_CHANNELS]; - CELTDecoder* CeltDecoderMono[MAX_NUM_CHANNELS]; - CELTMode* CeltModeStereo[MAX_NUM_CHANNELS]; - CELTEncoder* CeltEncoderStereo[MAX_NUM_CHANNELS]; - CELTDecoder* CeltDecoderStereo[MAX_NUM_CHANNELS]; - - CVector vstrChatColors; - - // actual working objects - CSocket Socket; - CCycleTimeVariance CycleTimeVariance; - - // logging - CServerLogging Logging; - - // HTML file server status - bool bWriteStatusHTMLFile; - QString strServerHTMLFileListName; - QString strServerNameWithPort; - - CHighPrecisionTimer HighPrecisionTimer; - CVector vecsSendData; - - // server list - CServerListManager ServerListManager; - -public slots: - void OnTimer(); - void OnSendProtMessage ( int iChID, CVector vecMessage ); - void OnSendCLProtMessage ( CHostAddress InetAddr, CVector vecMessage ); - - void OnCLPingReceived ( CHostAddress InetAddr, int iMs ) - { ConnLessProtocol.CreateCLPingMes ( InetAddr, iMs ); } - - void OnCLSendEmptyMes ( CHostAddress TargetInetAddr ) - { - // only send empty message if server list is enabled and this is not - // the central server - if ( ServerListManager.GetEnabled() && - !ServerListManager.GetIsCentralServer() ) - { - ConnLessProtocol.CreateCLEmptyMes ( TargetInetAddr ); - } - } - - void OnCLReqServerList ( CHostAddress InetAddr ) - { ServerListManager.QueryServerList ( InetAddr ); } - - void OnCLRegisterServerReceived ( CHostAddress InetAddr, - CServerCoreInfo ServerInfo ) - { - ServerListManager.RegisterServer ( InetAddr, ServerInfo ); - } - - - // CODE TAG: MAX_NUM_CHANNELS_TAG - // make sure we have MAX_NUM_CHANNELS connections!!! - // send message - void OnSendProtMessCh0 ( CVector mess ) { OnSendProtMessage ( 0, mess ); } - void OnSendProtMessCh1 ( CVector mess ) { OnSendProtMessage ( 1, mess ); } - void OnSendProtMessCh2 ( CVector mess ) { OnSendProtMessage ( 2, mess ); } - void OnSendProtMessCh3 ( CVector mess ) { OnSendProtMessage ( 3, mess ); } - void OnSendProtMessCh4 ( CVector mess ) { OnSendProtMessage ( 4, mess ); } - void OnSendProtMessCh5 ( CVector mess ) { OnSendProtMessage ( 5, mess ); } - void OnSendProtMessCh6 ( CVector mess ) { OnSendProtMessage ( 6, mess ); } - void OnSendProtMessCh7 ( CVector mess ) { OnSendProtMessage ( 7, mess ); } - void OnSendProtMessCh8 ( CVector mess ) { OnSendProtMessage ( 8, mess ); } - void OnSendProtMessCh9 ( CVector mess ) { OnSendProtMessage ( 9, mess ); } - void OnSendProtMessCh10 ( CVector mess ) { OnSendProtMessage ( 10, mess ); } - void OnSendProtMessCh11 ( CVector mess ) { OnSendProtMessage ( 11, mess ); } - - void OnNewConnectionCh0() { vecChannels[0].CreateReqJitBufMes(); } - void OnNewConnectionCh1() { vecChannels[1].CreateReqJitBufMes(); } - void OnNewConnectionCh2() { vecChannels[2].CreateReqJitBufMes(); } - void OnNewConnectionCh3() { vecChannels[3].CreateReqJitBufMes(); } - void OnNewConnectionCh4() { vecChannels[4].CreateReqJitBufMes(); } - void OnNewConnectionCh5() { vecChannels[5].CreateReqJitBufMes(); } - void OnNewConnectionCh6() { vecChannels[6].CreateReqJitBufMes(); } - void OnNewConnectionCh7() { vecChannels[7].CreateReqJitBufMes(); } - void OnNewConnectionCh8() { vecChannels[8].CreateReqJitBufMes(); } - void OnNewConnectionCh9() { vecChannels[9].CreateReqJitBufMes(); } - void OnNewConnectionCh10() { vecChannels[10].CreateReqJitBufMes(); } - void OnNewConnectionCh11() { vecChannels[11].CreateReqJitBufMes(); } - - void OnReqConnClientsListCh0() { CreateAndSendChanListForThisChan ( 0 ); } - void OnReqConnClientsListCh1() { CreateAndSendChanListForThisChan ( 1 ); } - void OnReqConnClientsListCh2() { CreateAndSendChanListForThisChan ( 2 ); } - void OnReqConnClientsListCh3() { CreateAndSendChanListForThisChan ( 3 ); } - void OnReqConnClientsListCh4() { CreateAndSendChanListForThisChan ( 4 ); } - void OnReqConnClientsListCh5() { CreateAndSendChanListForThisChan ( 5 ); } - void OnReqConnClientsListCh6() { CreateAndSendChanListForThisChan ( 6 ); } - void OnReqConnClientsListCh7() { CreateAndSendChanListForThisChan ( 7 ); } - void OnReqConnClientsListCh8() { CreateAndSendChanListForThisChan ( 8 ); } - void OnReqConnClientsListCh9() { CreateAndSendChanListForThisChan ( 9 ); } - void OnReqConnClientsListCh10() { CreateAndSendChanListForThisChan ( 10 ); } - void OnReqConnClientsListCh11() { CreateAndSendChanListForThisChan ( 11 ); } - - void OnNameHasChangedCh0() { CreateAndSendChanListForAllConChannels(); } - void OnNameHasChangedCh1() { CreateAndSendChanListForAllConChannels(); } - void OnNameHasChangedCh2() { CreateAndSendChanListForAllConChannels(); } - void OnNameHasChangedCh3() { CreateAndSendChanListForAllConChannels(); } - void OnNameHasChangedCh4() { CreateAndSendChanListForAllConChannels(); } - void OnNameHasChangedCh5() { CreateAndSendChanListForAllConChannels(); } - void OnNameHasChangedCh6() { CreateAndSendChanListForAllConChannels(); } - void OnNameHasChangedCh7() { CreateAndSendChanListForAllConChannels(); } - void OnNameHasChangedCh8() { CreateAndSendChanListForAllConChannels(); } - void OnNameHasChangedCh9() { CreateAndSendChanListForAllConChannels(); } - void OnNameHasChangedCh10() { CreateAndSendChanListForAllConChannels(); } - void OnNameHasChangedCh11() { CreateAndSendChanListForAllConChannels(); } - - void OnChatTextReceivedCh0 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 0, strChatText ); } - void OnChatTextReceivedCh1 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 1, strChatText ); } - void OnChatTextReceivedCh2 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 2, strChatText ); } - void OnChatTextReceivedCh3 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 3, strChatText ); } - void OnChatTextReceivedCh4 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 4, strChatText ); } - void OnChatTextReceivedCh5 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 5, strChatText ); } - void OnChatTextReceivedCh6 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 6, strChatText ); } - void OnChatTextReceivedCh7 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 7, strChatText ); } - void OnChatTextReceivedCh8 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 8, strChatText ); } - void OnChatTextReceivedCh9 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 9, strChatText ); } - void OnChatTextReceivedCh10 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 10, strChatText ); } - void OnChatTextReceivedCh11 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 11, strChatText ); } - - void OnPingReceivedCh0 ( int iMs ) { vecChannels[0].CreatePingMes ( iMs ); } - void OnPingReceivedCh1 ( int iMs ) { vecChannels[1].CreatePingMes ( iMs ); } - void OnPingReceivedCh2 ( int iMs ) { vecChannels[2].CreatePingMes ( iMs ); } - void OnPingReceivedCh3 ( int iMs ) { vecChannels[3].CreatePingMes ( iMs ); } - void OnPingReceivedCh4 ( int iMs ) { vecChannels[4].CreatePingMes ( iMs ); } - void OnPingReceivedCh5 ( int iMs ) { vecChannels[5].CreatePingMes ( iMs ); } - void OnPingReceivedCh6 ( int iMs ) { vecChannels[6].CreatePingMes ( iMs ); } - void OnPingReceivedCh7 ( int iMs ) { vecChannels[7].CreatePingMes ( iMs ); } - void OnPingReceivedCh8 ( int iMs ) { vecChannels[8].CreatePingMes ( iMs ); } - void OnPingReceivedCh9 ( int iMs ) { vecChannels[9].CreatePingMes ( iMs ); } - void OnPingReceivedCh10 ( int iMs ) { vecChannels[10].CreatePingMes ( iMs ); } - void OnPingReceivedCh11 ( int iMs ) { vecChannels[11].CreatePingMes ( iMs ); } -}; - -#endif /* !defined ( SERVER_HOIHGE7LOKIH83JH8_3_43445KJIUHF1912__INCLUDED_ ) */ +/******************************************************************************\ + * Copyright (c) 2004-2011 + * + * Author(s): + * Volker Fischer + * + ****************************************************************************** + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +\******************************************************************************/ + +#if !defined ( SERVER_HOIHGE7LOKIH83JH8_3_43445KJIUHF1912__INCLUDED_ ) +#define SERVER_HOIHGE7LOKIH83JH8_3_43445KJIUHF1912__INCLUDED_ + +#include +#include +#include +#include +#include "celt.h" +#include "global.h" +#include "socket.h" +#include "channel.h" +#include "util.h" +#include "serverlogging.h" +#include "serverlist.h" + + +/* Definitions ****************************************************************/ +// no valid channel number +#define INVALID_CHANNEL_ID ( MAX_NUM_CHANNELS + 1 ) + +// minimum timer precision +#define MIN_TIMER_RESOLUTION_MS 1 // ms + + +/* Classes ********************************************************************/ +#if defined ( __APPLE__ ) || defined ( __MACOSX ) +// using mach timers for Mac +class CHighPrecisionTimer : public QThread +{ + Q_OBJECT + +public: + CHighPrecisionTimer(); + + void Start(); + void Stop(); + bool isActive() { return bRun; } + +protected: + virtual void run(); + + bool bRun; + uint64_t iMachDelay; + uint64_t iNextEnd; + +signals: + void timeout(); +}; +#else +// using QTimer for Windows and Linux +class CHighPrecisionTimer : public QObject +{ + Q_OBJECT + +public: + CHighPrecisionTimer(); + + void Start(); + void Stop(); + bool isActive() const { return Timer.isActive(); } + +protected: + QTimer Timer; + CVector veciTimeOutIntervals; + int iCurPosInVector; + int iIntervalCounter; + +public slots: + void OnTimer(); + +signals: + void timeout(); +}; +#endif + + +class CServer : public QObject +{ + Q_OBJECT + +public: + CServer ( const QString& strLoggingFileName, + const quint16 iPortNumber, + const QString& strHTMLStatusFileName, + const QString& strHistoryFileName, + const QString& strServerNameForHTMLStatusFile, + const QString& strCentralServer ); + + void Start(); + void Stop(); + bool IsRunning() { return HighPrecisionTimer.isActive(); } + + bool GetTimingStdDev ( double& dCurTiStdDev ); + + bool PutData ( const CVector& vecbyRecBuf, + const int iNumBytesRead, + const CHostAddress& HostAdr ); + + void GetConCliParam ( CVector& vecHostAddresses, + CVector& vecsName, + CVector& veciJitBufNumFrames, + CVector& veciNetwFrameSizeFact ); + +protected: + // access functions for actual channels + bool IsConnected ( const int iChanNum ) + { return vecChannels[iChanNum].IsConnected(); } + + void StartStatusHTMLFileWriting ( const QString& strNewFileName, + const QString& strNewServerNameWithPort ); + + int CheckAddr ( const CHostAddress& Addr ); + int GetFreeChan(); + int GetNumberOfConnectedClients(); + CVector CreateChannelList(); + void CreateAndSendChanListForAllConChannels(); + void CreateAndSendChanListForThisChan ( const int iCurChanID ); + void CreateAndSendChatTextForAllConChannels ( const int iCurChanID, + const QString& strChatText ); + void WriteHTMLChannelList(); + + CVector ProcessData ( const int iCurIndex, + CVector >& vecvecsData, + CVector& vecdGains, + CVector& vecNumAudioChannels ); + + virtual void customEvent ( QEvent* Event ); + + // do not use the vector class since CChannel does not have appropriate + // copy constructor/operator + CChannel vecChannels[MAX_NUM_CHANNELS]; + CProtocol ConnLessProtocol; + QMutex Mutex; + + // audio encoder/decoder + CELTMode* CeltModeMono[MAX_NUM_CHANNELS]; + CELTEncoder* CeltEncoderMono[MAX_NUM_CHANNELS]; + CELTDecoder* CeltDecoderMono[MAX_NUM_CHANNELS]; + CELTMode* CeltModeStereo[MAX_NUM_CHANNELS]; + CELTEncoder* CeltEncoderStereo[MAX_NUM_CHANNELS]; + CELTDecoder* CeltDecoderStereo[MAX_NUM_CHANNELS]; + + CVector vstrChatColors; + + // actual working objects + CSocket Socket; + CCycleTimeVariance CycleTimeVariance; + + // logging + CServerLogging Logging; + + // HTML file server status + bool bWriteStatusHTMLFile; + QString strServerHTMLFileListName; + QString strServerNameWithPort; + + CHighPrecisionTimer HighPrecisionTimer; + CVector vecsSendData; + + // server list + CServerListManager ServerListManager; + +public slots: + void OnTimer(); + void OnSendProtMessage ( int iChID, CVector vecMessage ); + void OnSendCLProtMessage ( CHostAddress InetAddr, CVector vecMessage ); + + void OnCLPingReceived ( CHostAddress InetAddr, int iMs ) + { + ConnLessProtocol.CreateCLPingWithNumClientsMes ( InetAddr, + iMs, + GetNumberOfConnectedClients() ); + } + + void OnCLSendEmptyMes ( CHostAddress TargetInetAddr ) + { + // only send empty message if server list is enabled and this is not + // the central server + if ( ServerListManager.GetEnabled() && + !ServerListManager.GetIsCentralServer() ) + { + ConnLessProtocol.CreateCLEmptyMes ( TargetInetAddr ); + } + } + + void OnCLReqServerList ( CHostAddress InetAddr ) + { ServerListManager.QueryServerList ( InetAddr ); } + + void OnCLRegisterServerReceived ( CHostAddress InetAddr, + CServerCoreInfo ServerInfo ) + { + ServerListManager.RegisterServer ( InetAddr, ServerInfo ); + } + + + // CODE TAG: MAX_NUM_CHANNELS_TAG + // make sure we have MAX_NUM_CHANNELS connections!!! + // send message + void OnSendProtMessCh0 ( CVector mess ) { OnSendProtMessage ( 0, mess ); } + void OnSendProtMessCh1 ( CVector mess ) { OnSendProtMessage ( 1, mess ); } + void OnSendProtMessCh2 ( CVector mess ) { OnSendProtMessage ( 2, mess ); } + void OnSendProtMessCh3 ( CVector mess ) { OnSendProtMessage ( 3, mess ); } + void OnSendProtMessCh4 ( CVector mess ) { OnSendProtMessage ( 4, mess ); } + void OnSendProtMessCh5 ( CVector mess ) { OnSendProtMessage ( 5, mess ); } + void OnSendProtMessCh6 ( CVector mess ) { OnSendProtMessage ( 6, mess ); } + void OnSendProtMessCh7 ( CVector mess ) { OnSendProtMessage ( 7, mess ); } + void OnSendProtMessCh8 ( CVector mess ) { OnSendProtMessage ( 8, mess ); } + void OnSendProtMessCh9 ( CVector mess ) { OnSendProtMessage ( 9, mess ); } + void OnSendProtMessCh10 ( CVector mess ) { OnSendProtMessage ( 10, mess ); } + void OnSendProtMessCh11 ( CVector mess ) { OnSendProtMessage ( 11, mess ); } + + void OnNewConnectionCh0() { vecChannels[0].CreateReqJitBufMes(); } + void OnNewConnectionCh1() { vecChannels[1].CreateReqJitBufMes(); } + void OnNewConnectionCh2() { vecChannels[2].CreateReqJitBufMes(); } + void OnNewConnectionCh3() { vecChannels[3].CreateReqJitBufMes(); } + void OnNewConnectionCh4() { vecChannels[4].CreateReqJitBufMes(); } + void OnNewConnectionCh5() { vecChannels[5].CreateReqJitBufMes(); } + void OnNewConnectionCh6() { vecChannels[6].CreateReqJitBufMes(); } + void OnNewConnectionCh7() { vecChannels[7].CreateReqJitBufMes(); } + void OnNewConnectionCh8() { vecChannels[8].CreateReqJitBufMes(); } + void OnNewConnectionCh9() { vecChannels[9].CreateReqJitBufMes(); } + void OnNewConnectionCh10() { vecChannels[10].CreateReqJitBufMes(); } + void OnNewConnectionCh11() { vecChannels[11].CreateReqJitBufMes(); } + + void OnReqConnClientsListCh0() { CreateAndSendChanListForThisChan ( 0 ); } + void OnReqConnClientsListCh1() { CreateAndSendChanListForThisChan ( 1 ); } + void OnReqConnClientsListCh2() { CreateAndSendChanListForThisChan ( 2 ); } + void OnReqConnClientsListCh3() { CreateAndSendChanListForThisChan ( 3 ); } + void OnReqConnClientsListCh4() { CreateAndSendChanListForThisChan ( 4 ); } + void OnReqConnClientsListCh5() { CreateAndSendChanListForThisChan ( 5 ); } + void OnReqConnClientsListCh6() { CreateAndSendChanListForThisChan ( 6 ); } + void OnReqConnClientsListCh7() { CreateAndSendChanListForThisChan ( 7 ); } + void OnReqConnClientsListCh8() { CreateAndSendChanListForThisChan ( 8 ); } + void OnReqConnClientsListCh9() { CreateAndSendChanListForThisChan ( 9 ); } + void OnReqConnClientsListCh10() { CreateAndSendChanListForThisChan ( 10 ); } + void OnReqConnClientsListCh11() { CreateAndSendChanListForThisChan ( 11 ); } + + void OnNameHasChangedCh0() { CreateAndSendChanListForAllConChannels(); } + void OnNameHasChangedCh1() { CreateAndSendChanListForAllConChannels(); } + void OnNameHasChangedCh2() { CreateAndSendChanListForAllConChannels(); } + void OnNameHasChangedCh3() { CreateAndSendChanListForAllConChannels(); } + void OnNameHasChangedCh4() { CreateAndSendChanListForAllConChannels(); } + void OnNameHasChangedCh5() { CreateAndSendChanListForAllConChannels(); } + void OnNameHasChangedCh6() { CreateAndSendChanListForAllConChannels(); } + void OnNameHasChangedCh7() { CreateAndSendChanListForAllConChannels(); } + void OnNameHasChangedCh8() { CreateAndSendChanListForAllConChannels(); } + void OnNameHasChangedCh9() { CreateAndSendChanListForAllConChannels(); } + void OnNameHasChangedCh10() { CreateAndSendChanListForAllConChannels(); } + void OnNameHasChangedCh11() { CreateAndSendChanListForAllConChannels(); } + + void OnChatTextReceivedCh0 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 0, strChatText ); } + void OnChatTextReceivedCh1 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 1, strChatText ); } + void OnChatTextReceivedCh2 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 2, strChatText ); } + void OnChatTextReceivedCh3 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 3, strChatText ); } + void OnChatTextReceivedCh4 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 4, strChatText ); } + void OnChatTextReceivedCh5 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 5, strChatText ); } + void OnChatTextReceivedCh6 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 6, strChatText ); } + void OnChatTextReceivedCh7 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 7, strChatText ); } + void OnChatTextReceivedCh8 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 8, strChatText ); } + void OnChatTextReceivedCh9 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 9, strChatText ); } + void OnChatTextReceivedCh10 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 10, strChatText ); } + void OnChatTextReceivedCh11 ( QString strChatText ) { CreateAndSendChatTextForAllConChannels ( 11, strChatText ); } + + void OnPingReceivedCh0 ( int iMs ) { vecChannels[0].CreatePingMes ( iMs ); } + void OnPingReceivedCh1 ( int iMs ) { vecChannels[1].CreatePingMes ( iMs ); } + void OnPingReceivedCh2 ( int iMs ) { vecChannels[2].CreatePingMes ( iMs ); } + void OnPingReceivedCh3 ( int iMs ) { vecChannels[3].CreatePingMes ( iMs ); } + void OnPingReceivedCh4 ( int iMs ) { vecChannels[4].CreatePingMes ( iMs ); } + void OnPingReceivedCh5 ( int iMs ) { vecChannels[5].CreatePingMes ( iMs ); } + void OnPingReceivedCh6 ( int iMs ) { vecChannels[6].CreatePingMes ( iMs ); } + void OnPingReceivedCh7 ( int iMs ) { vecChannels[7].CreatePingMes ( iMs ); } + void OnPingReceivedCh8 ( int iMs ) { vecChannels[8].CreatePingMes ( iMs ); } + void OnPingReceivedCh9 ( int iMs ) { vecChannels[9].CreatePingMes ( iMs ); } + void OnPingReceivedCh10 ( int iMs ) { vecChannels[10].CreatePingMes ( iMs ); } + void OnPingReceivedCh11 ( int iMs ) { vecChannels[11].CreatePingMes ( iMs ); } +}; + +#endif /* !defined ( SERVER_HOIHGE7LOKIH83JH8_3_43445KJIUHF1912__INCLUDED_ ) */ diff --git a/src/serverlist.cpp b/src/serverlist.cpp index fcb0a8a9..eb798fed 100755 --- a/src/serverlist.cpp +++ b/src/serverlist.cpp @@ -62,7 +62,6 @@ ServerList.append ( CServerListEntry ( "", QLocale::Germany, // TEST "Munich", // TEST - 0, // will be updated later USED_NUM_CHANNELS, true ) ); // TEST @@ -187,7 +186,6 @@ void CServerListManager::RegisterServer ( const CHostAddress& InetAddr, ServerList[iSelIdx].strTopic = ServerInfo.strTopic; ServerList[iSelIdx].eCountry = ServerInfo.eCountry; ServerList[iSelIdx].strCity = ServerInfo.strCity; - ServerList[iSelIdx].iNumClients = ServerInfo.iNumClients; ServerList[iSelIdx].iMaxNumClients = ServerInfo.iMaxNumClients; ServerList[iSelIdx].bPermanentOnline = ServerInfo.bPermanentOnline; ServerList[iSelIdx].UpdateRegistration(); diff --git a/src/serverlist.h b/src/serverlist.h index 0e612874..0e95c400 100755 --- a/src/serverlist.h +++ b/src/serverlist.h @@ -1,156 +1,152 @@ -/******************************************************************************\ - * Copyright (c) 2004-2011 - * - * Author(s): - * Volker Fischer - * - -Currently, if you want to run a private server, you have to open the firewall of -your computer at the correct ports and introduce a port forwarding at your -router to get it work. Using a central server simplifies the process. The user -who wants to run a llcon server just registers his server a the central server -and a mechanism implemented in the protocol opens the firewall similar to STUN. - -REQUIREMENTS: - -The client sets the URL of the central llcon server and can get a list of all -currently activated and registered private llcon servers. If the user clicks on -the server of his choice, he gets connected to this server. - -The server list must be available in both cases: if the client is connected to -the central server or not. - -The server list contains the name of the server, an optional topic, an optional -location, the number of connected users and a ping time which is updated as -long as the server list is visible (similar to the ping measurement in the -general settings dialog). Additional information may be also present in the list -like reliability of the server, etc. - -CONNECTION PROCESS: - -The private server contacts the central server and registers through some -protocol mechanism. - -If a client requests the server list from the central server, the central server -sends the IP address of the client to each registered private servers so that -they can immediately send a "firewall opening" UDP packet to this IP address. -If the client now sends ping messages to each of the private servers in the -list, the firewalls and routers are prepared for receiving UDP packets from this -IP address and will tunnel it through. Note: this mechanism will not work in a -private network. - - ****************************************************************************** - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -\******************************************************************************/ - -#if !defined ( SERVERLIST_HOIJH8OUWEF_WFEIOBU_3_43445KJIUHF1912__INCLUDED_ ) -#define SERVERLIST_HOIJH8OUWEF_WFEIOBU_3_43445KJIUHF1912__INCLUDED_ - -#include -#include -#include -#include -#include -#include "global.h" -#include "util.h" -#include "protocol.h" - - -/* Classes ********************************************************************/ -class CServerListEntry : public CServerInfo -{ -public: - CServerListEntry() : - CServerInfo ( CHostAddress(), - "", - "", - QLocale::AnyCountry, - "", - 0, - 0, - false ) { UpdateRegistration(); } - - CServerListEntry ( const CHostAddress& NHAddr, - const QString& NsName, - const QString& NsTopic, - const QLocale::Country& NeCountry, - const QString& NsCity, - const int NiNumClients, - const int NiMaxNumClients, - const bool NbPermOnline) - : CServerInfo ( NHAddr, - NsName, - NsTopic, - NeCountry, - NsCity, - NiNumClients, - NiMaxNumClients, - NbPermOnline ) { UpdateRegistration(); } - - CServerListEntry ( const CHostAddress& NHAddr, - const CServerCoreInfo& NewCoreServerInfo ) - : CServerInfo ( NHAddr, - NewCoreServerInfo.strName, - NewCoreServerInfo.strTopic, - NewCoreServerInfo.eCountry, - NewCoreServerInfo.strCity, - NewCoreServerInfo.iNumClients, - NewCoreServerInfo.iMaxNumClients, - NewCoreServerInfo.bPermanentOnline ) - { UpdateRegistration(); } - - void UpdateRegistration() { RegisterTime.start(); } - -public: - // time on which the entry was registered - QTime RegisterTime; -}; - -class CServerListManager : public QObject -{ - Q_OBJECT - -public: - CServerListManager ( const QString& sNCentServAddr, - CProtocol* pNConLProt ); - - void SetEnabled ( const bool bState ); - bool GetEnabled() const { return bEnabled; } - bool GetIsCentralServer() const { return bIsCentralServer; } - - void RegisterServer ( const CHostAddress& InetAddr, - const CServerCoreInfo& ServerInfo ); - - void QueryServerList ( const CHostAddress& InetAddr ); - -protected: - QTimer TimerPollList; - QTimer TimerRegistering; - QMutex Mutex; - QList ServerList; - QString strCentralServerAddress; - bool bEnabled; - bool bIsCentralServer; - - CProtocol* pConnLessProtocol; - -public slots: - void OnTimerPollList(); - void OnTimerRegistering(); -}; - -#endif /* !defined ( SERVERLIST_HOIJH8OUWEF_WFEIOBU_3_43445KJIUHF1912__INCLUDED_ ) */ +/******************************************************************************\ + * Copyright (c) 2004-2011 + * + * Author(s): + * Volker Fischer + * + +Currently, if you want to run a private server, you have to open the firewall of +your computer at the correct ports and introduce a port forwarding at your +router to get it work. Using a central server simplifies the process. The user +who wants to run a llcon server just registers his server a the central server +and a mechanism implemented in the protocol opens the firewall similar to STUN. + +REQUIREMENTS: + +The client sets the URL of the central llcon server and can get a list of all +currently activated and registered private llcon servers. If the user clicks on +the server of his choice, he gets connected to this server. + +The server list must be available in both cases: if the client is connected to +the central server or not. + +The server list contains the name of the server, an optional topic, an optional +location, the number of connected users and a ping time which is updated as +long as the server list is visible (similar to the ping measurement in the +general settings dialog). Additional information may be also present in the list +like reliability of the server, etc. + +CONNECTION PROCESS: + +The private server contacts the central server and registers through some +protocol mechanism. + +If a client requests the server list from the central server, the central server +sends the IP address of the client to each registered private servers so that +they can immediately send a "firewall opening" UDP packet to this IP address. +If the client now sends ping messages to each of the private servers in the +list, the firewalls and routers are prepared for receiving UDP packets from this +IP address and will tunnel it through. Note: this mechanism will not work in a +private network. + + ****************************************************************************** + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +\******************************************************************************/ + +#if !defined ( SERVERLIST_HOIJH8OUWEF_WFEIOBU_3_43445KJIUHF1912__INCLUDED_ ) +#define SERVERLIST_HOIJH8OUWEF_WFEIOBU_3_43445KJIUHF1912__INCLUDED_ + +#include +#include +#include +#include +#include +#include "global.h" +#include "util.h" +#include "protocol.h" + + +/* Classes ********************************************************************/ +class CServerListEntry : public CServerInfo +{ +public: + CServerListEntry() : + CServerInfo ( CHostAddress(), + "", + "", + QLocale::AnyCountry, + "", + 0, + false ) { UpdateRegistration(); } + + CServerListEntry ( const CHostAddress& NHAddr, + const QString& NsName, + const QString& NsTopic, + const QLocale::Country& NeCountry, + const QString& NsCity, + const int NiMaxNumClients, + const bool NbPermOnline) + : CServerInfo ( NHAddr, + NsName, + NsTopic, + NeCountry, + NsCity, + NiMaxNumClients, + NbPermOnline ) { UpdateRegistration(); } + + CServerListEntry ( const CHostAddress& NHAddr, + const CServerCoreInfo& NewCoreServerInfo ) + : CServerInfo ( NHAddr, + NewCoreServerInfo.strName, + NewCoreServerInfo.strTopic, + NewCoreServerInfo.eCountry, + NewCoreServerInfo.strCity, + NewCoreServerInfo.iMaxNumClients, + NewCoreServerInfo.bPermanentOnline ) + { UpdateRegistration(); } + + void UpdateRegistration() { RegisterTime.start(); } + +public: + // time on which the entry was registered + QTime RegisterTime; +}; + +class CServerListManager : public QObject +{ + Q_OBJECT + +public: + CServerListManager ( const QString& sNCentServAddr, + CProtocol* pNConLProt ); + + void SetEnabled ( const bool bState ); + bool GetEnabled() const { return bEnabled; } + bool GetIsCentralServer() const { return bIsCentralServer; } + + void RegisterServer ( const CHostAddress& InetAddr, + const CServerCoreInfo& ServerInfo ); + + void QueryServerList ( const CHostAddress& InetAddr ); + +protected: + QTimer TimerPollList; + QTimer TimerRegistering; + QMutex Mutex; + QList ServerList; + QString strCentralServerAddress; + bool bEnabled; + bool bIsCentralServer; + + CProtocol* pConnLessProtocol; + +public slots: + void OnTimerPollList(); + void OnTimerRegistering(); +}; + +#endif /* !defined ( SERVERLIST_HOIJH8OUWEF_WFEIOBU_3_43445KJIUHF1912__INCLUDED_ ) */ diff --git a/src/util.h b/src/util.h index ae4891e1..ee402395 100755 --- a/src/util.h +++ b/src/util.h @@ -487,7 +487,6 @@ public: strTopic ( "" ), eCountry ( QLocale::AnyCountry ), strCity ( "" ), - iNumClients ( 0 ), iMaxNumClients ( 0 ), bPermanentOnline ( false ) {} @@ -496,14 +495,12 @@ public: const QString& NsTopic, const QLocale::Country& NeCountry, const QString& NsCity, - const int NiNumClients, const int NiMaxNumClients, const bool NbPermOnline) : strName ( NsName ), strTopic ( NsTopic ), eCountry ( NeCountry ), strCity ( NsCity ), - iNumClients ( NiNumClients ), iMaxNumClients ( NiMaxNumClients ), bPermanentOnline ( NbPermOnline ) {} @@ -520,9 +517,6 @@ public: // city in which the server is located QString strCity; - // current number of connected clients - int iNumClients; - // maximum number of clients which can connect to the server at the same // time int iMaxNumClients; @@ -540,7 +534,6 @@ public: QLocale::AnyCountry, "", 0, - 0, false ), HostAddr ( CHostAddress() ) {} CServerInfo ( @@ -549,14 +542,12 @@ public: const QString& NsTopic, const QLocale::Country& NeCountry, const QString& NsCity, - const int NiNumClients, const int NiMaxNumClients, const bool NbPermOnline) : CServerCoreInfo ( NsName, NsTopic, NeCountry, NsCity, - NiNumClients, NiMaxNumClients, NbPermOnline ), HostAddr ( NHAddr ) {}