Added support for putting the receive socket in a separate thread. Unfortunately the current code does not work as expected. Some Qt warnings appear and after a while the receive socket does not receive any more network packets. Therefore a global macro is introduced to enable/disable the new code. Default is: disabled.
This commit is contained in:
parent
b8e9fcc4a3
commit
6bdb82c65f
12 changed files with 483 additions and 374 deletions
303
src/channel.cpp
303
src/channel.cpp
|
@ -102,10 +102,6 @@ QObject::connect ( &Protocol,
|
||||||
SIGNAL ( OpusSupported() ),
|
SIGNAL ( OpusSupported() ),
|
||||||
SIGNAL ( OpusSupported() ) );
|
SIGNAL ( OpusSupported() ) );
|
||||||
|
|
||||||
QObject::connect ( &Protocol,
|
|
||||||
SIGNAL ( DetectedCLMessage ( CVector<uint8_t>, int ) ),
|
|
||||||
SIGNAL ( DetectedCLMessage ( CVector<uint8_t>, int ) ) );
|
|
||||||
|
|
||||||
QObject::connect ( &Protocol,
|
QObject::connect ( &Protocol,
|
||||||
SIGNAL ( NetTranspPropsReceived ( CNetworkTransportProps ) ),
|
SIGNAL ( NetTranspPropsReceived ( CNetworkTransportProps ) ),
|
||||||
this, SLOT ( OnNetTranspPropsReceived ( CNetworkTransportProps ) ) );
|
this, SLOT ( OnNetTranspPropsReceived ( CNetworkTransportProps ) ) );
|
||||||
|
@ -113,6 +109,14 @@ QObject::connect ( &Protocol,
|
||||||
QObject::connect ( &Protocol,
|
QObject::connect ( &Protocol,
|
||||||
SIGNAL ( ReqNetTranspProps() ),
|
SIGNAL ( ReqNetTranspProps() ),
|
||||||
this, SLOT ( OnReqNetTranspProps() ) );
|
this, SLOT ( OnReqNetTranspProps() ) );
|
||||||
|
|
||||||
|
#ifdef ENABLE_RECEIVE_SOCKET_IN_SEPARATE_THREAD
|
||||||
|
// this connection is intended for a thread transition if we have a
|
||||||
|
// separate socket thread running
|
||||||
|
QObject::connect ( this,
|
||||||
|
SIGNAL ( ParseMessageBody ( CVector<uint8_t>, int, int ) ),
|
||||||
|
this, SLOT ( OnParseMessageBody ( CVector<uint8_t>, int, int ) ) );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CChannel::ProtocolIsEnabled()
|
bool CChannel::ProtocolIsEnabled()
|
||||||
|
@ -151,60 +155,83 @@ void CChannel::SetAudioStreamProperties ( const EAudComprType eNewAudComprType,
|
||||||
const int iNewNetwFrameSizeFact,
|
const int iNewNetwFrameSizeFact,
|
||||||
const int iNewNumAudioChannels )
|
const int iNewNumAudioChannels )
|
||||||
{
|
{
|
||||||
// this function is intended for the server (not the client)
|
/*
|
||||||
QMutexLocker locker ( &Mutex );
|
this function is intended for the server (not the client)
|
||||||
|
*/
|
||||||
|
|
||||||
// store new values
|
CNetworkTransportProps NetworkTransportProps;
|
||||||
eAudioCompressionType = eNewAudComprType;
|
|
||||||
iNumAudioChannels = iNewNumAudioChannels;
|
|
||||||
iNetwFrameSize = iNewNetwFrameSize;
|
|
||||||
iNetwFrameSizeFact = iNewNetwFrameSizeFact;
|
|
||||||
|
|
||||||
// init socket buffer
|
Mutex.lock();
|
||||||
SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames );
|
{
|
||||||
|
// store new values
|
||||||
|
eAudioCompressionType = eNewAudComprType;
|
||||||
|
iNumAudioChannels = iNewNumAudioChannels;
|
||||||
|
iNetwFrameSize = iNewNetwFrameSize;
|
||||||
|
iNetwFrameSizeFact = iNewNetwFrameSizeFact;
|
||||||
|
|
||||||
// init conversion buffer
|
// init socket buffer
|
||||||
ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact );
|
SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames );
|
||||||
|
|
||||||
// tell the server that audio coding has changed
|
// init conversion buffer
|
||||||
CreateNetTranspPropsMessFromCurrentSettings();
|
ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact );
|
||||||
|
|
||||||
|
// fill network transport properties struct
|
||||||
|
NetworkTransportProps =
|
||||||
|
GetNetworkTransportPropsFromCurrentSettings();
|
||||||
|
}
|
||||||
|
Mutex.unlock();
|
||||||
|
|
||||||
|
// tell the server about the new network settings
|
||||||
|
Protocol.CreateNetwTranspPropsMes ( NetworkTransportProps );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CChannel::SetSockBufNumFrames ( const int iNewNumFrames,
|
bool CChannel::SetSockBufNumFrames ( const int iNewNumFrames,
|
||||||
const bool bPreserve )
|
const bool bPreserve )
|
||||||
{
|
{
|
||||||
QMutexLocker locker ( &Mutex ); // this operation must be done with mutex
|
bool ReturnValue = true; // init with error
|
||||||
|
bool bCurDoAutoSockBufSize = false; // we have to init but init values does not matter
|
||||||
|
|
||||||
// first check for valid input parameter range
|
Mutex.lock();
|
||||||
if ( ( iNewNumFrames >= MIN_NET_BUF_SIZE_NUM_BL ) &&
|
|
||||||
( iNewNumFrames <= MAX_NET_BUF_SIZE_NUM_BL ) )
|
|
||||||
{
|
{
|
||||||
// only apply parameter if new parameter is different from current one
|
// first check for valid input parameter range
|
||||||
if ( iCurSockBufNumFrames != iNewNumFrames )
|
if ( ( iNewNumFrames >= MIN_NET_BUF_SIZE_NUM_BL ) &&
|
||||||
|
( iNewNumFrames <= MAX_NET_BUF_SIZE_NUM_BL ) )
|
||||||
{
|
{
|
||||||
// store new value
|
// only apply parameter if new parameter is different from current one
|
||||||
iCurSockBufNumFrames = iNewNumFrames;
|
if ( iCurSockBufNumFrames != iNewNumFrames )
|
||||||
|
|
||||||
// the network block size is a multiple of the minimum network
|
|
||||||
// block size
|
|
||||||
SockBuf.Init ( iNetwFrameSize, iNewNumFrames, bPreserve );
|
|
||||||
|
|
||||||
// only in case we are the server and auto jitter buffer setting is
|
|
||||||
// enabled, we have to report the current setting to the client
|
|
||||||
if ( bIsServer && bDoAutoSockBufSize )
|
|
||||||
{
|
{
|
||||||
// we cannot call the "CreateJitBufMes" function directly since
|
// store new value
|
||||||
// this would give us problems with different threads (e.g. the
|
iCurSockBufNumFrames = iNewNumFrames;
|
||||||
// timer thread) and the protocol mechanism (problem with
|
|
||||||
// qRegisterMetaType(), etc.)
|
|
||||||
emit ServerAutoSockBufSizeChange ( iNewNumFrames );
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // -> no error
|
// the network block size is a multiple of the minimum network
|
||||||
|
// block size
|
||||||
|
SockBuf.Init ( iNetwFrameSize, iNewNumFrames, bPreserve );
|
||||||
|
|
||||||
|
// store current auto socket buffer size setting in the mutex
|
||||||
|
// region since if we use the current parameter below in the
|
||||||
|
// if condition, it may have been changed in between the time
|
||||||
|
// when we have left the mutex region and entered the if
|
||||||
|
// condition
|
||||||
|
bCurDoAutoSockBufSize = bDoAutoSockBufSize;
|
||||||
|
|
||||||
|
ReturnValue = false; // -> no error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Mutex.unlock();
|
||||||
|
|
||||||
return true; // set error flag
|
// only in case there is no error, we are the server and auto jitter buffer
|
||||||
|
// setting is enabled, we have to report the current setting to the client
|
||||||
|
if ( !ReturnValue && bIsServer && bCurDoAutoSockBufSize )
|
||||||
|
{
|
||||||
|
// we cannot call the "CreateJitBufMes" function directly since
|
||||||
|
// this would give us problems with different threads (e.g. the
|
||||||
|
// timer thread) and the protocol mechanism (problem with
|
||||||
|
// qRegisterMetaType(), etc.)
|
||||||
|
emit ServerAutoSockBufSizeChange ( iNewNumFrames );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReturnValue; // set error flag
|
||||||
}
|
}
|
||||||
|
|
||||||
void CChannel::SetGain ( const int iChanID,
|
void CChannel::SetGain ( const int iChanID,
|
||||||
|
@ -373,7 +400,7 @@ void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTranspor
|
||||||
|
|
||||||
// if old CELT codec is used, inform the client that the new OPUS codec
|
// if old CELT codec is used, inform the client that the new OPUS codec
|
||||||
// is supported
|
// is supported
|
||||||
if ( eAudioCompressionType != CT_OPUS )
|
if ( NetworkTransportProps.eAudioCodingType != CT_OPUS )
|
||||||
{
|
{
|
||||||
Protocol.CreateOpusSupportedMes();
|
Protocol.CreateOpusSupportedMes();
|
||||||
}
|
}
|
||||||
|
@ -382,12 +409,15 @@ void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTranspor
|
||||||
|
|
||||||
void CChannel::OnReqNetTranspProps()
|
void CChannel::OnReqNetTranspProps()
|
||||||
{
|
{
|
||||||
CreateNetTranspPropsMessFromCurrentSettings();
|
// fill network transport properties struct from current settings and send it
|
||||||
|
Protocol.CreateNetwTranspPropsMes ( GetNetworkTransportPropsFromCurrentSettings() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void CChannel::CreateNetTranspPropsMessFromCurrentSettings()
|
CNetworkTransportProps CChannel::GetNetworkTransportPropsFromCurrentSettings()
|
||||||
{
|
{
|
||||||
CNetworkTransportProps NetworkTransportProps (
|
// use current stored settings of the channel to fill the network transport
|
||||||
|
// properties structure
|
||||||
|
return CNetworkTransportProps (
|
||||||
iNetwFrameSize,
|
iNetwFrameSize,
|
||||||
iNetwFrameSizeFact,
|
iNetwFrameSizeFact,
|
||||||
iNumAudioChannels,
|
iNumAudioChannels,
|
||||||
|
@ -395,9 +425,6 @@ void CChannel::CreateNetTranspPropsMessFromCurrentSettings()
|
||||||
eAudioCompressionType,
|
eAudioCompressionType,
|
||||||
0, // version of the codec
|
0, // version of the codec
|
||||||
0 );
|
0 );
|
||||||
|
|
||||||
// send current network transport properties
|
|
||||||
Protocol.CreateNetwTranspPropsMes ( NetworkTransportProps );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CChannel::Disconnect()
|
void CChannel::Disconnect()
|
||||||
|
@ -415,45 +442,88 @@ void CChannel::Disconnect()
|
||||||
EPutDataStat CChannel::PutData ( const CVector<uint8_t>& vecbyData,
|
EPutDataStat CChannel::PutData ( const CVector<uint8_t>& vecbyData,
|
||||||
int iNumBytes )
|
int iNumBytes )
|
||||||
{
|
{
|
||||||
EPutDataStat eRet = PS_GEN_ERROR;
|
/*
|
||||||
|
Note that this function might be called from a different thread (separate
|
||||||
|
Socket thread) and therefore we should not call functions which emit signals
|
||||||
|
themself directly but emit a signal here so that the thread transition is
|
||||||
|
done as early as possible.
|
||||||
|
This is the reason why "ParseMessageBody" is not called directly but through a
|
||||||
|
signal-slot mechanism.
|
||||||
|
*/
|
||||||
|
|
||||||
// init flags
|
// init return state
|
||||||
bool bIsProtocolPacket = false;
|
EPutDataStat eRet = PS_GEN_ERROR;
|
||||||
bool bNewConnection = false;
|
|
||||||
|
|
||||||
if ( bIsEnabled )
|
if ( bIsEnabled )
|
||||||
{
|
{
|
||||||
// first check if this is protocol data
|
int iRecCounter;
|
||||||
// only use protocol data if protocol mechanism is enabled
|
int iRecID;
|
||||||
if ( ProtocolIsEnabled() )
|
CVector<uint8_t> vecbyMesBodyData;
|
||||||
|
|
||||||
|
// init flag
|
||||||
|
bool bNewConnection = false;
|
||||||
|
|
||||||
|
// check if this is a protocol message by trying to parse the message
|
||||||
|
// frame
|
||||||
|
if ( !Protocol.ParseMessageFrame ( vecbyData,
|
||||||
|
iNumBytes,
|
||||||
|
vecbyMesBodyData,
|
||||||
|
iRecCounter,
|
||||||
|
iRecID ) )
|
||||||
{
|
{
|
||||||
// parse the message assuming this is a protocol message
|
// This is a protocol message:
|
||||||
if ( !Protocol.ParseMessage ( vecbyData, iNumBytes ) )
|
|
||||||
|
// only use protocol data if protocol mechanism is enabled
|
||||||
|
if ( ProtocolIsEnabled() )
|
||||||
{
|
{
|
||||||
// set status flags
|
// in case this is a connection less message, we do not process it here
|
||||||
eRet = PS_PROT_OK;
|
if ( Protocol.IsConnectionLessMessageID ( iRecID ) )
|
||||||
bIsProtocolPacket = true;
|
{
|
||||||
|
// fire a signal so that an other class can process this type of
|
||||||
|
// message
|
||||||
|
emit DetectedCLMessage ( vecbyMesBodyData, iRecID );
|
||||||
|
|
||||||
|
// set status flag
|
||||||
|
eRet = PS_PROT_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_RECEIVE_SOCKET_IN_SEPARATE_THREAD
|
||||||
|
// parse the message assuming this is a regular protocol message
|
||||||
|
emit ParseMessageBody ( vecbyMesBodyData, iRecCounter, iRecID );
|
||||||
|
|
||||||
|
// note that protocol OK is not correct here since we do not
|
||||||
|
// check if the protocol was ok since we emit just a signal
|
||||||
|
// and do not get any feedback on the protocol decoding state
|
||||||
|
eRet = PS_PROT_OK;
|
||||||
|
#else
|
||||||
|
// parse the message assuming this is a protocol message
|
||||||
|
if ( !Protocol.ParseMessageBody ( vecbyMesBodyData, iRecCounter, iRecID ) )
|
||||||
|
{
|
||||||
|
// set status flag
|
||||||
|
eRet = PS_PROT_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// In case we are the server and the current channel is not
|
||||||
|
// connected, we do not evaluate protocol messages but these
|
||||||
|
// messages could start the server which is not desired,
|
||||||
|
// especially not for the disconnect messages.
|
||||||
|
// We now do not start the server if a valid protocol message
|
||||||
|
// was received but only start the server on audio packets.
|
||||||
|
|
||||||
|
// set status flag
|
||||||
|
eRet = PS_PROT_OK_MESS_NOT_EVALUATED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// In case we are the server and the current channel is not
|
// This seems to be an audio packet (only try to parse audio if it
|
||||||
// connected, we do not evaluate protocal messages but these
|
// was not a protocol packet):
|
||||||
// messages could start the server which is not desired, especially
|
|
||||||
// not for the disconnect messages.
|
|
||||||
// We now do not start the server if a valid protocol message
|
|
||||||
// was received but only start the server on audio packets
|
|
||||||
if ( Protocol.IsProtocolMessage ( vecbyData, iNumBytes ) )
|
|
||||||
{
|
|
||||||
// set status flags
|
|
||||||
eRet = PS_PROT_OK_MESS_NOT_EVALUATED;
|
|
||||||
bIsProtocolPacket = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// only try to parse audio if it was not a protocol packet
|
|
||||||
if ( !bIsProtocolPacket )
|
|
||||||
{
|
|
||||||
Mutex.lock();
|
Mutex.lock();
|
||||||
{
|
{
|
||||||
// only process audio if packet has correct size
|
// only process audio if packet has correct size
|
||||||
|
@ -476,12 +546,12 @@ EPutDataStat CChannel::PutData ( const CVector<uint8_t>& vecbyData,
|
||||||
eRet = PS_PROT_ERR;
|
eRet = PS_PROT_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// all network packets except of valid protocol messages
|
// All network packets except of valid protocol messages
|
||||||
// regardless if they are valid or invalid audio packets lead to
|
// regardless if they are valid or invalid audio packets lead to
|
||||||
// a state change to a connected channel
|
// a state change to a connected channel.
|
||||||
// this is because protocol messages can only be sent on a
|
// This is because protocol messages can only be sent on a
|
||||||
// connected channel and the client has to inform the server
|
// connected channel and the client has to inform the server
|
||||||
// about the audio packet properties via the protocol
|
// about the audio packet properties via the protocol.
|
||||||
|
|
||||||
// check if channel was not connected, this is a new connection
|
// check if channel was not connected, this is a new connection
|
||||||
// (do not fire an event directly since we are inside a mutex
|
// (do not fire an event directly since we are inside a mutex
|
||||||
|
@ -506,55 +576,62 @@ EPutDataStat CChannel::PutData ( const CVector<uint8_t>& vecbyData,
|
||||||
|
|
||||||
EGetDataStat CChannel::GetData ( CVector<uint8_t>& vecbyData )
|
EGetDataStat CChannel::GetData ( CVector<uint8_t>& vecbyData )
|
||||||
{
|
{
|
||||||
QMutexLocker locker ( &Mutex );
|
|
||||||
|
|
||||||
EGetDataStat eGetStatus;
|
EGetDataStat eGetStatus;
|
||||||
|
|
||||||
const bool bSockBufState = SockBuf.Get ( vecbyData );
|
Mutex.lock();
|
||||||
|
|
||||||
// decrease time-out counter
|
|
||||||
if ( iConTimeOut > 0 )
|
|
||||||
{
|
{
|
||||||
// subtract the number of samples of the current block since the
|
// the socket access must be inside a mutex
|
||||||
// time out counter is based on samples not on blocks (definition:
|
const bool bSockBufState = SockBuf.Get ( vecbyData );
|
||||||
// always one atomic block is get by using the GetData() function
|
|
||||||
// where the atomic block size is "SYSTEM_FRAME_SIZE_SAMPLES")
|
// decrease time-out counter
|
||||||
|
if ( iConTimeOut > 0 )
|
||||||
|
{
|
||||||
|
// subtract the number of samples of the current block since the
|
||||||
|
// time out counter is based on samples not on blocks (definition:
|
||||||
|
// always one atomic block is get by using the GetData() function
|
||||||
|
// where the atomic block size is "SYSTEM_FRAME_SIZE_SAMPLES")
|
||||||
|
|
||||||
// TODO this code only works with the above assumption -> better
|
// TODO this code only works with the above assumption -> better
|
||||||
// implementation so that we are not depending on assumptions
|
// implementation so that we are not depending on assumptions
|
||||||
|
|
||||||
iConTimeOut -= SYSTEM_FRAME_SIZE_SAMPLES;
|
iConTimeOut -= SYSTEM_FRAME_SIZE_SAMPLES;
|
||||||
|
|
||||||
if ( iConTimeOut <= 0 )
|
if ( iConTimeOut <= 0 )
|
||||||
{
|
|
||||||
// channel is just disconnected
|
|
||||||
eGetStatus = GS_CHAN_NOW_DISCONNECTED;
|
|
||||||
iConTimeOut = 0; // make sure we do not have negative values
|
|
||||||
|
|
||||||
// reset network transport properties
|
|
||||||
ResetNetworkTransportProperties();
|
|
||||||
|
|
||||||
// emit message
|
|
||||||
emit Disconnected();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( bSockBufState )
|
|
||||||
{
|
{
|
||||||
// everything is ok
|
// channel is just disconnected
|
||||||
eGetStatus = GS_BUFFER_OK;
|
eGetStatus = GS_CHAN_NOW_DISCONNECTED;
|
||||||
|
iConTimeOut = 0; // make sure we do not have negative values
|
||||||
|
|
||||||
|
// reset network transport properties
|
||||||
|
ResetNetworkTransportProperties();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// channel is not yet disconnected but no data in buffer
|
if ( bSockBufState )
|
||||||
eGetStatus = GS_BUFFER_UNDERRUN;
|
{
|
||||||
|
// everything is ok
|
||||||
|
eGetStatus = GS_BUFFER_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// channel is not yet disconnected but no data in buffer
|
||||||
|
eGetStatus = GS_BUFFER_UNDERRUN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// channel is disconnected
|
||||||
|
eGetStatus = GS_CHAN_NOT_CONNECTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
Mutex.unlock();
|
||||||
|
|
||||||
|
// in case we are just disconnected, we have to fire a message
|
||||||
|
if ( eGetStatus == GS_CHAN_NOW_DISCONNECTED )
|
||||||
{
|
{
|
||||||
// channel is disconnected
|
// emit message
|
||||||
eGetStatus = GS_CHAN_NOT_CONNECTED;
|
emit Disconnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
return eGetStatus;
|
return eGetStatus;
|
||||||
|
|
|
@ -150,7 +150,7 @@ void CreateConClientListNameMes ( const CVector<CChannelInfo>& vecChanInfo )
|
||||||
void CreateConClientListMes ( const CVector<CChannelInfo>& vecChanInfo )
|
void CreateConClientListMes ( const CVector<CChannelInfo>& vecChanInfo )
|
||||||
{ Protocol.CreateConClientListMes ( vecChanInfo ); }
|
{ Protocol.CreateConClientListMes ( vecChanInfo ); }
|
||||||
|
|
||||||
void CreateNetTranspPropsMessFromCurrentSettings();
|
CNetworkTransportProps GetNetworkTransportPropsFromCurrentSettings();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ProtocolIsEnabled();
|
bool ProtocolIsEnabled();
|
||||||
|
@ -209,6 +209,12 @@ public slots:
|
||||||
void OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps );
|
void OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTransportProps );
|
||||||
void OnReqNetTranspProps();
|
void OnReqNetTranspProps();
|
||||||
|
|
||||||
|
#ifdef ENABLE_RECEIVE_SOCKET_IN_SEPARATE_THREAD
|
||||||
|
void OnParseMessageBody ( CVector<uint8_t> vecbyMesBodyData,
|
||||||
|
int iRecCounter,
|
||||||
|
int iRecID ) { Protocol.ParseMessageBody ( vecbyMesBodyData, iRecCounter, iRecID ); }
|
||||||
|
#endif
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void MessReadyForSending ( CVector<uint8_t> vecMessage );
|
void MessReadyForSending ( CVector<uint8_t> vecMessage );
|
||||||
void NewConnection();
|
void NewConnection();
|
||||||
|
@ -225,8 +231,15 @@ signals:
|
||||||
void PingReceived ( int iMs );
|
void PingReceived ( int iMs );
|
||||||
void ReqNetTranspProps();
|
void ReqNetTranspProps();
|
||||||
void Disconnected();
|
void Disconnected();
|
||||||
void DetectedCLMessage ( CVector<uint8_t> vecbyData,
|
|
||||||
int iNumBytes );
|
void DetectedCLMessage ( CVector<uint8_t> vecbyMesBodyData,
|
||||||
|
int iRecID );
|
||||||
|
|
||||||
|
#ifdef ENABLE_RECEIVE_SOCKET_IN_SEPARATE_THREAD
|
||||||
|
void ParseMessageBody ( CVector<uint8_t> vecbyMesBodyData,
|
||||||
|
int iRecCounter,
|
||||||
|
int iRecID );
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* !defined ( CHANNEL_HOIH9345KJH98_3_4344_BB23945IUHF1912__INCLUDED_ ) */
|
#endif /* !defined ( CHANNEL_HOIH9345KJH98_3_4344_BB23945IUHF1912__INCLUDED_ ) */
|
||||||
|
|
|
@ -225,29 +225,29 @@ void CClient::OnInvalidPacketReceived ( CVector<uint8_t> vecbyRecBuf,
|
||||||
// e.g., open the connection setup dialog since then we are not
|
// e.g., open the connection setup dialog since then we are not
|
||||||
// yet connected but talk to the central server with the
|
// yet connected but talk to the central server with the
|
||||||
// connection less protocol)
|
// connection less protocol)
|
||||||
if ( ConnLessProtocol.ParseConnectionLessMessage ( vecbyRecBuf,
|
if ( ConnLessProtocol.ParseConnectionLessMessageWithFrame ( vecbyRecBuf,
|
||||||
iNumBytesRead,
|
iNumBytesRead,
|
||||||
RecHostAddr ) )
|
RecHostAddr ) )
|
||||||
{
|
{
|
||||||
// message coult not be parsed, check if the packet comes
|
// message coult not be parsed, check if the packet comes
|
||||||
// from the server we just connected -> if yes, send
|
// from the server we just connected -> if yes, send
|
||||||
// disconnect message since the server may not know that we
|
// disconnect message since the server may not know that we
|
||||||
// are not connected anymore
|
// are not connected anymore
|
||||||
if ( Channel. GetAddress() == RecHostAddr )
|
if ( Channel.GetAddress() == RecHostAddr )
|
||||||
{
|
{
|
||||||
ConnLessProtocol.CreateCLDisconnection ( RecHostAddr );
|
ConnLessProtocol.CreateCLDisconnection ( RecHostAddr );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::OnDetectedCLMessage ( CVector<uint8_t> vecbyData,
|
void CClient::OnDetectedCLMessage ( CVector<uint8_t> vecbyMesBodyData,
|
||||||
int iNumBytes )
|
int iRecID )
|
||||||
{
|
{
|
||||||
// this is a special case: we received a connection less message but we are
|
// this is a special case: we received a connection less message but we are
|
||||||
// in a connection
|
// in a connection
|
||||||
ConnLessProtocol.ParseConnectionLessMessage ( vecbyData,
|
ConnLessProtocol.ParseConnectionLessMessageBody ( vecbyMesBodyData,
|
||||||
iNumBytes,
|
iRecID,
|
||||||
Channel.GetAddress() );
|
Channel.GetAddress() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::OnJittBufSizeChanged ( int iNewJitBufSize )
|
void CClient::OnJittBufSizeChanged ( int iNewJitBufSize )
|
||||||
|
|
|
@ -301,7 +301,11 @@ void SetAudoCompressiontype ( const EAudComprType eNAudCompressionType );
|
||||||
bool bIsInitializationPhase;
|
bool bIsInitializationPhase;
|
||||||
CVector<unsigned char> vecCeltData;
|
CVector<unsigned char> vecCeltData;
|
||||||
|
|
||||||
|
#ifdef ENABLE_RECEIVE_SOCKET_IN_SEPARATE_THREAD
|
||||||
|
CHighPrioSocket Socket;
|
||||||
|
#else
|
||||||
CSocket Socket;
|
CSocket Socket;
|
||||||
|
#endif
|
||||||
CSound Sound;
|
CSound Sound;
|
||||||
CStereoSignalLevelMeter SignalLevelMeter;
|
CStereoSignalLevelMeter SignalLevelMeter;
|
||||||
|
|
||||||
|
@ -350,7 +354,7 @@ public slots:
|
||||||
void OnInvalidPacketReceived ( CVector<uint8_t> vecbyRecBuf,
|
void OnInvalidPacketReceived ( CVector<uint8_t> vecbyRecBuf,
|
||||||
int iNumBytesRead,
|
int iNumBytesRead,
|
||||||
CHostAddress RecHostAddr );
|
CHostAddress RecHostAddr );
|
||||||
void OnDetectedCLMessage ( CVector<uint8_t> vecbyData, int iNumBytes );
|
void OnDetectedCLMessage ( CVector<uint8_t> vecbyMesBodyData, int iRecID );
|
||||||
void OnReqJittBufSize() { CreateServerJitterBufferMessage(); }
|
void OnReqJittBufSize() { CreateServerJitterBufferMessage(); }
|
||||||
void OnJittBufSizeChanged ( int iNewJitBufSize );
|
void OnJittBufSizeChanged ( int iNewJitBufSize );
|
||||||
void OnReqChanInfo() { Channel.SetRemoteInfo ( ChannelInfo ); }
|
void OnReqChanInfo() { Channel.SetRemoteInfo ( ChannelInfo ); }
|
||||||
|
|
|
@ -324,17 +324,8 @@ CClientDlg::CClientDlg ( CClient* pNCliP,
|
||||||
// View menu --------------------------------------------------------------
|
// View menu --------------------------------------------------------------
|
||||||
pViewMenu = new QMenu ( "&View", this );
|
pViewMenu = new QMenu ( "&View", this );
|
||||||
|
|
||||||
|
|
||||||
// TODO This View menu item is disabled for now. The reason for that is that if
|
|
||||||
// if the connection setup dialog is opened during an active connection, we will
|
|
||||||
// get audio drop outs everytime the ping times in the list are updated which is
|
|
||||||
// not acceptable.
|
|
||||||
// Fix the issue with the thread priorities and enable the menu item again...
|
|
||||||
/*
|
|
||||||
pViewMenu->addAction ( tr ( "&Connection Setup..." ), this,
|
pViewMenu->addAction ( tr ( "&Connection Setup..." ), this,
|
||||||
SLOT ( OnOpenConnectionSetupDialog() ) );
|
SLOT ( OnOpenConnectionSetupDialog() ) );
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
pViewMenu->addAction ( tr ( "C&hat..." ), this,
|
pViewMenu->addAction ( tr ( "C&hat..." ), this,
|
||||||
SLOT ( OnOpenChatDialog() ) );
|
SLOT ( OnOpenChatDialog() ) );
|
||||||
|
|
18
src/global.h
18
src/global.h
|
@ -65,6 +65,24 @@ LED bar: lbr
|
||||||
|
|
||||||
|
|
||||||
/* Definitions ****************************************************************/
|
/* Definitions ****************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The receive socket should be put in a high priority thread to ensure the GUI
|
||||||
|
// does not effect the stability of the audio stream (e.g. if the GUI is on
|
||||||
|
// high load because of a table update, the incoming network packets must still
|
||||||
|
// be put in the jitter buffer with highest priority).
|
||||||
|
// Unfortunately, the current implementation of the separate thread does not
|
||||||
|
// work correctly. Therefore we introduced this macro to enable/disable the new
|
||||||
|
// code. If the new code is enabled, under Windows Qt warnings like
|
||||||
|
// "QSocketNotifier: Multiple socket notifiers for same socket" appear and after
|
||||||
|
// a while the receive socket does not receive any new network packets anymore.
|
||||||
|
// This has to be solved!
|
||||||
|
//#define ENABLE_RECEIVE_SOCKET_IN_SEPARATE_THREAD
|
||||||
|
#undef ENABLE_RECEIVE_SOCKET_IN_SEPARATE_THREAD
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// define this macro to get debug output
|
// define this macro to get debug output
|
||||||
//#define _DEBUG_
|
//#define _DEBUG_
|
||||||
#undef _DEBUG_
|
#undef _DEBUG_
|
||||||
|
|
10
src/main.cpp
10
src/main.cpp
|
@ -372,9 +372,17 @@ int main ( int argc, char** argv )
|
||||||
QApplication app ( argc, argv, bUseGUI );
|
QApplication app ( argc, argv, bUseGUI );
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Set application priority class -> high priority
|
// set application priority class -> high priority
|
||||||
SetPriorityClass ( GetCurrentProcess(), HIGH_PRIORITY_CLASS );
|
SetPriorityClass ( GetCurrentProcess(), HIGH_PRIORITY_CLASS );
|
||||||
|
|
||||||
|
#ifdef ENABLE_RECEIVE_SOCKET_IN_SEPARATE_THREAD
|
||||||
|
// Since we have a higher priority for the entire application, we can give
|
||||||
|
// the GUI thread the lowest possible priority which is still above the
|
||||||
|
// Windows "normal" priority so that it does not slow down the sound card
|
||||||
|
// and network working threads.
|
||||||
|
QThread::currentThread()->setPriority ( QThread::LowestPriority );
|
||||||
|
#endif
|
||||||
|
|
||||||
// For accessible support we need to add a plugin to qt. The plugin has to
|
// For accessible support we need to add a plugin to qt. The plugin has to
|
||||||
// be located in the install directory of the software by the installer.
|
// be located in the install directory of the software by the installer.
|
||||||
// Here, we set the path to our application path.
|
// Here, we set the path to our application path.
|
||||||
|
|
340
src/protocol.cpp
340
src/protocol.cpp
|
@ -425,176 +425,168 @@ void CProtocol::CreateAndImmSendConLessMessage ( const int iID,
|
||||||
emit CLMessReadyForSending ( InetAddr, vecNewMessage );
|
emit CLMessReadyForSending ( InetAddr, vecNewMessage );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CProtocol::IsProtocolMessage ( const CVector<uint8_t>& vecbyData,
|
bool CProtocol::ParseMessageBody ( const CVector<uint8_t>& vecbyMesBodyData,
|
||||||
const int iNumBytes )
|
const int iRecCounter,
|
||||||
{
|
const int iRecID )
|
||||||
/*
|
|
||||||
just check if this is a protocol message but do not act on message
|
|
||||||
*/
|
|
||||||
int iRecCounter, iRecID;
|
|
||||||
CVector<uint8_t> vecData;
|
|
||||||
|
|
||||||
return !ParseMessageFrame ( vecbyData,
|
|
||||||
iNumBytes,
|
|
||||||
iRecCounter,
|
|
||||||
iRecID,
|
|
||||||
vecData );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CProtocol::ParseMessage ( const CVector<uint8_t>& vecbyData,
|
|
||||||
const int iNumBytes )
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
return code: false -> ok; true -> error
|
return code: false -> ok; true -> error
|
||||||
*/
|
*/
|
||||||
bool bRet = false;
|
bool bRet = false;
|
||||||
bool bSendNextMess;
|
bool bSendNextMess;
|
||||||
int iRecCounter, iRecID;
|
|
||||||
CVector<uint8_t> vecData;
|
|
||||||
|
|
||||||
if ( !ParseMessageFrame ( vecbyData, iNumBytes, iRecCounter, iRecID, vecData ) )
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// TEST channel implementation: randomly delete protocol messages (50 % loss)
|
// TEST channel implementation: randomly delete protocol messages (50 % loss)
|
||||||
if ( rand() < ( RAND_MAX / 2 ) ) return false;
|
if ( rand() < ( RAND_MAX / 2 ) ) return false;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// in case this is a connection less message, we do not process it here
|
// In case we received a message and returned an answer but our answer
|
||||||
if ( IsConnectionLessMessageID ( iRecID ) )
|
// 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 )
|
||||||
{
|
{
|
||||||
// fire a signal so that an other class can process this type of
|
// resend acknowledgement
|
||||||
// message
|
CreateAndImmSendAcknMess ( iRecID, iRecCounter );
|
||||||
emit DetectedCLMessage ( vecbyData, iNumBytes );
|
|
||||||
|
|
||||||
// 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
|
else
|
||||||
// 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
|
// special treatment for acknowledge messages
|
||||||
// case, just resend our old answer again
|
if ( iRecID == PROTMESSID_ACKN )
|
||||||
if ( ( iOldRecID == iRecID ) && ( iOldRecCnt == iRecCounter ) )
|
|
||||||
{
|
{
|
||||||
// acknowledgments are not acknowledged
|
// extract data from stream and emit signal for received value
|
||||||
if ( iRecID != PROTMESSID_ACKN )
|
int iPos = 0;
|
||||||
|
const int iData =
|
||||||
|
static_cast<int> ( GetValFromStream ( vecbyMesBodyData, iPos, 2 ) );
|
||||||
|
|
||||||
|
Mutex.lock();
|
||||||
{
|
{
|
||||||
// resend acknowledgement
|
// check if this is the correct acknowledgment
|
||||||
CreateAndImmSendAcknMess ( iRecID, iRecCounter );
|
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
|
else
|
||||||
{
|
{
|
||||||
// special treatment for acknowledge messages
|
// check which type of message we received and do action
|
||||||
if ( iRecID == PROTMESSID_ACKN )
|
switch ( iRecID )
|
||||||
{
|
{
|
||||||
// extract data from stream and emit signal for received value
|
case PROTMESSID_JITT_BUF_SIZE:
|
||||||
int iPos = 0;
|
bRet = EvaluateJitBufMes ( vecbyMesBodyData );
|
||||||
const int iData =
|
break;
|
||||||
static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
|
|
||||||
|
|
||||||
Mutex.lock();
|
case PROTMESSID_REQ_JITT_BUF_SIZE:
|
||||||
{
|
bRet = EvaluateReqJitBufMes();
|
||||||
// check if this is the correct acknowledgment
|
break;
|
||||||
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
|
case PROTMESSID_CHANNEL_GAIN:
|
||||||
bSendNextMess = true;
|
bRet = EvaluateChanGainMes ( vecbyMesBodyData );
|
||||||
}
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
|
|
||||||
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
|
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
|
||||||
case PROTMESSID_CONN_CLIENTS_LIST_NAME:
|
case PROTMESSID_CONN_CLIENTS_LIST_NAME:
|
||||||
bRet = EvaluateConClientListNameMes ( vecData );
|
bRet = EvaluateConClientListNameMes ( vecbyMesBodyData );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_CONN_CLIENTS_LIST:
|
case PROTMESSID_CONN_CLIENTS_LIST:
|
||||||
bRet = EvaluateConClientListMes ( vecData );
|
bRet = EvaluateConClientListMes ( vecbyMesBodyData );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_REQ_CONN_CLIENTS_LIST:
|
case PROTMESSID_REQ_CONN_CLIENTS_LIST:
|
||||||
bRet = EvaluateReqConnClientsList();
|
bRet = EvaluateReqConnClientsList();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
|
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
|
||||||
case PROTMESSID_CHANNEL_NAME:
|
case PROTMESSID_CHANNEL_NAME:
|
||||||
bRet = EvaluateChanNameMes ( vecData );
|
bRet = EvaluateChanNameMes ( vecbyMesBodyData );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_CHANNEL_INFOS:
|
case PROTMESSID_CHANNEL_INFOS:
|
||||||
bRet = EvaluateChanInfoMes ( vecData );
|
bRet = EvaluateChanInfoMes ( vecbyMesBodyData );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_REQ_CHANNEL_INFOS:
|
case PROTMESSID_REQ_CHANNEL_INFOS:
|
||||||
bRet = EvaluateReqChanInfoMes();
|
bRet = EvaluateReqChanInfoMes();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_CHAT_TEXT:
|
case PROTMESSID_CHAT_TEXT:
|
||||||
bRet = EvaluateChatTextMes ( vecData );
|
bRet = EvaluateChatTextMes ( vecbyMesBodyData );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
|
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
|
||||||
case PROTMESSID_PING_MS:
|
case PROTMESSID_PING_MS:
|
||||||
bRet = EvaluatePingMes ( vecData );
|
bRet = EvaluatePingMes ( vecbyMesBodyData );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_NETW_TRANSPORT_PROPS:
|
case PROTMESSID_NETW_TRANSPORT_PROPS:
|
||||||
bRet = EvaluateNetwTranspPropsMes ( vecData );
|
bRet = EvaluateNetwTranspPropsMes ( vecbyMesBodyData );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_REQ_NETW_TRANSPORT_PROPS:
|
case PROTMESSID_REQ_NETW_TRANSPORT_PROPS:
|
||||||
bRet = EvaluateReqNetwTranspPropsMes();
|
bRet = EvaluateReqNetwTranspPropsMes();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
|
// #### COMPATIBILITY OLD VERSION, TO BE REMOVED ####
|
||||||
case PROTMESSID_OPUS_SUPPORTED:
|
case PROTMESSID_OPUS_SUPPORTED:
|
||||||
bRet = EvaluateOpusSupportedMes();
|
bRet = EvaluateOpusSupportedMes();
|
||||||
break;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// immediately send acknowledge message
|
||||||
|
CreateAndImmSendAcknMess ( iRecID, iRecCounter );
|
||||||
|
|
||||||
|
// save current message ID and counter to find out if message
|
||||||
|
// was resent
|
||||||
|
iOldRecID = iRecID;
|
||||||
|
iOldRecCnt = iRecCounter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CProtocol::ParseConnectionLessMessageWithFrame ( const CVector<uint8_t>& vecbyData,
|
||||||
|
const int iNumBytesIn,
|
||||||
|
const CHostAddress& InetAddr )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
return code: false -> ok; true -> error
|
||||||
|
*/
|
||||||
|
bool bRet = false;
|
||||||
|
int iRecCounter, iRecID;
|
||||||
|
CVector<uint8_t> vecbyMesBodyData;
|
||||||
|
|
||||||
|
if ( !ParseMessageFrame ( vecbyData,
|
||||||
|
iNumBytesIn,
|
||||||
|
vecbyMesBodyData,
|
||||||
|
iRecCounter,
|
||||||
|
iRecID ) )
|
||||||
|
{
|
||||||
|
bRet = ParseConnectionLessMessageBody ( vecbyMesBodyData,
|
||||||
|
iRecID,
|
||||||
|
InetAddr );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bRet = true; // return error code
|
bRet = true; // return error code
|
||||||
|
@ -603,70 +595,60 @@ case PROTMESSID_OPUS_SUPPORTED:
|
||||||
return bRet;
|
return bRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CProtocol::ParseConnectionLessMessage ( const CVector<uint8_t>& vecbyData,
|
bool CProtocol::ParseConnectionLessMessageBody ( const CVector<uint8_t>& vecbyMesBodyData,
|
||||||
const int iNumBytes,
|
const int iRecID,
|
||||||
const CHostAddress& InetAddr )
|
const CHostAddress& InetAddr )
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
return code: false -> ok; true -> error
|
return code: false -> ok; true -> error
|
||||||
*/
|
*/
|
||||||
bool bRet = false;
|
bool bRet = false;
|
||||||
int iRecCounter, iRecID;
|
|
||||||
CVector<uint8_t> vecData;
|
|
||||||
|
|
||||||
if ( !ParseMessageFrame ( vecbyData, iNumBytes, iRecCounter, iRecID, vecData ) )
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// TEST channel implementation: randomly delete protocol messages (50 % loss)
|
// TEST channel implementation: randomly delete protocol messages (50 % loss)
|
||||||
if ( rand() < ( RAND_MAX / 2 ) ) return false;
|
if ( rand() < ( RAND_MAX / 2 ) ) return false;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ( IsConnectionLessMessageID ( iRecID ) )
|
if ( IsConnectionLessMessageID ( iRecID ) )
|
||||||
|
{
|
||||||
|
// check which type of message we received and do action
|
||||||
|
switch ( iRecID )
|
||||||
{
|
{
|
||||||
// check which type of message we received and do action
|
case PROTMESSID_CLM_PING_MS:
|
||||||
switch ( iRecID )
|
bRet = EvaluateCLPingMes ( InetAddr, vecbyMesBodyData );
|
||||||
{
|
break;
|
||||||
case PROTMESSID_CLM_PING_MS:
|
|
||||||
bRet = EvaluateCLPingMes ( InetAddr, vecData );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PROTMESSID_CLM_PING_MS_WITHNUMCLIENTS:
|
case PROTMESSID_CLM_PING_MS_WITHNUMCLIENTS:
|
||||||
bRet = EvaluateCLPingWithNumClientsMes ( InetAddr, vecData );
|
bRet = EvaluateCLPingWithNumClientsMes ( InetAddr, vecbyMesBodyData );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_CLM_SERVER_FULL:
|
case PROTMESSID_CLM_SERVER_FULL:
|
||||||
bRet = EvaluateCLServerFullMes();
|
bRet = EvaluateCLServerFullMes();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_CLM_SERVER_LIST:
|
case PROTMESSID_CLM_SERVER_LIST:
|
||||||
bRet = EvaluateCLServerListMes ( InetAddr, vecData );
|
bRet = EvaluateCLServerListMes ( InetAddr, vecbyMesBodyData );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_CLM_REQ_SERVER_LIST:
|
case PROTMESSID_CLM_REQ_SERVER_LIST:
|
||||||
bRet = EvaluateCLReqServerListMes ( InetAddr );
|
bRet = EvaluateCLReqServerListMes ( InetAddr );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_CLM_SEND_EMPTY_MESSAGE:
|
case PROTMESSID_CLM_SEND_EMPTY_MESSAGE:
|
||||||
bRet = EvaluateCLSendEmptyMesMes ( vecData );
|
bRet = EvaluateCLSendEmptyMesMes ( vecbyMesBodyData );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_CLM_REGISTER_SERVER:
|
case PROTMESSID_CLM_REGISTER_SERVER:
|
||||||
bRet = EvaluateCLRegisterServerMes ( InetAddr, vecData );
|
bRet = EvaluateCLRegisterServerMes ( InetAddr, vecbyMesBodyData );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_CLM_UNREGISTER_SERVER:
|
case PROTMESSID_CLM_UNREGISTER_SERVER:
|
||||||
bRet = EvaluateCLUnregisterServerMes ( InetAddr );
|
bRet = EvaluateCLUnregisterServerMes ( InetAddr );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PROTMESSID_CLM_DISCONNECTION:
|
case PROTMESSID_CLM_DISCONNECTION:
|
||||||
bRet = EvaluateCLDisconnectionMes ( InetAddr );
|
bRet = EvaluateCLDisconnectionMes ( InetAddr );
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bRet = true; // return error code
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1872,11 +1854,11 @@ bool CProtocol::EvaluateCLDisconnectionMes ( const CHostAddress& InetAddr )
|
||||||
/******************************************************************************\
|
/******************************************************************************\
|
||||||
* Message generation and parsing *
|
* Message generation and parsing *
|
||||||
\******************************************************************************/
|
\******************************************************************************/
|
||||||
bool CProtocol::ParseMessageFrame ( const CVector<uint8_t>& vecIn,
|
bool CProtocol::ParseMessageFrame ( const CVector<uint8_t>& vecbyData,
|
||||||
const int iNumBytesIn,
|
const int iNumBytesIn,
|
||||||
|
CVector<uint8_t>& vecbyMesBodyData,
|
||||||
int& iCnt,
|
int& iCnt,
|
||||||
int& iID,
|
int& iID )
|
||||||
CVector<uint8_t>& vecData )
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int iLenBy;
|
int iLenBy;
|
||||||
|
@ -1893,7 +1875,7 @@ bool CProtocol::ParseMessageFrame ( const CVector<uint8_t>& vecIn,
|
||||||
iCurPos = 0; // start from beginning
|
iCurPos = 0; // start from beginning
|
||||||
|
|
||||||
// 2 bytes TAG
|
// 2 bytes TAG
|
||||||
const int iTag = static_cast<int> ( GetValFromStream ( vecIn, iCurPos, 2 ) );
|
const int iTag = static_cast<int> ( GetValFromStream ( vecbyData, iCurPos, 2 ) );
|
||||||
|
|
||||||
// check if tag is correct
|
// check if tag is correct
|
||||||
if ( iTag != 0 )
|
if ( iTag != 0 )
|
||||||
|
@ -1902,13 +1884,13 @@ bool CProtocol::ParseMessageFrame ( const CVector<uint8_t>& vecIn,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2 bytes ID
|
// 2 bytes ID
|
||||||
iID = static_cast<int> ( GetValFromStream ( vecIn, iCurPos, 2 ) );
|
iID = static_cast<int> ( GetValFromStream ( vecbyData, iCurPos, 2 ) );
|
||||||
|
|
||||||
// 1 byte cnt
|
// 1 byte cnt
|
||||||
iCnt = static_cast<int> ( GetValFromStream ( vecIn, iCurPos, 1 ) );
|
iCnt = static_cast<int> ( GetValFromStream ( vecbyData, iCurPos, 1 ) );
|
||||||
|
|
||||||
// 2 bytes length
|
// 2 bytes length
|
||||||
iLenBy = static_cast<int> ( GetValFromStream ( vecIn, iCurPos, 2 ) );
|
iLenBy = static_cast<int> ( GetValFromStream ( vecbyData, iCurPos, 2 ) );
|
||||||
|
|
||||||
// make sure the length is correct
|
// make sure the length is correct
|
||||||
if ( iLenBy != iNumBytesIn - MESS_LEN_WITHOUT_DATA_BYTE )
|
if ( iLenBy != iNumBytesIn - MESS_LEN_WITHOUT_DATA_BYTE )
|
||||||
|
@ -1927,24 +1909,24 @@ bool CProtocol::ParseMessageFrame ( const CVector<uint8_t>& vecIn,
|
||||||
for ( i = 0; i < iLenCRCCalc; i++ )
|
for ( i = 0; i < iLenCRCCalc; i++ )
|
||||||
{
|
{
|
||||||
CRCObj.AddByte ( static_cast<uint8_t> (
|
CRCObj.AddByte ( static_cast<uint8_t> (
|
||||||
GetValFromStream ( vecIn, iCurPos, 1 ) ) );
|
GetValFromStream ( vecbyData, iCurPos, 1 ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( CRCObj.GetCRC () != GetValFromStream ( vecIn, iCurPos, 2 ) )
|
if ( CRCObj.GetCRC () != GetValFromStream ( vecbyData, iCurPos, 2 ) )
|
||||||
{
|
{
|
||||||
return true; // return error code
|
return true; // return error code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Extract actual data -----------------------------------------------------
|
// Extract actual data -----------------------------------------------------
|
||||||
vecData.Init ( iLenBy );
|
vecbyMesBodyData.Init ( iLenBy );
|
||||||
|
|
||||||
iCurPos = MESS_HEADER_LENGTH_BYTE; // start from beginning of data
|
iCurPos = MESS_HEADER_LENGTH_BYTE; // start from beginning of data
|
||||||
|
|
||||||
for ( i = 0; i < iLenBy; i++ )
|
for ( i = 0; i < iLenBy; i++ )
|
||||||
{
|
{
|
||||||
vecData[i] = static_cast<uint8_t> (
|
vecbyMesBodyData[i] = static_cast<uint8_t> (
|
||||||
GetValFromStream ( vecIn, iCurPos, 1 ) );
|
GetValFromStream ( vecbyData, iCurPos, 1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return false; // no error
|
return false; // no error
|
||||||
|
|
|
@ -118,15 +118,26 @@ public:
|
||||||
void CreateCLEmptyMes ( const CHostAddress& InetAddr );
|
void CreateCLEmptyMes ( const CHostAddress& InetAddr );
|
||||||
void CreateCLDisconnection ( const CHostAddress& InetAddr );
|
void CreateCLDisconnection ( const CHostAddress& InetAddr );
|
||||||
|
|
||||||
bool ParseMessage ( const CVector<uint8_t>& vecbyData,
|
bool ParseMessageFrame ( const CVector<uint8_t>& vecbyData,
|
||||||
const int iNumBytes );
|
const int iNumBytesIn,
|
||||||
|
CVector<uint8_t>& vecbyMesBodyData,
|
||||||
|
int& iRecCounter,
|
||||||
|
int& iRecID );
|
||||||
|
|
||||||
bool ParseConnectionLessMessage ( const CVector<uint8_t>& vecbyData,
|
bool ParseMessageBody ( const CVector<uint8_t>& vecbyMesBodyData,
|
||||||
const int iNumBytes,
|
const int iRecCounter,
|
||||||
const CHostAddress& InetAddr );
|
const int iRecID );
|
||||||
|
|
||||||
bool IsProtocolMessage ( const CVector<uint8_t>& vecbyData,
|
bool ParseConnectionLessMessageWithFrame ( const CVector<uint8_t>& vecbyData,
|
||||||
const int iNumBytes );
|
const int iNumBytesIn,
|
||||||
|
const CHostAddress& InetAddr );
|
||||||
|
|
||||||
|
bool ParseConnectionLessMessageBody ( const CVector<uint8_t>& vecbyMesBodyData,
|
||||||
|
const int iRecID,
|
||||||
|
const CHostAddress& InetAddr );
|
||||||
|
|
||||||
|
bool IsConnectionLessMessageID ( const int iID ) const
|
||||||
|
{ return (iID >= 1000) & (iID < 2000); }
|
||||||
|
|
||||||
// this function is public because we need it in the test bench
|
// this function is public because we need it in the test bench
|
||||||
void CreateAndImmSendAcknMess ( const int& iID,
|
void CreateAndImmSendAcknMess ( const int& iID,
|
||||||
|
@ -160,12 +171,6 @@ protected:
|
||||||
const int iCnt,
|
const int iCnt,
|
||||||
const int iID );
|
const int iID );
|
||||||
|
|
||||||
bool ParseMessageFrame ( const CVector<uint8_t>& vecIn,
|
|
||||||
const int iNumBytesIn,
|
|
||||||
int& iCnt,
|
|
||||||
int& iID,
|
|
||||||
CVector<uint8_t>& vecData );
|
|
||||||
|
|
||||||
void GenMessageFrame ( CVector<uint8_t>& vecOut,
|
void GenMessageFrame ( CVector<uint8_t>& vecOut,
|
||||||
const int iCnt,
|
const int iCnt,
|
||||||
const int iID,
|
const int iID,
|
||||||
|
@ -189,9 +194,6 @@ protected:
|
||||||
const int iMaxStringLen,
|
const int iMaxStringLen,
|
||||||
QString& strOut );
|
QString& strOut );
|
||||||
|
|
||||||
bool IsConnectionLessMessageID ( const int iID ) const
|
|
||||||
{ return (iID >= 1000) & (iID < 2000); }
|
|
||||||
|
|
||||||
void SendMessage();
|
void SendMessage();
|
||||||
|
|
||||||
void CreateAndSendMessage ( const int iID,
|
void CreateAndSendMessage ( const int iID,
|
||||||
|
@ -280,9 +282,6 @@ signals:
|
||||||
void CLReqServerList ( CHostAddress InetAddr );
|
void CLReqServerList ( CHostAddress InetAddr );
|
||||||
void CLSendEmptyMes ( CHostAddress TargetInetAddr );
|
void CLSendEmptyMes ( CHostAddress TargetInetAddr );
|
||||||
void CLDisconnection ( CHostAddress InetAddr );
|
void CLDisconnection ( CHostAddress InetAddr );
|
||||||
|
|
||||||
void DetectedCLMessage ( CVector<uint8_t> vecbyData,
|
|
||||||
int iNumBytes );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* !defined ( PROTOCOL_H__3B123453_4344_BB2392354455IUHF1912__INCLUDED_ ) */
|
#endif /* !defined ( PROTOCOL_H__3B123453_4344_BB2392354455IUHF1912__INCLUDED_ ) */
|
||||||
|
|
|
@ -537,15 +537,15 @@ void CServer::OnSendCLProtMessage ( CHostAddress InetAddr,
|
||||||
Socket.SendPacket ( vecMessage, InetAddr );
|
Socket.SendPacket ( vecMessage, InetAddr );
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServer::OnDetCLMess ( const CVector<uint8_t>& vecbyData,
|
void CServer::OnDetCLMess ( const CVector<uint8_t>& vecbyMesBodyData,
|
||||||
const int iNumBytes,
|
const int iRecID,
|
||||||
const CHostAddress& InetAddr )
|
const CHostAddress& InetAddr )
|
||||||
{
|
{
|
||||||
// this is a special case: we received a connection less message but we are
|
// this is a special case: we received a connection less message but we are
|
||||||
// in a connection
|
// in a connection
|
||||||
ConnLessProtocol.ParseConnectionLessMessage ( vecbyData,
|
ConnLessProtocol.ParseConnectionLessMessageBody ( vecbyMesBodyData,
|
||||||
iNumBytes,
|
iRecID,
|
||||||
InetAddr );
|
InetAddr );
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServer::OnCLDisconnection ( CHostAddress InetAddr )
|
void CServer::OnCLDisconnection ( CHostAddress InetAddr )
|
||||||
|
@ -1195,9 +1195,9 @@ bool CServer::PutData ( const CVector<uint8_t>& vecbyRecBuf,
|
||||||
{
|
{
|
||||||
// this is a new client, we then first check if this is a connection
|
// this is a new client, we then first check if this is a connection
|
||||||
// less message before we create a new official channel
|
// less message before we create a new official channel
|
||||||
if ( ConnLessProtocol.ParseConnectionLessMessage ( vecbyRecBuf,
|
if ( ConnLessProtocol.ParseConnectionLessMessageWithFrame ( vecbyRecBuf,
|
||||||
iNumBytesRead,
|
iNumBytesRead,
|
||||||
HostAdr ) )
|
HostAdr ) )
|
||||||
{
|
{
|
||||||
// a new client is calling, look for free channel
|
// a new client is calling, look for free channel
|
||||||
iCurChanID = GetFreeChan();
|
iCurChanID = GetFreeChan();
|
||||||
|
|
28
src/server.h
28
src/server.h
|
@ -265,8 +265,8 @@ public slots:
|
||||||
void OnNewConnection ( int iChID );
|
void OnNewConnection ( int iChID );
|
||||||
void OnSendCLProtMessage ( CHostAddress InetAddr, CVector<uint8_t> vecMessage );
|
void OnSendCLProtMessage ( CHostAddress InetAddr, CVector<uint8_t> vecMessage );
|
||||||
|
|
||||||
void OnDetCLMess ( const CVector<uint8_t>& vecbyData,
|
void OnDetCLMess ( const CVector<uint8_t>& vecbyMesBodyData,
|
||||||
const int iNumBytes,
|
const int iRecID,
|
||||||
const CHostAddress& InetAddr );
|
const CHostAddress& InetAddr );
|
||||||
|
|
||||||
void OnCLPingReceived ( CHostAddress InetAddr, int iMs )
|
void OnCLPingReceived ( CHostAddress InetAddr, int iMs )
|
||||||
|
@ -325,18 +325,18 @@ public slots:
|
||||||
void OnSendProtMessCh10 ( CVector<uint8_t> mess ) { OnSendProtMessage ( 10, mess ); }
|
void OnSendProtMessCh10 ( CVector<uint8_t> mess ) { OnSendProtMessage ( 10, mess ); }
|
||||||
void OnSendProtMessCh11 ( CVector<uint8_t> mess ) { OnSendProtMessage ( 11, mess ); }
|
void OnSendProtMessCh11 ( CVector<uint8_t> mess ) { OnSendProtMessage ( 11, mess ); }
|
||||||
|
|
||||||
void OnDetCLMessCh0 ( CVector<uint8_t> vData, int iNBy ) { OnDetCLMess ( vData, iNBy, vecChannels[0].GetAddress() ); }
|
void OnDetCLMessCh0 ( CVector<uint8_t> vData, int iID ) { OnDetCLMess ( vData, iID, vecChannels[0].GetAddress() ); }
|
||||||
void OnDetCLMessCh1 ( CVector<uint8_t> vData, int iNBy ) { OnDetCLMess ( vData, iNBy, vecChannels[1].GetAddress() ); }
|
void OnDetCLMessCh1 ( CVector<uint8_t> vData, int iID ) { OnDetCLMess ( vData, iID, vecChannels[1].GetAddress() ); }
|
||||||
void OnDetCLMessCh2 ( CVector<uint8_t> vData, int iNBy ) { OnDetCLMess ( vData, iNBy, vecChannels[2].GetAddress() ); }
|
void OnDetCLMessCh2 ( CVector<uint8_t> vData, int iID ) { OnDetCLMess ( vData, iID, vecChannels[2].GetAddress() ); }
|
||||||
void OnDetCLMessCh3 ( CVector<uint8_t> vData, int iNBy ) { OnDetCLMess ( vData, iNBy, vecChannels[3].GetAddress() ); }
|
void OnDetCLMessCh3 ( CVector<uint8_t> vData, int iID ) { OnDetCLMess ( vData, iID, vecChannels[3].GetAddress() ); }
|
||||||
void OnDetCLMessCh4 ( CVector<uint8_t> vData, int iNBy ) { OnDetCLMess ( vData, iNBy, vecChannels[4].GetAddress() ); }
|
void OnDetCLMessCh4 ( CVector<uint8_t> vData, int iID ) { OnDetCLMess ( vData, iID, vecChannels[4].GetAddress() ); }
|
||||||
void OnDetCLMessCh5 ( CVector<uint8_t> vData, int iNBy ) { OnDetCLMess ( vData, iNBy, vecChannels[5].GetAddress() ); }
|
void OnDetCLMessCh5 ( CVector<uint8_t> vData, int iID ) { OnDetCLMess ( vData, iID, vecChannels[5].GetAddress() ); }
|
||||||
void OnDetCLMessCh6 ( CVector<uint8_t> vData, int iNBy ) { OnDetCLMess ( vData, iNBy, vecChannels[6].GetAddress() ); }
|
void OnDetCLMessCh6 ( CVector<uint8_t> vData, int iID ) { OnDetCLMess ( vData, iID, vecChannels[6].GetAddress() ); }
|
||||||
void OnDetCLMessCh7 ( CVector<uint8_t> vData, int iNBy ) { OnDetCLMess ( vData, iNBy, vecChannels[7].GetAddress() ); }
|
void OnDetCLMessCh7 ( CVector<uint8_t> vData, int iID ) { OnDetCLMess ( vData, iID, vecChannels[7].GetAddress() ); }
|
||||||
void OnDetCLMessCh8 ( CVector<uint8_t> vData, int iNBy ) { OnDetCLMess ( vData, iNBy, vecChannels[8].GetAddress() ); }
|
void OnDetCLMessCh8 ( CVector<uint8_t> vData, int iID ) { OnDetCLMess ( vData, iID, vecChannels[8].GetAddress() ); }
|
||||||
void OnDetCLMessCh9 ( CVector<uint8_t> vData, int iNBy ) { OnDetCLMess ( vData, iNBy, vecChannels[9].GetAddress() ); }
|
void OnDetCLMessCh9 ( CVector<uint8_t> vData, int iID ) { OnDetCLMess ( vData, iID, vecChannels[9].GetAddress() ); }
|
||||||
void OnDetCLMessCh10 ( CVector<uint8_t> vData, int iNBy ) { OnDetCLMess ( vData, iNBy, vecChannels[10].GetAddress() ); }
|
void OnDetCLMessCh10 ( CVector<uint8_t> vData, int iID ) { OnDetCLMess ( vData, iID, vecChannels[10].GetAddress() ); }
|
||||||
void OnDetCLMessCh11 ( CVector<uint8_t> vData, int iNBy ) { OnDetCLMess ( vData, iNBy, vecChannels[11].GetAddress() ); }
|
void OnDetCLMessCh11 ( CVector<uint8_t> vData, int iID ) { OnDetCLMess ( vData, iID, vecChannels[11].GetAddress() ); }
|
||||||
|
|
||||||
void OnNewConnectionCh0() { OnNewConnection ( 0 ); }
|
void OnNewConnectionCh0() { OnNewConnection ( 0 ); }
|
||||||
void OnNewConnectionCh1() { OnNewConnection ( 1 ); }
|
void OnNewConnectionCh1() { OnNewConnection ( 1 ); }
|
||||||
|
|
53
src/socket.h
53
src/socket.h
|
@ -90,41 +90,58 @@ signals:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ENABLE_RECEIVE_SOCKET_IN_SEPARATE_THREAD
|
||||||
/* Socket which runs in a separate high priority thread ----------------------*/
|
/* Socket which runs in a separate high priority thread ----------------------*/
|
||||||
|
class CHighPrioSocket : public QObject
|
||||||
/*
|
|
||||||
// TEST
|
|
||||||
|
|
||||||
// http://qt-project.org/forums/viewthread/14393
|
|
||||||
// http://qt-project.org/doc/qt-5.0/qtcore/qthread.html#Priority-enum
|
|
||||||
// http://qt-project.org/wiki/Threads_Events_QObjects
|
|
||||||
|
|
||||||
class CHighPrioSocket
|
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CHighPrioSocket ( CChannel* pNewChannel,
|
CHighPrioSocket ( CChannel* pNewChannel,
|
||||||
const quint16 iPortNumber )
|
const quint16 iPortNumber )
|
||||||
{
|
{
|
||||||
|
|
||||||
// TEST
|
// TEST we have to register some classes to the Qt signal/slot mechanism
|
||||||
worker = new CSocket ( pNewChannel, iPortNumber );
|
// since now we actually have thread crossings with the new code
|
||||||
worker->moveToThread(&workerThread);
|
qRegisterMetaType<CVector<uint8_t> > ( "CVector<uint8_t>" );
|
||||||
workerThread.start(QThread::TimeCriticalPriority);
|
qRegisterMetaType<CHostAddress> ( "CHostAddress" );
|
||||||
|
|
||||||
|
|
||||||
|
// TEST actual creation of the new thread, see internet references below:
|
||||||
|
// http://qt-project.org/forums/viewthread/14393
|
||||||
|
// http://qt-project.org/doc/qt-5.0/qtcore/qthread.html#Priority-enum
|
||||||
|
// http://qt-project.org/wiki/Threads_Events_QObjects
|
||||||
|
|
||||||
|
pSocket = new CSocket ( pNewChannel, iPortNumber );
|
||||||
|
pSocket->moveToThread ( &NetworkWorkerThread );
|
||||||
|
NetworkWorkerThread.start ( QThread::TimeCriticalPriority );
|
||||||
|
|
||||||
|
|
||||||
|
QObject::connect ( pSocket,
|
||||||
|
SIGNAL ( InvalidPacketReceived ( CVector<uint8_t>, int, CHostAddress ) ),
|
||||||
|
SIGNAL ( InvalidPacketReceived ( CVector<uint8_t>, int, CHostAddress ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~CHighPrioSocket()
|
||||||
|
{
|
||||||
|
NetworkWorkerThread.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendPacket ( const CVector<uint8_t>& vecbySendBuf,
|
void SendPacket ( const CVector<uint8_t>& vecbySendBuf,
|
||||||
const CHostAddress& HostAddr )
|
const CHostAddress& HostAddr )
|
||||||
{
|
{
|
||||||
worker->SendPacket ( vecbySendBuf, HostAddr );
|
pSocket->SendPacket ( vecbySendBuf, HostAddr );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
QThread NetworkWorkerThread;
|
||||||
|
CSocket* pSocket;
|
||||||
|
|
||||||
// TEST
|
signals:
|
||||||
QThread workerThread;
|
void InvalidPacketReceived ( CVector<uint8_t> vecbyRecBuf,
|
||||||
CSocket* worker;
|
int iNumBytesRead,
|
||||||
|
CHostAddress RecHostAddr );
|
||||||
};
|
};
|
||||||
*/
|
#endif
|
||||||
|
|
||||||
#endif /* !defined ( SOCKET_HOIHGE76GEKJH98_3_4344_BB23945IUHF1912__INCLUDED_ ) */
|
#endif /* !defined ( SOCKET_HOIHGE76GEKJH98_3_4344_BB23945IUHF1912__INCLUDED_ ) */
|
||||||
|
|
Loading…
Reference in a new issue