33#include " V2Server.hpp"
44
55#include < afunix.h>
6+ #include < expected>
67#include < shlobj.h>
78#include < wil/filesystem.h>
89#include < wil/result.h>
1314#include < fstream>
1415#include < functional>
1516#include < iostream>
17+ #include < print>
18+ #include < variant>
1619
1720#include < OTDIPC/DebugMessage.hpp>
1821#include < OTDIPC/Ping.hpp>
@@ -37,6 +40,33 @@ void InitHeader(T& msg, uint32_t tabletId, std::size_t size = sizeof(T)) {
3740 msg.size = static_cast <uint32_t >(size);
3841 msg.nonPersistentTabletId = tabletId;
3942}
43+
44+ struct socket_closed_t {};
45+ struct wsa_error_t { int value {}; };
46+ inline constexpr socket_closed_t socket_closed;
47+
48+ std::expected<void , std::variant<socket_closed_t , wsa_error_t >>
49+ ReadNBytes (SOCKET socket, void * const buffer, const std::size_t count) {
50+ auto p = buffer;
51+ auto toRead = count;
52+ while (toRead > 0 ) {
53+ const int result
54+ = recv (socket, static_cast <char *>(p), static_cast <int >(toRead), 0 );
55+ if (result == 0 ) {
56+ return std::unexpected {socket_closed};
57+ }
58+ if (result == SOCKET_ERROR) {
59+ const auto error = WSAGetLastError ();
60+ if (error == WSAECONNRESET) {
61+ return std::unexpected {socket_closed};
62+ }
63+ return std::unexpected {wsa_error_t { error }};
64+ }
65+ toRead -= result;
66+ }
67+ return {};
68+ }
69+
4070}// namespace
4171
4272V2Server::V2Server (Config config, const DefaultBehavior defaultBehavior)
@@ -164,15 +194,53 @@ void V2Server::AcceptOnce(const std::stop_token st) {
164194 // send anything, so any read > 0 is weird (protocol violation), and read == 0
165195 // means disconnect.
166196
167- char buffer[1 ];
197+ std::vector<std::byte> buffer;
198+ buffer.resize (1024 );
168199 while (!st.stop_requested ()) {
169- int result = recv (mClientSocket .get (), buffer, 1 , 0 );
170- if (result <= 0 ) {
171- // 0 = Graceful disconnect, -1 = Error
172- break ;
200+ struct ReadErrorVisitor {
201+ static void operator ()(socket_closed_t ) {
202+ std::println (" Client has disconnected" );
203+ }
204+ static void operator ()(const wsa_error_t error) {
205+ std::println (
206+ stderr,
207+ " Reading from client failed with {:#010x}" ,
208+ static_cast <uint32_t >(HRESULT_FROM_WIN32 (error.value )));
209+ }
210+ };
211+
212+ auto it = buffer.data ();
213+ auto header = reinterpret_cast <OTDIPC::Messages::Header*>(buffer.data ());
214+ if (const auto ok = ReadNBytes (mClientSocket .get (), it, sizeof (*header));
215+ !ok) {
216+ std::visit (ReadErrorVisitor {}, ok.error ());
217+ return ;
218+ }
219+
220+ if (header->size > buffer.size ()) {
221+ buffer.resize (header->size );
222+ header = reinterpret_cast <OTDIPC::Messages::Header*>(buffer.data ());
223+ it = buffer.data ();
224+ }
225+ it += sizeof (*header);
226+
227+ if (const auto ok
228+ = ReadNBytes (mClientSocket .get (), it, header->size - sizeof (*header));
229+ !ok) {
230+ std::visit (ReadErrorVisitor {}, ok.error ());
231+ return ;
232+ }
233+
234+ if (header->messageType == OTDIPC::Messages::DebugMessage::MESSAGE_TYPE) {
235+ std::println (
236+ " Client message: {}" ,
237+ reinterpret_cast <OTDIPC::Messages::DebugMessage*>(header)->message ());
238+ } else {
239+ std::println (
240+ stderr,
241+ " Received unexpected client message type {}" ,
242+ std::to_underlying (header->messageType ));
173243 }
174- // If client sends data, we ignore it per protocol, but keep reading to
175- // detect disconnect.
176244 }
177245 mClientSocket .reset ();
178246}
@@ -255,7 +323,9 @@ void V2Server::SendDebugMessage(std::string_view message) {
255323
256324 std::vector<char > buffer (totalSize);
257325 InitHeader (
258- *reinterpret_cast <OTDIPC::Messages::DebugMessage*>(buffer.data ()), 0 , totalSize);
326+ *reinterpret_cast <OTDIPC::Messages::DebugMessage*>(buffer.data ()),
327+ 0 ,
328+ totalSize);
259329
260330 // Copy string data immediately after header
261331 std::memcpy (
0 commit comments