From a4af1b70d3f88609615bd6747f5d0b15ce74b3de Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Sun, 10 Jul 2022 11:12:40 +0200 Subject: [PATCH 1/3] webserver: use SO_REUSEADDR to not be blocked by TIME_WAIT This allows the webserver to be immediately restarted when it was stopped and not having to wait for the local port to be available again while it is in TIME_WAIT state. --- tools/webserver.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/webserver.cpp b/tools/webserver.cpp index e07f262..d559066 100644 --- a/tools/webserver.cpp +++ b/tools/webserver.cpp @@ -324,6 +324,7 @@ int main(int argc, char** argv) void startServer(char *port) { struct addrinfo hints, *res, *p; + int opt; // getaddrinfo for host memset (&hints, 0, sizeof(hints)); @@ -340,6 +341,12 @@ void startServer(char *port) { listenfd = socket (p->ai_family, p->ai_socktype, 0); if (listenfd == -1) continue; + opt = 1; + if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) + { + perror ("setsockopt(SO_REUSEADDR)"); + exit(1); + } if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) break; } if (p==NULL) From 6d0853ff8ebc68971f8fe56c38b82c82d785372e Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Sun, 10 Jul 2022 11:48:38 +0200 Subject: [PATCH 2/3] webserver: fix png generation This fixes the crash when generating the screenshot on the server side and no character rom was specified on the command line by reading the character rom from the configuration instead. --- tools/webserver.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/tools/webserver.cpp b/tools/webserver.cpp index d559066..d2dd19b 100644 --- a/tools/webserver.cpp +++ b/tools/webserver.cpp @@ -438,15 +438,35 @@ void getVram(uint8_t* vram, int len, int pos) void getMonoBitmap(int width, int height, int pos) { uint8_t vram[1024]; + static uint8_t last_configByte = 0; + #ifdef TEST + uint8_t configByte = 1; + #else + uint8_t configByte = romulatorReadConfig(); + #endif unsigned int startTime = Tools::Timer::millis(); getVram(vram, 1024, pos); unsigned int readVramTime = Tools::Timer::millis(); - if (characterRom == NULL) + if (characterRom == NULL || configByte != last_configByte) { + char *charRom = characterRomName; // read character rom from file - FILE* fp = fopen(characterRomName, "rb"); + if (strlen(charRom) == 0) { + // look up the character rom for this configuration + fprintf(stderr, "got rom request, config byte %d\n", configByte); + if (characterRoms == NULL || characterRoms[configByte] == NULL) { + fprintf(stderr, "No character rom for config %d!\n", configByte); + return; + } + charRom = characterRoms[configByte]; + } + FILE* fp = fopen(charRom, "rb"); + if (fp == NULL) { + perror("Can't open character rom"); + return; + } fseek(fp, 0, SEEK_END); int size = (int)ftell(fp); fseek(fp, 0, SEEK_SET); @@ -454,15 +474,18 @@ void getMonoBitmap(int width, int height, int pos) characterRom = (uint8_t*)malloc(size); fread(characterRom, 1, size, fp); fclose(fp); + last_configByte = configByte; } romulatorVramToBitmap(vram, characterRom, 25, 40, 8, 8, bitmap); unsigned int convertBitmap = Tools::Timer::millis(); + #ifdef TEST fprintf(stderr, "mono total %d read %d convert %d\n", convertBitmap - startTime, readVramTime - startTime, convertBitmap - readVramTime); + #endif } void getRGBBitmap(int width, int height, int pos) @@ -720,7 +743,9 @@ void respond(int n, int tmp, int* cc) unsigned int sendTime = sentDataMillis - readDataMillis; unsigned int totalTime = sentDataMillis - startMillis; + #ifdef TEST fprintf(stderr, "png time %d, read %d send %d\n", totalTime, dataReadTime, sendTime); + #endif } else { From 8ac628b87bb233fa294b64062f493d13483807c3 Mon Sep 17 00:00:00 2001 From: Michael Gernoth Date: Sun, 10 Jul 2022 12:27:48 +0200 Subject: [PATCH 3/3] webserver: send last known good vram image on any read error This sends back the last known good vram image on read error to avoid flickering. Also declare any read-error as failure even though a retry is successfull, as it seems there is a problem with the retry- implementation somewhere. --- tools/libRomulatorDebug.cpp | 2 ++ tools/webserver.cpp | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/libRomulatorDebug.cpp b/tools/libRomulatorDebug.cpp index fab93cb..725f266 100644 --- a/tools/libRomulatorDebug.cpp +++ b/tools/libRomulatorDebug.cpp @@ -306,6 +306,8 @@ bool romulatorReadVram(uint8_t* vram, int size, int valid_bytes, int retries) retries++; fprintf(stderr, "error byte %d retries %d\n", byte, retries); xfer(0x22); + // FIXME: retry doesn't seem to work, fail read for now... + read_success = false; } else { diff --git a/tools/webserver.cpp b/tools/webserver.cpp index d2dd19b..d1f67e0 100644 --- a/tools/webserver.cpp +++ b/tools/webserver.cpp @@ -422,6 +422,7 @@ void convertMonoToRGBBitmap(uint8_t* monoBitmap, uint8_t* rgbBitmap, int width, void getVram(uint8_t* vram, int len, int pos) { + static uint8_t last_good_vram[1024] = { 0 }; #ifdef TEST // fill screen with characters uint8_t v = pos % 256; @@ -431,7 +432,12 @@ void getVram(uint8_t* vram, int len, int pos) } #else // get vram from romulator - romulatorReadVram(vram, len, 1001, 5); + if(romulatorReadVram(vram, len, 1001, 5)) { + memcpy(last_good_vram, vram, sizeof(last_good_vram)); + } else { + fprintf(stderr, "Using last good vram image\n"); + memcpy(vram, last_good_vram, sizeof(last_good_vram)); + } #endif }