diff --git a/README.md b/README.md new file mode 100644 index 0000000..cfae9ef --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# Amiga BSD Socket coding + +Get your Amiga doing stuff on the Internet! + +All code in this repo is licensed under the MIT License. + +## The original AMOS code + +`amos_pro_original` contains the original AMOS Professional code to use +`bsdsocket.library` in BASIC. It requires the +[EasyLife](http://aminet.net/package/dev/amos/Easylife110_P1) extension. + +This is the code used in the [23 Year Old Code](https://youtu.be/l4GNHJfYOUU) video. + +## Server in C + +`server_in_c` uses SAS/C and the AmiTCK SDK to build a simple server that +prints out what is received, like a very basic `netcat`. + +This is the code used in the [Simple Server in C for the Commodore Amiga]() video. diff --git a/amos_pro_original/BSDSocket.amos b/amos_pro_original/BSDSocket.amos new file mode 100644 index 0000000..56a354a Binary files /dev/null and b/amos_pro_original/BSDSocket.amos differ diff --git a/amos_pro_original/BSDSocket.readme b/amos_pro_original/BSDSocket.readme new file mode 100644 index 0000000..03796c9 --- /dev/null +++ b/amos_pro_original/BSDSocket.readme @@ -0,0 +1,121 @@ +Short: Use bsdsocket.library calls in AmosPro +Uploader: John Bintz (hello@theindustriousrabbit.com) +Author: John Bintz (hello@theindustriousrabbit.com) +Type: dev/amos + +These procedures directly call bsdsocket.library, the TCP library created by +your Internet Dialer (Miami, AmiTCP, TermiteTCP). They are much faster and more +friendly than the TCP: device equivalents, as they allow transfers to be +Non-Blocking. Normally, with TCP:, if there was no data to get, TCP: would lock +until it got some. Now, the program will simply ignore lack of data and move +on. + +You need a lot of memory to run a Stack and Amos at the same time. I would say +three or four meg would do it, depending on what else you have running. + +The EasyLife extension is required. + +Licensed under the MIT license. + +Commands (port 80 is http): + +BSD_OPEN + Open the bsdsocket.library +BSD_CLOSE + Close the bsdsocket.library and all sockets attached +SOCK_OPENCONNECTION[HOST$,SPORT] + Open a connection to a computer in the fashion tcp://HOST$:SPORT/ + Returns Socket ID + Example: SOCK_OPENCONNECTION["www.yahoo.com",80] +SOCK_OPENSERVER[SPORT] + Create a server port on your computer + Returns Socket ID + Example: SOCK_OPENSERVER[80] +SOCK_CHECKHOSTPORT[SOCKET] + Check Host Socket for a connection + Returns Connected Socket ID (use this for transfers) or -1 + Example: SOCK_CHECKHOSTPORT[MYPORT] +SOCK_GETYOURHOST + Returns your host computer's name + Example: SOCK_GETYOURHOST : Print Param$ + "as1s23-wmn.erols.com" +SOCK_SENDSTRING[SOCKET,A$] +SOCK_READSTRING[SOCKET,MXSIZE] + Writes and reads strings over a socket + SENDSTRING returns characters sent + READSTRING returns string received +SOCK_SEND[SOCKET,ADR,LEN] +SOCK_READ[SOCKET,ADR,LEN] + Send and receive large chunks of data over a socket + Both return numbers of characters sent/received +SOCK_CLOSE[SOCKET] + Close a socket and save some memory +SOCK_ERR[VARADDR] + Set a certain 4-byte memory address to receive TCP errors +SOCK_NEW + Create a new socket + Returns socket ID of new socket +SOCK_SETIO[SOCKET] + Set Non-Blocking, Asynchronous IO on a Socket + +There are also a collection of commands especially for working with FTP, as it +uses a crazy system of ports and data links. I decided to save youall the +trouble of figuring out FTP. Grab the RFC for FTP. With these commands, you'll +have it all figured out. + +FTP_OPENCONNECTION[HOST$,SPORT] + Open an FTP connection (ftp://HOST$:SPORT/) +FTP_HOSTSOCK + Returns Socket ID of Host machine (where to send FTP commands) +FTP_YOURSOCK + Returns your Socket ID for transfers (where to check for files) +FTP_YOURPORT$ + Returns the PORT string to use +FTP_CLOSECONNECTION + Close FTP connections + +'A Sample TCP/FTP Session +'All the major commands are used in here + +(FTP port is 23) + +FTP_OPENCONNECTION["ftp.wustl.edu",23] +Proc FTP_HOSTSOCK : HOSTSOCK=Param +Proc FTP_YOURSOCK : YOURSOCK=Param +Proc FTP_YOURPORT$ : YOURPORT$=Param$ + +E$=Chr$(13)+Chr$(10) + +SOCK_SENDSTRING[HOSTSOCK,"USER anonymous"+E$] +SOCK_SENDSTRING[HOSTSOCK,"PASS uv334@victoria.tc.ca"+E$] +Repeat + SOCK_READSTRING[HOSTSOCK,256] + Print Param$ +Until Param$="" + +SOCK_SENDSTRING[HOSTSOCK,"CD /pub/aminet/game/rpg/"+E$] +SOCK_SENDSTRING[HOSTSOCK,YOURPORT$] +Repeat + SOCK_READSTRING[HOSTSOCK,256] + Print Param$ +Until Param$="" + +SOCK_SENDSTRING[HOSTSOCK,"GET FinalExistence.lha"] : Rem Shameless, aren't I? +CONN=-1 +Repeat + SOCK_CHECKHOSTPORT[YOURSOCK] + If Param>-1 + CONN=Param + Reserve As Work 23,2048 + Open Out 1,"FinalExistence.lha" + Repeat + SOCK_READ[CONN,Start(23),2048] : BYTES=Param + If BYTES>-1 + Ssave 1,Start(23) to Start(23)+BYTES-1 + End If + Until BYTES=-1 + End If +Until CONN>-1 +SOCK_CLOSE[CONN] + +FTP_CLOSECONNECTION diff --git a/amos_pro_original/BSDSocket.txt b/amos_pro_original/BSDSocket.txt new file mode 100644 index 0000000..0118925 --- /dev/null +++ b/amos_pro_original/BSDSocket.txt @@ -0,0 +1,193 @@ +'BSDSocket.library Procedures +'By John Bintz +' +'Licensed under the MIT License +'Extension 16 is the EasyLife extension + +'Open bsdsocket.library +Procedure BSD_OPEN +Lib Open 5,"bsdsocket.library",0 +End Proc +'Close bsdsocket.library +Procedure BSD_CLOSE +Lib Close 5 +End Proc + +'Create New Socket +Procedure SOCK_NEW +Dreg(0)=2 +Dreg(1)=1 +Dreg(2)=0 +WHICH=Lib Call(5,-$1E) +End Proc[WHICH] +'Set Memory Address to Place Errors +Procedure SOCK_ERR[VARADDR] +Areg(0)=VARADDR +Dreg(0)=4 +SUCCESS=Lib Call(5,-$A8) +End Proc + +'Open A Server Socket on Your Machine at PORT (mymachine.com:PORT) +Procedure SOCK_OPENSERVER[SPORT] + Proc SOCK_NEW : SOCKET=Param + + SOCK_GETYOURHOST + A$=Param$+Chr$(0) + Areg(0)=Varptr(A$) + + HOSTINFO=Lib Call(5,-$D2) + HOSTADDRESS=Leek(Leek(Leek(HOSTINFO+16))) + + A$=Chr$(16)+Chr$(2)+ Extension_16_04EA(SPORT)+ Extension_16_04CE(HOSTADDRESS)+String$(Chr$(0),8) + + Dreg(0)=SOCKET + Areg(0)=Varptr(A$) + Dreg(1)=Len(A$) + BIND=Lib Call(5,-$24) + + Dreg(0)=SOCKET + Dreg(1)=1 + LISTEN=Lib Call(5,-$2A) + SOCK_SETIO[SOCKET] + If BIND=-1 + SOCK_CLOSE[SOCKET] + SOCKET=-1 + End If +End Proc[SOCKET] +'Set Non-Blocking/Asynchronous IO +Procedure SOCK_SETIO[SOCKET] +IOC_FIONBIO=($80000000 or(4*65536) or 126 or(Asc("f")*256)) +IOC_FIOASYNC=($80000000 or(4*65536) or 125 or(Asc("f")*256)) + +NBIO=1 +Dreg(0)=SOCKET : Dreg(1)=IOC_FIONBIO : Areg(0)=Varptr(NBIO) +NOBLOCK=Lib Call(5,-$72) +NBIO=1 +Dreg(0)=SOCKET : Dreg(1)=IOC_FIOASYNC : Areg(0)=Varptr(NBIO) +NOBLOCK=Lib Call(5,-$72) +End Proc +'Connect to Another Computer (tcp://HOST$:SPORT/) +Procedure SOCK_OPENCONNECTION[HOST$,SPORT] + Proc SOCK_NEW : SOCKET=Param + A$=HOST$+Chr$(0) + Areg(0)=Varptr(A$) + + HOSTINFO=Lib Call(5,-$D2) + HOSTADDRESS=Leek(Leek(Leek(HOSTINFO+16))) + A$=Chr$(16)+Chr$(2)+ Extension_16_04EA(SPORT)+ Extension_16_04CE(HOSTADDRESS)+String$(Chr$(0),8) + + Dreg(0)=SOCKET + Areg(0)=Varptr(A$) + Dreg(1)=Len(A$) + CONNECT=Lib Call(5,-$36) + SOCK_SETIO[SOCKET] + If CONNECT=-1 + SOCK_CLOSE[SOCKET] + SOCKET=-1 + End If +End Proc[SOCKET] +'Check Your Host Port for Connection and Create A New Socket If So +Procedure SOCK_CHECKHOSTPORT[SOCKET] + A$=String$(Chr$(0),200) + FINSIZE=64 + Dreg(0)=SOCKET + Areg(0)=Varptr(A$) + Areg(1)=Varptr(FINSIZE) + NEWSOCKET=Lib Call(5,-$30) + SOCK_CONNURL= Extension_16_04DC(Mid$(A$,8,4)) +End Proc[NEWSOCKET] + +'Send A String to a Socket +Procedure SOCK_SENDSTRING[SOCKET,A$] + If SOCKET<>-1 + Dreg(0)=SOCKET + Areg(0)=Varptr(A$) + Dreg(1)=Len(A$) + Dreg(2)=0 + NBYTES=Lib Call(5,-$42) + End If +End Proc[NBYTES] +'Read A String from a Socket +Procedure SOCK_READSTRING[SOCKET,MXSIZE] + If SOCKET<>-1 + A$=Space$(MXSIZE) + Dreg(0)=SOCKET + Areg(0)=Varptr(A$) + Dreg(1)=MXSIZE + Dreg(2)=0 + NBYTES=Lib Call(5,-$4E) + If NBYTES>0 + A$=Left$(A$,NBYTES) + Else + A$="" + End If + Else + A$="" + End If +End Proc[A$] +'Send A Memory Buffer to a Socket +Procedure SOCK_SEND[SOCKET,ADR,ADRLEN] +Dreg(0)=SOCKET +Areg(0)=ADR +Dreg(1)=ADRLEN +Dreg(2)=0 +NBYTES=Lib Call(5,-$42) +End Proc[NBYTES] +'Read A Memory Buffer from a Socket +Procedure SOCK_READ[SOCKET,ADR,ADRLEN] +Dreg(0)=SOCKET +Areg(0)=ADR +Dreg(1)=ADRLEN +Dreg(2)=0 +NBYTES=Lib Call(5,-$4E) +End Proc[NBYTES] + +'Get Your Hostname (PPP) +Procedure SOCK_GETYOURHOST +Open In 1,"env:hostname" +A$=Input$(1,Lof(1)) : Close 1 +End Proc[A$] + +'Close A Socket (Save Memory) +Procedure SOCK_CLOSE[SOCKET] +If SOCKET<>-1 + Dreg(0)=SOCKET + SUCCESS=Lib Call(5,-$78) + Print SUCCESS,SOCK_ERRNO +End If +End Proc + +'These Commands are especially for FTP, which is weird... + +'Open An FTP Connection (ftp://HOST$:SPORT/) +Procedure FTP_OPENCONNECTION[HOST$,SPORT] +Shared _FTP_HOSTSOCK,_FTP_YOURSOCK,_FTP_YOURPORT$ +SOCK_OPENCONNECTION[HOST$,SPORT] : _FTP_HOSTSOCK=Param +SOCK_OPENSERVER[5000] : _FTP_YOURSOCK=Param +P$="" : H$=Mid$(Hex$(HOSTADDRESS,8),2) +For I=0 To 3 + P$=P$+Str$(Val("$"+Mid$(H$,I*2+1,2)))+"," +Next +P$=P$-" " +_FTP_YOURPORT$="PORT "+P$+"19,136"+Chr$(13)+Chr$(10) +End Proc +'Grab Host Socket ID +Procedure FTP_HOSTSOCK +Shared _FTP_HOSTSOCK +End Proc[_FTP_HOSTSOCK] +'Grab Your Socket ID +Procedure FTP_YOURSOCK +Shared _FTP_YOURSOCK +End Proc[_FTP_YOURSOCK] +'Grab PORT String (used to send files via FTP) +Procedure FTP_YOURPORT$ +Shared _FTP_YOURPORT$ +End Proc[_FTP_YOURPORT$] +'Close an FTP Connection +Procedure FTP_CLOSECONNECTION +Shared _FTP_HOSTSOCK,_FTP_YOURSOCK +SOCK_CLOSE[_FTP_HOSTSOCK] +SOCK_CLOSE[_FTP_YOURSOCK] +End Proc + + diff --git a/server_in_c/README.md b/server_in_c/README.md new file mode 100644 index 0000000..58c0eb5 --- /dev/null +++ b/server_in_c/README.md @@ -0,0 +1,16 @@ +# Amiga BSD Socket Server in C + +Built using SAS/C 6.58 and the +[AmiTCP 4.3 SDK](http://aminet.net/package/comm/tcp/AmiTCP-SDK-4.3). + +## Socket test code + +If you can build and run `test_setup.c`, your NDK setup is correct: + +`sc link test_setup.c` + +## Server + +Build it without the `chkabort` routine: + +`sc link nochkabort server.c` diff --git a/SCOPTIONS b/server_in_c/SCOPTIONS similarity index 100% rename from SCOPTIONS rename to server_in_c/SCOPTIONS diff --git a/server_in_c/server b/server_in_c/server new file mode 100755 index 0000000..51ad02e Binary files /dev/null and b/server_in_c/server differ diff --git a/server.c b/server_in_c/server.c similarity index 96% rename from server.c rename to server_in_c/server.c index 9c66d2e..343fae6 100644 --- a/server.c +++ b/server_in_c/server.c @@ -89,8 +89,6 @@ void teardown(void) { // SHUT_RDWR, stop all communication both ways 2 ); - // double close it to stop the listen as well - CloseSocket(serverSocket); CloseSocket(serverSocket); } @@ -136,7 +134,7 @@ void readData(int clientSocket) { printf("Got stuff: %i\n", msgSize); printf("%s\n", buffer); } - } while (msgSize == BUFFER_LENGTH); + } while (msgSize == 256); printf("Data received: %s\n", buffer); } @@ -166,7 +164,7 @@ int main(void) { // just enough to get WaitSelect working // this macro also wants strings.h included - FD_ZERO(&readFDs); (( + FD_ZERO(&readFDs); FD_SET(serverSocket, &readFDs); waitSelectResult = WaitSelect( serverSocket + 1, diff --git a/server_in_c/test_setup.c b/server_in_c/test_setup.c new file mode 100644 index 0000000..532ff8e --- /dev/null +++ b/server_in_c/test_setup.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include + +int main(void) { + if (!(SocketBase = OpenLibrary("bsdsocket.library", 4))) { + printf("Can't open socket library\n"); + return 1; + } + + serverSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (serverSocket < 0) { + printf("can't get a socket\n"); + return 1; + } + + CloseSocket(serverSocket); + CloseLibrary(SocketBase); +}