Skip to content

Commit

Permalink
Fixed a few remaining connection errors
Browse files Browse the repository at this point in the history
There was some issue on client detected connection rejection from server
Server wasn't releasing its client resources anymores after disconnect
  • Loading branch information
sammyfreg committed Dec 7, 2024
1 parent 84eac25 commit 1548168
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Code/Client/Private/NetImgui_Api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ bool IsConnected(void)

// If disconnected in middle of a remote frame drawing,
// want to behave like it is still connected to finish frame properly
return client.IsConnected() || IsDrawingRemote();
return client.IsConnected() || IsDrawingRemote();
}

//=================================================================================================
Expand Down
39 changes: 19 additions & 20 deletions Code/Client/Private/NetImgui_Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,8 @@ bool Communications_Initialize(ClientInfo& client)
{
CmdVersion cmdVersionSend, cmdVersionRcv;
PendingCom PendingRcv, PendingSend;

client.mbComInitActive = true;

//---------------------------------------------------------------------
// Handshake confirming connection validity
Expand Down Expand Up @@ -391,30 +393,25 @@ bool Communications_Initialize(ClientInfo& client)
//---------------------------------------------------------------------
// Connection established, init client
//---------------------------------------------------------------------
if( bCanConnect && !PendingSend.IsError() )
if( bCanConnect && !PendingSend.IsError() && (!client.IsConnected() || bForceConnect) )
{
Network::SocketInfo* pNewConnect = client.mpSocketPending.exchange(nullptr);
Network::SocketInfo* pNewComSocket = client.mpSocketPending.exchange(nullptr);

// If we detect an active connection with Server and 'ForceConnect was requested, close it first
if( client.IsConnected() )
{
// Force connect requested, disconnect current client and wait until it is free to connect to new server
if( bForceConnect ){
client.mbDisconnectPending = true;
while( client.IsConnected() );
}
// Close communication with server, client isn't available to connect to it
else{
NetImgui::Internal::Network::Disconnect(pNewConnect);
return false;
}
client.mbDisconnectPending = true;
while( client.IsConnected() );
}

for(auto& texture : client.mTextures)
{
texture.mbSent = false;
}

client.mpSocketComs = pNewComSocket; // Take ownerhip of socket
client.mbHasTextureUpdate = true; // Force sending the client textures
client.mBGSettingSent.mTextureId = client.mBGSetting.mTextureId-1u; // Force sending the Background settings (by making different than current settings)
client.mpSocketComs = pNewConnect;
client.mFrameIndex = 0;
client.mPendingSendNext = 0;
client.mServerForceConnectEnabled = (cmdVersionRcv.mFlags & static_cast<uint8_t>(CmdVersion::eFlags::ConnectExclusive)) == 0;
Expand All @@ -423,12 +420,14 @@ bool Communications_Initialize(ClientInfo& client)
}

// Disconnect pending socket if init failed
Network::SocketInfo* SocketPending = client.mpSocketPending.exchange(nullptr);
Network::SocketInfo* SocketPending = client.mpSocketPending.exchange(nullptr);
bool bValidConnection = SocketPending == nullptr;
if( SocketPending ){
NetImgui::Internal::Network::Disconnect(SocketPending);
return false;
}
return true;

client.mbComInitActive = false;
return bValidConnection;
}

//=================================================================================================
Expand Down Expand Up @@ -604,17 +603,17 @@ void ClientInfo::ContextOverride()
}
#endif
#if IMGUI_VERSION_NUM < 19110
newIO.GetClipboardTextFn = GetClipboardTextFn_NetImguiImpl;
newIO.SetClipboardTextFn = SetClipboardTextFn_NetImguiImpl;
newIO.ClipboardUserData = this;
newIO.GetClipboardTextFn = GetClipboardTextFn_NetImguiImpl;
newIO.SetClipboardTextFn = SetClipboardTextFn_NetImguiImpl;
newIO.ClipboardUserData = this;
#else
ImGuiPlatformIO& platformIO = ImGui::GetPlatformIO();
platformIO.Platform_GetClipboardTextFn = GetClipboardTextFn_NetImguiImpl;
platformIO.Platform_SetClipboardTextFn = SetClipboardTextFn_NetImguiImpl;
platformIO.Platform_ClipboardUserData = this;
#endif
#if defined(IMGUI_HAS_VIEWPORT)
newIO.ConfigFlags &= ~(ImGuiConfigFlags_ViewportsEnable); // Viewport unsupported at the moment
newIO.ConfigFlags &= ~(ImGuiConfigFlags_ViewportsEnable); // Viewport unsupported at the moment
#endif
}
}
Expand Down
1 change: 1 addition & 0 deletions Code/Client/Private/NetImgui_Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ struct ClientInfo

bool mbClientThreadActive = false; // True when connected and communicating with Server
bool mbListenThreadActive = false; // True when listening from connection request from Server
bool mbComInitActive = false; // True when attempting to initialize a new connection
bool mbHasTextureUpdate = false;
bool mbIsDrawing = false; // We are inside a 'NetImgui::NewFrame' / 'NetImgui::EndFrame' (even if not for a remote draw)
bool mbIsRemoteDrawing = false; // True if the rendering it meant for the remote netImgui server
Expand Down
2 changes: 1 addition & 1 deletion Code/Client/Private/NetImgui_Client.inl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ bool ClientInfo::IsConnected()const

bool ClientInfo::IsConnectPending()const
{
return mpSocketPending.load() != nullptr || mpSocketListen.load() != nullptr;
return mbComInitActive || mpSocketPending.load() != nullptr || mpSocketListen.load() != nullptr;
}

bool ClientInfo::IsActive()const
Expand Down
3 changes: 0 additions & 3 deletions Code/Client/Private/NetImgui_NetworkPosix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@
// -Sockets set to non blocking and immediate sending
// -Added 'DataReceivePending' function
// -Reworked 'DataReceive' and 'DataSend' to be non blocking socket operation
// but wait until all data has been processed
// -Connect now handle timeout instead of letting the socket timeout internally
// after a long time
static_assert(0)

namespace NetImgui { namespace Internal { namespace Network
Expand Down
4 changes: 2 additions & 2 deletions Code/Client/Private/NetImgui_NetworkUE4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ void DataReceive(SocketInfo* pClientSocket, NetImgui::Internal::PendingCom& Pend
else
{
const ESocketErrors SocketError = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->GetLastErrorCode();
if( SocketError != ESocketErrors::SE_EWOULDBLOCK ){
if( (SocketError != ESocketErrors::SE_EWOULDBLOCK) || (pClientSocket->mpSocket->GetConnectionState() != ESocketConnectionState::SCS_Connected) ){
PendingComRcv.bError = true;
}
}
Expand Down Expand Up @@ -217,7 +217,7 @@ void DataSend(SocketInfo* pClientSocket, NetImgui::Internal::PendingCom& Pending
else
{
const ESocketErrors SocketError = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->GetLastErrorCode();
if( SocketError != ESocketErrors::SE_EWOULDBLOCK )
if( (SocketError != ESocketErrors::SE_EWOULDBLOCK) || (pClientSocket->mpSocket->GetConnectionState() != ESocketConnectionState::SCS_Connected))
{
PendingComSend.bError = true;
}
Expand Down
36 changes: 26 additions & 10 deletions Code/Client/Private/NetImgui_NetworkWin32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ struct SocketInfo
constexpr DWORD kComsNoDelay = 1;
setsockopt(mSocket, SOL_SOCKET, TCP_NODELAY, reinterpret_cast<const char*>(&kComsNoDelay), sizeof(kComsNoDelay));

//constexpr int kComsSendBuffer = 1014*1024;
//setsockopt(mSocket, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char*>(&kComsSendBuffer), sizeof(kComsSendBuffer));
const int kComsSendBuffer = 2*mSendSizeMax;
setsockopt(mSocket, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char*>(&kComsSendBuffer), sizeof(kComsSendBuffer));

//constexpr int kComsRcvBuffer = 1014*1024;
//setsockopt(mSocket, SOL_SOCKET, SO_RCVBUF, reinterpret_cast<const char*>(&kComsRcvBuffer), sizeof(kComsRcvBuffer));
}

SOCKET mSocket;
int mSendSizeMax = 1024*1024; // Limit tx data to avoid socket error on large amount (texture)
};

bool Startup()
Expand Down Expand Up @@ -83,7 +84,7 @@ SocketInfo* Connect(const char* ServerHost, uint32_t ServerPort)
FD_ZERO(&SocketSet);
FD_SET(ClientSocket, &SocketSet);
Result = select(0, nullptr, &SocketSet, nullptr, &kConnectTimeout);
Connected = Result != SOCKET_ERROR;
Connected = Result == 1; // when 1 socket ready for write, otherwise it's -1 or 0
}

if( Connected )
Expand Down Expand Up @@ -166,10 +167,21 @@ void Disconnect(SocketInfo* pClientSocket)
//=================================================================================================
bool DataReceivePending(SocketInfo* pClientSocket)
{
char Unused[4];
int resultRcv = recv(pClientSocket->mSocket, Unused, 1, MSG_PEEK);
// Note: return true on a connection error, to exit code looping on the data wait
return !pClientSocket || resultRcv > 0 || (resultRcv == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK);
const timeval kConnectTimeout = {0, 0}; // No wait time
if( pClientSocket )
{
fd_set fdSetRead;
fd_set fdSetErr;
FD_ZERO(&fdSetRead);
FD_ZERO(&fdSetErr);
FD_SET(pClientSocket->mSocket, &fdSetRead);
FD_SET(pClientSocket->mSocket, &fdSetErr);

// Note: return true if data ready or connection error (to exit parent loop waiting on data)
int result = select(0, &fdSetRead, nullptr, &fdSetErr, &kConnectTimeout);
return result != 0;
}
return true;
}

//=================================================================================================
Expand All @@ -188,7 +200,9 @@ void DataReceive(SocketInfo* pClientSocket, NetImgui::Internal::PendingCom& Pend
static_cast<int>(PendingComRcv.pCommand->mSize-PendingComRcv.SizeCurrent),
0);

if( resultRcv != SOCKET_ERROR ){
// Note: 'DataReceive' is called after pending data has been confirm.
// 0 received data means connection lost
if( resultRcv != SOCKET_ERROR && resultRcv > 0 ){
PendingComRcv.SizeCurrent += static_cast<size_t>(resultRcv);
}
// Connection error, abort transmission
Expand All @@ -208,9 +222,11 @@ void DataSend(SocketInfo* pClientSocket, NetImgui::Internal::PendingCom& Pending
}

// Send data to remote connection
int resultSent = send( pClientSocket->mSocket,
int sizeToSend = static_cast<int>(PendingComSend.pCommand->mSize-PendingComSend.SizeCurrent);
sizeToSend = sizeToSend > pClientSocket->mSendSizeMax ? pClientSocket->mSendSizeMax : sizeToSend;
int resultSent = send( pClientSocket->mSocket,
&reinterpret_cast<char*>(PendingComSend.pCommand)[PendingComSend.SizeCurrent],
static_cast<int>(PendingComSend.pCommand->mSize-PendingComSend.SizeCurrent),
sizeToSend,
0);

if( resultSent != SOCKET_ERROR ){
Expand Down
4 changes: 2 additions & 2 deletions Code/ServerApp/Source/NetImguiServer_Network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ void Communications_ClientExchangeLoop(RemoteClient::Client* pClient)
NetImguiServer::Config::Client::SetProperty_Status(pClient->mClientConfigID, NetImguiServer::Config::Client::eStatus::Disconnected);
NetImgui::Internal::Network::Disconnect(pClient->mpSocket);
pClient->Release();
pClient->mbIsConnected = false;
gActiveClientThreadCount--;
}

Expand Down Expand Up @@ -376,8 +375,9 @@ void NetworkConnectRequest_Receive()
NetImguiServer::App::HAL_GetSocketInfo(pClientSocket, newClient.mConnectHost, sizeof(newClient.mConnectHost), newClient.mConnectPort);
NetworkConnectionNew(pClientSocket, &newClient, false);
}
else
else{
NetImgui::Internal::Network::Disconnect(pClientSocket);
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(16));
Expand Down
2 changes: 1 addition & 1 deletion Code/ServerApp/Source/NetImguiServer_RemoteClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ struct Client
bool mbIsVisible = false; //!< If currently shown
bool mbIsActive = false; //!< Is the current active window (will receive input, only one is true at a time)
bool mbIsReleased = false; //!< If released in com thread and main thread should delete resources
bool mbIsConnected = false; //!< If connected to a remote client
bool mbIsConnected = false; //!< If connected to a remote client. Set to false in Unitialize, after mIsRelease is set to unload resources
std::atomic_bool mbIsFree; //!< If available to use for a new connected client
std::atomic_bool mbCompressionSkipOncePending; //!< When we detect invalid previous DrawFrame command, cancel compression for 1 frame, to get good data
std::atomic_bool mbDisconnectPending; //!< Terminate Client/Server coms
Expand Down

0 comments on commit 1548168

Please sign in to comment.