From f8b27b8465c75d6f78d3fa2689e2cdcbdf76cc65 Mon Sep 17 00:00:00 2001 From: CrazyEttin <> Date: Sat, 1 Oct 2022 19:54:30 +0300 Subject: [PATCH] Add server functionality to the emulated modem --- emulator.pas | 93 ++++++++++++++++++++++++++++++++++++++++++---------- modemctl.pas | 58 ++++++++++++++++---------------- readme.md | 10 +++--- 3 files changed, 110 insertions(+), 51 deletions(-) diff --git a/emulator.pas b/emulator.pas index 4729163..2eb4e3c 100644 --- a/emulator.pas +++ b/emulator.pas @@ -26,9 +26,9 @@ type //Modem connection state Connection = record Call: boolean; + Answer: boolean; Addr: longword; Port: word; - Answer: boolean; Hang: boolean; end; {$endif} @@ -50,7 +50,7 @@ const {$endif} var - Hlt, Echo{$ifdef floppy}, DiscRead, DiscWrite, DiscTrackSet, DiscSectSet{$endif}{$ifdef modem}, Calling{$endif}: boolean; //Halt and echo flags, disc system flags, and modem connection flag + Hlt, Echo{$ifdef floppy}, DiscRead, DiscWrite, DiscTrackSet, DiscSectSet{$endif}{$ifdef modem}, Calling, Answering{$endif}: boolean; //Halt and echo flags, disc system flags, and modem connection flags Op, Regs: 0 .. $f; //Opcode X, Y: 0 .. 3; //Register arguments Addr, IP, RP: word; //Immediate or address argument and instruction and return pointers @@ -78,8 +78,8 @@ var {$ifdef modem} ModemConn: Connection; //State of the modem ModemState: file of Connection; //File storing the state of the modem - ServerSocket: longint; //Server socket - ServerAddr: TInetSockAddr; //Server address + ServerSocket, ListenSocket, ClientSocket, ClientAddrSize: longint; //Server socket + ServerAddr, ClientAddr: TInetSockAddr; //Server address {$endif} {$ifdef status} FileDescs: TFDset; //File descriptor set @@ -133,14 +133,40 @@ begin end; end; //Hang - if ModemConn.Hang then if Calling then begin - CloseSocket (ServerSocket); - ModemConn.Hang := false; - Calling := false; + if ModemConn.Hang then begin + if Calling then begin + CloseSocket (ServerSocket); + ModemConn.Hang := false; + Calling := false; + end + else if Answering then begin + CloseSocket (ClientSocket); + CloseSocket (ListenSocket); + ModemConn.Hang := false; + Answering := false; + end; end - else if ModemConn.Call then if Calling then begin - CloseSocket (ServerSocket); - Calling := false; + else if ModemConn.Call then begin + if Calling then begin + CloseSocket (ServerSocket); + Calling := false; + end + else if Answering then begin + CloseSocket (ClientSocket); + CloseSocket (ListenSocket); + Answering := false; + end; + end + else if ModemConn.Answer then begin + if Calling then begin + CloseSocket (ServerSocket); + Calling := false; + end + else if Answering then begin + CloseSocket (ClientSocket); + CloseSocket (ListenSocket); + Answering := false; + end; end; //Call if ModemConn.Call then if Calling = false then begin @@ -149,14 +175,36 @@ begin if ServerSocket <> -1 then begin //Connect ServerAddr.sin_family := AF_INET; - ServerAddr.sin_port := htons (ModemConn.Port); ServerAddr.sin_addr.s_addr := htonl (ModemConn.Addr); - if fpconnect (ServerSocket, @ServerAddr, Sizeof (ServerAddr)) <> -1 then begin + ServerAddr.sin_port := htons (ModemConn.Port); + if fpConnect (ServerSocket, @ServerAddr, Sizeof (ServerAddr)) <> -1 then begin ModemConn.Call := false; Calling := true; end; end; end; + //Answer + if ModemConn.Answer then if Answering = false then begin + //Create a socket + ListenSocket := fpSocket (AF_INET, SOCK_STREAM, 0); + if ListenSocket <> -1 then begin + //Listen + ServerAddr.sin_family := AF_INET; + ServerAddr.sin_addr.s_addr := htonl (ModemConn.Addr); + ServerAddr.sin_port := htons (ModemConn.Port); + if fpBind (ListenSocket, @ServerAddr, Sizeof (ServerAddr)) <> -1 then begin + if fpListen (ListenSocket, 1) <> -1 then begin + //Accept + ClientAddrSize := sizeof (ClientAddr); + ClientSocket := fpAccept (ListenSocket, @ClientAddr, @ClientAddrSize) ; + if ClientSocket <> -1 then begin + ModemConn.Answer := false; + Answering := true; + end; + end; + end; + end; + end; //Save the modem state if FileExists (ExpandFileName ('~/.thingamajig/connection')) then begin try @@ -261,12 +309,13 @@ begin //Modem else if W = $fffa then begin {$ifndef fast} - wait (26); + wait (33); {$endif} //Connect CallServer; //Recieve if Calling then fpRecv (ServerSocket, @B, 1, 0) + else if Answering then fpRecv (ClientSocket, @B, 1, 0) else B := 0; end {$endif} @@ -299,6 +348,11 @@ begin fpfd_zero (FileDescs); fpfd_set (ServerSocket, FileDescs); if fpSelect (ServerSocket + 1, @FileDescs, nil, nil, 0) > 0 then B := B or $20; + end + else if Answering then begin + fpfd_zero (FileDescs); + fpfd_set (ClientSocket, FileDescs); + if fpSelect (ClientSocket + 1, @FileDescs, nil, nil, 0) > 0 then B := B or $20; end; {$endif} {$ifndef modem} @@ -651,12 +705,13 @@ begin //Modem else if W = $fffa then begin {$ifndef fast} - wait (26); + wait (33); {$endif} //Connect CallServer; //Send - if Calling then fpSend (ServerSocket, @B, 1, 0); + if Calling then fpSend (ServerSocket, @B, 1, 0) + else if Answering then fpSend (ClientSocket, @B, 1, 0); end {$endif} //Regular store @@ -877,7 +932,11 @@ begin {$ifdef modem} //Disconnect the modem - if Calling then CloseSocket (ServerSocket); + if Calling then CloseSocket (ServerSocket) + else if Answering then begin + CloseSocket (ClientSocket); + CloseSocket (ListenSocket); + end; {$endif} {$ifndef fast} diff --git a/modemctl.pas b/modemctl.pas index dd27a2d..0a39259 100644 --- a/modemctl.pas +++ b/modemctl.pas @@ -8,9 +8,9 @@ type //Connection state Connection = record Call: boolean; + Answer: boolean; Addr: longword; Port: word; - Answer: boolean; Hang: boolean; end; @@ -23,14 +23,20 @@ begin //Check the arguments if ParamStr (1) = '-c' then begin - if ParamCount > 2 then begin - writeln ('Usage: modemctl [-c address:port]/-a/-h'); + if ParamCount <> 2 then begin + writeln ('Usage: modemctl [-c address:port]/[-a address:port]/-h'); + halt (1); + end; + end + else if ParamStr (1) = '-a' then begin + if ParamCount <> 2 then begin + writeln ('Usage: modemctl [-c address:port]/[-a address:port]/-h'); halt (1); end; end else begin if ParamCount > 1 then begin - writeln ('Usage: modemctl [-c address:port]/-a/-h'); + writeln ('Usage: modemctl [-c address:port]/[-a address:port]/-h'); halt (1); end; end; @@ -38,59 +44,53 @@ begin //Assign the state file assign (State, ExpandFileName ('~/.thingamajig/connection')); - //Read existing state if any - if FileExists (ExpandFileName ('~/.thingamajig/connection')) then begin - try - reset (State); - read (State, ModemConn); - close (State); - except - end; - end - //Or else assign a default state - else begin - ModemConn.Call := false; - ModemConn.Addr := 0; - ModemConn.Port := 0; - ModemConn.Answer := false; - ModemConn.Hang := false; - end; - //Set the connection if ParamStr (1) = '-c' then begin ModemConn.Call := true; + ModemConn.Answer := false; try Addr := StrToHostAddr (ExtractDelimited (1, ParamStr (2), [':'])); ModemConn.Addr := Addr.s_addr; except - writeln ('Usage: modemctl [-c address:port]/-a/-h'); + writeln ('Usage: modemctl [-c address:port]/[-a address:port]/-h'); halt (1); end; try ModemConn.Port := StrToInt (ExtractDelimited (2, ParamStr (2), [':'])); except - writeln ('Usage: modemctl [-c address:port]/-a/-h'); + writeln ('Usage: modemctl [-c address:port]/[-a address:port]/-h'); halt (1); end; - ModemConn.Answer := false; ModemConn.Hang := false; end else if ParamStr (1) = '-a' then begin ModemConn.Call := false; - ModemConn.Addr := 0; - ModemConn.Port := 0; ModemConn.Answer := true; + try + Addr := StrToHostAddr (ExtractDelimited (1, ParamStr (2), [':'])); + ModemConn.Addr := Addr.s_addr; + except + writeln ('Usage: modemctl [-c address:port]/[-a address:port]/-h'); + halt (1); + end; + try + ModemConn.Port := StrToInt (ExtractDelimited (2, ParamStr (2), [':'])); + except + writeln ('Usage: modemctl [-c address:port]/[-a address:port]/-h'); + halt (1); + end; + ModemConn.Hang := false; ModemConn.Hang := false; end else if ParamStr (1) = '-h' then begin ModemConn.Call := false; + ModemConn.Answer := false; ModemConn.Addr := 0; ModemConn.Port := 0; - ModemConn.Answer := false; ModemConn.Hang := true; end else begin - writeln ('Usage: modemctl [-c address:port]/-a/-h'); + writeln ('Usage: modemctl [-c address:port]/[-a address:port]/-h'); halt (1); end; diff --git a/readme.md b/readme.md index 3125568..28d529c 100644 --- a/readme.md +++ b/readme.md @@ -98,7 +98,7 @@ Usage: * emulator (-v) program (2> verbose_output) * tapectl (-r tape) (-p tape) * floppyctl (-0 disc) (-1 disc) - * modemctl [-c address:port]/-a/-h + * modemctl [-c address:port]/[-a address:port]/-h By default the emulator runs at roughly 500 KIPS and has 2 KiB of RAM. The arguments -dRAM4, -dRAM8, -dRAM16, -dRAM32, and -dRAM64 can be used @@ -133,10 +133,10 @@ arguments -0 and -1 respectively. The disc system uses hard sectored single-sided discs with 77 tracks of 32 sectors of 137 bytes, or 337568 bytes in total: the disc files must be of this size. The modem is controlled by the program modemctl: the option -c is used to call an IP -address and port, -a to set the modem ready for answering calls to port -1337, and -h to hang. Hanging manually is not necessary when making a -new call or switching between calling and answering. Note: Answering is -not implemented yet. +address and port, -a to set the modem ready for answering calls to a +loopback or local IP address and port, and -h to hang. Hanging manually +is not necessary when making or answering a new call or switching +between calling and answering. The floppy disc system uses two ports: command at FFFB and data at FFFC. Only the low nibble of the command port is used, consisting of a