-
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
deb9a7c
dce5eec
f06317a
916db14
5898b62
87e9738
f51c77f
701dc33
35593af
25ed276
a910871
1040adf
8727307
bc10c83
48d09b6
a352faf
220f425
dbdc65f
9ed9b5e
afe68dc
3dc6941
3d09c48
28565f8
1814940
d426fe3
fdc0fd2
581efa9
0170f83
7d8000a
89127e9
73cce24
36fdd4e
5f1b95f
20c70ce
8e295fa
e0ac6fa
1ec2e88
3356dee
fdcef54
3c9d5cc
fe7b02c
2d5ec89
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 |
|---|---|---|
|
|
@@ -148,7 +148,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 ); | ||
|
|
||
|
|
@@ -252,11 +254,80 @@ 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 shorter than Qt default 30 seconds | ||
|
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. If this is the keep alive timer - say that and say it's 15 seconds - rather than saying what it isn't.
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. No, it's the connect timeout. Qt by default returns "connect timeout" after no acceptance for 30 seconds. There's no point waiting that long - it will either succeed within a couple of seconds or never, nowadays. The keepalive timer is separate from that.
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. OK - so still say what the number is. Also, even though it's the client, I'd issue a warning level message with the source and dest ip/port numbers. |
||
| QTimer* pTimer = new QTimer ( this ); | ||
| pTimer->setSingleShot ( true ); | ||
|
|
||
| connect ( pTimer, &QTimer::timeout, this, [this, pSocket, pTimer]() { | ||
| if ( pSocket->state() != QAbstractSocket::ConnectedState ) | ||
| { | ||
| pSocket->abort(); | ||
| pSocket->deleteLater(); | ||
| qDebug() << "- TCP connect timeout"; | ||
| } | ||
| 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. |
||
| 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 ) | ||
|
|
@@ -271,10 +342,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 ) | ||
|
|
@@ -978,6 +1049,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 | ||
|
|
||
|
|
@@ -1013,11 +1094,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(); | ||
|
|
||
|
|
@@ -1038,6 +1160,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 🙂 .