Skip to content

Commit

Permalink
v0.6.0, solved client disconnect edge cases in dmdserver
Browse files Browse the repository at this point in the history
  • Loading branch information
mkalkbrenner committed Apr 5, 2024
1 parent ce648da commit 57efef3
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 12 deletions.
1 change: 1 addition & 0 deletions include/DMDUtil/DMD.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ class DMDUTILAPI DMD
std::vector<RGB24DMD*> m_rgb24DMDs;
std::vector<ConsoleDMD*> m_consoleDMDs;
sockpp::tcp_connector* m_pDMDServerConnector;
bool m_dmdServerDisconnectOthers = false;

std::thread* m_pLevelDMDThread;
std::thread* m_pRGB24DMDThread;
Expand Down
2 changes: 1 addition & 1 deletion include/DMDUtil/DMDUtil.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#define DMDUTIL_VERSION_MAJOR 0 // X Digits
#define DMDUTIL_VERSION_MINOR 5 // Max 2 Digits
#define DMDUTIL_VERSION_MINOR 6 // Max 2 Digits
#define DMDUTIL_VERSION_PATCH 0 // Max 2 Digits

#define _DMDUTIL_STR(x) #x
Expand Down
6 changes: 6 additions & 0 deletions src/DMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,13 +333,16 @@ void DMD::QueueUpdate(Update dmdUpdate, bool buffered)
{
StreamHeader streamHeader;
streamHeader.buffered = (uint8_t)buffered;
streamHeader.disconnectOthers = (uint8_t)m_dmdServerDisconnectOthers;
m_pDMDServerConnector->write_n(&streamHeader, sizeof(StreamHeader));
PathsHeader pathsHeader;
strcpy(pathsHeader.name, m_romName);
strcpy(pathsHeader.altColorPath, m_altColorPath);
strcpy(pathsHeader.pupVideosPath, m_pupVideosPath);
m_pDMDServerConnector->write_n(&pathsHeader, sizeof(PathsHeader));
m_pDMDServerConnector->write_n(&dmdUpdate, sizeof(Update));

if (streamHeader.disconnectOthers != 0) m_dmdServerDisconnectOthers = false;
}
})
.detach();
Expand Down Expand Up @@ -527,6 +530,9 @@ void DMD::DmdFrameThread()
{
strcpy(name, m_romName);

// In case of a new ROM, try to disconnect the other clients.
if (m_pDMDServerConnector) m_dmdServerDisconnectOthers = true;

if (Config::GetInstance()->IsAltColor())
{
m_serumMutex.lock();
Expand Down
38 changes: 27 additions & 11 deletions src/dmdServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ using namespace std;
DMDUtil::DMD* pDmd;
uint32_t currentThreadId = 0;
mutex threadMutex;
bool disconnectOtherClients = false;
uint32_t disconnectOtherClients = 0;
vector<uint32_t> threads;
bool opt_verbose = false;
bool opt_fixedAltColorPath = false;
Expand Down Expand Up @@ -87,7 +87,7 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)

if (opt_verbose) DMDUtil::Log("%d: New DMD client %d connected", threadId, threadId);

while (threadId == currentThreadId || !disconnectOtherClients)
while (threadId == currentThreadId || disconnectOtherClients == 0 || disconnectOtherClients <= threadId)
{
n = sock.read_n(buffer, sizeof(DMDUtil::DMD::StreamHeader));
// If the client disconnects or if a network error ocurres, exit the loop and terminate this thread.
Expand All @@ -104,14 +104,15 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
{
DMDUtil::Log("%d: Received DMDStream header version %d for DMD mode %d", threadId, pStreamHeader->version,
pStreamHeader->mode);
if (pStreamHeader->buffered) DMDUtil::Log("%d: Next data will be buffered", threadId);
if (pStreamHeader->buffered && threadId == currentThreadId)
DMDUtil::Log("%d: Next data will be buffered", threadId);
}

// Only the current (most recent) thread is allowed to disconnect other clients.
if (handleDisconnectOthers && threadId == currentThreadId && pStreamHeader->disconnectOthers)
{
threadMutex.lock();
disconnectOtherClients = true;
disconnectOtherClients = threadId;
threadMutex.unlock();
handleDisconnectOthers = false;
if (opt_verbose) DMDUtil::Log("%d: Other clients will be disconnected", threadId);
Expand All @@ -120,8 +121,7 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
switch (pStreamHeader->mode)
{
case DMDUtil::DMD::Mode::Data:
if ((n = sock.read_n(buffer, sizeof(DMDUtil::DMD::PathsHeader))) == sizeof(DMDUtil::DMD::PathsHeader) &&
threadId == currentThreadId)
if ((n = sock.read_n(buffer, sizeof(DMDUtil::DMD::PathsHeader))) == sizeof(DMDUtil::DMD::PathsHeader))
{
DMDUtil::DMD::PathsHeader pathsHeader;
memcpy(&pathsHeader, buffer, n);
Expand All @@ -131,7 +131,7 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
threadId == currentThreadId)
{
if (opt_verbose)
DMDUtil::Log("%d: Received AltColor header: ROM '%s', AltColorPath '%s', PupPath '%s'", threadId,
DMDUtil::Log("%d: Received paths header: ROM '%s', AltColorPath '%s', PupPath '%s'", threadId,
pathsHeader.name, pathsHeader.altColorPath, pathsHeader.pupVideosPath);
DMDUtil::DMD::Update data;
memcpy(&data, buffer, n);
Expand All @@ -149,9 +149,13 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
DMDUtil::Log("%d: TCP data package is missing or corrupted!", threadId);
}
}
else if (threadId != currentThreadId)
{
DMDUtil::Log("%d: Client %d blocks the DMD", threadId, currentThreadId);
}
else
{
DMDUtil::Log("%d: AltColor header is missing!", threadId);
DMDUtil::Log("%d: Paths header is missing!", threadId);
}
}
break;
Expand All @@ -167,6 +171,10 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
pDmd->UpdateRGB16Data((uint16_t*)buffer, pStreamHeader->width, pStreamHeader->height,
pStreamHeader->buffered == 1);
}
else if (threadId != currentThreadId)
{
DMDUtil::Log("%d: Client %d blocks the DMD", threadId, currentThreadId);
}
else
{
DMDUtil::Log("%d: TCP data package is missing or corrupted!", threadId);
Expand All @@ -180,6 +188,10 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
{
pDmd->UpdateRGB24Data(buffer, pStreamHeader->width, pStreamHeader->height, pStreamHeader->buffered == 1);
}
else if (threadId != currentThreadId)
{
DMDUtil::Log("%d: Client %d blocks the DMD", threadId, currentThreadId);
}
else
{
DMDUtil::Log("%d: TCP data package is missing or corrupted!", threadId);
Expand All @@ -198,6 +210,9 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
}
}

if (opt_verbose && disconnectOtherClients != 0 && disconnectOtherClients > threadId)
DMDUtil::Log("%d: Client %d requested disconnect", threadId, disconnectOtherClients);

// Display a buffered frame or clear the display on disconnect of the current thread.
if (threadId == currentThreadId && !pStreamHeader->buffered && !pDmd->QueueBuffer())
{
Expand All @@ -212,7 +227,7 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
threads.erase(remove(threads.begin(), threads.end(), threadId), threads.end());
if (threadId == currentThreadId)
{
if (disconnectOtherClients)
if (disconnectOtherClients == threadId)
{
// Wait until all other threads ended or a new client connnects in between.
while (threads.size() >= 1 && currentThreadId == threadId)
Expand All @@ -224,14 +239,14 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
}

currentThreadId = 0;
disconnectOtherClients = false;
disconnectOtherClients = 0;
}
else
{
currentThreadId = (threads.size() >= 1) ? threads.back() : 0;
}

if (opt_verbose) DMDUtil::Log("%d: DMD client %d set as current", currentThreadId, currentThreadId);
if (opt_verbose) DMDUtil::Log("%d: DMD client %d set as current", threadId, currentThreadId);
}
threadMutex.unlock();

Expand Down Expand Up @@ -364,6 +379,7 @@ int main(int argc, char* argv[])
currentThreadId = ++threadId;
threads.push_back(currentThreadId);
threadMutex.unlock();
if (opt_verbose) DMDUtil::Log("%d: DMD client %d set as current", threadId, currentThreadId);
// Create a thread and transfer the new stream to it.
thread thr(run, std::move(sock), currentThreadId);
thr.detach();
Expand Down

0 comments on commit 57efef3

Please sign in to comment.