Compare commits

..

29 Commits

Author SHA1 Message Date
John Bintz d670a1691f Update README 2024-06-09 15:17:19 -04:00
John Bintz 0f4d54ad70 Allow building extension for multiple slots 2024-06-09 15:14:03 -04:00
John Bintz 5c70c42570 Remove unneeded files 2024-05-04 09:25:23 -04:00
John Bintz 6c216b31e8 Improve release script, update root level extension library 2024-05-03 06:38:41 -04:00
John Bintz 8232bcf6ca 1.1.4 2024-05-02 17:26:52 -04:00
John Bintz 1ee8e2c60c Remove gitignored files 2024-05-02 17:23:25 -04:00
John Bintz 4b4ec33440 Merge branch 'jb/1.0.1-is-working' 2024-05-02 17:22:14 -04:00
John Bintz 780a1820f3 Missing label colon 2024-05-02 17:13:55 -04:00
John Bintz ab20c1b1ea Preparing for release 2024-05-02 17:08:44 -04:00
John Bintz 4ba0993483 Update README 2024-05-02 17:06:03 -04:00
John Bintz cf1dff31b9 Change HiChaine approach for Dns Get Address By Name$ 2024-05-02 17:04:54 -04:00
John Bintz 79e77287bb Improve build script 2024-05-02 17:04:43 -04:00
John Bintz f93a33ee0d Even more bugfixes, this test suite breaks the system around AMOS 2024-04-28 21:15:19 -04:00
John Bintz e041696136 Source build 2024-04-27 07:04:15 -04:00
John Bintz bd6d8a1295 Fix test contexts 2024-04-27 07:03:51 -04:00
John Bintz cbb822f895 fix api thing 2024-04-26 22:44:33 -04:00
John Bintz 6db285d328 Use build in src directory for source rebuilds 2024-04-26 22:39:41 -04:00
John Bintz 534f04273b Rebuild source 2024-04-26 22:37:58 -04:00
John Bintz 3452973001 Update README 2024-04-26 22:35:36 -04:00
John Bintz 2ba9fd6c82 Finish up 1.1.4 2024-04-26 22:22:46 -04:00
John Bintz 12b859eaf3 wow it's working 2024-04-26 16:14:46 -04:00
John Bintz 8a4235270c test suite stuff 2024-04-26 14:41:00 -04:00
John Bintz 882ee8cba2 Starting on test suite, fixing some bugs found via it 2024-04-26 08:32:52 -04:00
John Bintz e4711f1783 Change up documentation structure 2024-04-26 07:10:14 -04:00
John Bintz b25f08cdae 1.1.3 works 2024-04-25 17:03:25 -04:00
John Bintz 771d40fab7 1.1.2 applied 2024-04-25 16:18:31 -04:00
John Bintz 53c73d8888 1.1.1 applied and working 2024-04-25 14:53:17 -04:00
John Bintz fdab7b432e 1.1.0 applied and working 2024-04-25 14:40:47 -04:00
John Bintz ade45f63b8 why is this working 2024-04-25 13:54:01 -04:00
15 changed files with 752 additions and 317 deletions

12
.gitignore vendored
View File

@ -4,13 +4,17 @@ dist/
build/
aminet/
Disk.info
private-test/
stuff/
patches/
.vamosrc
activate
test/report.txt
test/TestSuite.info
src/report.txt
src/BSDSocket_Labels.s
src/BSDSocket_Size.s
src/bsdsocket_lib.fd
src/bsdsocket_lvo.i
src/*.Lib
.vamosrc
activate
test/
patches/
libs/

Binary file not shown.

50
API.md
View File

@ -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
@ -324,32 +337,6 @@ out. There's no way to set this timeout, or cancel or override it via AMOS.
String with IP address, or blank string on error.
---
#### RESULT=Socket Status(Socket)
Returns basic connection information about a socket.
##### Warning
Since none of the socket processing of this extension happens in the
background, you're likely better off using other means to detect
socket status.
* Disconnected: Try a recv and get zero bytes back. Check Socket Errno.
* Broken: Try a send. If it fails, check Socket Errno.
* Ready: Use the Async Wait functions.
##### Returns
Status of socket:
* 0 = Closed
* 2 = Listening
* 6 = Connecting
* 7 = Connected
---
## Low Level
@ -397,8 +384,6 @@ Set or clear a socket bit in an fd_set.
* Address to that particular fd_set
* -1 if fd_set is out of range or socket is out of range.
---
#### RESULT=Socket Fdset Is Set(fd_set, Socket)
See if the particular socket remained after a Socket Select call.
@ -407,8 +392,6 @@ See if the particular socket remained after a Socket Select call.
* True or False if the socket is set or not
---
#### RESULT=Socket Select(Max Socket, Read fd_set, Write fd_set, Error fd_set, TimeoutMS)
Wait for the specified number of milliseconds. If any of the sockets
@ -420,3 +403,4 @@ how many sockets were left.
* 0 on timeout
* -1 on error
* # of interesting sockets on success

View File

@ -130,6 +130,7 @@ Socket Library Close
* [Hop to the Top: Bunny's Revenge](https://rabbit.robsmithdev.co.uk/)
* The game uses this extension to send and receive high score information.
I also did some of the art for the game!
* [Gopherized](https://allanon71.itch.io/gopherized)
Doing something cool with the extension?
[Contact me](https://theindustriousrabbit.com/about) and I'll add it to the list!
@ -152,6 +153,16 @@ Doing something cool with the extension?
timeouts using `Socket Async Wait Writing` to determine if the Internet
is available.
## Slot 18 taken already?
I'm also building releases for slots 9, 11, and 17. They're available for
separate download from each Release version 1.1.4 and on.
Note that you won't be able to load the test AMOS programs, or any other
progaam using the Slot 18 version, because AMOS uses the extension's slot
number in the saved tile. You'll have to export and import ASCII versions
of programs.
## Versioning
This project uses semantic versioning.
@ -168,10 +179,12 @@ throw a link to theindustriousrabbit.com somewhere! You can
also find a donate link on
[the About section on The Industrious Rabbit](https://theindustriousrabbit.com/about).
## Feedback? Bug reports?
## Feedback? Bug reports? Patches?
Go to the [About section on The Industrious Rabbit](https://theindustriousrabbit.com/about)
to contact me.
First, run `test/TestSuite` to generate a `report.txt` file.
Then, go to the [About section on The Industrious Rabbit](https://theindustriousrabbit.com/about)
to contact me, send the `report.txt` along with the details on your issue.
## Changelog
@ -207,13 +220,20 @@ to contact me.
* `Dns Get Address By Name$`
* `Socket Recv$`
### 1.1.3 (2024-04-17)
### 1.1.3
* Fix bug in fdset macro where using D3 for a parameter could cause corruption
* Copy a null-terminated copy of IP address for SocketIPAddressPortToSockaddr
* Retructure API docs for easier reading
Internal release.
# Development
### 1.1.4 (2024-05-02)
* Fix bug in fdset macro where using D3 for a parameter could cause corruption.
* Copy a null-terminated copy of IP address for `SocketIPAddressPortToSockaddr`.
* Add test suite to exercise extension functionality.
* Fix several crash bugs found due to the test suite.
* Retructure API docs for easier reading.
* Improve build and release tooling.
## Development
### Environment
@ -245,9 +265,25 @@ Run `bin/setup` to do most of the setups above.
### Debugging
#### Cross-platform
Modify data in the `DebugArea` and read it by `Peek`/`Deek`/`Leek`ing from
the base address provided by `Socket Get Debug Area`.
#### WinUAE/FS-UAE
In the debugger, set a memory breakpoint at `$100` for two written bytes:
```
w 0 100 2
```
Then, in your code, clear those two bytes to stop execution at that point:
```asm
CLR.W $100
```
### Releasing
#### Ubuntu/Debian

View File

@ -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
~/Projects/amostools/listamos -e src/AMOSPro_BSDSocket.Lib "${i}" > "${i%.amos}.basic" 2>/dev/null
done

View File

@ -24,6 +24,22 @@ source.lines.each do |line|
end
end
FileUtils.cp 'src/AMOSPro_BSDSocket.Lib', 'AMOSPro_BSDSocket.Lib'
strings = []
Open3.popen2e('strings', 'AMOSPro_BSDSocket.Lib') do |stdin, stdout_and_stderr, wait_thr|
stdin.close
stdout_and_stderr.each { |l| strings << l }
wait_thr.join
end
unless strings.any? { |s| s[version] }
puts "Extension build doesn't match source version! Did you rebuild it yet on the Amiga?"
exit 1
end
FileUtils.mkdir_p 'dist'
build_base = 'build'
@ -35,8 +51,6 @@ FileUtils.rm_rf 'aminet'
FileUtils.mkdir_p build_dir
FileUtils.mkdir_p 'aminet'
FileUtils.mv 'src/AMOSPro_BSDSocket.Lib', 'AMOSPro_BSDSocket.Lib' if File.exist?('src/AMOSPro_BSDSocket.Lib')
hackerbun_target = File.expand_path("dist/AMOSPro_BSDSocket_#{version}.lha")
[

View File

@ -1,42 +0,0 @@
; get the effective address of something in extension memory
Dlea MACRO
MOVE.L ExtAdr+ExtNb*16(A5),\2
ADD.W #\1-MB,\2
ENDM
; load the base of extension memory into a register
Dload MACRO
MOVE.L ExtAdr+ExtNb*16(A5),\1
ENDM
; wrap code that doesn't take arguments with these
PreserveStackInstruction MACRO
MOVEM.L A2-A6/D6-D7,-(SP)
ENDM
RestoreStackInstruction MACRO
MOVEM.L (SP)+,A2-A6/D6-D7
ENDM
; wrap code that takes arguments with these
PreserveStackFunction MACRO
MOVEM.L A2/A4-A6/D6-D7,-(SP)
ENDM
RestoreStackFunction MACRO
MOVEM.L (SP)+,A2/A4-A6/D6-D7
ENDM
; Push and pop the extension's data storage into A3
WithDataStorageToA3 MACRO
MOVE.L A3,-(SP)
Dload A3
ENDM
EndDataStorage MACRO
MOVE.L (SP)+,A3
ENDM
EvenOutStringAddress MACRO
MOVE.W \1,\2
AND.W #$0001,\2
ADD.W \2,\1
ENDM

View File

@ -5,9 +5,10 @@
; Writing this code the right way, 25 years later.
; extension number 18
ExtNb equ 18-1
; this now comes from GenAm command line option
;ExtNb equ 18-1
Version MACRO
dc.b "1.1.3-20240417"
dc.b "1.1.4-20240502"
ENDM
VerNumber equ $1
@ -22,23 +23,190 @@ VerNumber equ $1
Include "+AMOS_Includes.s"
Include "bsdsocket_lvo.i"
Include "LongDivide.s"
Include "Constants.s"
Include "fd_set.s"
Include "AMOSMacros.s"
; get the effective address of something in extension memory
Dlea MACRO
MOVE.L ExtAdr+ExtNb*16(A5),\2
ADD.W #\1-MB,\2
ENDM
; load the base of extension memory into a register
Dload MACRO
MOVE.L ExtAdr+ExtNb*16(A5),\1
ENDM
; call an AmigaOS function via LVO(A6)
CALLLIB MACRO
JSR _LVO\1(A6)
ENDM
; bsdsocket library stuff
; ported from the various C include headers
SOCK_STREAM EQU 1
PF_INET EQU 2
AF_INET EQU PF_INET
IPPROTO_TCP EQU 6
; get the BSDSocket library ready for CALLLIB
LoadBSDSocketBaseFromA3 MACRO
INADDR_ANY EQU 0
FIONBIO EQU $8004667E
FIONASYNC EQU $8004667D
SOL_SOCKET EQU $FFFF
SO_REUSEADDR EQU $4
MAX_SOCKETS EQU 64
len_sockaddr_in EQU 16
sockaddr_in_sin_family EQU 1
sockaddr_in_sin_port EQU 2
sockaddr_in_sin_addr EQU 4
; global errors
Error_OtherError EQU -1
Error_LibraryNotOpen EQU -2
Error_PortOutOfRange EQU -11
Error_FdsetOutOfRange EQU -11
Error_UnableToBind EQU -12
; socket herrno and tag lists
; built from:
; * https://wiki.amigaos.net/amiga/autodocs/bsdsocket.doc.txt
; * https://github.com/deplinenoise/amiga-sdk/blob/master/netinclude/amitcp/socketbasetags.h
; * http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_2._guide/node012E.html
TAG_USER EQU (1<<31)
SBTF_REF EQU $8000
SBTB_CODE EQU 1
SBTS_CODE EQU $3FFF
SBTC_HERRNO EQU 6
HerrnoTag EQU (TAG_USER|SBTF_REF|((SBTC_HERRNO&SBTS_CODE)<<SBTB_CODE))
; wrap code that doesn't take arguments with these
PreserveStackInstruction MACRO
MOVEM.L A2-A6/D6-D7,-(SP)
ENDM
RestoreStackInstruction MACRO
MOVEM.L (SP)+,A2-A6/D6-D7
ENDM
; wrap code that takes arguments with these
PreserveStackFunction MACRO
MOVEM.L A2/A4-A6/D6-D7,-(SP)
ENDM
RestoreStackFunction MACRO
MOVEM.L (SP)+,A2/A4-A6/D6-D7
ENDM
LoadBSDSocketBase MACRO
MOVE.L BSDSocketBase-MB(A3),A6
ENDM
WithDataStorage MACRO
MOVE.L A3,-(SP)
Dload A3
ENDM
EndDataStorage MACRO
MOVE.L (SP)+,A3
ENDM
; fdset macros
EnsureValidFdset MACRO
CMP.L #MaxFd_sets,\1
BLT \2
MOVE.L #Error_FdsetOutOfRange,D3
RestoreStackFunction
Ret_Int
ENDM
EnsureValidFdsetBit MACRO
CMP.L #64,\1
BGE _EnsureValidFdsetBit_Fail\@
BRA \2
_EnsureValidFdsetBit_Fail\@:
MOVE.L \3,D3
RestoreStackFunction
Ret_Int
ENDM
LeaFdset MACRO
MOVE.L \1,-(SP)
Dlea fd_sets,\2 ; base of all, these are longs
ROL.L #3,\1 ; multiply by 8
ADD.L \1,\2 ; add to base of all
MOVE.L (SP)+,\1
ENDM
; LeaFdsetForBit fd_set reg,target address,target bit in address
LeaFdsetForBit MACRO
LeaFdset \1,\2 ; get fdset base address in \2
MOVEM.L D3-D4,-(SP)
MOVE.L \3,D3 ; Put target bit into D3
ROR.L #5,D3 ; lop off the first 5 bits
AND.L #$7,D3 ; only keep the top three
ROL.L #2,D3 ; multiply by 4
ADD.L D3,\2 ; add that value to the fdset address
MOVE.L \3,D4
AND.L #$1F,D4 ; only keep 0-31 in \3
MOVEQ #1,D3
ROL.L D4,D3 ; shift that bit left as many as target
MOVE.L D3,\3 ; put that in the target
MOVEM.L (SP)+,D3-D4
ENDM
; d0 = value to be divided
; d1 = divisor
; returns:
; d0 = divided value
; d1 = remainder
LongDivideD0ByD1 MACRO
CMP.L D0,D1
BMI _LongDivide_StartDivide\@
MOVE.L D0,D1
MOVEQ #0,D0
BRA _LongDivide_Skip\@
_LongDivide_StartDivide\@:
MOVEM.L D2-D4,-(SP)
MOVEQ #0,D2 ; remainder
MOVE.L #31,D3 ; bit tracking
; d4 tracks the status register
_LongDivide_ContinueDivide\@:
ASL.L #1,D0
SCS D4 ; bit that got rolled out
AND.L #1,D4
ROL.L #1,D2
ADD.L D4,D2 ; roll the value onto the remainder
MOVE.L D2,D4
SUB.L D1,D4
BMI _LongDivide_NotDivisible\@
ADDQ #1,D0
MOVE.L D4,D2
_LongDivide_NotDivisible\@:
DBRA D3,_LongDivide_ContinueDivide\@
MOVE.L D2,D1
MOVEM.L (SP)+,D2-D4
_LongDivide_Skip\@:
ENDM
EvenOutStringAddress MACRO
MOVE.W \1,\2
AND.W #$0001,\2
ADD.W \2,\1
ENDM
; check if we've opened the bsd socket library
; we do this a lot, this could probably become something
; we jsr to...
@ -290,16 +458,16 @@ End
CALLLIB OpenLibrary
MOVE.L D0,BSDSocketBase-MB(A3)
BEQ .Finish
BEQ _SocketLibraryOpen_Finish
; reserve ram for sockaddr_ins
MOVE.L #MAX_SOCKETS*len_sockaddr_in,D0
Rjsr L_RamFast
BEQ .Finish
BEQ _SocketLibraryOpen_Finish
MOVE.L D0,sockaddr_ram-MB(A3)
.Finish:
_SocketLibraryOpen_Finish:
MOVE.L BSDSocketBase-MB(A3),D3
RestoreStackInstruction
@ -345,7 +513,7 @@ End
;
; Turn an IP address and port into a sockaddr_in strucure
;
; d0 - 0 on success, -1 on failure
; d0 - address of sockaddr_in on success, -1 on failure
; - - - - - - - -
Lib_Def SocketIPAddressPortToSockaddr
@ -366,11 +534,19 @@ _ToSockaddr_PortOK:
MOVE.L sockaddr_ram-MB(A3),A0
ADD.L D3,A0 ; A0 contains our offset in ram
MOVEM.L A1-A3/D3,-(SP)
MOVEM.L A0-A3/D3,-(SP)
MOVE.L D1,A1 ; ip string address
MOVE.W (A1)+,D3 ; string length
BNE _ToSockaddr_StringHasLength
MOVEM.L (SP)+,A0-A3/D3
MOVEM.L (SP)+,A0/A3/D3
MOVE.L #-14,D0
RTS
_ToSockaddr_StringHasLength:
; temporarily store a null-terminated copy of the ip string in A0
MOVE.L A0,A2
SUBQ #1,D3 ; DBRA loop runs D3 + 1 times
@ -397,14 +573,15 @@ _ToSockaddr_KeepCheckingString_2:
_ToSockaddr_ParseIPAddress:
Dload A3
LoadBSDSocketBaseFromA3
LoadBSDSocketBase
CALLLIB inet_addr
_ToSockaddr_DoneParsing:
MOVEM.L (SP)+,A1-A3/D3
MOVEM.L (SP)+,A0-A3/D3
; create struct sockaddr_in
MOVE.W #AF_INET,sockaddr_in_sin_family(A0)
MOVE.B #len_sockaddr_in,(A0)
MOVE.B #AF_INET,sockaddr_in_sin_family(A0)
MOVE.W D2,sockaddr_in_sin_port(A0)
LEA sockaddr_in_sin_addr(A0),A3
MOVE.L D0,(A3)+
@ -440,7 +617,7 @@ _SocketCreateInetSocket_LibraryOpen:
MOVE.L #SOCK_STREAM,D1
MOVE.L #IPPROTO_TCP,D2
Dload A3
LoadBSDSocketBaseFromA3
LoadBSDSocketBase
CALLLIB socket
MOVE.L D0,D3
@ -489,7 +666,6 @@ _SocketCreateInetSocket_Done:
Ret_Int
_SocketConnect_LibraryOpen:
MOVE.L D0,-(SP) ; socket id onto stack
Rbsr L_SocketIPAddressPortToSockaddr
@ -513,7 +689,7 @@ _SocketConnect_SockaddrIn:
; socket id is in D0
; sockaddr_in is in A0
MOVE.L #len_sockaddr_in,D1 ; len
LoadBSDSocketBaseFromA3
LoadBSDSocketBase
CALLLIB connect
MOVEM.L (SP)+,A0/A3
@ -549,8 +725,8 @@ _SocketConnect_SockaddrIn:
_SocketSendString_LibraryOpen:
MOVEQ #0,D2 ; flags
WithDataStorageToA3
LoadBSDSocketBaseFromA3
WithDataStorage
LoadBSDSocketBase
CALLLIB send
EndDataStorage
@ -595,8 +771,8 @@ _SocketSendData_LibraryOpen:
_SocketSendData_NotNegative:
MOVEQ #0,D2 ; flags
WithDataStorageToA3
LoadBSDSocketBaseFromA3
WithDataStorage
LoadBSDSocketBase
CALLLIB send
EndDataStorage
@ -646,11 +822,11 @@ _SocketBind_SockaddrIn:
MOVE.L D0,A0
MOVE.L (SP)+,D0
WithDataStorageToA3
WithDataStorage
; socket id is in D0
; sockaddr_in is in A0
MOVE.L #len_sockaddr_in,D1 ; len
LoadBSDSocketBaseFromA3
LoadBSDSocketBase
CALLLIB bind
EndDataStorage
@ -669,22 +845,22 @@ _SocketBind_SockaddrIn:
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Lib_Par SocketErrno
; - - - - - - - - - - - - -
PreserveStackInstruction
PreserveStackFunction
EnsureBSDSocketLibrary _SocketErrno_LibraryOpen
RestoreStackInstruction
RestoreStackFunction
Ret_Int
_SocketErrno_LibraryOpen:
WithDataStorageToA3
LoadBSDSocketBaseFromA3
WithDataStorage
LoadBSDSocketBase
CALLLIB Errno
EndDataStorage
MOVE.L D0,D3
RestoreStackInstruction
RestoreStackFunction
RTS
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -712,8 +888,8 @@ _SocketListen_LibraryOpen:
MOVE.L D3,D2
MOVEQ #5,D1
WithDataStorageToA3
LoadBSDSocketBaseFromA3
WithDataStorage
LoadBSDSocketBase
CALLLIB listen
EndDataStorage
@ -748,10 +924,10 @@ _SocketAccept_LibraryOpen:
MOVE.L D3,D2
WithDataStorageToA3
WithDataStorage
Dlea AcceptScratchArea,A0
Dlea len_sockaddr_in_ptr,A1
LoadBSDSocketBaseFromA3
LoadBSDSocketBase
CALLLIB accept
EndDataStorage
@ -814,11 +990,11 @@ _SocketSetNonblocking_IsBlocking:
_SocketSetNonblocking_Ioctl:
WithDataStorageToA3
WithDataStorage
MOVE.L D1,IoctlSockOptScratch-MB(A3)
Dlea IoctlSockOptScratch,A0
MOVE.L #FIONBIO,D1
LoadBSDSocketBaseFromA3
LoadBSDSocketBase
CALLLIB IoctlSocket
MOVE.L D0,D3
@ -876,12 +1052,12 @@ _SocketGetsockoptInt_LibraryOpen:
MOVE.L #SOL_SOCKET,D1 ; level
MOVE.L A3,-(SP)
WithDataStorageToA3
WithDataStorage
Dlea IoctlSockOptScratch,A0 ; optval
MOVE.L #4,getsockopt_len-MB(A3)
Dlea getsockopt_len,A1
LoadBSDSocketBaseFromA3
LoadBSDSocketBase
CALLLIB getsockopt
EndDataStorage
MOVE.L (SP)+,A3
@ -1155,6 +1331,12 @@ _SocketSelect_PerformSelect
; - - - - - - - - - - - - -
PreserveStackFunction
EnsureBSDSocketLibrary _SocketGetHost_LibraryOpen
RestoreStackFunction
Ret_Int
_SocketGetHost_LibraryOpen:
MULU #len_sockaddr_in,D3
Dload A0
MOVE.L sockaddr_ram-MB(A0),A0
@ -1175,6 +1357,13 @@ _SocketSelect_PerformSelect
; - - - - - - - - - - - - -
PreserveStackFunction
EnsureBSDSocketLibrary _SocketGetPort_LibraryOpen
RestoreStackFunction
Ret_Int
_SocketGetPort_LibraryOpen:
MULU #len_sockaddr_in,D3
Dload A0
MOVE.L sockaddr_ram-MB(A0),A0
@ -1195,15 +1384,17 @@ _SocketSelect_PerformSelect
Lib_Par SocketInetNtoA
; - - - - - - - - - - - - -
PreserveStackFunction
EnsureBSDSocketLibrary _SocketInetNtoA_LibraryOpen
EnsureBSDSocketLibrary _SocketInetNtoa_LibraryOpen
MOVE.L ChVide(A5),D3
RestoreStackFunction
Ret_Int
Ret_String
_SocketInetNtoA_LibraryOpen:
_SocketInetNtoa_LibraryOpen:
MOVE.L D3,D0
WithDataStorageToA3
LoadBSDSocketBaseFromA3
WithDataStorage
LoadBSDSocketBase
CALLLIB Inet_NtoA
EndDataStorage
@ -1233,6 +1424,7 @@ _SocketInetNtoA_StringSizeLoop:
MOVE.W D4,(A0)+ ; length of string
SUBQ #1,D4
_SocketInetNtoA_StringCopyLoop:
MOVE.B (A2,D4),(A0,D4)
DBRA D4,_SocketInetNtoA_StringCopyLoop
@ -1283,12 +1475,14 @@ _SocketRecvString_NotNegative:
_SocketRecvString_NotTooLong:
MOVE.L A3,-(SP) ; preserve A3
MOVE.L D0,-(SP) ; preserve D0
; reserve memory for recv buffer
Rjsr L_RamFast ; D0 now contains memory pointer
BNE _SocketRecvString_BufferAllocated
; reserve failed
MOVE.L (SP)+,D0
MOVE.L (SP)+,A3
MOVE.L ChVide(A5),D3 ; empty string
@ -1302,10 +1496,12 @@ _SocketRecvString_BufferAllocated:
MOVEQ #0,D2 ; flags
MOVEM.L A0-A1/D1,-(SP)
WithDataStorageToA3
LoadBSDSocketBaseFromA3
WithDataStorage
LoadBSDSocketBase
CALLLIB recv ; D0 has received length or -1
EndDataStorage
MOVEM.L (SP)+,A0-A1/D1
; did we receive data? if we didn't get a single byte, we're done
@ -1316,6 +1512,7 @@ _SocketRecvString_BufferAllocated:
MOVE.L D1,D0
MOVE.L A0,A1
Rjsr L_RamFree
MOVE.L (SP)+,A3
MOVE.L ChVide(A5),D3
@ -1323,7 +1520,6 @@ _SocketRecvString_BufferAllocated:
Ret_String
; TODO received data is wrong somewhere
_SocketRecvString_DataReceived:
; D0 contains socket receive length
@ -1355,7 +1551,7 @@ _SocketRecvString_CopyData:
MOVE.L A0,-(SP)
MOVE.L A3,A1
Rjsr L_RamFree
MOVE.L (SP)+,D3
MOVE.L (SP)+,D3 ; string return
MOVE.L (SP)+,A3
RestoreStackFunction
@ -1394,8 +1590,8 @@ _SocketRecvData_LibraryOpen:
Ret_Int
_SocketRecvData_PositiveLength:
WithDataStorageToA3
LoadBSDSocketBaseFromA3
WithDataStorage
LoadBSDSocketBase
CALLLIB recv ; D0 has received length or -1
EndDataStorage
@ -1404,6 +1600,8 @@ _SocketRecvData_PositiveLength:
RestoreStackFunction
Ret_Int
; actually close the library
Lib_Def DoSocketLibraryClose
@ -1418,6 +1616,7 @@ _SocketRecvData_PositiveLength:
CLR.L sockaddr_ram-MB(A3) ; prevent double free
_DoSocketLibraryClose_CloseLibrary:
MOVE.L BSDSocketBase-MB(A3),D0
BEQ _DoSocketLibraryClose_Skip
@ -1474,7 +1673,7 @@ _SocketWaitAsyncWriting_LibraryOpen:
Rbsr L_MicrosecondsToTimeval ; A3 contains timeval
Dload A4
MOVE.L D0,-(SP)
MOVEM.L D0,-(SP)
; set up WaitSelect
MOVEQ #0,D1
LeaFdset D1,A1 ; write fdset
@ -1496,7 +1695,7 @@ _SocketWaitAsyncWriting_LibraryOpen:
TST.L D0
BEQ _SocketWaitAsyncWriting_Timeout
BMI _SocketWaitAsyncWriting_Error
MOVE.L (SP)+,D0 ; D0 contains socket again
MOVEM.L (SP)+,D0 ; D0 contains socket again
Dload A4
; a socket became interesting, check the Fdset
@ -1522,19 +1721,19 @@ _SocketWaitAsyncWriting_CheckSockopt:
MOVE.L A3,-(SP)
WithDataStorageToA3
WithDataStorage
Dlea IoctlSockOptScratch,A0 ; optval
MOVE.L #4,getsockopt_len-MB(A3)
Dlea getsockopt_len,A1
LoadBSDSocketBaseFromA3
LoadBSDSocketBase
CALLLIB getsockopt
EndDataStorage
MOVE.L (SP)+,A3
TST.L D0
BMI _SocketWaitAsyncWriting_Error
BMI _SocketWaitAsyncWriting_Error2
Dlea IoctlSockOptScratch,A0
MOVE.L (A0),D0
@ -1556,6 +1755,7 @@ _SocketWaitAsyncWriting_Ready:
_SocketWaitAsyncWriting_Error:
MOVE.L (SP)+,D1
_SocketWaitAsyncWriting_Error2:
MOVEM.L (SP)+,A3-A4
MOVE.L #-1,D3
@ -1637,7 +1837,6 @@ _SocketWaitAsyncReading_LibraryOpen:
BMI _SocketWaitAsyncReading_Done
MOVE.L (SP)+,D0 ; D0 contains socket again
;Dload A4
; a socket became interesting, check the Fdset
MOVE.L D0,D3 ; socket in D3
MOVEQ #0,D1 ; fdset in D1
@ -1732,12 +1931,12 @@ _SocketReuseAddr_LibraryOpen:
MOVE.L #SOL_SOCKET,D1 ; Level
WithDataStorageToA3
WithDataStorage
Dlea IoctlSockOptScratch,A0 ; optval
MOVE.L D3,A0
MOVEQ #4,D3
LoadBSDSocketBaseFromA3
LoadBSDSocketBase
CALLLIB setsockopt
EndDataStorage
@ -1748,44 +1947,46 @@ _SocketReuseAddr_LibraryOpen:
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; =Dns Get Address By Name$(Name String)
;
; Get the status of a socket
; Convert a host name to an IP address
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Lib_Par DnsGetHostAddressByName
PreserveStackFunction
EnsureBSDSocketLibrary .LibraryOpen
EnsureBSDSocketLibrary _DnsGetHostAddressByName_LibraryOpen
MOVE.L ChVide(A5),D3
RestoreStackFunction
Ret_String
.LibraryOpen:
_DnsGetHostAddressByName_LibraryOpen:
; string so you need demande, hichaine, and chvide
MOVE.L D3,A0 ; name
MOVEQ #0,D0
MOVE.W (A0)+,D0 ; d0 contains length
MOVE.L D0,D1 ; d1 also has length
MOVE.L D0,D2 ; d2 also has length
Rjsr L_RamFast ; d0 contains address
BNE .StringRamAllocated
BNE _DnsGetHostAddressByName_StringRamAllocated
MOVE.L ChVide(A5),D3
RestoreStackFunction
Ret_String
.StringRamAllocated:
_DnsGetHostAddressByName_StringRamAllocated:
MOVE.L D0,A1 ; a1 contains address
SUBQ #1,D1 ; reduce by one for DBRA
.KeepCopyingAMOSString
_DnsGetHostAddressByName_KeepCopyingAMOSString:
MOVE.B (A0)+,(A1)+ ; byte copy
DBRA D1,.KeepCopyingAMOSString ; keep copying
DBRA D1,_DnsGetHostAddressByName_KeepCopyingAMOSString ; keep copying
MOVE.B #0,(A1)+ ; null terminate string
MOVE.L D0,A0 ; first param of gethostbyname
MOVEM.L A0/D2,-(SP)
WithDataStorageToA3
LoadBSDSocketBaseFromA3
WithDataStorage
LoadBSDSocketBase
CALLLIB gethostbyname
EndDataStorage
MOVEM.L (SP)+,A0/D2
@ -1798,21 +1999,21 @@ _SocketReuseAddr_LibraryOpen:
MOVE.L (SP)+,D0
TST.L D0
BNE .GetIPAddress
BNE _DnsGetHostAddressByName_GetIPAddress
RestoreStackFunction
MOVE.L ChVide(A5),D3
Ret_String
.GetIPAddress:
_DnsGetHostAddressByName_GetIPAddress:
MOVE.L D0,A0
MOVE.L 16(A0),A1 ; **h_addr_list
MOVE.L (A1),A1 ; *h_addr_list
MOVE.L (A1),D0 ; h_addr_list[0]
WithDataStorageToA3
LoadBSDSocketBaseFromA3
WithDataStorage
LoadBSDSocketBase
CALLLIB Inet_NtoA
EndDataStorage
@ -1820,27 +2021,32 @@ _SocketReuseAddr_LibraryOpen:
MOVE.L A2,-(SP)
MOVEQ #0,D3
.GetIPAddressLength:
_DnsGetHostAddressByName_GetIPAddressLength:
ADDQ #1,D3
TST.B (A2)+
BNE .GetIPAddressLength
BNE _DnsGetHostAddressByName_GetIPAddressLength
MOVE.L (SP)+,A2
SUBQ #1,D3
MOVE.L D3,D4
AND.W #$FFFE,D3
ADDQ #2,D3
Rjsr L_Demande ; string is in A0/A1
LEA 2(A0,D3.W),A1
MOVE.L A1,HiChaine(A5)
MOVE.L A0,D3
MOVE.L A0,A1
MOVE.W D4,(A1)+
MOVE.W D4,(A0)+
SUBQ #1,D4
.KeepCopying:
MOVE.B (A2,D4),(A0,D4)
DBRA D4,.KeepCopying
_DnsGetHostAddressByName_KeepCopying:
MOVE.B (A2)+,(A1)+
DBRA D4,_DnsGetHostAddressByName_KeepCopying
MOVE.L A0,D3
RestoreStackFunction
@ -1855,7 +2061,7 @@ _SocketReuseAddr_LibraryOpen:
; - - - - - - - - - - - - -
PreserveStackFunction
MOVE.L D3,D4 ; milliseconds
MOVE.L D3,D4 ; milliseconts
MOVE.L (A3)+,D0 ; socket id
EnsureBSDSocketLibrary _SocketSetTimeout_LibraryOpen
@ -1877,7 +2083,7 @@ _SocketSetTimeout_LibraryOpen:
MOVE.L (A0)+,(A1)+
SUB.L #8,A1 ; go back
WithDataStorageToA3
WithDataStorage
; socket is d0
MOVE.L #SOL_SOCKET,D1 ; Level
MOVE.L #$1005,D2 ; SO_SNDTIMEO
@ -1885,7 +2091,7 @@ _SocketSetTimeout_LibraryOpen:
MOVEQ #8,D3
MOVEM.L D0/A0,-(SP)
LoadBSDSocketBaseFromA3
LoadBSDSocketBase
CALLLIB setsockopt
TST.L D0
@ -1896,7 +2102,7 @@ _SocketSetTimeout_LibraryOpen:
MOVE.L #$1006,D2 ; SO_RCVTIMEO
MOVEQ #8,D3
LoadBSDSocketBaseFromA3
LoadBSDSocketBase
CALLLIB setsockopt
EndDataStorage
@ -1923,17 +2129,17 @@ _SocketSetTimeout_Fail:
Lib_Par SocketCloseSocket
; - - - - - - - - - - - - -
PreserveStackFunction
EnsureBSDSocketLibrary .LibraryOpen
EnsureBSDSocketLibrary _SocketCloseSocket_LibraryOpen
RestoreStackFunction
Ret_Int
.LibraryOpen:
_SocketCloseSocket_LibraryOpen:
MOVE.L D3,D0
WithDataStorageToA3
LoadBSDSocketBaseFromA3
WithDataStorage
LoadBSDSocketBase
CALLLIB CloseSocket
EndDataStorage
@ -1950,7 +2156,12 @@ _SocketSetTimeout_Fail:
Lib_Par SocketHerrno
; - - - - - - - - - - - - -
PreserveStackFunction
EnsureBSDSocketLibrary _SocketHerrno_LibraryOpen
RestoreStackFunction
Ret_Int
_SocketHerrno_LibraryOpen:
; set up tag list memory and place for herrno to go
Dlea AcceptScratchArea,A0
MOVE.L A0,A2
@ -1963,13 +2174,13 @@ _SocketSetTimeout_Fail:
MOVE.L 0,(A0)+
MOVE.L A2,A0
WithDataStorageToA3
LoadBSDSocketBaseFromA3
WithDataStorage
LoadBSDSocketBase
CALLLIB SocketBaseTagList
EndDataStorage
TST.L D0
BEQ .success
BEQ _SocketHerrno_success
; failed
MOVE.L #-1,D3
@ -1977,7 +2188,7 @@ _SocketSetTimeout_Fail:
RestoreStackFunction
Ret_Int
.success
_SocketHerrno_success:
MOVE.L (A1),D3
RestoreStackFunction

View File

@ -1,42 +0,0 @@
; bsdsocket library stuff
; ported from the various C include headers
SOCK_STREAM EQU 1
PF_INET EQU 2
AF_INET EQU PF_INET
IPPROTO_TCP EQU 6
INADDR_ANY EQU 0
FIONBIO EQU $8004667E
FIONASYNC EQU $8004667D
SOL_SOCKET EQU $FFFF
SO_REUSEADDR EQU $4
MAX_SOCKETS EQU 64
len_sockaddr_in EQU 16
sockaddr_in_sin_family EQU 0
sockaddr_in_sin_port EQU 2
sockaddr_in_sin_addr EQU 4
; global errors
Error_OtherError EQU -1
Error_LibraryNotOpen EQU -2
Error_PortOutOfRange EQU -11
Error_FdsetOutOfRange EQU -11
Error_UnableToBind EQU -12
; socket herrno and tag lists
; built from:
; * https://wiki.amigaos.net/amiga/autodocs/bsdsocket.doc.txt
; * https://github.com/deplinenoise/amiga-sdk/blob/master/netinclude/amitcp/socketbasetags.h
; * http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_2._guide/node012E.html
TAG_USER EQU (1<<31)
SBTF_REF EQU $8000
SBTB_CODE EQU 1
SBTS_CODE EQU $3FFF
SBTC_HERRNO EQU 6
HerrnoTag EQU (TAG_USER|SBTF_REF|((SBTC_HERRNO&SBTS_CODE)<<SBTB_CODE))

View File

@ -1,43 +0,0 @@
; d0 = value to be divided
; d1 = divisor
; returns:
; d0 = divided value
; d1 = remainder
LongDivideD0ByD1 MACRO
CMP.L D0,D1
BMI _LongDivide_StartDivide\@
MOVE.L D0,D1
MOVEQ #0,D0
BRA _LongDivide_Skip\@
_LongDivide_StartDivide\@:
MOVEM.L D2-D4,-(SP)
MOVEQ #0,D2 ; remainder
MOVE.L #31,D3 ; bit tracking
; d4 tracks the status register
_LongDivide_ContinueDivide\@:
ASL.L #1,D0
SCS D4 ; bit that got rolled out
AND.L #1,D4
ROL.L #1,D2
ADD.L D4,D2 ; roll the value onto the remainder
MOVE.L D2,D4
SUB.L D1,D4
BMI _LongDivide_NotDivisible\@
ADDQ #1,D0
MOVE.L D4,D2
_LongDivide_NotDivisible\@:
DBRA D3,_LongDivide_ContinueDivide\@
MOVE.L D2,D1
MOVEM.L (SP)+,D2-D4
_LongDivide_Skip\@:
ENDM

View File

@ -2,12 +2,19 @@ echo "***Assembling AMOSPro_BSDSocket.Lib"
assign AMOSPro_System: SYS:Development/AMOS_Pro
assign AMOSPro_Sources: amos-pro-bsdsocket-extension:stuff/AMOS-Professional-Official
AMOSPro_Sources:c/Library_Digest BSDSocket.s
AMOSPro_Sources:c/Genam FROM BSDSocket.s TO AMOSPro_BSDSocket.Lib
AMOSPro_Sources:c/Genam FROM BSDSocket.s TO AMOSPro_BSDSocket.Lib -e ExtNb=18-1
;delete >NIL: BSDSocket_Labels.s
;delete >NIL: BSDSocket_Size.s
FAILAT 21
copy AMOSPro_System:APSystem/AMOSPro_BSDSocket.lib AMOSPro_System:APSystem/AMOSPro_BSDSocket.lib.bak
FAILAT 10
copy AMOSPro_BSDSocket.Lib AMOSPro_System:APSystem/
;use an amos file here that includes the plugin to quickly build a test program
;apcmp "aqua_test_plugin.amos" inclib
apcmp "/test/TestSuite.amos" inclib
echo "Build for slot 9"
AMOSPro_Sources:c/Genam FROM BSDSocket.s TO AMOSPro_BSDSocket_Slot9.Lib -e ExtNb=9-1
echo "Build for slot 11"
AMOSPro_Sources:c/Genam FROM BSDSocket.s TO AMOSPro_BSDSocket_Slot11.Lib -e ExtNb=11-1
echo "Build for slot 17"
AMOSPro_Sources:c/Genam FROM BSDSocket.s TO AMOSPro_BSDSocket_Slot17.Lib -e ExtNb=17-1

View File

@ -1,48 +0,0 @@
; fdset macros
EnsureValidFdset MACRO
CMP.L #MaxFd_sets,\1
BLT \2
MOVE.L #Error_FdsetOutOfRange,D3
RestoreStackFunction
Ret_Int
ENDM
EnsureValidFdsetBit MACRO
CMP.L #64,\1
BGE _EnsureValidFdsetBit_Fail\@
BRA \2
_EnsureValidFdsetBit_Fail\@:
MOVE.L \3,D3
RestoreStackFunction
Ret_Int
ENDM
; LeaFdset fd_set reg,target
LeaFdset MACRO
MOVE.L \1,-(SP)
Dlea fd_sets,\2 ; base of all, these are longs
ROL.L #3,\1 ; multiply by 8
ADD.L \1,\2 ; add to base of all
MOVE.L (SP)+,\1
ENDM
; LeaFdsetForBit fd_set reg,target address,target bit in address
LeaFdsetForBit MACRO
LeaFdset \1,\2 ; get fdset base address in \2
MOVEM.L D3-D4,-(SP)
MOVE.L \3,D3 ; Put target bit into D3
ROR.L #5,D3 ; lop off the first 5 bits
AND.L #$7,D3 ; only keep the top three
ROL.L #2,D3 ; multiply by 4
ADD.L D3,\2 ; add that value to the fdset address
MOVE.L \3,D4
AND.L #$1F,D4 ; only keep 0-31 in \3
MOVEQ #1,D3
ROL.L D4,D3 ; shift that bit left as many as target
MOVE.L D3,\3 ; put that in the target
MOVEM.L (SP)+,D3-D4
ENDM

BIN
test/TestSuite Normal file

Binary file not shown.

BIN
test/TestSuite.amos Normal file

Binary file not shown.

354
test/TestSuite.basic Normal file
View File

@ -0,0 +1,354 @@
' 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
_END_CONTEXT
_BEGIN_CONTEXT["Socket Get Host"]
_BEGIN_CONTEXT["socket id too high"]
RESULT=Socket Get Host(999999)
_ADD_TO_REPORT[Str$(RESULT)]
_END_CONTEXT
_BEGIN_CONTEXT["socket id is valid"]
RESULT=Socket Get Host(SOCKET)
_ADD_TO_REPORT[Str$(RESULT)]
_END_CONTEXT
_END_CONTEXT
_BEGIN_CONTEXT["Socket Get Port"]
_BEGIN_CONTEXT["socket id too high"]
RESULT=Socket Get Port(999999)
_ADD_TO_REPORT[Str$(RESULT)]
_END_CONTEXT
_BEGIN_CONTEXT["socket id is valid"]
RESULT=Socket Get Port(SOCKET)
_ADD_TO_REPORT[Str$(RESULT)]
_END_CONTEXT
_END_CONTEXT
_BEGIN_CONTEXT["Socket Inet Ntoa$"]
_BEGIN_CONTEXT["Use the socket host"]
RESULT$=Socket Inet Ntoa$(Socket Get Host(SOCKET))
_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 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
'Goto _FINISH_SUITE
_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"]
BASE$="12345678901234567890"
For I=0 To 19
Mid$(BASE$,I+1,1)=Chr$(Peek(Start(20)+I))
Next I
_ADD_TO_REPORT[BASE$]
_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
_BEGIN_CONTEXT["Call functions with library closed"]
_=Socket Set Nonblocking(0,True)
_ADD_TO_REPORT["Socket Set Nonblocking"]
_=Socket Reuse Addr(0)
_ADD_TO_REPORT["Socket Reuse Addr"]
_=Socket Create Inet Socket
_ADD_TO_REPORT["Socket Create Inet Socket"]
_=Socket Connect(0 To "",0)
_ADD_TO_REPORT["Socket Connect"]
_=Socket Bind(0 To "",0)
_ADD_TO_REPORT["Socket Bind"]
_=Socket Listen(0)
_ADD_TO_REPORT["Socket Listen"]
_=Socket Accept(0)
_ADD_TO_REPORT["Socket Accept"]
_=Socket Wait Async Reading(0,0)
_ADD_TO_REPORT["Socket Wait Async Reading"]
_=Socket Wait Async Writing(0,0)
_ADD_TO_REPORT["Socket Wait Async Writing"]
_=Socket Set Timeout(0,0)
_ADD_TO_REPORT["Socket Set Timeout"]
_=Socket Close Socket(0)
_ADD_TO_REPORT["Socket Close Socket"]
_=Socket Send$(0,"")
_ADD_TO_REPORT["Socket Send$"]
_=Socket Send(0,0,0)
_ADD_TO_REPORT["Socket Send"]
_$=Socket Recv$(0,0)
_ADD_TO_REPORT["Socket Recv$"]
_=Socket Recv(0 To 0,0)
_ADD_TO_REPORT["Socket Recv"]
_=Socket Get Host(0)
_ADD_TO_REPORT["Socket Get Host"]
_=Socket Get Port(0)
_ADD_TO_REPORT["Socket Get Port"]
_$=Socket Inet Ntoa$(0)
_ADD_TO_REPORT["Socket Inet Ntoa$"]
_=Socket Errno
_ADD_TO_REPORT["Socket Errno"]
_=Socket Herrno
_ADD_TO_REPORT["Socket Herrno"]
_$=Dns Get Address By Name$("")
_ADD_TO_REPORT["Dns Get Address By Name$"]
_END_CONTEXT
Close 1