From 51845b2d171f0abc021960d085a1675ce1b36a1a Mon Sep 17 00:00:00 2001 From: nishi Date: Wed, 5 Jun 2024 10:39:54 +0000 Subject: [PATCH] add server git-svn-id: file:///raid/svn-main/nishi-dataworks/trunk@156 d4a5a174-5a4a-5b4b-b672-37683c10d7d5 --- Platforms/win32.mk | 1 + Platforms/win64.mk | 1 + Server/Makefile | 17 +++ Server/server.c | 260 +++++++++++++++++++++++++++++++++++++++++++++ common-decl.mk | 1 + common.mk | 19 +++- 6 files changed, 296 insertions(+), 3 deletions(-) create mode 100644 Server/Makefile create mode 100644 Server/server.c diff --git a/Platforms/win32.mk b/Platforms/win32.mk index 261630d..e46aa4e 100644 --- a/Platforms/win32.mk +++ b/Platforms/win32.mk @@ -7,6 +7,7 @@ RANLIB = i686-w64-mingw32-ranlib WINDRES = i686-w64-mingw32-windres LIB_PREFIX = LIB_SUFFIX = .dll +SERVER = EXEC_SUFFIX = .exe STATICLIB_PREFIX = STATICLIB_SUFFIX = .a diff --git a/Platforms/win64.mk b/Platforms/win64.mk index 3c46063..c5db322 100644 --- a/Platforms/win64.mk +++ b/Platforms/win64.mk @@ -7,6 +7,7 @@ RANLIB = x86_64-w64-mingw32-ranlib WINDRES = x86_64-w64-mingw32-windres LIB_PREFIX = LIB_SUFFIX = .dll +SERVER = EXEC_SUFFIX = .exe STATICLIB_PREFIX = STATICLIB_SUFFIX = .a diff --git a/Server/Makefile b/Server/Makefile new file mode 100644 index 0000000..10573c3 --- /dev/null +++ b/Server/Makefile @@ -0,0 +1,17 @@ +# $Id$ + +.PHONY: all clean +.SUFFIXES: .c .o + +OBJS = server.o + +all: dataworks_server$(EXEC_SUFFIX) + +dataworks_server$(EXEC_SUFFIX): $(OBJS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(LINK_LIB) + +.c.o: + $(CC) $(CFLAGS) -I../Library -c -o $@ $< + +clean: + rm -f *.o *.so *.dll *.exe *.com dataworks_server *.a *.lib diff --git a/Server/server.c b/Server/server.c new file mode 100644 index 0000000..915daa1 --- /dev/null +++ b/Server/server.c @@ -0,0 +1,260 @@ +/* $Id$ */ +/* --- START LICENSE --- */ +/* -------------------------------------------------------------------------- */ +/* Copyright (c) 2024 Crabware. */ +/* Redistribution and use in source and binary forms, with or without modific */ +/* ation, are permitted provided that the following conditions are met: */ +/* 1. Redistributions of source code must retain the above copyright noti */ +/* ce, this list of conditions and the following disclaimer. */ +/* 2. Redistributions in binary form must reproduce the above copyright n */ +/* otice, this list of conditions and the following disclaimer in the documen */ +/* tation and/or other materials provided with the distribution. */ +/* 3. Neither the name of the copyright holder nor the names of its contr */ +/* ibutors may be used to endorse or promote products derived from this softw */ +/* are without specific prior written permission. */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS */ +/* " AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, TH */ +/* E IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPO */ +/* SE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS */ +/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CON */ +/* SEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITU */ +/* TE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPT */ +/* ION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, S */ +/* TRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN AN */ +/* Y WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY */ +/* OF SUCH DAMAGE. */ +/* -------------------------------------------------------------------------- */ +/* --- END LICENSE --- */ + +#include + +#include + +#include +#include +#include +#include + +int argc; +char** argv; + +#ifdef __DOS__ +#include + +/* Why would you run the database server on DOS, tho ... */ +#define HAYES +#else +#include +#include +#include +#include +#include +#include + +#define TCPIP +#endif + +void protocol_init(int sock); + +#ifdef HAYES +int port = -1; + +void write_serial(const char* str) { + const char* ptr = str; + while(1) { + if(_bios_serialcom(_COM_STATUS, port, 0) & 0x10) { + _bios_serialcom(_COM_SEND, port, *ptr); + ptr++; + if(*ptr == 0) break; + } + } +} + +char* modem_response(void) { + char* buf = malloc(513); + buf[0] = 0; + int count = 0; + while(1) { + if(_bios_serialcom(_COM_STATUS, port, 0) & 0x0100) { + unsigned short b = _bios_serialcom(_COM_RECEIVE, port, 0); + char ch = b & 0xff; + if(ch != '\r' && ch != '\n' && ch != 0) { + buf[count] = ch; + buf[count + 1] = 0; + count++; + } else if(ch == '\r') { + if(strlen(buf) != 0) break; + } + } + } + return buf; +} + +int server_init(void) { + printf("Using Hayes Modem\n"); + int i; + for(i = 1; i < argc; i++) { + if(__dw_strcaseequ(argv[i], "COM1")) { + port = 0; + } else if(__dw_strcaseequ(argv[i], "COM2")) { + port = 1; + } else if(__dw_strcaseequ(argv[i], "COM3")) { + port = 2; + } else if(__dw_strcaseequ(argv[i], "COM4")) { + port = 3; + } else { + fprintf(stderr, "Invalid port: %s\n", argv[i]); + return 1; + } + } + if(port == -1) { + fprintf(stderr, "Specify serial port\n"); + return 1; + } + _bios_serialcom(_COM_INIT, port, _COM_9600 | _COM_NOPARITY | _COM_CHR8 | _COM_STOP1); + write_serial("AT&FE0F1\r"); + free(modem_response()); /* Kill echo */ + char* resp = modem_response(); + if(__dw_strcaseequ(resp, "OK")) { + fprintf(stderr, "Modem initialization successful\n"); + } else { + fprintf(stderr, "Modem initialization fail\n"); + free(resp); + return 1; + } + free(resp); + return 0; +} + +void server_loop(void) { + bool connected = false; + while(1) { + char* resp = modem_response(); + if(__dw_strcaseequ(resp, "NO CARRIER")) { + free(resp); + printf("Disconnected\n"); + connected = false; + continue; + } + int i; + bool has_arg = false; + for(i = 0; resp[i] != 0; i++) { + if(resp[i] == ' ') { + resp[i] = 0; + has_arg = true; + break; + } + } + if(connected) { + } else { + if(__dw_strcaseequ(resp, "RING")) { + printf("Got a call, answering\n"); + write_serial("ATA\r"); + } else if(__dw_strcaseequ(resp, "CONNECT")) { + printf("Connection successful"); + if(has_arg) printf(", %s BPS", resp + i + 1); + printf("\n"); + printf("Entering connected state\n"); + connected = true; + protocol_init(0); + } + } + free(resp); + } +} + +void writeline(int sock, const char* str) { + char* snd = __dw_strcat(str, "\r\n"); + write_serial(snd); + free(snd); +} +#endif + +#ifdef TCPIP +int port = 4096; +int server_socket; +struct sockaddr_in6 server_address; + +int server_init(void) { + printf("Using BSD TCP/IP\n"); + int i; + for(i = 1; i < argc; i++) { + port = atoi(argv[i]); + } + if((server_socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)) < 0) { + fprintf(stderr, "BSD TCP/IP initialization fail\n"); + return 1; + } + int yes = 1; + if(setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { + fprintf(stderr, "BSD TCP/IP initialization fail\n"); + close(server_socket); + return 1; + } + if(setsockopt(server_socket, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) < 0) { + fprintf(stderr, "BSD TCP/IP initialization fail\n"); + close(server_socket); + return 1; + } + int no = 0; + if(setsockopt(server_socket, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no)) < 0) { + fprintf(stderr, "BSD TCP/IP initialization fail\n"); + close(server_socket); + return 1; + } + memset(&server_address, 0, sizeof(server_address)); + server_address.sin6_family = AF_INET6; + server_address.sin6_addr = in6addr_any; + server_address.sin6_port = htons(port); + if(bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) { + fprintf(stderr, "BSD TCP/IP initialization fail\n"); + close(server_socket); + return 1; + } + if(listen(server_socket, 128) < 0) { + fprintf(stderr, "BSD TCP/IP initialization fail\n"); + close(server_socket); + return 1; + } + signal(SIGCHLD, SIG_IGN); + fprintf(stderr, "BSD TCP/IP initialization successful\n"); + return 0; +} + +void server_loop(void) { + while(1) { + struct sockaddr_in claddr; + int clen = sizeof(claddr); + int sock = accept(server_socket, (struct sockaddr*)&claddr, &clen); + pid_t p = fork(); + if(p == 0) { + protocol_init(sock); + _exit(0); + } else { + close(sock); + } + } +} + +void writeline(int sock, const char* str) { + char* snd = __dw_strcat(str, "\r\n"); + send(sock, snd, strlen(snd), 0); + free(snd); +} +#endif + +void protocol_init(int sock) { + /* sock is ignored on hayes */ + char* verstr = __dw_strcat("READY:VER=", dataworks_get_version()); + writeline(sock, verstr); + writeline(sock, "ATTR:AUTH=YES"); +} + +int main(int _argc, char** _argv) { + argc = _argc; + argv = _argv; + printf("DataWorks Server version %s %s %s\n", dataworks_get_version(), dataworks_get_compile_date(), dataworks_get_platform()); + int st; + if((st = server_init()) != 0) return st; + server_loop(); +} diff --git a/common-decl.mk b/common-decl.mk index 23e9eef..fe1db40 100644 --- a/common-decl.mk +++ b/common-decl.mk @@ -21,5 +21,6 @@ EXEC_SUFFIX = PLATFORM_M = `uname -m` PLATFORM_P = `uname -p | sed -E "s/[ \\(\\)]/-/g"` LINK_LIB = ../Library/$(STATICLIB_PREFIX)dataworks$(STATICLIB_SUFFIX) +SERVER = ./Server COMPILE_FLAGS = CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" LIBS="$(LIBS)" LIB_PREFIX="$(LIB_PREFIX)" LIB_SUFFIX="$(LIB_SUFFIX)" EXEC_SUFFIX="$(EXEC_SUFFIX)" PLATFORM_M="$(PLATFORM_M)" PLATFORM_P="$(PLATFORM_P)" STATICLIB_PREFIX="$(STATICLIB_PREFIX)" STATICLIB_SUFFIX="$(STATICLIB_SUFFIX)" AR="$(AR)" RANLIB="$(RANLIB)" SHCC="$(SHCC)" LINK_LIB="$(LINK_LIB)" AR_ARGS="$(AR_ARGS)" WINDRES="$(WINDRES)" YACC="$(YACC)" LEX="$(LEX)" LFLAGS="$(LFLAGS)" YFLAGS="$(YFLAGS)" diff --git a/common.mk b/common.mk index 93bb05e..37752dc 100644 --- a/common.mk +++ b/common.mk @@ -2,9 +2,9 @@ .PHONY: all no-doc replace format clean ./Library ./Client ./Document ./Grammar archive archive-prepare archive-cleanup archive-targz archive-zip dosbox prepare-dosbox dosbox-x cleanup-dosbox -all: ./Grammar ./Library ./Client ./Document +all: ./Grammar ./Library ./Client $(SERVER) ./Document -no-doc: ./Grammar ./Library ./Client +no-doc: ./Grammar ./Library ./Client $(SERVER) ./Grammar:: $(MAKE) -C $@ $(COMPILE_FLAGS) @@ -15,6 +15,9 @@ no-doc: ./Grammar ./Library ./Client ./Client:: ./Library $(MAKE) -C $@ $(COMPILE_FLAGS) +./Server:: ./Library + $(MAKE) -C $@ $(COMPILE_FLAGS) + ./Document:: $(MAKE) -C ./Document $(COMPILE_FLAGS) @@ -36,6 +39,7 @@ clean: $(MAKE) -C ./Grammar clean $(COMPILE_FLAGS) $(MAKE) -C ./Library clean $(COMPILE_FLAGS) $(MAKE) -C ./Client clean $(COMPILE_FLAGS) + $(MAKE) -C ./Server clean $(COMPILE_FLAGS) $(MAKE) -C ./Document clean $(COMPILE_FLAGS) archive-prepare: all @@ -74,12 +78,21 @@ archive: prepare-dosbox: no-doc echo 'create_table("test", "string:key", "floating:value");' > op.txt echo '.tables' >> op.txt - echo "[cpu]" > dosbox.conf + echo "[serial]" > dosbox.conf + echo "serial1=modem listenport:4096" >> dosbox.conf + echo "[sdl]" >> dosbox.conf + echo "windowresolution=640x400" >> dosbox.conf + echo "[render]" >> dosbox.conf + echo "aspect=true surface" >> dosbox.conf + echo "aspect_ratio=16:9" >> dosbox.conf + echo "[cpu]" >> dosbox.conf echo "cycles=12000" >> dosbox.conf echo "[autoexec]" >> dosbox.conf echo "mount c: ." >> dosbox.conf echo "c:" >> dosbox.conf + echo "copy Server\*$(EXEC_SUFFIX) dwserv$(EXEC_SUFFIX)" >> dosbox.conf echo "copy Client\*$(EXEC_SUFFIX) dw$(EXEC_SUFFIX)" >> dosbox.conf + echo "dwserv COM1" >> dosbox.conf echo "dw /NC /f op.txt /create db.dwf" >> dosbox.conf echo "dw /NC /f op.txt db.dwf" >> dosbox.conf echo "pause" >> dosbox.conf -- 2.43.0