Skip to content

Commit b8389b3

Browse files
authored
force network byte order for dmdserver (#80)
1 parent c7530fb commit b8389b3

File tree

3 files changed

+93
-8
lines changed

3 files changed

+93
-8
lines changed

include/DMDUtil/DMD.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@
1515
#define DMDUTIL_MAX_PATH_SIZE 256
1616
#define DMDUTIL_MAX_TRANSITIONAL_FRAME_DURATION 25
1717

18+
#if defined(_WIN32) || defined(_WIN64)
19+
#include <winsock2.h> // Windows byte-order functions
20+
#else
21+
#include <arpa/inet.h> // Linux/macOS byte-order functions
22+
#endif
23+
1824
#include <atomic>
1925
#include <condition_variable>
2026
#include <cstdint>
@@ -122,6 +128,44 @@ class DMDUTILAPI DMD
122128
uint8_t b;
123129
uint16_t width;
124130
uint16_t height;
131+
132+
void convertToHostByteOrder()
133+
{
134+
// uint8_t and bool are not converted, as they are already in host byte order.
135+
mode = static_cast<Mode>(ntohl(static_cast<uint32_t>(mode)));
136+
layout = static_cast<AlphaNumericLayout>(ntohl(static_cast<uint32_t>(layout)));
137+
depth = ntohl(depth);
138+
for (size_t i = 0; i < 256 * 64; i++)
139+
{
140+
segData[i] = ntohs(segData[i]);
141+
}
142+
for (size_t i = 0; i < 128; i++)
143+
{
144+
segData2[i] = ntohs(segData2[i]);
145+
}
146+
width = ntohs(width);
147+
height = ntohs(height);
148+
}
149+
150+
Update toNetworkByteOrder() const
151+
{
152+
// uint8_t and bool are not converted, as they are already in network byte order.
153+
Update copy = *this;
154+
copy.mode = static_cast<Mode>(htonl(static_cast<uint32_t>(mode)));
155+
copy.layout = static_cast<AlphaNumericLayout>(htonl(static_cast<uint32_t>(layout)));
156+
copy.depth = htonl(depth);
157+
for (size_t i = 0; i < 256 * 64; i++)
158+
{
159+
copy.segData[i] = htons(segData[i]);
160+
}
161+
for (size_t i = 0; i < 128; i++)
162+
{
163+
copy.segData2[i] = htons(segData2[i]);
164+
}
165+
copy.width = htons(width);
166+
copy.height = htons(height);
167+
return copy;
168+
}
125169
};
126170

127171
struct StreamHeader
@@ -134,6 +178,24 @@ class DMDUTILAPI DMD
134178
uint8_t buffered = 0; // 0 => unbuffered, 1 => buffered
135179
uint8_t disconnectOthers = 0; // 0 => no, 1 => yes
136180
uint32_t length = 0;
181+
182+
void convertToHostByteOrder()
183+
{
184+
// uint8_t and char are not converted, as they are already in host byte order.
185+
mode = static_cast<Mode>(ntohl(static_cast<uint32_t>(mode)));
186+
width = ntohs(width);
187+
height = ntohs(height);
188+
length = ntohl(length);
189+
}
190+
191+
void convertToNetworkByteOrder()
192+
{
193+
// uint8_t and char are not converted, as they are already in network byte order.
194+
mode = static_cast<Mode>(htonl(static_cast<uint32_t>(mode)));
195+
width = htons(width);
196+
height = htons(height);
197+
length = htonl(length);
198+
}
137199
};
138200

139201
struct PathsHeader
@@ -142,6 +204,10 @@ class DMDUTILAPI DMD
142204
char name[DMDUTIL_MAX_NAME_SIZE] = {0};
143205
char altColorPath[DMDUTIL_MAX_PATH_SIZE] = {0};
144206
char pupVideosPath[DMDUTIL_MAX_PATH_SIZE] = {0};
207+
208+
void convertToHostByteOrder() {}
209+
210+
void convertToNetworkByteOrder() {}
145211
};
146212
#pragma pack(pop) // Reset to default packing
147213

src/DMD.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ class DMDServerConnector
5353
static DMDServerConnector* Create(const char* pAddress, int port)
5454
{
5555
sockpp::tcp_connector* pConnector = new sockpp::tcp_connector({pAddress, (in_port_t)port});
56-
return pConnector ? new DMDServerConnector(pConnector) : nullptr;
56+
if (pConnector)
57+
{
58+
return new DMDServerConnector(pConnector);
59+
}
60+
return nullptr;
5761
}
5862

5963
ssize_t Write(const void* buf, size_t size) { return m_pConnector->write_n(buf, size); }
@@ -284,7 +288,8 @@ void DMD::AddRGB24DMD(RGB24DMD* pRGB24DMD)
284288
{
285289
m_rgb24DMDs.push_back(pRGB24DMD);
286290
Log(DMDUtil_LogLevel_INFO, "Added RGB24DMD");
287-
if (!m_pRGB24DMDThread) {
291+
if (!m_pRGB24DMDThread)
292+
{
288293
m_pRGB24DMDThread = new std::thread(&DMD::RGB24DMDThread, this);
289294
Log(DMDUtil_LogLevel_INFO, "RGB24DMDThread started");
290295
}
@@ -396,13 +401,16 @@ void DMD::QueueUpdate(const std::shared_ptr<Update> dmdUpdate, bool buffered)
396401
StreamHeader streamHeader;
397402
streamHeader.buffered = (uint8_t)buffered;
398403
streamHeader.disconnectOthers = (uint8_t)m_dmdServerDisconnectOthers;
404+
streamHeader.convertToNetworkByteOrder();
399405
m_pDMDServerConnector->Write(&streamHeader, sizeof(StreamHeader));
400406
PathsHeader pathsHeader;
401407
strcpy(pathsHeader.name, m_romName);
402408
strcpy(pathsHeader.altColorPath, m_altColorPath);
403409
strcpy(pathsHeader.pupVideosPath, m_pupVideosPath);
410+
pathsHeader.convertToNetworkByteOrder();
404411
m_pDMDServerConnector->Write(&pathsHeader, sizeof(PathsHeader));
405-
m_pDMDServerConnector->Write(dmdUpdate.get(), sizeof(Update));
412+
Update dmdUpdateNetwork = dmdUpdate->toNetworkByteOrder();
413+
m_pDMDServerConnector->Write(&dmdUpdateNetwork, sizeof(Update));
406414

407415
if (streamHeader.disconnectOthers != 0) m_dmdServerDisconnectOthers = false;
408416
}

src/dmdServer.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#if defined(_WIN32) || defined(_WIN64)
2+
#include <winsock2.h> // Windows byte-order functions
3+
#else
4+
#include <arpa/inet.h> // Linux/macOS byte-order functions
5+
#endif
6+
17
#include <algorithm>
28
#include <chrono>
39
#include <iostream>
@@ -94,9 +100,8 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
94100

95101
if (n == sizeof(DMDUtil::DMD::StreamHeader))
96102
{
97-
// At the moment the server only listens on localhost.
98-
// Therefore, we don't have to take care about litte vs. big endian and can use memcpy.
99103
memcpy(pStreamHeader, buffer, n);
104+
pStreamHeader->convertToHostByteOrder();
100105
if (strcmp(pStreamHeader->header, "DMDStream") == 0 && pStreamHeader->version == 1)
101106
{
102107
if (opt_verbose)
@@ -124,6 +129,7 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
124129
{
125130
DMDUtil::DMD::PathsHeader pathsHeader;
126131
memcpy(&pathsHeader, buffer, n);
132+
pathsHeader.convertToHostByteOrder();
127133

128134
if (strcmp(pathsHeader.header, "Paths") == 0 &&
129135
(n = sock.read_n(buffer, sizeof(DMDUtil::DMD::Update))) == sizeof(DMDUtil::DMD::Update) &&
@@ -135,6 +141,7 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
135141
pathsHeader.name, pathsHeader.altColorPath, pathsHeader.pupVideosPath);
136142
auto data = std::make_shared<DMDUtil::DMD::Update>();
137143
memcpy(data.get(), buffer, n);
144+
data->convertToHostByteOrder();
138145

139146
if (data->width <= DMDSERVER_MAX_WIDTH && data->height <= DMDSERVER_MAX_HEIGHT)
140147
{
@@ -165,9 +172,13 @@ void run(sockpp::tcp_socket sock, uint32_t threadId)
165172
threadId == currentThreadId && pStreamHeader->width <= DMDSERVER_MAX_WIDTH &&
166173
pStreamHeader->height <= DMDSERVER_MAX_HEIGHT)
167174
{
168-
// At the moment the server only listens on localhost.
169-
// Therefore, we don't have to take care about litte vs. big endian and can use the buffer as uint16_t as
170-
// it is.
175+
uint16_t* pixelData = (uint16_t*)buffer;
176+
size_t pixelCount = pStreamHeader->length / sizeof(uint16_t);
177+
for (size_t i = 0; i < pixelCount; i++)
178+
{
179+
pixelData[i] = ntohs(pixelData[i]);
180+
}
181+
171182
pDmd->UpdateRGB16Data((uint16_t*)buffer, pStreamHeader->width, pStreamHeader->height,
172183
pStreamHeader->buffered == 1);
173184
}

0 commit comments

Comments
 (0)