diff --git a/API.md b/API.md index 3f07354..e1d86ec 100644 --- a/API.md +++ b/API.md @@ -63,8 +63,19 @@ Create a new Internet socket for reading or writing. #### RESULT=Socket Connect(Socket to IPAddress$, Port) -Attempt to connect to a remote host. Currently doesn't -support DNS lookups. +Attempt to connect to a remote IP address. + +##### Emulation vs. Physical/FPGA Amiga note + +On emulated Amigas (FS-UAE) with emulated `bsdsocket.library`, a failure in +`Socket Connect` due to giving the function a bad IP address allows you to reuse +the socket. On real or FPGA-based Amiga running real TCP/IP stacks (MiamiDX, +Roadshow), the socket will be made unusable and you'll need to +`Socket Close Socket` and reopen the socket with whatever parameters necessary. +Closing and opening `bsdsocket.library` has the same effect. + +Always close and re-open a socket if you have any `Socket Connect` failure and +any non-blocking polling loops time out! ##### Returns @@ -74,6 +85,7 @@ support DNS lookups. the socket with Socket Select and Socket Getsockopt Int to see if the connection succeeded * -11 port out of range +* -13 IP address has zero length --- @@ -82,7 +94,7 @@ support DNS lookups. Set a server socket to reuse an interface and port that had been used recently. You likely want this if you're building something that listens on a port for connections. This calls -setsockopt() for you. +`setsockopt()` for you. ##### Returns @@ -182,6 +194,7 @@ Set a socket to timeout after Wait_ms milliseconds if reading or writing doesn't Close a socket. + ##### Returns * 0 on success diff --git a/bin/rebuild_raw_source b/bin/rebuild_raw_source index 2a1b19b..3c2c04a 100755 --- a/bin/rebuild_raw_source +++ b/bin/rebuild_raw_source @@ -1,6 +1,6 @@ #!/bin/bash -for i in examples/*.amos; do +for i in examples/*.amos test/*.amos; do echo "$i" ~/Projects/amostools/listamos -e AMOSPro_BSDSocket.Lib "${i}" > "${i%.amos}.basic" 2>/dev/null done diff --git a/src/AMOSPro_BSDSocket.Lib b/src/AMOSPro_BSDSocket.Lib index 781ff6c..c7308ec 100644 Binary files a/src/AMOSPro_BSDSocket.Lib and b/src/AMOSPro_BSDSocket.Lib differ diff --git a/src/BSDSocket.s b/src/BSDSocket.s index 49f4e5a..e557aad 100644 --- a/src/BSDSocket.s +++ b/src/BSDSocket.s @@ -682,8 +682,6 @@ _SocketConnect_SockaddrIn: MOVE.L D0,A0 MOVE.L (SP)+,D0 - CLR.W $100 - MOVE.L D0,-(SP) MOVEM.L A0/A3,-(SP) Dload A3 diff --git a/src/BSDSocket_Labels.s b/src/BSDSocket_Labels.s index 5e81b7d..e449567 100644 --- a/src/BSDSocket_Labels.s +++ b/src/BSDSocket_Labels.s @@ -1,5 +1,5 @@ ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -; BSDSocket.s, list of the library functions on the 26-04-2024 08:23:46 +; BSDSocket.s, list of the library functions on the 26-04-2024 14:45:36 ; ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ L_Cold: set 0 diff --git a/src/BSDSocket_Size.s b/src/BSDSocket_Size.s index f3e9d7f..7aa7186 100644 --- a/src/BSDSocket_Size.s +++ b/src/BSDSocket_Size.s @@ -1,5 +1,5 @@ ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -; BSDSocket.s, library size on the 26-04-2024 08:23:46 +; BSDSocket.s, library size on the 26-04-2024 14:45:36 ; ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Lib_Size equ 39 diff --git a/src/report.txt b/src/report.txt new file mode 100644 index 0000000..9caf71b --- /dev/null +++ b/src/report.txt @@ -0,0 +1,34 @@ +[Socket Library Open/Open Library] 1075577444 +[Socket Library Open/Double open] 1075577444 +[Socket Create Inet Socket] 0 +[Socket Set Nonblocking/False] 0 +[Socket Set Nonblocking/True] 0 +[Socket Set Nonblocking/True] Preserving this state for rest of tests +[Dns Get Address By Name$/Bad domain name] +[Dns Get Address By Name$/localhost] 127.0.0.1 +[Dns Get Address By Name$/aminet.net] 35.223.124.178 +[Dns Get Address By Name$/aminet.net] Using this IP address for connection tests +[Dns Get Address By Name$/Returned string can be manipulated] Cat35.223.124.178Dog +[Socket Connect/port too high] -11 +[Socket Connect/blank ip] -14 +[Socket Connect/invalid ip] -1 +[Socket Connect/aminet IP (35.223.124.178) from above] -1 (ok to be -1, will Wait Async Writing next) +[Socket Wait Async Writing/With unconnected socket/2 second timeout] 1 +[Socket Wait Async Writing/With unconnected socket/Zero timeout] 1 +[Socket Wait Async Writing/Connected socket/Two second timeout] 1 +[Socket Wait Async Writing/Connected socket/Zero timeout] 1 +[Socket Wait Async Writing/Connected socket/Attempt to get actual connection] 1 +[Socket Wait Async Writing/Socket Send and Socket Send$/Socket send$ first half] 10 +[Socket Wait Async Writing/Socket Send and Socket Send$/Socket send second half] 18 +[Socket Wait Async Writing/Socket wait Async Reading/With unconnected socket/2 second timeout] 1 +[Socket Wait Async Writing/Socket wait Async Reading/With unconnected socket/Zero timeout] 1 +[Socket Wait Async Writing/Socket wait Async Reading/With aminet socket/2 second timeout] 1 +[Socket Wait Async Writing/Socket wait Async Reading/With aminet socket/Zero timeout] 1 +[Socket Wait Async Writing/Socket Recv$ and Socket Recv/Socket Recv$/Read 20 characters] HTTP/1.1 302 Found + +[Socket Wait Async Writing/Socket Recv$ and Socket Recv/Socket Recv$/String can be manipulated] CatHTTP/1.1 302 Found +Dog +[Socket Wait Async Writing/Socket Recv$ and Socket Recv/Socket Read/Read 20 bytes] 20 +[Socket Wait Async Writing/Socket Recv$ and Socket Recv/Socket Read/Data was read] Date: Fri, 26 Apr 20 +[Socket Wait Async Writing/Socket Library Close/Close] Success +[Socket Wait Async Writing/Socket Library Close/Double close] Success diff --git a/test/TestSuite b/test/TestSuite index bedc0e5..01256c2 100644 Binary files a/test/TestSuite and b/test/TestSuite differ diff --git a/test/TestSuite.amos b/test/TestSuite.amos index 1cd02b1..58bbeea 100644 Binary files a/test/TestSuite.amos and b/test/TestSuite.amos differ diff --git a/test/TestSuite.basic b/test/TestSuite.basic new file mode 100644 index 0000000..372e6ed --- /dev/null +++ b/test/TestSuite.basic @@ -0,0 +1,271 @@ +' BSD Socket Extension Test Suite +' +' Exercise all known functionality of the extension and write +' a report file detailing the result. + +Screen Open 0,640,200,4,Hires + +_FILE_HANDLE=1 +Dim _CONTEXT$(10) +_CONTEXT_INDEX=0 + +Global _FILE_HANDLE,_CONTEXT$(),_CONTEXT_INDEX + +Procedure _ADD_TO_REPORT[MESSAGE$] + _CONTEXT_STRING$="" + For I=0 To _CONTEXT_INDEX-1 + _CONTEXT_STRING$=_CONTEXT_STRING$+_CONTEXT$(I) + If I<>(_CONTEXT_INDEX-1) + _CONTEXT_STRING$=_CONTEXT_STRING$+"/" + End If + Next I + _OUTPUT$="["+_CONTEXT_STRING$+"] "+MESSAGE$ + Print #_FILE_HANDLE,_OUTPUT$ + Print _OUTPUT$ + ' ensure line is printed on screen to catch crashes + Wait Vbl +End Proc + +Procedure _BEGIN_CONTEXT[NAME$] + _CONTEXT$(_CONTEXT_INDEX)=NAME$ + _CONTEXT_INDEX=_CONTEXT_INDEX+1 +End Proc + +Procedure _END_CONTEXT + _CONTEXT_INDEX=_CONTEXT_INDEX-1 +End Proc + +Open Out _FILE_HANDLE,"report.txt" + +_BEGIN_CONTEXT["Socket Library Open"] +_BEGIN_CONTEXT["Open Library"] + +_LIBRARY_ADDRESS=Socket Library Open +_ADD_TO_REPORT[Str$(_LIBRARY_ADDRESS)] + +_END_CONTEXT + +If _LIBRARY_ADDRESS=0 + _ADD_TO_REPORT["bsdsocket.library not available, ending tests"] + _END_CONTEXT + Goto _FINISH_SUITE +End If + +_BEGIN_CONTEXT["Double open"] +_NEW_LIBRARY_ADDRESS=Socket Library Open +_ADD_TO_REPORT[Str$(_NEW_LIBRARY_ADDRESS)] +_END_CONTEXT + +_END_CONTEXT + + +_BEGIN_CONTEXT["Socket Create Inet Socket"] +SOCKET=Socket Create Inet Socket +_ADD_TO_REPORT[Str$(SOCKET)] +_END_CONTEXT + +_BEGIN_CONTEXT["Socket Reuse Addr"] +RESULT=Socket Reuse Addr(SOCKET) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT + +_BEGIN_CONTEXT["Socket Set Nonblocking"] +_BEGIN_CONTEXT["False"] +RESULT=Socket Set Nonblocking(SOCKET,False) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT + +_BEGIN_CONTEXT["True"] +RESULT=Socket Set Nonblocking(SOCKET,True) +_ADD_TO_REPORT[Str$(RESULT)] +_ADD_TO_REPORT["Preserving this state for rest of tests"] +_END_CONTEXT +_END_CONTEXT + +_BEGIN_CONTEXT["Dns Get Address By Name$"] + +_BEGIN_CONTEXT["Bad domain name"] +IP$=Dns Get Address By Name$("u8dsf93jsdfoiodsoi.sdfjdsoifueru.sadfasdsdasd") +Print IP$ +_ADD_TO_REPORT[IP$] +_END_CONTEXT + +_BEGIN_CONTEXT["localhost"] +IP$=Dns Get Address By Name$("localhost") +_ADD_TO_REPORT[IP$] +_END_CONTEXT + +_BEGIN_CONTEXT["aminet.net"] +IP$=Dns Get Address By Name$("aminet.net") +Print IP$ +_ADD_TO_REPORT[IP$] +_ADD_TO_REPORT["Using this IP address for connection tests"] +_END_CONTEXT + +_BEGIN_CONTEXT["Returned string can be manipulated"] +_ADD_TO_REPORT["Cat"+IP$+"Dog"] +_END_CONTEXT +_END_CONTEXT + +_BEGIN_CONTEXT["Socket Connect"] +_BEGIN_CONTEXT["port too high"] +RESULT=Socket Connect(SOCKET To IP$,999999) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT + +_BEGIN_CONTEXT["blank ip"] +RESULT=Socket Connect(SOCKET To "",80) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT + +_BEGIN_CONTEXT["invalid ip -- requires reopening failed socket"] +RESULT=Socket Connect(SOCKET To "999.999.999.999",80) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT + +_BEGIN_CONTEXT["Socket Close Socket"] +RESULT=Socket Close Socket(SOCKET) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT + +' re-set up this socket after a failed connection +SOCKET=Socket Create Inet Socket +_=Socket Set Nonblocking(SOCKET,True) + +_BEGIN_CONTEXT["aminet IP ("+IP$+") from above"] +RESULT=Socket Connect(SOCKET To IP$,80) +_ADD_TO_REPORT[Str$(RESULT)+" (ok to be -1, will Wait Async Writing next)"] +_END_CONTEXT +_END_CONTEXT + +_BEGIN_CONTEXT["Socket Wait Async Writing"] + +_BEGIN_CONTEXT["With unconnected socket"] +OTHER_SOCKET=Socket Create Inet Socket +_=Socket Set Nonblocking(OTHER_SOCKET,True) + +_BEGIN_CONTEXT["2 second timeout"] +RESULT=Socket Wait Async Writing(OTHER_SOCKET,2000) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT + +_BEGIN_CONTEXT["Zero timeout"] +RESULT=Socket Wait Async Writing(OTHER_SOCKET,0) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT +_END_CONTEXT + +_BEGIN_CONTEXT["Connected socket"] +_BEGIN_CONTEXT["Two second timeout"] +RESULT=Socket Wait Async Writing(SOCKET,2000) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT + +_BEGIN_CONTEXT["Zero timeout"] +RESULT=Socket Wait Async Writing(SOCKET,0) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT + +_BEGIN_CONTEXT["Attempt to get actual connection"] +For TRIES=0 To 10 + RESULT=Socket Wait Async Writing(SOCKET,500) + _ADD_TO_REPORT[Str$(RESULT)] + If RESULT>0 + Exit + End If +Next TRIES +_END_CONTEXT +_END_CONTEXT + +_BEGIN_CONTEXT["Socket Send and Socket Send$"] +HTTP_REQUEST_HEADERS$="GET / HTTP/1.0"+Chr$(10)+"Host: amiga"+Chr$(10)+Chr$(10) + +_BEGIN_CONTEXT["Socket send$ first half"] +FIRST_HALF$=Left$(HTTP_REQUEST_HEADERS$,10) +RESULT=Socket Send$(SOCKET,FIRST_HALF$) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT + +_BEGIN_CONTEXT["Socket send second half"] +SECOND_HALF_START=Varptr(HTTP_REQUEST_HEADERS$)+10 +SECOND_HALF_LENGTH=Len(HTTP_REQUEST_HEADERS$)-10 +RESULT=Socket Send(SOCKET,SECOND_HALF_START,SECOND_HALF_LENGTH) +_ADD_TO_REPORT[Str$(RESULT)] + +_END_CONTEXT +_END_CONTEXT + +_BEGIN_CONTEXT["Socket wait Async Reading"] +_BEGIN_CONTEXT["With unconnected socket"] +_BEGIN_CONTEXT["2 second timeout"] +RESULT=Socket Wait Async Reading(OTHER_SOCKET,2000) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT +_BEGIN_CONTEXT["Zero timeout"] +RESULT=Socket Wait Async Reading(OTHER_SOCKET,0) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT +_END_CONTEXT + +_BEGIN_CONTEXT["With aminet socket"] +_BEGIN_CONTEXT["2 second timeout"] +RESULT=Socket Wait Async Reading(SOCKET,2000) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT + +_BEGIN_CONTEXT["Zero timeout"] +RESULT=Socket Wait Async Reading(SOCKET,0) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT +_END_CONTEXT + +_END_CONTEXT + +_BEGIN_CONTEXT["Socket Recv$ and Socket Recv"] +_BEGIN_CONTEXT["Socket Recv$"] +_BEGIN_CONTEXT["Read 20 characters"] +RESULT$=Socket Recv$(SOCKET,20) +_ADD_TO_REPORT[RESULT$] +_END_CONTEXT + +_BEGIN_CONTEXT["String can be manipulated"] +_ADD_TO_REPORT["Cat"+RESULT$+"Dog"] +_END_CONTEXT + +_END_CONTEXT + +_BEGIN_CONTEXT["Socket Read"] +Reserve As Work 20,20 + +_BEGIN_CONTEXT["Read 20 bytes"] +RESULT=Socket Recv(SOCKET To Start(20),20) +_ADD_TO_REPORT[Str$(RESULT)] +_END_CONTEXT + +_BEGIN_CONTEXT["Data was read"] +' this value will change in the interpreter as tests run +' we are hacking the gibson here +BASE$="12345678901234567890" +Copy Start(20),Start(20)+20 To Varptr(DEST$) +_ADD_TO_REPORT[DEST$] +_END_CONTEXT + +Erase 20 +_END_CONTEXT +_END_CONTEXT + +_FINISH_SUITE: + +_BEGIN_CONTEXT["Socket Library Close"] +_BEGIN_CONTEXT["Close"] +Socket Library Close +_ADD_TO_REPORT["Success"] +_END_CONTEXT + +_BEGIN_CONTEXT["Double close"] +Socket Library Close +_ADD_TO_REPORT["Success"] +_END_CONTEXT +_END_CONTEXT + +Close 1