-
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
02ae7cc
57207c3
c12ccd5
e0200a2
4b34af8
5809531
7e23497
a189a12
b3fb072
77862ff
4a4b1c5
abe1c15
34ced7d
f806eb1
95ddc63
892e470
6991107
3c1de42
42a1ba4
db4b5fd
485d133
3555fa3
6e14110
fbcbaf3
b8a4754
03dff67
120c9ea
1c50e7c
bfaa89b
01c2b80
73e391a
7989e79
b41bc21
e38ceb3
30a4f4b
ba3c4b3
e29c55c
20ee030
11d314b
bcb4b78
86149e3
f1dcc0a
bbc0905
eda100e
8b14d66
dded0ca
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 |
|---|---|---|
|
|
@@ -170,7 +170,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::CLTcpSupported, this, &CClient::OnCLTcpSupported ); | ||
|
|
||
| QObject::connect ( &ConnLessProtocol, &CProtocol::CLConnClientsListMesReceived, this, &CClient::OnCLConnClientsListMesReceived ); | ||
|
|
||
| QObject::connect ( &ConnLessProtocol, &CProtocol::CLPingReceived, this, &CClient::OnCLPingReceived ); | ||
|
|
||
|
|
@@ -274,11 +276,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 ) | ||
|
|
@@ -293,10 +365,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 ) | ||
|
|
@@ -1000,6 +1072,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 | ||
|
|
||
|
|
@@ -1035,11 +1117,52 @@ void CClient::OnRawAudioSupported() | |
| } | ||
| } | ||
|
|
||
| void CClient::OnCLTcpSupported ( CHostAddress InetAddr, int iID ) | ||
| { | ||
| qDebug() << "- TCP supported at server" << InetAddr.toString() << "for ID =" << iID; | ||
|
|
||
| if ( iID != PROTMESSID_CLM_CLIENT_ID ) | ||
| { | ||
| emit CLTcpSupported ( 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(); | ||
|
|
||
|
|
@@ -1060,6 +1183,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 🙂 .