network digital outputs: check config option when game starts

Avoid the need to restart when enabling or disabling this option
Send game name to newly connected sockets
ignore SIGPIPE (telnet)
Log network errors
This commit is contained in:
Flyinghead 2025-02-04 17:46:02 +01:00
parent bf1d4a56ae
commit b9df7d3469
4 changed files with 30 additions and 13 deletions

View File

@ -201,8 +201,6 @@ static void Naomi_DmaEnable(u32 addr, u32 data)
void naomi_reg_Init()
{
networkOutput.init();
static const u8 romSerialData[0x84] = {
0x19, 0x00, 0xaa, 0x55,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

View File

@ -87,6 +87,9 @@ void os_InstallFaultHandler()
#ifndef __SWITCH__
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, nullptr);
act.sa_sigaction = fault_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;

View File

@ -55,7 +55,7 @@ typedef int sock_t;
#define L_EINPROGRESS EINPROGRESS
#define get_last_error() (errno)
#define INVALID_SOCKET (-1)
#define perror(s) do { INFO_LOG(NETWORK, "%s: %s", (s) != NULL ? (s) : "", strerror(get_last_error())); } while (false)
#define perror(s) do { ERROR_LOG(NETWORK, "%s: %s", (s) != NULL ? (s) : "", strerror(get_last_error())); } while (false)
#else
typedef SOCKET sock_t;
#define VALID(s) ((s) != INVALID_SOCKET)
@ -63,7 +63,7 @@ typedef SOCKET sock_t;
#define L_EAGAIN WSAEWOULDBLOCK
#define L_EINPROGRESS WSAEINPROGRESS
#define get_last_error() (WSAGetLastError())
#define perror(s) do { INFO_LOG(NETWORK, "%s: Winsock error: %d", (s) != NULL ? (s) : "", WSAGetLastError()); } while (false)
#define perror(s) do { ERROR_LOG(NETWORK, "%s: Winsock error: %d", (s) != NULL ? (s) : "", WSAGetLastError()); } while (false)
#ifndef SHUT_WR
#define SHUT_WR SD_SEND
#endif

View File

@ -27,10 +27,14 @@
class NetworkOutput
{
public:
void init()
{
if (!config::NetworkOutput || settings.naomi.slave || settings.naomi.drivingSimSlave == 1)
if (!config::NetworkOutput || settings.naomi.slave || settings.naomi.drivingSimSlave == 1) {
term();
return;
}
if (server != INVALID_SOCKET)
// already done
return;
server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
@ -44,13 +48,13 @@ public:
saddr.sin_port = htons(8000 + settings.naomi.drivingSimSlave);
if (::bind(server, (sockaddr *)&saddr, saddr_len) < 0)
{
perror("bind");
perror("Network output: bind failed");
term();
return;
}
if (listen(server, 5) < 0)
{
perror("listen");
perror("Network output: listen failed");
term();
return;
}
@ -58,27 +62,27 @@ public:
EventManager::listen(Event::VBlank, vblankCallback, this);
}
public:
void term()
{
EventManager::unlisten(Event::VBlank, vblankCallback, this);
for (sock_t sock : clients)
closesocket(sock);
clients.clear();
if (server != INVALID_SOCKET)
{
if (server != INVALID_SOCKET) {
closesocket(server);
server = INVALID_SOCKET;
}
}
void reset()
{
void reset() {
init();
gameNameSent = false;
}
void output(const char *name, u32 value)
{
if (!config::NetworkOutput || clients.empty())
if (clients.empty())
return;
if (!gameNameSent)
{
@ -104,6 +108,18 @@ private:
if (sockfd != INVALID_SOCKET)
{
set_non_blocking(sockfd);
if (gameNameSent)
{
std::string msg = "game = " + settings.content.gameId + "\n";
if (::send(sockfd, msg.c_str(), msg.length(), 0) < 0)
{
int error = get_last_error();
if (error != L_EWOULDBLOCK && error != L_EAGAIN) {
closesocket(sockfd);
return;
}
}
}
clients.push_back(sockfd);
}
}