-
Notifications
You must be signed in to change notification settings - Fork 246
Support TCP for protocol messages #3636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
6f5c808
1b99e62
67ad212
f161d58
5156f49
fa91c4a
50d3a0b
f11002c
82436cd
e1f0b44
c0b5930
fe107b9
3ff35e9
68b2e4b
1a240ce
53608c4
3e780eb
ea4a9a8
13ac448
5f0c7ce
ea1567c
049c763
f65206f
5d4bbc0
9af106f
a7c96bb
136de93
e86cff2
ae96f7c
cef9b56
a90ed45
0df0eca
4542044
45f42ce
5044eed
41adeb7
1704686
00d4f2b
3eb801e
be8acbb
fc2e58c
e443c66
2da453e
0a3009b
8af225b
b85b415
6c33975
a41ab9f
efdad4f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -169,7 +169,9 @@ CClient::CClient ( const quint16 iPortNumber, | |
|
|
||
| QObject::connect ( &ConnLessProtocol, &CProtocol::CLRedServerListReceived, this, &CClient::CLRedServerListReceived ); | ||
|
|
||
| QObject::connect ( &ConnLessProtocol, &CProtocol::CLConnClientsListMesReceived, this, &CClient::CLConnClientsListMesReceived ); | ||
| QObject::connect ( &ConnLessProtocol, &CProtocol::CLTcpSupportedReceived, this, &CClient::OnCLTcpSupportedReceived ); | ||
|
|
||
| QObject::connect ( &ConnLessProtocol, &CProtocol::CLConnClientsListMesReceived, this, &CClient::OnCLConnClientsListMesReceived ); | ||
|
|
||
| QObject::connect ( &ConnLessProtocol, &CProtocol::CLPingReceived, this, &CClient::OnCLPingReceived ); | ||
|
|
||
|
|
@@ -266,11 +268,81 @@ void CClient::OnSendProtMessage ( CVector<uint8_t> vecMessage ) | |
| Socket.SendPacket ( vecMessage, Channel.GetAddress() ); | ||
| } | ||
|
|
||
| void CClient::OnSendCLProtMessage ( CHostAddress InetAddr, CVector<uint8_t> vecMessage ) | ||
| void CClient::OnSendCLProtMessage ( CHostAddress InetAddr, CVector<uint8_t> vecMessage, CTcpConnection* pTcpConnection, enum EProtoMode eProtoMode ) | ||
| { | ||
| if ( pTcpConnection ) | ||
| { | ||
| // already have TCP connection - just send and return | ||
| pTcpConnection->write ( (const char*) &( (CVector<uint8_t>) vecMessage )[0], vecMessage.Size() ); | ||
| return; | ||
| } | ||
|
|
||
| // the protocol queries me to call the function to send the message | ||
| // send it through the network | ||
| Socket.SendPacket ( vecMessage, InetAddr ); | ||
| if ( eProtoMode != PROTO_UDP ) | ||
| { | ||
| // create a TCP client connection and send message | ||
| QTcpSocket* pSocket = new QTcpSocket ( this ); | ||
|
|
||
| // timer for TCP connect timeout because Qt defaults to 30 seconds | ||
| // and we want it to be 3 seconds (TCP_CONNECT_TIMEOUT_MS) | ||
| QTimer* pTimer = new QTimer ( this ); | ||
| pTimer->setSingleShot ( true ); | ||
|
|
||
| connect ( pTimer, &QTimer::timeout, this, [this, pSocket, pTimer, InetAddr]() { | ||
| if ( pSocket->state() != QAbstractSocket::ConnectedState ) | ||
| { | ||
| pSocket->abort(); | ||
| pSocket->deleteLater(); | ||
| qWarning() << "- Jamulus-TCP: timeout connecting to" << InetAddr.toString(); | ||
| } | ||
| pTimer->deleteLater(); | ||
| } ); | ||
|
|
||
| #if QT_VERSION >= QT_VERSION_CHECK( 5, 15, 0 ) | ||
| # define ERRORSIGNAL &QTcpSocket::errorOccurred | ||
| #else | ||
| # define ERRORSIGNAL QOverload<QAbstractSocket::SocketError>::of ( &QAbstractSocket::error ) | ||
| #endif | ||
| connect ( pSocket, ERRORSIGNAL, this, [this, pSocket, pTimer] ( QAbstractSocket::SocketError err ) { | ||
| Q_UNUSED ( err ); | ||
|
|
||
| pTimer->stop(); | ||
| pTimer->deleteLater(); | ||
|
|
||
| qWarning() << "- TCP connection error:" << pSocket->errorString(); | ||
| // may want to specifically handle ConnectionRefusedError? | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem is knowing why the connection was refused. Saying "Maybe check your firewall" isn't much help. Client-side is always tricky because most diagnostics never get looked at.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can always revisit it based on experience. |
||
| pSocket->deleteLater(); | ||
| } ); | ||
|
|
||
| connect ( pSocket, &QTcpSocket::connected, this, [this, pSocket, pTimer, InetAddr, vecMessage, eProtoMode]() { | ||
| pTimer->stop(); | ||
| pTimer->deleteLater(); | ||
|
|
||
| // connection succeeded, give it to a CTcpConnection | ||
| CTcpConnection* pTcpConnection = new CTcpConnection ( pSocket, | ||
| InetAddr, | ||
| this, | ||
| &Channel, | ||
| eProtoMode == PROTO_TCP_LONG ); // client connection, will self-delete on disconnect | ||
|
|
||
| if ( eProtoMode == PROTO_TCP_LONG ) | ||
| { | ||
| Channel.SetTcpConnection ( pTcpConnection ); // link session connection with channel | ||
| } | ||
|
|
||
| pTcpConnection->write ( (const char*) &( (CVector<uint8_t>) vecMessage )[0], vecMessage.Size() ); | ||
|
|
||
| // the CTcpConnection object will pass the reply back up to CClient::Channel | ||
| } ); | ||
|
|
||
| pSocket->connectToHost ( InetAddr.InetAddr, InetAddr.iPort ); | ||
| pTimer->start ( TCP_CONNECT_TIMEOUT_MS ); | ||
| } | ||
| else | ||
| { | ||
| Socket.SendPacket ( vecMessage, InetAddr ); | ||
| } | ||
| } | ||
|
|
||
| void CClient::OnInvalidPacketReceived ( CHostAddress RecHostAddr ) | ||
|
|
@@ -285,10 +357,10 @@ void CClient::OnInvalidPacketReceived ( CHostAddress RecHostAddr ) | |
| } | ||
| } | ||
|
|
||
| void CClient::OnDetectedCLMessage ( CVector<uint8_t> vecbyMesBodyData, int iRecID, CHostAddress RecHostAddr ) | ||
| void CClient::OnDetectedCLMessage ( CVector<uint8_t> vecbyMesBodyData, int iRecID, CHostAddress RecHostAddr, CTcpConnection* pTcpConnection ) | ||
| { | ||
| // connection less messages are always processed | ||
| ConnLessProtocol.ParseConnectionLessMessageBody ( vecbyMesBodyData, iRecID, RecHostAddr ); | ||
| ConnLessProtocol.ParseConnectionLessMessageBody ( vecbyMesBodyData, iRecID, RecHostAddr, pTcpConnection ); | ||
| } | ||
|
|
||
| void CClient::OnJittBufSizeChanged ( int iNewJitBufSize ) | ||
|
|
@@ -992,6 +1064,16 @@ void CClient::OnClientIDReceived ( int iServerChanID ) | |
| ClearClientChannels(); | ||
| } | ||
|
|
||
| // if TCP Supported has already been received, make TCP connection to server | ||
| iClientID = iServerChanID; // for sending back to server over TCP | ||
|
|
||
| if ( bTcpSupported ) | ||
| { | ||
| // *** Make TCP connection | ||
| qDebug() << Q_FUNC_INFO << "need to make TCP connection for" << iClientID; | ||
| ConnLessProtocol.CreateCLClientIDMes ( Channel.GetAddress(), iClientID, PROTO_TCP_LONG ); // create persistent TCP connection | ||
| } | ||
|
|
||
| // allocate and map client-side channel 0 | ||
| int iChanID = FindClientChannel ( iServerChanID, true ); // should always return channel 0 | ||
|
|
||
|
|
@@ -1027,11 +1109,52 @@ void CClient::OnRawAudioSupported() | |
| } | ||
| } | ||
|
|
||
| void CClient::OnCLTcpSupportedReceived ( CHostAddress InetAddr, int iID ) | ||
| { | ||
| qDebug() << "- TCP supported at server" << InetAddr.toString() << "for ID =" << iID; | ||
|
|
||
| if ( iID != PROTMESSID_CLM_CLIENT_ID ) | ||
| { | ||
| emit CLTcpSupportedReceived ( InetAddr, iID ); // pass to connect dialog | ||
| return; | ||
| } | ||
|
|
||
| // if client ID already received, make TCP connection to server | ||
| bTcpSupported = true; | ||
|
|
||
| if ( iClientID != INVALID_INDEX ) | ||
| { | ||
| // *** Make TCP connection | ||
| qDebug() << Q_FUNC_INFO << "need to make TCP connection for" << iClientID; | ||
| Q_ASSERT ( InetAddr == Channel.GetAddress() ); | ||
| ConnLessProtocol.CreateCLClientIDMes ( InetAddr, iClientID, PROTO_TCP_LONG ); // create persistent TCP connection | ||
| } | ||
| } | ||
|
|
||
| void CClient::OnCLConnClientsListMesReceived ( CHostAddress InetAddr, CVector<CChannelInfo> vecChanInfo, CTcpConnection* pTcpConnection ) | ||
| { | ||
| // test if we are receiving for the connect dialog or a connected session | ||
| if ( pTcpConnection && pTcpConnection->IsSession() ) | ||
| { | ||
| qDebug() << "- sending client list to client dialog"; | ||
| OnConClientListMesReceived ( vecChanInfo ); // connected session | ||
| } | ||
| else | ||
| { | ||
| qDebug() << "- sending client list to connect dialog"; | ||
| emit CLConnClientsListMesReceived ( InetAddr, vecChanInfo ); // connect dialog | ||
| } | ||
| } | ||
|
|
||
| void CClient::Start() | ||
| { | ||
| // init object | ||
| Init(); | ||
|
|
||
| // clear TCP info | ||
| iClientID = INVALID_INDEX; | ||
| bTcpSupported = false; | ||
|
|
||
| // initialise client channels | ||
| ClearClientChannels(); | ||
|
|
||
|
|
@@ -1052,6 +1175,14 @@ void CClient::Stop() | |
| // stop audio interface | ||
| Sound.Stop(); | ||
|
|
||
| // close any session TCP connection | ||
| CTcpConnection* pTcpConnection = Channel.GetTcpConnection(); | ||
| if ( pTcpConnection ) | ||
| { | ||
| Channel.SetTcpConnection ( nullptr ); | ||
| pTcpConnection->disconnectFromHost(); | ||
| } | ||
|
|
||
| // disable channel | ||
| Channel.SetEnable ( false ); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, makes sense. Next to try and work out how the fits around it 🙂 .