mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 10:19:47 -04:00
Apply TCP debug policy on every game session
Start a newly selected production listener on offline rematch, reuse an existing listener, and cleanly release its transport state when disabled. Balance Winsock ownership and failed starts. Native production runtime and four focused tests pass, including six isolated real listener/bulk-write launch cases. Tracking: beads-eio.3.385.
This commit is contained in:
@@ -23,6 +23,10 @@ psxrecomp_add_runtime_target(psx-runtime
|
||||
# (docs/ENHANCEMENTS.md G1.10). Titles get their <exe>_pgxp the same way.
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_executable(debug_server_policy_test tests/test_debug_server_policy.c src/debug_server_policy.c)
|
||||
target_include_directories(debug_server_policy_test PRIVATE include)
|
||||
target_compile_definitions(debug_server_policy_test PRIVATE PSX_NO_DEBUG_TOOLS=1)
|
||||
add_test(NAME debug_server_policy_test COMMAND debug_server_policy_test)
|
||||
add_executable(debug_bulk_write_test tests/test_debug_bulk_write.c src/debug_bulk_write.c)
|
||||
target_include_directories(debug_bulk_write_test PRIVATE include)
|
||||
add_test(NAME debug_bulk_write_test COMMAND debug_bulk_write_test)
|
||||
|
||||
@@ -89,6 +89,9 @@ void debug_server_init(int port);
|
||||
* Reset the mod request before activating each new session's plugins. */
|
||||
void debug_server_request(int enabled);
|
||||
int debug_server_requested(void);
|
||||
/* Reconcile listener policy after every session's mod activation. Keeps an
|
||||
* enabled listener, starts a newly enabled one, and closes a disabled one. */
|
||||
void debug_server_apply_request(int port);
|
||||
|
||||
/* Current listener status for heartbeat diagnostics. error is the platform
|
||||
* socket error captured by init, or 0 when the listener is active. */
|
||||
|
||||
@@ -475,6 +475,7 @@ set(PSXRECOMP_RUNTIME_SOURCES
|
||||
${PSXRECOMP_ROOT}/runtime/src/mod_builtin_speed.c
|
||||
${PSXRECOMP_ROOT}/runtime/src/mod_builtin_debug.c
|
||||
${PSXRECOMP_ROOT}/runtime/src/debug_bulk_write.c
|
||||
${PSXRECOMP_ROOT}/runtime/src/debug_server_policy.c
|
||||
${PSXRECOMP_ROOT}/runtime/src/mod_builtin_pgxp.c
|
||||
${PSXRECOMP_ROOT}/runtime/src/mod_builtin_bezel.c
|
||||
${PSXRECOMP_ROOT}/runtime/src/mod_builtin_ram.c
|
||||
|
||||
+20
-19
@@ -127,24 +127,9 @@ static sock_t s_listen = SOCK_INVALID;
|
||||
static sock_t s_client = SOCK_INVALID;
|
||||
static int s_port = DEFAULT_DEBUG_PORT;
|
||||
static int s_listen_err = 0; /* platform socket error captured by init */
|
||||
static int s_requested = 0;
|
||||
|
||||
void debug_server_request(int enabled)
|
||||
{
|
||||
s_requested = enabled != 0;
|
||||
}
|
||||
|
||||
int debug_server_requested(void)
|
||||
{
|
||||
const char *env = getenv("PSX_DEBUG_SERVER");
|
||||
if (env && strcmp(env, "0") == 0) return 0;
|
||||
if (env && strcmp(env, "1") == 0) return 1;
|
||||
#ifdef PSX_NO_DEBUG_TOOLS
|
||||
return s_requested;
|
||||
#else
|
||||
return 1;
|
||||
#ifdef _WIN32
|
||||
static int s_wsa_started;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define RECV_BUF_SIZE 8192
|
||||
static PSX_BSS char s_recv_buf[RECV_BUF_SIZE];
|
||||
@@ -16121,6 +16106,7 @@ malformed:
|
||||
|
||||
void debug_server_init(int port)
|
||||
{
|
||||
if (s_listen != SOCK_INVALID) return;
|
||||
if (port > 0) s_port = port;
|
||||
|
||||
/* Deterministic cold-boot controller probe. Unlike a TCP set_input command,
|
||||
@@ -16218,13 +16204,16 @@ void debug_server_init(int port)
|
||||
|
||||
#ifdef _WIN32
|
||||
WSADATA wsa;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsa);
|
||||
s_listen_err = WSAStartup(MAKEWORD(2, 2), &wsa);
|
||||
if (s_listen_err) return;
|
||||
s_wsa_started = 1;
|
||||
#endif
|
||||
|
||||
s_listen = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s_listen == SOCK_INVALID) {
|
||||
s_listen_err = sock_error();
|
||||
fprintf(stdout, "psxrecomp: debug server socket() FAILED\n");
|
||||
debug_server_shutdown();
|
||||
return;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
@@ -16248,6 +16237,7 @@ void debug_server_init(int port)
|
||||
fprintf(stdout, "psxrecomp: debug server bind(%d) FAILED\n", s_port);
|
||||
sock_close(s_listen);
|
||||
s_listen = SOCK_INVALID;
|
||||
debug_server_shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -16276,6 +16266,10 @@ void debug_server_init(int port)
|
||||
s_io_thread = SDL_CreateThread(io_thread_main, "psx-dbg-io", NULL);
|
||||
if (!s_io_thread) s_io_running = 0;
|
||||
}
|
||||
if (!s_io_thread) {
|
||||
debug_server_shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s_frame_history) {
|
||||
s_frame_history = (PSXFrameRecord *)calloc(FRAME_HISTORY_CAP, sizeof(PSXFrameRecord));
|
||||
@@ -16859,8 +16853,15 @@ void debug_server_shutdown(void)
|
||||
sock_close(s_client);
|
||||
s_client = SOCK_INVALID;
|
||||
}
|
||||
if (s_io_mutex) { SDL_DestroyMutex(s_io_mutex); s_io_mutex = NULL; }
|
||||
if (s_io_req_cv) { SDL_DestroyCond(s_io_req_cv); s_io_req_cv = NULL; }
|
||||
if (s_io_resp_cv) { SDL_DestroyCond(s_io_resp_cv); s_io_resp_cv = NULL; }
|
||||
free(s_resp_buf);
|
||||
s_resp_buf = NULL;
|
||||
s_resp_cap = s_resp_len = 0;
|
||||
s_io_state = IO_IDLE;
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
if (s_wsa_started) { WSACleanup(); s_wsa_started = 0; }
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "debug_server.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static int requested;
|
||||
|
||||
void debug_server_request(int enabled) { requested = enabled != 0; }
|
||||
|
||||
int debug_server_requested(void)
|
||||
{
|
||||
const char *env = getenv("PSX_DEBUG_SERVER");
|
||||
if (env && strcmp(env, "0") == 0) return 0;
|
||||
if (env && strcmp(env, "1") == 0) return 1;
|
||||
#ifdef PSX_NO_DEBUG_TOOLS
|
||||
return requested;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void debug_server_apply_request(int port)
|
||||
{
|
||||
int listening = 0;
|
||||
debug_server_get_status(&listening, NULL, NULL);
|
||||
if (debug_server_requested()) {
|
||||
if (!listening) debug_server_init(port);
|
||||
} else if (listening) {
|
||||
debug_server_shutdown();
|
||||
}
|
||||
}
|
||||
@@ -18844,13 +18844,13 @@ session_reboot:
|
||||
};
|
||||
memcard_init_slots(memcard_dir_str.c_str(), slots);
|
||||
}
|
||||
debug_server_apply_request(debug_port);
|
||||
if (!rematch_session) {
|
||||
std::atexit(memcard_flush_all);
|
||||
/* Persist the game's native OPTION settings on any exit path (belt-and-
|
||||
* suspenders; save-on-change already persists them live). No-op if not yet
|
||||
* armed, so it can't overwrite the saved file with boot defaults. */
|
||||
std::atexit(game_options_save_now);
|
||||
if (debug_server_requested()) debug_server_init(debug_port);
|
||||
#ifndef PSX_NO_DEBUG_TOOLS
|
||||
host_sampler_start(); /* this is the emulation thread */
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "debug_server.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int listening, starts, stops, last_port, failures;
|
||||
void debug_server_get_status(int *active, int *port, int *error) {
|
||||
if (active) *active=listening;
|
||||
if (port) *port=last_port;
|
||||
if (error) *error=0;
|
||||
}
|
||||
void debug_server_init(int port) { ++starts;listening=1;last_port=port; }
|
||||
void debug_server_shutdown(void) { ++stops;listening=0; }
|
||||
#define CHECK(x) do { if (!(x)) { fprintf(stderr,"line %d: %s\n",__LINE__,#x);++failures; } } while(0)
|
||||
static void env_choice(const char *value) {
|
||||
#ifdef _WIN32
|
||||
_putenv_s("PSX_DEBUG_SERVER",value?value:"");
|
||||
#else
|
||||
if(value)setenv("PSX_DEBUG_SERVER",value,1);else unsetenv("PSX_DEBUG_SERVER");
|
||||
#endif
|
||||
}
|
||||
int main(void) {
|
||||
env_choice(NULL);
|
||||
debug_server_request(0);debug_server_apply_request(4370);
|
||||
CHECK(!listening && starts==0 && stops==0);
|
||||
/* First session was vanilla netplay; the next offline session selects it. */
|
||||
debug_server_request(1);debug_server_apply_request(4370);
|
||||
CHECK(listening && starts==1 && last_port==4370);
|
||||
debug_server_apply_request(4370);
|
||||
CHECK(listening && starts==1 && stops==0);
|
||||
debug_server_request(0);debug_server_apply_request(4370);
|
||||
CHECK(!listening && stops==1);
|
||||
debug_server_apply_request(4370);CHECK(stops==1);
|
||||
debug_server_request(1);env_choice("0");debug_server_apply_request(4370);
|
||||
CHECK(!listening && starts==1);
|
||||
debug_server_request(0);env_choice("1");debug_server_apply_request(4488);
|
||||
CHECK(listening && starts==2 && last_port==4488);
|
||||
env_choice(NULL);debug_server_apply_request(4488);
|
||||
CHECK(!listening && stops==2);
|
||||
if(!failures)puts("PASS debug server session policy: late enable, reuse, disable, overrides");
|
||||
return failures?1:0;
|
||||
}
|
||||
Reference in New Issue
Block a user