diff --git a/src/channel.cpp b/src/channel.cpp index 44450067..8a33a008 100755 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -25,532 +25,6 @@ #include "channel.h" -/******************************************************************************\ -* CChannelSet * -\******************************************************************************/ -CChannelSet::CChannelSet() : - bWriteStatusHTMLFile ( false ) -{ - // enable all channels (for the server all channel must be enabled the - // entire life time of the software - for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) - { - vecChannels[i].SetEnable ( true ); - } - - // define colors for chat window identifiers - vstrChatColors.Init ( 6 ); - vstrChatColors[0] = "mediumblue"; - vstrChatColors[1] = "red"; - vstrChatColors[2] = "darkorchid"; - vstrChatColors[3] = "green"; - vstrChatColors[4] = "maroon"; - vstrChatColors[5] = "coral"; - - // CODE TAG: MAX_NUM_CHANNELS_TAG - // make sure we have MAX_NUM_CHANNELS connections!!! - // send message - QObject::connect ( &vecChannels[0], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh0 ( CVector ) ) ); - QObject::connect ( &vecChannels[1], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh1 ( CVector ) ) ); - QObject::connect ( &vecChannels[2], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh2 ( CVector ) ) ); - QObject::connect ( &vecChannels[3], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh3 ( CVector ) ) ); - QObject::connect ( &vecChannels[4], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh4 ( CVector ) ) ); - QObject::connect ( &vecChannels[5], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh5 ( CVector ) ) ); - QObject::connect ( &vecChannels[6], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh6 ( CVector ) ) ); - QObject::connect ( &vecChannels[7], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh7 ( CVector ) ) ); - QObject::connect ( &vecChannels[8], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh8 ( CVector ) ) ); - QObject::connect ( &vecChannels[9], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh9 ( CVector ) ) ); - - // request jitter buffer size - QObject::connect ( &vecChannels[0], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh0() ) ); - QObject::connect ( &vecChannels[1], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh1() ) ); - QObject::connect ( &vecChannels[2], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh2() ) ); - QObject::connect ( &vecChannels[3], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh3() ) ); - QObject::connect ( &vecChannels[4], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh4() ) ); - QObject::connect ( &vecChannels[5], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh5() ) ); - QObject::connect ( &vecChannels[6], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh6() ) ); - QObject::connect ( &vecChannels[7], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh7() ) ); - QObject::connect ( &vecChannels[8], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh8() ) ); - QObject::connect ( &vecChannels[9], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh9() ) ); - - // request connected clients list - QObject::connect ( &vecChannels[0], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh0() ) ); - QObject::connect ( &vecChannels[1], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh1() ) ); - QObject::connect ( &vecChannels[2], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh2() ) ); - QObject::connect ( &vecChannels[3], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh3() ) ); - QObject::connect ( &vecChannels[4], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh4() ) ); - QObject::connect ( &vecChannels[5], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh5() ) ); - QObject::connect ( &vecChannels[6], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh6() ) ); - QObject::connect ( &vecChannels[7], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh7() ) ); - QObject::connect ( &vecChannels[8], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh8() ) ); - QObject::connect ( &vecChannels[9], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh9() ) ); - - // channel name has changed - QObject::connect ( &vecChannels[0], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh0() ) ); - QObject::connect ( &vecChannels[1], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh1() ) ); - QObject::connect ( &vecChannels[2], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh2() ) ); - QObject::connect ( &vecChannels[3], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh3() ) ); - QObject::connect ( &vecChannels[4], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh4() ) ); - QObject::connect ( &vecChannels[5], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh5() ) ); - QObject::connect ( &vecChannels[6], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh6() ) ); - QObject::connect ( &vecChannels[7], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh7() ) ); - QObject::connect ( &vecChannels[8], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh8() ) ); - QObject::connect ( &vecChannels[9], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh9() ) ); - - // chat text received - QObject::connect ( &vecChannels[0], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh0 ( QString ) ) ); - QObject::connect ( &vecChannels[1], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh1 ( QString ) ) ); - QObject::connect ( &vecChannels[2], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh2 ( QString ) ) ); - QObject::connect ( &vecChannels[3], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh3 ( QString ) ) ); - QObject::connect ( &vecChannels[4], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh4 ( QString ) ) ); - QObject::connect ( &vecChannels[5], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh5 ( QString ) ) ); - QObject::connect ( &vecChannels[6], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh6 ( QString ) ) ); - QObject::connect ( &vecChannels[7], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh7 ( QString ) ) ); - QObject::connect ( &vecChannels[8], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh8 ( QString ) ) ); - QObject::connect ( &vecChannels[9], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh9 ( QString ) ) ); - - // ping message received - QObject::connect ( &vecChannels[0], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh0 ( int ) ) ); - QObject::connect ( &vecChannels[1], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh1 ( int ) ) ); - QObject::connect ( &vecChannels[2], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh2 ( int ) ) ); - QObject::connect ( &vecChannels[3], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh3 ( int ) ) ); - QObject::connect ( &vecChannels[4], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh4 ( int ) ) ); - QObject::connect ( &vecChannels[5], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh5 ( int ) ) ); - QObject::connect ( &vecChannels[6], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh6 ( int ) ) ); - QObject::connect ( &vecChannels[7], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh7 ( int ) ) ); - QObject::connect ( &vecChannels[8], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh8 ( int ) ) ); - QObject::connect ( &vecChannels[9], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh9 ( int ) ) ); -} - -CVector CChannelSet::CreateChannelList() -{ - CVector vecChanInfo ( 0 ); - - // look for free channels - for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) - { - if ( vecChannels[i].IsConnected() ) - { - // append channel ID, IP address and channel name to storing vectors - vecChanInfo.Add ( CChannelShortInfo ( - i, // ID - vecChannels[i].GetAddress().InetAddr.toIPv4Address(), // IP address - vecChannels[i].GetName() /* name */ ) ); - } - } - - return vecChanInfo; -} - -void CChannelSet::CreateAndSendChanListForAllConChannels() -{ - // create channel list - CVector vecChanInfo ( CChannelSet::CreateChannelList() ); - - // now send connected channels list to all connected clients - for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) - { - if ( vecChannels[i].IsConnected() ) - { - // send message - vecChannels[i].CreateConClientListMes ( vecChanInfo ); - } - } - - // create status HTML file if enabled - if ( bWriteStatusHTMLFile ) - { - WriteHTMLChannelList(); - } -} - -void CChannelSet::CreateAndSendChanListForAllExceptThisChan ( const int iCurChanID ) -{ - // create channel list - CVector vecChanInfo ( CChannelSet::CreateChannelList() ); - - // now send connected channels list to all connected clients except for - // the channel with the ID "iCurChanID" - for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) - { - if ( ( vecChannels[i].IsConnected() ) && ( i != iCurChanID ) ) - { - // send message - vecChannels[i].CreateConClientListMes ( vecChanInfo ); - } - } - - // create status HTML file if enabled - if ( bWriteStatusHTMLFile ) - { - WriteHTMLChannelList(); - } -} - -void CChannelSet::CreateAndSendChanListForThisChan ( const int iCurChanID ) -{ - // create channel list - CVector vecChanInfo ( CChannelSet::CreateChannelList() ); - - // now send connected channels list to the channel with the ID "iCurChanID" - vecChannels[iCurChanID].CreateConClientListMes ( vecChanInfo ); -} - -void CChannelSet::CreateAndSendChatTextForAllConChannels ( const int iCurChanID, - const QString& strChatText ) -{ - // create message which is sent to all connected clients ------------------- - // get client name, if name is empty, use IP address instead - QString ChanName = vecChannels[iCurChanID].GetName(); - if ( ChanName.isEmpty() ) - { - // convert IP address to text and show it - ChanName = - vecChannels[iCurChanID].GetAddress().GetIpAddressStringNoLastByte(); - } - - // add name of the client at the beginning of the message text and use - // different colors, to get correct HTML, the "<" and ">" signs must be - // replaced by "<" and ">" - QString sCurColor = vstrChatColors[iCurChanID % vstrChatColors.Size()]; - const QString strActualMessageText = - "<" + ChanName + - "> " + strChatText; - - - // send chat text to all connected clients --------------------------------- - for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) - { - if ( vecChannels[i].IsConnected() ) - { - // send message - vecChannels[i].CreateChatTextMes ( strActualMessageText ); - } - } -} - -int CChannelSet::GetFreeChan() -{ - // look for a free channel - for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) - { - if ( !vecChannels[i].IsConnected() ) - { - return i; - } - } - - // no free channel found, return invalid ID - return INVALID_CHANNEL_ID; -} - -int CChannelSet::CheckAddr ( const CHostAddress& Addr ) -{ - CHostAddress InetAddr; - - // check for all possible channels if IP is already in use - for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) - { - if ( vecChannels[i].IsConnected() ) - { - if ( vecChannels[i].GetAddress ( InetAddr ) ) - { - // IP found, return channel number - if ( InetAddr == Addr ) - { - return i; - } - } - } - } - - // IP not found, return invalid ID - return INVALID_CHANNEL_ID; -} - -bool CChannelSet::PutData ( const CVector& vecbyRecBuf, - const int iNumBytesRead, - const CHostAddress& HostAdr ) -{ - bool bAudioOK = false; - bool bNewChannelReserved = false; - - Mutex.lock(); - { - bool bChanOK = true; - - // Get channel ID ------------------------------------------------------ - // check address - int iCurChanID = CheckAddr ( HostAdr ); - - if ( iCurChanID == INVALID_CHANNEL_ID ) - { - // a new client is calling, look for free channel - iCurChanID = GetFreeChan(); - - if ( iCurChanID != INVALID_CHANNEL_ID ) - { - // initialize current channel by storing the calling host - // address - vecChannels[iCurChanID].SetAddress ( HostAdr ); - - // reset the channel gains of current channel, at the same - // time reset gains of this channel ID for all other channels - for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) - { - vecChannels[iCurChanID].SetGain ( i, (double) 1.0 ); - - // other channels (we do not distinguish the case if - // i == iCurChanID for simplicity) - vecChannels[i].SetGain ( iCurChanID, (double) 1.0 ); - } - - // set flag for new reserved channel - bNewChannelReserved = true; - } - else - { - // no free channel available - bChanOK = false; - - // create and send "server full" message - -// TODO problem: if channel is not officially connected, we cannot send messages - - } - } - - - // Put received data in jitter buffer ---------------------------------- - if ( bChanOK ) - { - // put packet in socket buffer - switch ( vecChannels[iCurChanID].PutData ( vecbyRecBuf, iNumBytesRead ) ) - { - case PS_AUDIO_OK: - PostWinMessage ( MS_JIT_BUF_PUT, MUL_COL_LED_GREEN, iCurChanID ); - bAudioOK = true; // in case we have an audio packet, return true - break; - - case PS_AUDIO_ERR: - PostWinMessage ( MS_JIT_BUF_PUT, MUL_COL_LED_RED, iCurChanID ); - bAudioOK = true; // in case we have an audio packet, return true - break; - - case PS_PROT_ERR: - PostWinMessage ( MS_JIT_BUF_PUT, MUL_COL_LED_YELLOW, iCurChanID ); - -// TEST -bAudioOK = true; - - break; - } - } - - // after data is put in channel buffer, create channel list message if - // requested - if ( bNewChannelReserved && bAudioOK ) - { - // send message about new channel - emit ChannelConnected ( HostAdr ); - - // A new client connected to the server, create and - // send all clients the updated channel list (the list has to - // be created after the received data has to be put to the - // channel first so that this channel is marked as connected) - // - // connected clients list is only send for new connected clients after - // request, only the already connected clients get the list - // automatically, because they don't know when new clients connect - CreateAndSendChanListForAllExceptThisChan ( iCurChanID ); - } - } - Mutex.unlock(); - - return bAudioOK; -} - -void CChannelSet::GetBlockAllConC ( CVector& vecChanID, - CVector >& vecvecdData, - CVector >& vecvecdGains ) -{ - int i, j; - bool bChannelIsNowDisconnected = false; - - // init temporal data vector and clear input buffers - CVector vecdData ( SYSTEM_BLOCK_SIZE_SAMPLES ); - - vecChanID.Init ( 0 ); - vecvecdData.Init ( 0 ); - vecvecdGains.Init ( 0 ); - - // make put and get calls thread safe. Do not forget to unlock mutex - // afterwards! - Mutex.lock(); - { - // check all possible channels - for ( i = 0; i < USED_NUM_CHANNELS; i++ ) - { - // read out all input buffers to decrease timeout counter on - // disconnected channels -// const EGetDataStat eGetStat = vecChannels[i].GetData ( vecdData ); -const EGetDataStat eGetStat=GS_BUFFER_OK;//TEST - - // if channel was just disconnected, set flag that connected - // client list is sent to all other clients - if ( eGetStat == GS_CHAN_NOW_DISCONNECTED ) - { - bChannelIsNowDisconnected = true; - } - - if ( vecChannels[i].IsConnected() ) - { - // add ID and data - vecChanID.Add ( i ); - - const int iOldSize = vecvecdData.Size(); - vecvecdData.Enlarge ( 1 ); - vecvecdData[iOldSize].Init ( vecdData.Size() ); - vecvecdData[iOldSize] = vecdData; - - // send message for get status (for GUI) - if ( eGetStat == GS_BUFFER_OK ) - { - PostWinMessage ( MS_JIT_BUF_GET, MUL_COL_LED_GREEN, i ); - } - else - { - PostWinMessage ( MS_JIT_BUF_GET, MUL_COL_LED_RED, i ); - } - } - } - - // now that we know the IDs of the connected clients, get gains - const int iNumCurConnChan = vecChanID.Size(); - vecvecdGains.Init ( iNumCurConnChan ); - - for ( i = 0; i < iNumCurConnChan; i++ ) - { - vecvecdGains[i].Init ( iNumCurConnChan ); - - for ( j = 0; j < iNumCurConnChan; j++ ) - { - // The second index of "vecvecdGains" does not represent - // the channel ID! Therefore we have to use "vecChanID" to - // query the IDs of the currently connected channels - vecvecdGains[i][j] = - vecChannels[vecChanID[i]].GetGain( vecChanID[j] ); - } - } - - // a channel is now disconnected, take action on it - if ( bChannelIsNowDisconnected ) - { - // update channel list for all currently connected clients - CreateAndSendChanListForAllConChannels(); - } - } - Mutex.unlock(); // release mutex -} - -void CChannelSet::GetConCliParam ( CVector& vecHostAddresses, - CVector& vecsName, - CVector& veciJitBufSize, - CVector& veciNetwOutBlSiFact ) -{ - CHostAddress InetAddr; - - // init return values - vecHostAddresses.Init ( USED_NUM_CHANNELS ); - vecsName.Init ( USED_NUM_CHANNELS ); - veciJitBufSize.Init ( USED_NUM_CHANNELS ); - veciNetwOutBlSiFact.Init ( USED_NUM_CHANNELS ); - - // check all possible channels - for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) - { - if ( vecChannels[i].GetAddress ( InetAddr ) ) - { - // get requested data - vecHostAddresses[i] = InetAddr; - vecsName[i] = vecChannels[i].GetName(); - veciJitBufSize[i] = vecChannels[i].GetSockBufSize(); - veciNetwOutBlSiFact[i] = vecChannels[i].GetNetwBufSizeFactOut(); - } - } -} - -void CChannelSet::StartStatusHTMLFileWriting ( const QString& strNewFileName, - const QString& strNewServerNameWithPort ) -{ - // set important parameters - strServerHTMLFileListName = strNewFileName; - strServerNameWithPort = strNewServerNameWithPort; - - // set flag - bWriteStatusHTMLFile = true; - - // write initial file - WriteHTMLChannelList(); -} - -void CChannelSet::WriteHTMLChannelList() -{ - // create channel list - CVector vecChanInfo ( CChannelSet::CreateChannelList() ); - - // prepare file and stream - QFile serverFileListFile ( strServerHTMLFileListName ); - if ( !serverFileListFile.open ( QIODevice::WriteOnly | QIODevice::Text ) ) - { - return; - } - - QTextStream streamFileOut ( &serverFileListFile ); - streamFileOut << strServerNameWithPort << endl << "
    " << endl; - - // get the number of connected clients - int iNumConnClients = 0; - for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) - { - if ( vecChannels[i].IsConnected() ) - { - iNumConnClients++; - } - } - - // depending on number of connected clients write list - if ( iNumConnClients == 0 ) - { - // no clients are connected -> empty server - streamFileOut << " No client connected" << endl; - } - else - { - // write entry for each connected client - for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) - { - if ( vecChannels[i].IsConnected() ) - { - QString strCurChanName = vecChannels[i].GetName(); - - // if text is empty, show IP address instead - if ( strCurChanName.isEmpty() ) - { - // convert IP address to text and show it, remove last - // digits - strCurChanName = - vecChannels[i].GetAddress().GetIpAddressStringNoLastByte(); - } - - streamFileOut << "
  • " << strCurChanName << "
  • " << endl; - } - } - } - - // finish list - streamFileOut << "
" << endl; -} diff --git a/src/channel.h b/src/channel.h index a2b692e3..3e3fc820 100755 --- a/src/channel.h +++ b/src/channel.h @@ -41,9 +41,6 @@ // correction is implemented) #define CON_TIME_OUT_SEC_MAX 60 // seconds -// no valid channel number -#define INVALID_CHANNEL_ID ( MAX_NUM_CHANNELS + 1 ) - enum EPutDataStat { PS_GEN_ERROR, @@ -53,17 +50,8 @@ enum EPutDataStat PS_PROT_ERR }; -enum EGetDataStat -{ - GS_BUFFER_OK, - GS_BUFFER_UNDERRUN, - GS_CHAN_NOW_DISCONNECTED, - GS_CHAN_NOT_CONNECTED -}; - /* Classes ********************************************************************/ -// CChannel -------------------------------------------------------------------- class CChannel : public QObject { Q_OBJECT @@ -205,139 +193,4 @@ signals: void ReqNetTranspProps(); }; - -// CChannelSet (for server) ---------------------------------------------------- -class CChannelSet : public QObject -{ - Q_OBJECT - -public: - CChannelSet(); - virtual ~CChannelSet() {} - - bool PutData ( const CVector& vecbyRecBuf, - const int iNumBytesRead, const CHostAddress& HostAdr ); - - int GetFreeChan(); - - int CheckAddr ( const CHostAddress& Addr ); - - void GetBlockAllConC ( CVector& vecChanID, - CVector >& vecvecdData, - CVector >& vecvecdGains ); - - void GetConCliParam ( CVector& vecHostAddresses, - CVector& vecsName, - CVector& veciJitBufSize, - CVector& veciNetwOutBlSiFact ); - - // access functions for actual channels - bool IsConnected ( const int iChanNum ) - { return vecChannels[iChanNum].IsConnected(); } - - CVector PrepSendPacket ( const int iChanNum, - const CVector& vecsNPacket ) - { return vecChannels[iChanNum].PrepSendPacket ( vecsNPacket ); } - - CHostAddress GetAddress ( const int iChanNum ) - { return vecChannels[iChanNum].GetAddress(); } - - void StartStatusHTMLFileWriting ( const QString& strNewFileName, - const QString& strNewServerNameWithPort ); - -protected: - CVector CreateChannelList(); - void CreateAndSendChanListForAllConChannels(); - void CreateAndSendChanListForAllExceptThisChan ( const int iCurChanID ); - void CreateAndSendChanListForThisChan ( const int iCurChanID ); - void CreateAndSendChatTextForAllConChannels ( const int iCurChanID, const QString& strChatText ); - void WriteHTMLChannelList(); - - /* do not use the vector class since CChannel does not have appropriate - copy constructor/operator */ - CChannel vecChannels[MAX_NUM_CHANNELS]; - QMutex Mutex; - - CVector vstrChatColors; - - // HTML file server status - bool bWriteStatusHTMLFile; - QString strServerHTMLFileListName; - QString strServerNameWithPort; - -public slots: - // CODE TAG: MAX_NUM_CHANNELS_TAG - // make sure we have MAX_NUM_CHANNELS connections!!! - // send message - void OnSendProtMessCh0 ( CVector mess ) { emit MessReadyForSending ( 0, mess ); } - void OnSendProtMessCh1 ( CVector mess ) { emit MessReadyForSending ( 1, mess ); } - void OnSendProtMessCh2 ( CVector mess ) { emit MessReadyForSending ( 2, mess ); } - void OnSendProtMessCh3 ( CVector mess ) { emit MessReadyForSending ( 3, mess ); } - void OnSendProtMessCh4 ( CVector mess ) { emit MessReadyForSending ( 4, mess ); } - void OnSendProtMessCh5 ( CVector mess ) { emit MessReadyForSending ( 5, mess ); } - void OnSendProtMessCh6 ( CVector mess ) { emit MessReadyForSending ( 6, mess ); } - void OnSendProtMessCh7 ( CVector mess ) { emit MessReadyForSending ( 7, mess ); } - void OnSendProtMessCh8 ( CVector mess ) { emit MessReadyForSending ( 8, mess ); } - void OnSendProtMessCh9 ( CVector mess ) { emit MessReadyForSending ( 9, 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 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 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 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 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 ); } - -signals: - void MessReadyForSending ( int iChID, CVector vecMessage ); - void ChannelConnected ( CHostAddress ChanAddr ); -}; - #endif /* !defined ( CHANNEL_HOIH9345KJH98_3_4344_BB23945IUHF1912__INCLUDED_ ) */ diff --git a/src/llconserverdlg.cpp b/src/llconserverdlg.cpp index 1de8da2b..7f0ea7a4 100755 --- a/src/llconserverdlg.cpp +++ b/src/llconserverdlg.cpp @@ -79,13 +79,12 @@ void CLlconServerDlg::OnTimer() CVector vecsName; CVector veciJitBufSize; CVector veciNetwOutBlSiFact; - CVector veceAudComprType; double dCurTiStdDev; ListViewMutex.lock(); pServer->GetConCliParam ( vecHostAddresses, vecsName, veciJitBufSize, - veciNetwOutBlSiFact, veceAudComprType ); + veciNetwOutBlSiFact ); // fill list with connected clients for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) @@ -109,22 +108,6 @@ void CLlconServerDlg::OnTimer() QString().setNum ( static_cast ( veciNetwOutBlSiFact[i] * SYSTEM_BLOCK_DURATION_MS_FLOAT ), 'f', 2 ) ); - // output audio compression - switch ( veceAudComprType[i] ) - { - case CT_NONE: - vecpListViewItems[i]->setText ( 6, "None" ); - break; - - case CT_CELT: - vecpListViewItems[i]->setText ( 6, "CELT" ); - break; - - default: - vecpListViewItems[i]->setText ( 6, "Unknown" ); - break; - } - vecpListViewItems[i]->setHidden ( false ); } else diff --git a/src/llconserverdlgbase.ui b/src/llconserverdlgbase.ui index 789bad4a..2dcd7da4 100755 --- a/src/llconserverdlgbase.ui +++ b/src/llconserverdlgbase.ui @@ -69,11 +69,6 @@ Block Size Out - - - Audio Compr. Out - - diff --git a/src/server.cpp b/src/server.cpp index c67cd0ca..74cde90f 100755 --- a/src/server.cpp +++ b/src/server.cpp @@ -31,8 +31,25 @@ CServer::CServer ( const QString& strLoggingFileName, const QString& strHTMLStatusFileName, const QString& strHistoryFileName, const QString& strServerNameForHTMLStatusFile ) : - Socket ( &ChannelSet, this, iPortNumber ) + Socket ( this, iPortNumber ), + bWriteStatusHTMLFile ( false ) { + // enable all channels (for the server all channel must be enabled the + // entire life time of the software + for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) + { + vecChannels[i].SetEnable ( true ); + } + + // define colors for chat window identifiers + vstrChatColors.Init ( 6 ); + vstrChatColors[0] = "mediumblue"; + vstrChatColors[1] = "red"; + vstrChatColors[2] = "darkorchid"; + vstrChatColors[3] = "green"; + vstrChatColors[4] = "maroon"; + vstrChatColors[5] = "coral"; + vecsSendData.Init ( SYSTEM_BLOCK_SIZE_SAMPLES ); // init moving average buffer for response time evaluation @@ -43,16 +60,6 @@ CServer::CServer ( const QString& strLoggingFileName, QObject::connect ( &Timer, SIGNAL ( timeout() ), this, SLOT ( OnTimer() ) ); - // connection for protocol - QObject::connect ( &ChannelSet, - SIGNAL ( MessReadyForSending ( int, CVector ) ), - this, SLOT ( OnSendProtMessage ( int, CVector ) ) ); - - // connection for logging - QObject::connect ( &ChannelSet, - SIGNAL ( ChannelConnected ( CHostAddress ) ), - this, SLOT ( OnNewChannel ( CHostAddress ) ) ); - // enable logging (if requested) if ( !strLoggingFileName.isEmpty() ) { @@ -78,17 +85,91 @@ CServer::CServer ( const QString& strLoggingFileName, // (the static cast to integer of the port number is required so that it // works correctly under Linux) - ChannelSet.StartStatusHTMLFileWriting ( strHTMLStatusFileName, + StartStatusHTMLFileWriting ( strHTMLStatusFileName, strCurServerNameForHTMLStatusFile + ":" + QString().number( static_cast ( iPortNumber ) ) ); } + + // CODE TAG: MAX_NUM_CHANNELS_TAG + // make sure we have MAX_NUM_CHANNELS connections!!! + // send message + QObject::connect ( &vecChannels[0], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh0 ( CVector ) ) ); + QObject::connect ( &vecChannels[1], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh1 ( CVector ) ) ); + QObject::connect ( &vecChannels[2], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh2 ( CVector ) ) ); + QObject::connect ( &vecChannels[3], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh3 ( CVector ) ) ); + QObject::connect ( &vecChannels[4], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh4 ( CVector ) ) ); + QObject::connect ( &vecChannels[5], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh5 ( CVector ) ) ); + QObject::connect ( &vecChannels[6], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh6 ( CVector ) ) ); + QObject::connect ( &vecChannels[7], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh7 ( CVector ) ) ); + QObject::connect ( &vecChannels[8], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh8 ( CVector ) ) ); + QObject::connect ( &vecChannels[9], SIGNAL ( MessReadyForSending ( CVector ) ), this, SLOT ( OnSendProtMessCh9 ( CVector ) ) ); + + // request jitter buffer size + QObject::connect ( &vecChannels[0], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh0() ) ); + QObject::connect ( &vecChannels[1], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh1() ) ); + QObject::connect ( &vecChannels[2], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh2() ) ); + QObject::connect ( &vecChannels[3], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh3() ) ); + QObject::connect ( &vecChannels[4], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh4() ) ); + QObject::connect ( &vecChannels[5], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh5() ) ); + QObject::connect ( &vecChannels[6], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh6() ) ); + QObject::connect ( &vecChannels[7], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh7() ) ); + QObject::connect ( &vecChannels[8], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh8() ) ); + QObject::connect ( &vecChannels[9], SIGNAL ( NewConnection() ), this, SLOT ( OnNewConnectionCh9() ) ); + + // request connected clients list + QObject::connect ( &vecChannels[0], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh0() ) ); + QObject::connect ( &vecChannels[1], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh1() ) ); + QObject::connect ( &vecChannels[2], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh2() ) ); + QObject::connect ( &vecChannels[3], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh3() ) ); + QObject::connect ( &vecChannels[4], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh4() ) ); + QObject::connect ( &vecChannels[5], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh5() ) ); + QObject::connect ( &vecChannels[6], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh6() ) ); + QObject::connect ( &vecChannels[7], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh7() ) ); + QObject::connect ( &vecChannels[8], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh8() ) ); + QObject::connect ( &vecChannels[9], SIGNAL ( ReqConnClientsList() ), this, SLOT ( OnReqConnClientsListCh9() ) ); + + // channel name has changed + QObject::connect ( &vecChannels[0], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh0() ) ); + QObject::connect ( &vecChannels[1], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh1() ) ); + QObject::connect ( &vecChannels[2], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh2() ) ); + QObject::connect ( &vecChannels[3], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh3() ) ); + QObject::connect ( &vecChannels[4], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh4() ) ); + QObject::connect ( &vecChannels[5], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh5() ) ); + QObject::connect ( &vecChannels[6], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh6() ) ); + QObject::connect ( &vecChannels[7], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh7() ) ); + QObject::connect ( &vecChannels[8], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh8() ) ); + QObject::connect ( &vecChannels[9], SIGNAL ( NameHasChanged() ), this, SLOT ( OnNameHasChangedCh9() ) ); + + // chat text received + QObject::connect ( &vecChannels[0], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh0 ( QString ) ) ); + QObject::connect ( &vecChannels[1], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh1 ( QString ) ) ); + QObject::connect ( &vecChannels[2], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh2 ( QString ) ) ); + QObject::connect ( &vecChannels[3], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh3 ( QString ) ) ); + QObject::connect ( &vecChannels[4], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh4 ( QString ) ) ); + QObject::connect ( &vecChannels[5], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh5 ( QString ) ) ); + QObject::connect ( &vecChannels[6], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh6 ( QString ) ) ); + QObject::connect ( &vecChannels[7], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh7 ( QString ) ) ); + QObject::connect ( &vecChannels[8], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh8 ( QString ) ) ); + QObject::connect ( &vecChannels[9], SIGNAL ( ChatTextReceived ( QString ) ), this, SLOT ( OnChatTextReceivedCh9 ( QString ) ) ); + + // ping message received + QObject::connect ( &vecChannels[0], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh0 ( int ) ) ); + QObject::connect ( &vecChannels[1], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh1 ( int ) ) ); + QObject::connect ( &vecChannels[2], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh2 ( int ) ) ); + QObject::connect ( &vecChannels[3], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh3 ( int ) ) ); + QObject::connect ( &vecChannels[4], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh4 ( int ) ) ); + QObject::connect ( &vecChannels[5], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh5 ( int ) ) ); + QObject::connect ( &vecChannels[6], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh6 ( int ) ) ); + QObject::connect ( &vecChannels[7], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh7 ( int ) ) ); + QObject::connect ( &vecChannels[8], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh8 ( int ) ) ); + QObject::connect ( &vecChannels[9], SIGNAL ( PingReceived ( int ) ), this, SLOT ( OnPingReceivedCh9 ( int ) ) ); } void CServer::OnSendProtMessage ( int iChID, CVector vecMessage ) { // the protocol queries me to call the function to send the message // send it through the network - Socket.SendPacket ( vecMessage, ChannelSet.GetAddress ( iChID ) ); + Socket.SendPacket ( vecMessage, GetAddress ( iChID ) ); } void CServer::Start() @@ -114,12 +195,6 @@ void CServer::Stop() Logging.AddServerStopped(); } -void CServer::OnNewChannel ( CHostAddress ChanAddr ) -{ - // logging of new connected channel - Logging.AddNewConnection ( ChanAddr.InetAddr ); -} - void CServer::OnTimer() { CVector vecChanID; @@ -127,7 +202,7 @@ void CServer::OnTimer() CVector > vecvecdGains; // get data from all connected clients - ChannelSet.GetBlockAllConC ( vecChanID, vecvecdData, vecvecdGains ); + GetBlockAllConC ( vecChanID, vecvecdData, vecvecdGains ); const int iNumClients = vecChanID.Size(); // Check if at least one client is connected. If not, stop server until @@ -142,8 +217,8 @@ void CServer::OnTimer() // send separate mix to current clients Socket.SendPacket ( - ChannelSet.PrepSendPacket ( vecChanID[i], vecsSendData ), - ChannelSet.GetAddress ( vecChanID[i] ) ); + PrepSendPacket ( vecChanID[i], vecsSendData ), + GetAddress ( vecChanID[i] ) ); } } else @@ -157,6 +232,436 @@ void CServer::OnTimer() CycleTimeVariance.Update(); } +void CServer::GetBlockAllConC ( CVector& vecChanID, + CVector >& vecvecdData, + CVector >& vecvecdGains ) +{ + int i, j; + bool bChannelIsNowDisconnected = false; + + // init temporal data vector and clear input buffers + CVector vecdData ( SYSTEM_BLOCK_SIZE_SAMPLES ); + + vecChanID.Init ( 0 ); + vecvecdData.Init ( 0 ); + vecvecdGains.Init ( 0 ); + + // make put and get calls thread safe. Do not forget to unlock mutex + // afterwards! + Mutex.lock(); + { + // check all possible channels + for ( i = 0; i < USED_NUM_CHANNELS; i++ ) + { + // read out all input buffers to decrease timeout counter on + // disconnected channels +// const EGetDataStat eGetStat = vecChannels[i].GetData ( vecdData ); +const EGetDataStat eGetStat=GS_BUFFER_OK;//TEST + + // if channel was just disconnected, set flag that connected + // client list is sent to all other clients + if ( eGetStat == GS_CHAN_NOW_DISCONNECTED ) + { + bChannelIsNowDisconnected = true; + } + + if ( vecChannels[i].IsConnected() ) + { + // add ID and data + vecChanID.Add ( i ); + + const int iOldSize = vecvecdData.Size(); + vecvecdData.Enlarge ( 1 ); + vecvecdData[iOldSize].Init ( vecdData.Size() ); + vecvecdData[iOldSize] = vecdData; + + // send message for get status (for GUI) + if ( eGetStat == GS_BUFFER_OK ) + { + PostWinMessage ( MS_JIT_BUF_GET, MUL_COL_LED_GREEN, i ); + } + else + { + PostWinMessage ( MS_JIT_BUF_GET, MUL_COL_LED_RED, i ); + } + } + } + + // now that we know the IDs of the connected clients, get gains + const int iNumCurConnChan = vecChanID.Size(); + vecvecdGains.Init ( iNumCurConnChan ); + + for ( i = 0; i < iNumCurConnChan; i++ ) + { + vecvecdGains[i].Init ( iNumCurConnChan ); + + for ( j = 0; j < iNumCurConnChan; j++ ) + { + // The second index of "vecvecdGains" does not represent + // the channel ID! Therefore we have to use "vecChanID" to + // query the IDs of the currently connected channels + vecvecdGains[i][j] = + vecChannels[vecChanID[i]].GetGain( vecChanID[j] ); + } + } + + // a channel is now disconnected, take action on it + if ( bChannelIsNowDisconnected ) + { + // update channel list for all currently connected clients + CreateAndSendChanListForAllConChannels(); + } + } + Mutex.unlock(); // release mutex +} + +CVector CServer::CreateChannelList() +{ + CVector vecChanInfo ( 0 ); + + // look for free channels + for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) + { + if ( vecChannels[i].IsConnected() ) + { + // append channel ID, IP address and channel name to storing vectors + vecChanInfo.Add ( CChannelShortInfo ( + i, // ID + vecChannels[i].GetAddress().InetAddr.toIPv4Address(), // IP address + vecChannels[i].GetName() /* name */ ) ); + } + } + + return vecChanInfo; +} + +void CServer::CreateAndSendChanListForAllConChannels() +{ + // create channel list + CVector vecChanInfo ( CreateChannelList() ); + + // now send connected channels list to all connected clients + for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) + { + if ( vecChannels[i].IsConnected() ) + { + // send message + vecChannels[i].CreateConClientListMes ( vecChanInfo ); + } + } + + // create status HTML file if enabled + if ( bWriteStatusHTMLFile ) + { + WriteHTMLChannelList(); + } +} + +void CServer::CreateAndSendChanListForAllExceptThisChan ( const int iCurChanID ) +{ + // create channel list + CVector vecChanInfo ( CreateChannelList() ); + + // now send connected channels list to all connected clients except for + // the channel with the ID "iCurChanID" + for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) + { + if ( ( vecChannels[i].IsConnected() ) && ( i != iCurChanID ) ) + { + // send message + vecChannels[i].CreateConClientListMes ( vecChanInfo ); + } + } + + // create status HTML file if enabled + if ( bWriteStatusHTMLFile ) + { + WriteHTMLChannelList(); + } +} + +void CServer::CreateAndSendChanListForThisChan ( const int iCurChanID ) +{ + // create channel list + CVector vecChanInfo ( CreateChannelList() ); + + // now send connected channels list to the channel with the ID "iCurChanID" + vecChannels[iCurChanID].CreateConClientListMes ( vecChanInfo ); +} + +void CServer::CreateAndSendChatTextForAllConChannels ( const int iCurChanID, + const QString& strChatText ) +{ + // create message which is sent to all connected clients ------------------- + // get client name, if name is empty, use IP address instead + QString ChanName = vecChannels[iCurChanID].GetName(); + if ( ChanName.isEmpty() ) + { + // convert IP address to text and show it + ChanName = + vecChannels[iCurChanID].GetAddress().GetIpAddressStringNoLastByte(); + } + + // add name of the client at the beginning of the message text and use + // different colors, to get correct HTML, the "<" and ">" signs must be + // replaced by "<" and ">" + QString sCurColor = vstrChatColors[iCurChanID % vstrChatColors.Size()]; + const QString strActualMessageText = + "<" + ChanName + + "> " + strChatText; + + + // send chat text to all connected clients --------------------------------- + for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) + { + if ( vecChannels[i].IsConnected() ) + { + // send message + vecChannels[i].CreateChatTextMes ( strActualMessageText ); + } + } +} + +int CServer::GetFreeChan() +{ + // look for a free channel + for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) + { + if ( !vecChannels[i].IsConnected() ) + { + return i; + } + } + + // no free channel found, return invalid ID + return INVALID_CHANNEL_ID; +} + +int CServer::CheckAddr ( const CHostAddress& Addr ) +{ + CHostAddress InetAddr; + + // check for all possible channels if IP is already in use + for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) + { + if ( vecChannels[i].IsConnected() ) + { + if ( vecChannels[i].GetAddress ( InetAddr ) ) + { + // IP found, return channel number + if ( InetAddr == Addr ) + { + return i; + } + } + } + } + + // IP not found, return invalid ID + return INVALID_CHANNEL_ID; +} + +bool CServer::PutData ( const CVector& vecbyRecBuf, + const int iNumBytesRead, + const CHostAddress& HostAdr ) +{ + bool bAudioOK = false; + bool bNewChannelReserved = false; + + Mutex.lock(); + { + bool bChanOK = true; + + // Get channel ID ------------------------------------------------------ + // check address + int iCurChanID = CheckAddr ( HostAdr ); + + if ( iCurChanID == INVALID_CHANNEL_ID ) + { + // a new client is calling, look for free channel + iCurChanID = GetFreeChan(); + + if ( iCurChanID != INVALID_CHANNEL_ID ) + { + // initialize current channel by storing the calling host + // address + vecChannels[iCurChanID].SetAddress ( HostAdr ); + + // reset the channel gains of current channel, at the same + // time reset gains of this channel ID for all other channels + for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) + { + vecChannels[iCurChanID].SetGain ( i, (double) 1.0 ); + + // other channels (we do not distinguish the case if + // i == iCurChanID for simplicity) + vecChannels[i].SetGain ( iCurChanID, (double) 1.0 ); + } + + // set flag for new reserved channel + bNewChannelReserved = true; + } + else + { + // no free channel available + bChanOK = false; + + // create and send "server full" message + +// TODO problem: if channel is not officially connected, we cannot send messages + + } + } + + + // Put received data in jitter buffer ---------------------------------- + if ( bChanOK ) + { + // put packet in socket buffer + switch ( vecChannels[iCurChanID].PutData ( vecbyRecBuf, iNumBytesRead ) ) + { + case PS_AUDIO_OK: + PostWinMessage ( MS_JIT_BUF_PUT, MUL_COL_LED_GREEN, iCurChanID ); + bAudioOK = true; // in case we have an audio packet, return true + break; + + case PS_AUDIO_ERR: + PostWinMessage ( MS_JIT_BUF_PUT, MUL_COL_LED_RED, iCurChanID ); + bAudioOK = true; // in case we have an audio packet, return true + break; + + case PS_PROT_ERR: + PostWinMessage ( MS_JIT_BUF_PUT, MUL_COL_LED_YELLOW, iCurChanID ); + +// TEST +bAudioOK = true; + + break; + } + } + + // after data is put in channel buffer, create channel list message if + // requested + if ( bNewChannelReserved && bAudioOK ) + { + // logging of new connected channel + Logging.AddNewConnection ( HostAdr.InetAddr ); + + // A new client connected to the server, create and + // send all clients the updated channel list (the list has to + // be created after the received data has to be put to the + // channel first so that this channel is marked as connected) + // + // connected clients list is only send for new connected clients after + // request, only the already connected clients get the list + // automatically, because they don't know when new clients connect + CreateAndSendChanListForAllExceptThisChan ( iCurChanID ); + } + } + Mutex.unlock(); + + return bAudioOK; +} + +void CServer::GetConCliParam ( CVector& vecHostAddresses, + CVector& vecsName, + CVector& veciJitBufSize, + CVector& veciNetwOutBlSiFact ) +{ + CHostAddress InetAddr; + + // init return values + vecHostAddresses.Init ( USED_NUM_CHANNELS ); + vecsName.Init ( USED_NUM_CHANNELS ); + veciJitBufSize.Init ( USED_NUM_CHANNELS ); + veciNetwOutBlSiFact.Init ( USED_NUM_CHANNELS ); + + // check all possible channels + for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) + { + if ( vecChannels[i].GetAddress ( InetAddr ) ) + { + // get requested data + vecHostAddresses[i] = InetAddr; + vecsName[i] = vecChannels[i].GetName(); + veciJitBufSize[i] = vecChannels[i].GetSockBufSize(); + veciNetwOutBlSiFact[i] = vecChannels[i].GetNetwBufSizeFactOut(); + } + } +} + +void CServer::StartStatusHTMLFileWriting ( const QString& strNewFileName, + const QString& strNewServerNameWithPort ) +{ + // set important parameters + strServerHTMLFileListName = strNewFileName; + strServerNameWithPort = strNewServerNameWithPort; + + // set flag + bWriteStatusHTMLFile = true; + + // write initial file + WriteHTMLChannelList(); +} + +void CServer::WriteHTMLChannelList() +{ + // create channel list + CVector vecChanInfo ( CreateChannelList() ); + + // prepare file and stream + QFile serverFileListFile ( strServerHTMLFileListName ); + if ( !serverFileListFile.open ( QIODevice::WriteOnly | QIODevice::Text ) ) + { + return; + } + + QTextStream streamFileOut ( &serverFileListFile ); + streamFileOut << strServerNameWithPort << endl << "
    " << endl; + + // get the number of connected clients + int iNumConnClients = 0; + for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) + { + if ( vecChannels[i].IsConnected() ) + { + iNumConnClients++; + } + } + + // depending on number of connected clients write list + if ( iNumConnClients == 0 ) + { + // no clients are connected -> empty server + streamFileOut << " No client connected" << endl; + } + else + { + // write entry for each connected client + for ( int i = 0; i < USED_NUM_CHANNELS; i++ ) + { + if ( vecChannels[i].IsConnected() ) + { + QString strCurChanName = vecChannels[i].GetName(); + + // if text is empty, show IP address instead + if ( strCurChanName.isEmpty() ) + { + // convert IP address to text and show it, remove last + // digits + strCurChanName = + vecChannels[i].GetAddress().GetIpAddressStringNoLastByte(); + } + + streamFileOut << "
  • " << strCurChanName << "
  • " << endl; + } + } + } + + // finish list + streamFileOut << "
" << endl; +} + CVector CServer::ProcessData ( CVector >& vecvecdData, CVector& vecdGains ) { diff --git a/src/server.h b/src/server.h index fcf176eb..6023851d 100755 --- a/src/server.h +++ b/src/server.h @@ -36,6 +36,11 @@ #include "serverlogging.h" +/* Definitions ****************************************************************/ +// no valid channel number +#define INVALID_CHANNEL_ID ( MAX_NUM_CHANNELS + 1 ) + + /* Classes ********************************************************************/ class CServer : public QObject { @@ -53,33 +58,65 @@ public: void Stop(); bool IsRunning() { return Timer.isActive(); } - void GetConCliParam ( CVector& vecHostAddresses, - CVector& vecsName, - CVector& veciJitBufSize, - CVector& veciNetwOutBlSiFact, - CVector& veceAudComprType ) - { - ChannelSet.GetConCliParam ( vecHostAddresses, - vecsName, - veciJitBufSize, - veciNetwOutBlSiFact ); - } - bool GetTimingStdDev ( double& dCurTiStdDev ); - CChannelSet* GetChannelSet() { return &ChannelSet; } + bool PutData ( const CVector& vecbyRecBuf, + const int iNumBytesRead, const CHostAddress& HostAdr ); + + void GetConCliParam ( CVector& vecHostAddresses, + CVector& vecsName, + CVector& veciJitBufSize, + CVector& veciNetwOutBlSiFact ); protected: + // access functions for actual channels + bool IsConnected ( const int iChanNum ) + { return vecChannels[iChanNum].IsConnected(); } + + CVector PrepSendPacket ( const int iChanNum, + const CVector& vecsNPacket ) + { return vecChannels[iChanNum].PrepSendPacket ( vecsNPacket ); } + + CHostAddress GetAddress ( const int iChanNum ) + { return vecChannels[iChanNum].GetAddress(); } + + void StartStatusHTMLFileWriting ( const QString& strNewFileName, + const QString& strNewServerNameWithPort ); + + void GetBlockAllConC ( CVector& vecChanID, + CVector >& vecvecdData, + CVector >& vecvecdGains ); + + int CheckAddr ( const CHostAddress& Addr ); + int GetFreeChan(); + CVector CreateChannelList(); + void CreateAndSendChanListForAllConChannels(); + void CreateAndSendChanListForAllExceptThisChan ( const int iCurChanID ); + void CreateAndSendChanListForThisChan ( const int iCurChanID ); + void CreateAndSendChatTextForAllConChannels ( const int iCurChanID, const QString& strChatText ); + void WriteHTMLChannelList(); + CVector ProcessData ( CVector >& vecvecdData, CVector& vecdGains ); 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]; + QMutex Mutex; + + CVector vstrChatColors; + + // HTML file server status + bool bWriteStatusHTMLFile; + QString strServerHTMLFileListName; + QString strServerNameWithPort; + QTimer Timer; CVector vecsSendData; // actual working objects - CChannelSet ChannelSet; CSocket Socket; CCycleTimeVariance CycleTimeVariance; @@ -90,7 +127,75 @@ protected: public slots: void OnTimer(); void OnSendProtMessage ( int iChID, CVector vecMessage ); - void OnNewChannel ( CHostAddress ChanAddr ); + + // 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 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 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 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 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 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 ); } }; #endif /* !defined ( SERVER_HOIHGE7LOKIH83JH8_3_43445KJIUHF1912__INCLUDED_ ) */ diff --git a/src/socket.cpp b/src/socket.cpp index 071445a4..518c10db 100755 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -122,7 +122,7 @@ void CSocket::OnDataReceived() else { // server - if ( pChannelSet->PutData ( vecbyRecBuf, iNumBytesRead, RecHostAddr ) ) + if ( pServer->PutData ( vecbyRecBuf, iNumBytesRead, RecHostAddr ) ) { // this was an audio packet, start server // tell the server object to wake up if it diff --git a/src/socket.h b/src/socket.h index 0bb2219a..ec73eea5 100755 --- a/src/socket.h +++ b/src/socket.h @@ -49,8 +49,8 @@ class CSocket : public QObject public: CSocket ( CChannel* pNewChannel, const quint16 iPortNumber ) : pChannel( pNewChannel ), bIsClient ( true ) { Init ( iPortNumber ); } - CSocket ( CChannelSet* pNewChannelSet, QObject* pNServP, const quint16 iPortNumber ) : - pChannelSet ( pNewChannelSet ), pServer ( pNServP ), bIsClient ( false ) + CSocket ( QObject* pNServP, const quint16 iPortNumber ) : + pServer ( pNServP ), bIsClient ( false ) { Init ( iPortNumber ); } virtual ~CSocket() {} @@ -65,8 +65,7 @@ protected: CVector vecbyRecBuf; CHostAddress RecHostAddr; - CChannel* pChannel; // for client - CChannelSet* pChannelSet; // for server + CChannel* pChannel; // for client QObject* pServer; bool bIsClient; diff --git a/src/util.h b/src/util.h index ba914be1..7ab6f154 100755 --- a/src/util.h +++ b/src/util.h @@ -419,6 +419,14 @@ enum EAudComprType CT_CELT = 1 }; +enum EGetDataStat +{ + GS_BUFFER_OK, + GS_BUFFER_UNDERRUN, + GS_CHAN_NOW_DISCONNECTED, + GS_CHAN_NOT_CONNECTED +}; + class CNetworkTransportProps { public: