Compare commits

..

40 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
John Bintz fbc9dae690 fix readme 2024-03-18 21:23:01 -04:00
John Bintz 4ed1d7347a fix readme 2024-03-18 21:19:24 -04:00
John Bintz e5cb65a302 Fix string returns 2024-03-18 12:34:30 -04:00
John Bintz bfe0f8a09b fix Inet NtoA bugs and release bugs 2024-03-17 13:42:22 -04:00
John Bintz a6500640fa tweak readme 2024-02-24 11:49:42 -05:00
John Bintz 36b696bc45 1.1.0 2024-02-24 11:42:04 -05:00
John Bintz ff2ca6969d fix function name 2024-02-22 07:12:30 -05:00
John Bintz bb4d447f20 Fix up install instructions for emulated building 2024-02-22 07:08:06 -05:00
John Bintz df18b0b124 other note 2023-10-29 15:40:42 -04:00
John Bintz 7d25a56a90 Add HttT: Bunny's Revenge 2023-10-29 15:39:06 -04:00
John Bintz 0b08c2e258 Remove files that would be ignored by gitignore from releases 2023-04-05 09:43:33 -04:00
12 changed files with 862 additions and 157 deletions

14
.gitignore vendored
View File

@ -4,3 +4,17 @@ dist/
build/ build/
aminet/ aminet/
Disk.info 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
libs/

Binary file not shown.

127
API.md
View File

@ -3,7 +3,9 @@
Most functions will return -2 if the bsdsocket.library is Most functions will return -2 if the bsdsocket.library is
not open. not open.
### Setup ---
## Setup
#### ADDR=Socket Library Open #### ADDR=Socket Library Open
@ -16,11 +18,15 @@ Try to open bsdsocket.library version 4.
* If needed, you'll be able to directly access library functions * If needed, you'll be able to directly access library functions
using this address. using this address.
---
#### Socket Library Close #### Socket Library Close
Close bsdsocket.library. This is safe to call if the library Close bsdsocket.library. This is safe to call if the library
is not open is not open
---
#### RESULT=Socket Set Nonblocking(Socket, IsNonblocking BOOL) #### RESULT=Socket Set Nonblocking(Socket, IsNonblocking BOOL)
Make a socket blocking (False, default), or nonblocking (True). Make a socket blocking (False, default), or nonblocking (True).
@ -29,6 +35,8 @@ Make a socket blocking (False, default), or nonblocking (True).
* Result of IoctlSocket call. * Result of IoctlSocket call.
---
#### RESULT=Socket Reuse Addr(Socket) #### RESULT=Socket Reuse Addr(Socket)
Make a listening socket reuse the address it's trying to bind to. Make a listening socket reuse the address it's trying to bind to.
@ -38,9 +46,9 @@ You probably want to call this right before Socket Listen.
* Result of setsockopt call. * Result of setsockopt call.
---
## Connections
### Connections
#### SOCKET=Socket Create Inet Socket #### SOCKET=Socket Create Inet Socket
@ -51,10 +59,23 @@ Create a new Internet socket for reading or writing.
* Socket number on success * Socket number on success
* -1 on failure * -1 on failure
---
#### RESULT=Socket Connect(Socket to IPAddress$, Port) #### RESULT=Socket Connect(Socket to IPAddress$, Port)
Attempt to connect to a remote host. Currently doesn't Attempt to connect to a remote IP address.
support DNS lookups.
##### 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 ##### Returns
@ -64,19 +85,24 @@ support DNS lookups.
the socket with Socket Select and Socket Getsockopt Int the socket with Socket Select and Socket Getsockopt Int
to see if the connection succeeded to see if the connection succeeded
* -11 port out of range * -11 port out of range
* -13 IP address has zero length
---
#### RESULT=Socket Reuse Addr(Socket) #### RESULT=Socket Reuse Addr(Socket)
Set a server socket to reuse an interface and port that had Set a server socket to reuse an interface and port that had
been used recently. You likely want this if you're building been used recently. You likely want this if you're building
something that listens on a port for connections. This calls something that listens on a port for connections. This calls
setsockopt() for you. `setsockopt()` for you.
##### Returns ##### Returns
The result of calling setsockopt() while setting your socket The result of calling setsockopt() while setting your socket
to reuse addresses. to reuse addresses.
---
#### RESULT=Socket Bind(Socket to IPAddress, Port) #### RESULT=Socket Bind(Socket to IPAddress, Port)
Attempt to bind a socket to a network interface. Use Attempt to bind a socket to a network interface. Use
@ -89,6 +115,8 @@ interfaces.
* -1 on other error * -1 on other error
* -11 port out of range * -11 port out of range
---
#### RESULT=Socket Listen(Socket) #### RESULT=Socket Listen(Socket)
Start listening for connections. Start listening for connections.
@ -98,6 +126,8 @@ Start listening for connections.
* 0 on success * 0 on success
* -1 on failure * -1 on failure
---
#### NEW_SOCKET=Socket Accept(Socket) #### NEW_SOCKET=Socket Accept(Socket)
Get the socket that connected to this one. Wait for a connect Get the socket that connected to this one. Wait for a connect
@ -115,11 +145,13 @@ socket non-blocking and use Fdsets and Select!
* The remote socket number on success * The remote socket number on success
* -1 on failure * -1 on failure
#### RESULT=Socket Async Wait Reading(Socket, Wait_ms) ---
#### RESULT=Socket Wait Async Reading(Socket, Wait_ms)
Wait the given number of milliseconds for the nonblocking socket to be ready for reading. Wait the given number of milliseconds for the nonblocking socket to be ready for reading.
Use this when you're waiting for a client to connect to you, or if you're waiting for Use on a listen socket to await new connections, or on a connected socket to await
a remote socket to send you data. incoming data packets.
##### Returns ##### Returns
@ -127,7 +159,9 @@ a remote socket to send you data.
* -1 on error. Use `Socket Errno` for more detail. * -1 on error. Use `Socket Errno` for more detail.
* 1 on success. * 1 on success.
#### RESULT=Socket Async Wait Writing(Socket, Wait_ms) ---
#### RESULT=Socket Wait Async Writing(Socket, Wait_ms)
Wait the given number of milliseconds for the nonblocking socket to be ready for writing. Wait the given number of milliseconds for the nonblocking socket to be ready for writing.
Use this when you're connecting to a remote server and want to know if the connection Use this when you're connecting to a remote server and want to know if the connection
@ -143,6 +177,8 @@ has been completed.
checks will return 1. checks will return 1.
* 1 on success. * 1 on success.
---
#### RESULT=Socket Set Timeout(Socket, Wait_ms) #### RESULT=Socket Set Timeout(Socket, Wait_ms)
Set a socket to timeout after Wait_ms milliseconds if reading or writing doesn't complete. Set a socket to timeout after Wait_ms milliseconds if reading or writing doesn't complete.
@ -152,18 +188,21 @@ Set a socket to timeout after Wait_ms milliseconds if reading or writing doesn't
* 0 on success * 0 on success
* -1 on error * -1 on error
#### RESULT=Socket Close(Socket) ---
#### RESULT=Socket Close Socket(Socket)
Close a socket. Close a socket.
##### Returns ##### Returns
* 0 on success * 0 on success
* -1 on error * -1 on error
---
## Data Transfers
### Data Transfers
#### SENT=Socket Send$(Socket, String$) #### SENT=Socket Send$(Socket, String$)
@ -194,6 +233,8 @@ End Proc
* Number of characters sent * Number of characters sent
* -1 on other error * -1 on other error
---
#### SENT=Socket Send(Socket, Data Pointer, Length) #### SENT=Socket Send(Socket, Data Pointer, Length)
Send a block of data to a connected socket. Send a block of data to a connected socket.
@ -203,6 +244,8 @@ Send a block of data to a connected socket.
* Number of characters sent * Number of characters sent
* -1 on other error * -1 on other error
---
#### DATA$=Socket Recv$(Socket, MaxLength) #### DATA$=Socket Recv$(Socket, MaxLength)
Retrieve at most MaxLength bytes from Socket, and put them into a string. Retrieve at most MaxLength bytes from Socket, and put them into a string.
@ -212,7 +255,9 @@ If Len(DATA$) < MaxLength, you've read the last bit of data from the socket.
* String of data, which is blank if there is no more data. * String of data, which is blank if there is no more data.
### LENGTH=Socket Recv(Socket to Dataptr, MaxLength) ---
#### LENGTH=Socket Recv(Socket to Dataptr, MaxLength)
Retrieve at most MaxLength bytes from Socket, and put them into the memory Retrieve at most MaxLength bytes from Socket, and put them into the memory
address at Dataptr. address at Dataptr.
@ -222,9 +267,9 @@ address at Dataptr.
* Count of bytes read * Count of bytes read
* -1 on error * -1 on error
---
## Informational
### Informational
#### HOST=Socket Get Host(Socket) #### HOST=Socket Get Host(Socket)
@ -234,6 +279,8 @@ Get the IPv4 (Long) host value the given socket is using.
* Host as a long value * Host as a long value
---
#### PORT=Socket Get Port(Socket) #### PORT=Socket Get Port(Socket)
Get the 16-bit port (Word) value the given socket is using. Get the 16-bit port (Word) value the given socket is using.
@ -242,6 +289,8 @@ Get the 16-bit port (Word) value the given socket is using.
* Port as a word value * Port as a word value
---
#### RESULT$=Socket Inet Ntoa$(Host) #### RESULT$=Socket Inet Ntoa$(Host)
Turn a long Host address into a string. Turn a long Host address into a string.
@ -250,6 +299,8 @@ Turn a long Host address into a string.
* IP address as string * IP address as string
---
#### RESULT=Socket Errno #### RESULT=Socket Errno
Get the error from the last command. Note that this is Get the error from the last command. Note that this is
@ -260,6 +311,18 @@ not cleared on a successful command!
Error number from last call. Look in <sys/error.h> for more Error number from last call. Look in <sys/error.h> for more
details. details.
---
#### RESULT=Socket Herrno
Get the error from the last DNS resolver command.
##### Returns
Resolver error number (`h_errno`) from last call.
---
#### RESULT$=Dns Get Address By Name$(Domain Name$) #### RESULT$=Dns Get Address By Name$(Domain Name$)
Look up the first IP address associated with this hostname. Look up the first IP address associated with this hostname.
@ -274,32 +337,8 @@ 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. String with IP address, or blank string on error.
#### RESULT=Socket Status(Socket)
Returns basic connection information about a socket. ## Low Level
##### 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
#### RESULT=Socket Setsockopt Int(Socket, Option, Value) #### RESULT=Socket Setsockopt Int(Socket, Option, Value)
@ -311,6 +350,8 @@ Socket Reuse Addr().
* Result of setsockopt call * Result of setsockopt call
---
#### RESULT=Socket Getsockopt Int(Socket, Option) #### RESULT=Socket Getsockopt Int(Socket, Option)
Get a socket option. You probably want SO_ERROR, Get a socket option. You probably want SO_ERROR,
@ -321,6 +362,8 @@ attempt a connection with a non-blocking socket.
* Result of getsockopt call * Result of getsockopt call
---
#### ADDR=Socket Fdset Zero(fd_set) #### ADDR=Socket Fdset Zero(fd_set)
Clear out the specified fd_set. Clear out the specified fd_set.
@ -330,6 +373,8 @@ Clear out the specified fd_set.
* Address to that particular fd_set * Address to that particular fd_set
* -1 if fd_set out of range. You get 16 of them. * -1 if fd_set out of range. You get 16 of them.
---
#### ADDR=Socket Fdset Set(fd_set, Socket to Value BOOL) #### ADDR=Socket Fdset Set(fd_set, Socket to Value BOOL)
Set or clear a socket bit in an fd_set. Set or clear a socket bit in an fd_set.

108
README.md
View File

@ -127,6 +127,10 @@ Socket Library Close
* [AQUABYSS](https://agedcode.com/agedcode/en/games/aquabyss) * [AQUABYSS](https://agedcode.com/agedcode/en/games/aquabyss)
* As of April 2023, the extension's been in heavy use for over a month * As of April 2023, the extension's been in heavy use for over a month
on the client side of the game. on the client side of the game.
* [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? Doing something cool with the extension?
[Contact me](https://theindustriousrabbit.com/about) and I'll add it to the list! [Contact me](https://theindustriousrabbit.com/about) and I'll add it to the list!
@ -149,6 +153,16 @@ Doing something cool with the extension?
timeouts using `Socket Async Wait Writing` to determine if the Internet timeouts using `Socket Async Wait Writing` to determine if the Internet
is available. 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 ## Versioning
This project uses semantic versioning. This project uses semantic versioning.
@ -158,17 +172,19 @@ This project uses semantic versioning.
## License ## License
Copyright 2023 John Bintz. Licensed under the MIT License. Copyright 2023-2024 John Bintz. Licensed under the MIT License.
If you use this in your project, and you really want to, If you use this in your project, and you really want to,
throw a link to theindustriousrabbit.com somewhere! You can throw a link to theindustriousrabbit.com somewhere! You can
also find a donate link on also find a donate link on
[the About section on The Industrious Rabbit](https://theindustriousrabbit.com/about). [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) First, run `test/TestSuite` to generate a `report.txt` file.
to contact me.
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 ## Changelog
@ -181,14 +197,92 @@ to contact me.
* Fix bug in Socket Wait Async Writing where result of getsockopt was * Fix bug in Socket Wait Async Writing where result of getsockopt was
incorrectly used. incorrectly used.
### 1.1.0 (2024-02-23)
* Fix bug in `Dns Get Host Address By Name$` where it assumed AMOS strings are
null-terminated. They are not.
* Add `Socket Herrno` to aid in debugging resolver errors.
### 1.1.1 (2024-03-17)
* Fix bug in `Socket Inet Ntoa$` where the null terminator on the result of
calling `Inet_NtoA` was being included in the AMOS string.
* Fix crash bug in `Socket Inet Ntoa$` if called with the BSD Socket library
was not open.
### 1.1.2 (2024-03-18)
* Fix all functions that return strings so that strings work properly
in AMOS. While you could kind of use the immediate return value of the
string, any future manipulation of that string would fail. This fixes
the following functions:
* `Socket Inet Ntoa$`
* `Dns Get Address By Name$`
* `Socket Recv$`
### 1.1.3
Internal release.
### 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 ## Development
### Environment ### Environment
#### Native Amiga
* Clone the [AMOS Professional source code](https://github.com/AOZ-Studio/AMOS-Professional-Official) * Clone the [AMOS Professional source code](https://github.com/AOZ-Studio/AMOS-Professional-Official)
* Run `execute absdsocket` * Copy `AMOSPro Sources/+lequ.s` to `+LEqu.s`
* Note that you'll have to fix up some assigns and files in the AMOS Professional * Generate the socket LVO file in the `src` directory
source directory. I'll update this README with those changes once I track them down... * Install [`fd2pragma`](https://aminet.net/package/dev/misc/fd2pragma) in your path
* Download `https://raw.githubusercontent.com/cnvogelg/amitools/master/amitools/data/fd/bsdsocket_lib.fd` to `src`
* In a Shell:
```
cd src
fd2pragma bsdsocket_lib.fd to "" special 20
```
* Fix up `src/absdsocket` to match your system's setup
* In a Shell:
```
cd src
execute absdsocket
```
#### Emulated setup (WinUAE, FS-UAE, Amiberry)
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 ### Releasing

View File

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
for i in examples/*.amos; do for i in examples/*.amos test/*.amos; do
echo "$i" 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 done

View File

@ -6,7 +6,7 @@ require 'erb'
source = File.read('src/BSDSocket.s') source = File.read('src/BSDSocket.s')
aminet_template = ERB.new(File.read("aminet.readme.erb")) aminet_template = ERB.new(File.read('aminet.readme.erb'))
capture_version = false capture_version = false
version = nil version = nil
@ -24,6 +24,22 @@ source.lines.each do |line|
end end
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' FileUtils.mkdir_p 'dist'
build_base = 'build' build_base = 'build'
@ -31,40 +47,48 @@ project_name = 'BSDSocket-Extension'
build_dir = File.join(build_base, project_name) build_dir = File.join(build_base, project_name)
FileUtils.rm_rf build_dir FileUtils.rm_rf build_dir
FileUtils.rm_rf 'aminet'
FileUtils.mkdir_p build_dir FileUtils.mkdir_p build_dir
FileUtils.mkdir_p 'aminet' FileUtils.mkdir_p 'aminet'
hackerbun_target = File.expand_path("dist/AMOSPro_BSDSocket_#{version}.lha") hackerbun_target = File.expand_path("dist/AMOSPro_BSDSocket_#{version}.lha")
[ [
"AMOSPro_BSDSocket.Lib", 'AMOSPro_BSDSocket.Lib',
"README.md", 'README.md',
"API.md", 'API.md',
"LICENSE", 'LICENSE'
].each do |file| ].each do |file|
target = "#{build_dir}/#{file}" target = "#{build_dir}/#{file}"
FileUtils.mkdir_p File.dirname(target) FileUtils.mkdir_p File.dirname(target)
FileUtils.cp file, target FileUtils.cp file, target
end end
[ gitignores = File.readlines('.gitignore').map(&:strip)
"src",
"examples" %w[
src
examples
].each do |dir| ].each do |dir|
FileUtils.cp_r dir, "#{build_dir}/#{dir}" FileUtils.cp_r dir, "#{build_dir}/#{dir}"
Dir["#{build_dir}/#{dir}/**/*"].each do |file|
FileUtils.rm file if gitignores.any? { |gi| File.fnmatch(gi, file) }
FileUtils.rm file if [/\.fd$/, /\.i$/].any? { |p| file[p] }
end
end end
Dir["icons/**/*.info"].each do |info| Dir['icons/**/*.info'].each do |info|
target = info.gsub("icons/", build_base + "/") target = info.gsub('icons/', build_base + '/')
FileUtils.mkdir_p File.dirname(target) FileUtils.mkdir_p File.dirname(target)
FileUtils.cp info, target FileUtils.cp info, target
end end
Dir.chdir build_base do Dir.chdir build_base do
Open3.popen2e( Open3.popen2e(
"jlha", "c", hackerbun_target, 'jlha', 'c', hackerbun_target,
*(Dir["*"])) do |stdin, stdout_and_stderr, wait_thr| *(Dir['*'])
) do |stdin, stdout_and_stderr, wait_thr|
Thread.new do Thread.new do
stdout_and_stderr.each { |l| puts l } stdout_and_stderr.each { |l| puts l }
end end
@ -75,7 +99,7 @@ Dir.chdir build_base do
end end
end end
FileUtils.cp hackerbun_target, "aminet/BSDSocket-Extension.lha" FileUtils.cp hackerbun_target, 'aminet/BSDSocket-Extension.lha'
File.open("aminet/BSDSocket-Extension.readme", "w") do |fh| File.open('aminet/BSDSocket-Extension.readme', 'w') do |fh|
fh.puts aminet_template.result(binding) fh.puts aminet_template.result(binding)
end end

24
bin/setup Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash
mkdir -p stuff
if [ ! -d stuff/AMOS-Professional-Official ]; then
cd stuff
git clone https://code.hackerbun.dev/TheIndustriousRabbit/amos-professional.git
cd ..
fi
if [ ! -f src/bsdsocket_lib.fd ]; then
cd src
wget https://raw.githubusercontent.com/cnvogelg/amitools/master/amitools/data/fd/bsdsocket_lib.fd
cd ..
fi
echo "On the emulated Amiga, mount this folder at amos-pro-bsdsocket-extension: and run"
echo
echo "cd amos-pro-bsdsocket-extension:"
echo "cd src"
echo 'fd2pragma bsdsocket_lib.fd to "" special 20'
echo
echo "Then, to build the software, run:"
echo
echo "execute absdsocket"

View File

@ -1,13 +1,14 @@
; BSDSocket Extension for AMOS Professional ; BSDSocket Extension for AMOS Professional
; Copyright 2023 John Bintz ; Copyright 2023-2024 John Bintz
; Licensed under the MIT License ; Licensed under the MIT License
; ;
; Writing this code the right way, 25 years later. ; Writing this code the right way, 25 years later.
; extension number 18 ; extension number 18
ExtNb equ 18-1 ; this now comes from GenAm command line option
;ExtNb equ 18-1
Version MACRO Version MACRO
dc.b "1.0.1-20230403" dc.b "1.1.4-20240502"
ENDM ENDM
VerNumber equ $1 VerNumber equ $1
@ -15,12 +16,12 @@ VerNumber equ $1
; Include the files automatically calculated by ; Include the files automatically calculated by
; Library_Digest.AMOS ; Library_Digest.AMOS
;--------------------------------------------------------------------- ;---------------------------------------------------------------------
Incdir "Stuff:development/amos-professional-official-mas/" Incdir "AMOSPro_Sources:"
Incdir "Stuff:development/amos-professional-official-mas/includes/" Incdir "AMOSPro_Sources:includes/"
Include "BSDSocket_Size.s" Include "BSDSocket_Size.s"
Include "BSDSocket_Labels.s" Include "BSDSocket_Labels.s"
Include "+AMOS_Includes.s" Include "+AMOS_Includes.s"
Include "socket_lvo.i" Include "bsdsocket_lvo.i"
; get the effective address of something in extension memory ; get the effective address of something in extension memory
Dlea MACRO Dlea MACRO
@ -56,7 +57,6 @@ SO_REUSEADDR EQU $4
MAX_SOCKETS EQU 64 MAX_SOCKETS EQU 64
len_sockaddr_in EQU 16 len_sockaddr_in EQU 16
sockaddr_in_sin_len EQU 0
sockaddr_in_sin_family EQU 1 sockaddr_in_sin_family EQU 1
sockaddr_in_sin_port EQU 2 sockaddr_in_sin_port EQU 2
sockaddr_in_sin_addr EQU 4 sockaddr_in_sin_addr EQU 4
@ -68,6 +68,20 @@ Error_PortOutOfRange EQU -11
Error_FdsetOutOfRange EQU -11 Error_FdsetOutOfRange EQU -11
Error_UnableToBind EQU -12 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 ; wrap code that doesn't take arguments with these
PreserveStackInstruction MACRO PreserveStackInstruction MACRO
MOVEM.L A2-A6/D6-D7,-(SP) MOVEM.L A2-A6/D6-D7,-(SP)
@ -128,19 +142,20 @@ LeaFdset MACRO
; LeaFdsetForBit fd_set reg,target address,target bit in address ; LeaFdsetForBit fd_set reg,target address,target bit in address
LeaFdsetForBit MACRO LeaFdsetForBit MACRO
LeaFdset \1,\2 ; get fdset base address in \2 LeaFdset \1,\2 ; get fdset base address in \2
MOVE.L D3,-(SP) MOVEM.L D3-D4,-(SP)
MOVE.L \3,D3 ; Put target bit into D3 MOVE.L \3,D3 ; Put target bit into D3
ROR.L #5,D3 ; lop off the first 5 bits ROR.L #5,D3 ; lop off the first 5 bits
AND.L #$7,D3 ; only keep the top three AND.L #$7,D3 ; only keep the top three
ROL.L #2,D3 ; multiply by 4 ROL.L #2,D3 ; multiply by 4
ADD.L D3,\2 ; add that value to the fdset address ADD.L D3,\2 ; add that value to the fdset address
AND.L #$1F,\3 ; only keep 0-31 in \3 MOVE.L \3,D4
AND.L #$1F,D4 ; only keep 0-31 in \3
MOVEQ #1,D3 MOVEQ #1,D3
ROL.L \3,D3 ; shift that bit left as many as target ROL.L D4,D3 ; shift that bit left as many as target
MOVE.L D3,\3 ; put that in the target MOVE.L D3,\3 ; put that in the target
MOVE.L (SP)+,D3 MOVEM.L (SP)+,D3-D4
ENDM ENDM
@ -330,6 +345,9 @@ C_Tk dc.w 1,0
AddTokenFunction SocketCloseSocket AddTokenFunction SocketCloseSocket
dc.b "socket close socke","t"+$80,"00",-1 dc.b "socket close socke","t"+$80,"00",-1
AddTokenFunction SocketHerrno
dc.b "socket herrn","o"+$80,"0",-1
; TOKEN_END ; TOKEN_END
dc.w 0 dc.w 0
dc.l 0 ; Important! dc.l 0 ; Important!
@ -386,6 +404,8 @@ getsockopt_len ds.l 1
MaxSocketSeen dc.w 0 MaxSocketSeen dc.w 0
sockaddr_ram ds.l 1 sockaddr_ram ds.l 1
; also used for errno tags
AcceptScratchArea ds.b 16 AcceptScratchArea ds.b 16
SelectScratchArea ds.l 2 SelectScratchArea ds.l 2
@ -493,7 +513,7 @@ _SocketLibraryOpen_Finish:
; ;
; Turn an IP address and port into a sockaddr_in strucure ; 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 Lib_Def SocketIPAddressPortToSockaddr
@ -514,14 +534,26 @@ _ToSockaddr_PortOK:
MOVE.L sockaddr_ram-MB(A3),A0 MOVE.L sockaddr_ram-MB(A3),A0
ADD.L D3,A0 ; A0 contains our offset in ram ADD.L D3,A0 ; A0 contains our offset in ram
MOVE.B #len_sockaddr_in,sockaddr_in_sin_len(A0)
MOVE.B #AF_INET,sockaddr_in_sin_family(A0)
MOVE.W D2,sockaddr_in_sin_port(A0)
MOVEM.L A0-A3/D3,-(SP) MOVEM.L A0-A3/D3,-(SP)
MOVE.L D1,A1 ; ip string address
MOVE.W (A1)+,D3 ; string length
MOVE.L D1,A0 ; ip address BNE _ToSockaddr_StringHasLength
ADDQ #2,A0 ; string data starts 2 bytes in 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
_ToSockaddr_CopyIPString:
MOVE.B (A1)+,(A2)+
DBRA D3,_ToSockaddr_CopyIPString
MOVE.B #0,(A2) ; end of string
; if the string contains "INADDR_ANY", we use that value instead ; if the string contains "INADDR_ANY", we use that value instead
MOVE.L A0,A1 MOVE.L A0,A1
@ -546,7 +578,15 @@ _ToSockaddr_ParseIPAddress:
_ToSockaddr_DoneParsing: _ToSockaddr_DoneParsing:
MOVEM.L (SP)+,A0-A3/D3 MOVEM.L (SP)+,A0-A3/D3
MOVE.L D0,sockaddr_in_sin_addr(A0)
; create struct sockaddr_in
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)+
CLR.L (A3)+
CLR.L (A3)+
MOVE.L A0,D0 MOVE.L A0,D0
MOVEM.L (SP)+,A0/A3/D3 MOVEM.L (SP)+,A0/A3/D3
@ -626,7 +666,6 @@ _SocketCreateInetSocket_Done:
Ret_Int Ret_Int
_SocketConnect_LibraryOpen: _SocketConnect_LibraryOpen:
MOVE.L D0,-(SP) ; socket id onto stack MOVE.L D0,-(SP) ; socket id onto stack
Rbsr L_SocketIPAddressPortToSockaddr Rbsr L_SocketIPAddressPortToSockaddr
@ -806,11 +845,11 @@ _SocketBind_SockaddrIn:
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Lib_Par SocketErrno Lib_Par SocketErrno
; - - - - - - - - - - - - - ; - - - - - - - - - - - - -
PreserveStackInstruction PreserveStackFunction
EnsureBSDSocketLibrary _SocketErrno_LibraryOpen EnsureBSDSocketLibrary _SocketErrno_LibraryOpen
RestoreStackInstruction RestoreStackFunction
Ret_Int Ret_Int
_SocketErrno_LibraryOpen: _SocketErrno_LibraryOpen:
@ -821,7 +860,7 @@ _SocketErrno_LibraryOpen:
MOVE.L D0,D3 MOVE.L D0,D3
RestoreStackInstruction RestoreStackFunction
RTS RTS
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1292,6 +1331,12 @@ _SocketSelect_PerformSelect
; - - - - - - - - - - - - - ; - - - - - - - - - - - - -
PreserveStackFunction PreserveStackFunction
EnsureBSDSocketLibrary _SocketGetHost_LibraryOpen
RestoreStackFunction
Ret_Int
_SocketGetHost_LibraryOpen:
MULU #len_sockaddr_in,D3 MULU #len_sockaddr_in,D3
Dload A0 Dload A0
MOVE.L sockaddr_ram-MB(A0),A0 MOVE.L sockaddr_ram-MB(A0),A0
@ -1312,6 +1357,13 @@ _SocketSelect_PerformSelect
; - - - - - - - - - - - - - ; - - - - - - - - - - - - -
PreserveStackFunction PreserveStackFunction
EnsureBSDSocketLibrary _SocketGetPort_LibraryOpen
RestoreStackFunction
Ret_Int
_SocketGetPort_LibraryOpen:
MULU #len_sockaddr_in,D3 MULU #len_sockaddr_in,D3
Dload A0 Dload A0
MOVE.L sockaddr_ram-MB(A0),A0 MOVE.L sockaddr_ram-MB(A0),A0
@ -1334,8 +1386,10 @@ _SocketSelect_PerformSelect
PreserveStackFunction PreserveStackFunction
EnsureBSDSocketLibrary _SocketInetNtoa_LibraryOpen EnsureBSDSocketLibrary _SocketInetNtoa_LibraryOpen
RestoreStackInstruction MOVE.L ChVide(A5),D3
Ret_Int
RestoreStackFunction
Ret_String
_SocketInetNtoa_LibraryOpen: _SocketInetNtoa_LibraryOpen:
MOVE.L D3,D0 MOVE.L D3,D0
@ -1352,21 +1406,28 @@ _SocketInetNtoA_StringSizeLoop:
TST.B (A0)+ TST.B (A0)+
BNE _SocketInetNtoA_StringSizeLoop BNE _SocketInetNtoA_StringSizeLoop
MOVE.L A0,D3 MOVE.L A0,D4
SUB.L A2,D3 ; D3 = length SUB.L A2,D4 ; D4 = length
SUBQ #1,D4 ; get rid of the null terminator
; add 2 and even out the space
MOVE.L D4,D3
AND.W #$FFFE,D3
ADDQ.W #2,D3
Rjsr L_Demande ; string base address is in A0/A1 Rjsr L_Demande ; string base address is in A0/A1
MOVE.W D3,(A0)+ ; length of string LEA 2(A0,D3.W),A1
SUBQ #1,D3
MOVE.L A1,HiChaine(A5)
MOVE.L A0,A1
MOVE.W D4,(A0)+ ; length of string
SUBQ #1,D4
_SocketInetNtoA_StringCopyLoop: _SocketInetNtoA_StringCopyLoop:
MOVE.B (A2,D3),(A0,D3) MOVE.B (A2,D4),(A0,D4)
DBRA D3,_SocketInetNtoA_StringCopyLoop DBRA D4,_SocketInetNtoA_StringCopyLoop
; make the address even
EvenOutStringAddress A0,D3
MOVE.L A0,HiChaine(A5) ; Does L_Demande nuke A5 too?
MOVE.L A1,D3 ; string return MOVE.L A1,D3 ; string return
@ -1431,7 +1492,7 @@ _SocketRecvString_NotTooLong:
_SocketRecvString_BufferAllocated: _SocketRecvString_BufferAllocated:
MOVE.L D0,A0 ; buffer address MOVE.L D0,A0 ; buffer address
MOVE.L D1,D0 ; socket MOVE.L D1,D0 ; socket
MOVE.L (SP)+,D1 ; length MOVE.L (SP)+,D1 ; reserved ram buffer length
MOVEQ #0,D2 ; flags MOVEQ #0,D2 ; flags
MOVEM.L A0-A1/D1,-(SP) MOVEM.L A0-A1/D1,-(SP)
@ -1459,39 +1520,38 @@ _SocketRecvString_BufferAllocated:
Ret_String Ret_String
; TODO received data is wrong somewhere ; TODO received data is wrong somewhere
_SocketRecvString_DataReceived: _SocketRecvString_DataReceived:
; D0 contains receive length ; D0 contains socket receive length
MOVE.L D1,-(SP) ; TODO: handle zero return length
MOVE.L A0,A2 ; A2 contains read buffer
MOVE.L D1,-(SP) ; reserved ram buffer length
; demande/hichaine string setup
MOVEQ #0,D3 MOVEQ #0,D3
MOVE.W D0,D3 ; prep for L_Demande. can we request a zero length string? MOVE.W D0,D3
MOVE.L A0,A2 ; L_Demande blows away A0 and A1, A2 now contains buffer AND.W #$FFFE,D3
ADDQ #2,D3
Rjsr L_Demande ; A0/A1 contain string address Rjsr L_Demande ; A0/A1 contain string address
MOVE.W D3,(A0)+ ; put in string length LEA 2(A0,D3.W),A1
SUBQ #1,D3 ; reduce by one for DBRA MOVE.L A1,HiChaine(A5)
MOVE.L A0,A1
MOVE.W D0,(A1)+ ; put in string length
SUBQ #1,D0 ; reduce by one for DBRA
MOVE.L A2,A3 ; A3 now contains start of buffer MOVE.L A2,A3 ; A3 now contains start of buffer
_SocketRecvString_CopyData: _SocketRecvString_CopyData:
MOVE.B (A2,D3),(A0,D3) MOVE.B (A2,D0),(A1,D0)
DBRA D3,_SocketRecvString_CopyData DBRA D0,_SocketRecvString_CopyData
MOVE.L (SP)+,D0 ; reserved ram buffer length
EvenOutStringAddress A0,D2 MOVE.L A0,-(SP)
; add to string manager for garbage collection?
MOVE.L A0,HiChaine(A5)
MOVE.L (SP)+,D0
; free ram
MOVE.L A1,-(SP) ; A1 contains our string addres
;MOVE.L D1,D0
MOVE.L A3,A1 MOVE.L A3,A1
Rjsr L_RamFree Rjsr L_RamFree
MOVE.L (SP)+,D3 ; string return MOVE.L (SP)+,D3 ; string return
MOVE.L (SP)+,A3 MOVE.L (SP)+,A3
RestoreStackFunction RestoreStackFunction
@ -1613,7 +1673,7 @@ _SocketWaitAsyncWriting_LibraryOpen:
Rbsr L_MicrosecondsToTimeval ; A3 contains timeval Rbsr L_MicrosecondsToTimeval ; A3 contains timeval
Dload A4 Dload A4
MOVE.L D0,-(SP) MOVEM.L D0,-(SP)
; set up WaitSelect ; set up WaitSelect
MOVEQ #0,D1 MOVEQ #0,D1
LeaFdset D1,A1 ; write fdset LeaFdset D1,A1 ; write fdset
@ -1635,7 +1695,7 @@ _SocketWaitAsyncWriting_LibraryOpen:
TST.L D0 TST.L D0
BEQ _SocketWaitAsyncWriting_Timeout BEQ _SocketWaitAsyncWriting_Timeout
BMI _SocketWaitAsyncWriting_Error BMI _SocketWaitAsyncWriting_Error
MOVE.L (SP)+,D0 ; D0 contains socket again MOVEM.L (SP)+,D0 ; D0 contains socket again
Dload A4 Dload A4
; a socket became interesting, check the Fdset ; a socket became interesting, check the Fdset
@ -1673,7 +1733,7 @@ _SocketWaitAsyncWriting_CheckSockopt:
MOVE.L (SP)+,A3 MOVE.L (SP)+,A3
TST.L D0 TST.L D0
BMI _SocketWaitAsyncWriting_Error BMI _SocketWaitAsyncWriting_Error2
Dlea IoctlSockOptScratch,A0 Dlea IoctlSockOptScratch,A0
MOVE.L (A0),D0 MOVE.L (A0),D0
@ -1695,6 +1755,7 @@ _SocketWaitAsyncWriting_Ready:
_SocketWaitAsyncWriting_Error: _SocketWaitAsyncWriting_Error:
MOVE.L (SP)+,D1 MOVE.L (SP)+,D1
_SocketWaitAsyncWriting_Error2:
MOVEM.L (SP)+,A3-A4 MOVEM.L (SP)+,A3-A4
MOVE.L #-1,D3 MOVE.L #-1,D3
@ -1776,7 +1837,6 @@ _SocketWaitAsyncReading_LibraryOpen:
BMI _SocketWaitAsyncReading_Done BMI _SocketWaitAsyncReading_Done
MOVE.L (SP)+,D0 ; D0 contains socket again MOVE.L (SP)+,D0 ; D0 contains socket again
;Dload A4
; a socket became interesting, check the Fdset ; a socket became interesting, check the Fdset
MOVE.L D0,D3 ; socket in D3 MOVE.L D0,D3 ; socket in D3
MOVEQ #0,D1 ; fdset in D1 MOVEQ #0,D1 ; fdset in D1
@ -1885,9 +1945,9 @@ _SocketReuseAddr_LibraryOpen:
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; =Dns Get Host Address By Name$(Name String) ; =Dns Get Address By Name$(Name String)
; ;
; Get the status of a socket ; Convert a host name to an IP address
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Lib_Par DnsGetHostAddressByName Lib_Par DnsGetHostAddressByName
@ -1900,15 +1960,43 @@ _SocketReuseAddr_LibraryOpen:
Ret_String Ret_String
_DnsGetHostAddressByName_LibraryOpen: _DnsGetHostAddressByName_LibraryOpen:
; string so you need demande, hichaine, and chvide ; string so you need demande, hichaine, and chvide
MOVE.L D3,A0 ; name MOVE.L D3,A0 ; name
ADD.L #2,A0 ; skip length, string is null terminated (?) 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 _DnsGetHostAddressByName_StringRamAllocated
MOVE.L ChVide(A5),D3
RestoreStackFunction
Ret_String
_DnsGetHostAddressByName_StringRamAllocated:
MOVE.L D0,A1 ; a1 contains address
SUBQ #1,D1 ; reduce by one for DBRA
_DnsGetHostAddressByName_KeepCopyingAMOSString:
MOVE.B (A0)+,(A1)+ ; byte copy
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)
WithDataStorage WithDataStorage
LoadBSDSocketBase LoadBSDSocketBase
CALLLIB gethostbyname CALLLIB gethostbyname
EndDataStorage EndDataStorage
MOVEM.L (SP)+,A0/D2
; free the ram before we go any farther
MOVE.L D0,-(SP)
MOVE.L A0,A1
MOVE.L D2,D0
Rjsr L_RamFree
MOVE.L (SP)+,D0
TST.L D0 TST.L D0
BNE _DnsGetHostAddressByName_GetIPAddress BNE _DnsGetHostAddressByName_GetIPAddress
@ -1919,7 +2007,6 @@ _DnsGetHostAddressByName_LibraryOpen:
Ret_String Ret_String
_DnsGetHostAddressByName_GetIPAddress: _DnsGetHostAddressByName_GetIPAddress:
MOVE.L D0,A0 MOVE.L D0,A0
MOVE.L 16(A0),A1 ; **h_addr_list MOVE.L 16(A0),A1 ; **h_addr_list
MOVE.L (A1),A1 ; *h_addr_list MOVE.L (A1),A1 ; *h_addr_list
@ -1940,18 +2027,26 @@ _DnsGetHostAddressByName_GetIPAddressLength:
BNE _DnsGetHostAddressByName_GetIPAddressLength BNE _DnsGetHostAddressByName_GetIPAddressLength
MOVE.L (SP)+,A2 MOVE.L (SP)+,A2
Rjsr L_Demande ; string is in A0/A1
MOVE.W D3,(A0)+
SUBQ #1,D3 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,A1
MOVE.W D4,(A1)+
SUBQ #1,D4
_DnsGetHostAddressByName_KeepCopying: _DnsGetHostAddressByName_KeepCopying:
MOVE.B (A2,D3),(A0,D3) MOVE.B (A2)+,(A1)+
DBRA D3,_DnsGetHostAddressByName_KeepCopying DBRA D4,_DnsGetHostAddressByName_KeepCopying
EvenOutStringAddress A0,D0 MOVE.L A0,D3
MOVE.L A0,HiChaine(A5)
MOVE.L A1,D3
RestoreStackFunction RestoreStackFunction
@ -2053,6 +2148,51 @@ _SocketCloseSocket_LibraryOpen:
RestoreStackFunction RestoreStackFunction
Ret_Int Ret_Int
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Int=Socket Herrno
;
; Return Herrno value, errors related to DNS resolution
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
Dlea SelectScratchArea,A1
; build the tag list
MOVE.L HerrnoTag,(A0)+
MOVE.L A1,(A0)+
MOVE.L 0,(A0)+
MOVE.L 0,(A0)+
MOVE.L A2,A0
WithDataStorage
LoadBSDSocketBase
CALLLIB SocketBaseTagList
EndDataStorage
TST.L D0
BEQ _SocketHerrno_success
; failed
MOVE.L #-1,D3
RestoreStackFunction
Ret_Int
_SocketHerrno_success:
MOVE.L (A1),D3
RestoreStackFunction
Ret_Int
; ;
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Even if you do not have error messages, you MUST ; Even if you do not have error messages, you MUST

View File

@ -1,10 +1,20 @@
echo "***Assembling AMOSPro_BSDSocket.Lib" echo "***Assembling AMOSPro_BSDSocket.Lib"
assign AMOSPro_System: MiSTerHD:Development/AMOSPro/AMOS_Pro assign AMOSPro_System: SYS:Development/AMOS_Pro
Stuff:Development/AMOS-Professional-Official-mas/c/Library_Digest BSDSocket.s assign AMOSPro_Sources: amos-pro-bsdsocket-extension:stuff/AMOS-Professional-Official
Stuff:Development/AMOS-Professional-Official-mas/c/Genam FROM BSDSocket.s TO AMOSPro_BSDSocket.Lib AMOSPro_Sources:c/Library_Digest BSDSocket.s
AMOSPro_Sources:c/Genam FROM BSDSocket.s TO AMOSPro_BSDSocket.Lib -e ExtNb=18-1
;delete >NIL: BSDSocket_Labels.s ;delete >NIL: BSDSocket_Labels.s
;delete >NIL: BSDSocket_Size.s ;delete >NIL: BSDSocket_Size.s
FAILAT 21
copy AMOSPro_System:APSystem/AMOSPro_BSDSocket.lib AMOSPro_System:APSystem/AMOSPro_BSDSocket.lib.bak copy AMOSPro_System:APSystem/AMOSPro_BSDSocket.lib AMOSPro_System:APSystem/AMOSPro_BSDSocket.lib.bak
FAILAT 10
copy AMOSPro_BSDSocket.Lib AMOSPro_System:APSystem/ copy AMOSPro_BSDSocket.Lib AMOSPro_System:APSystem/
;use an amos file here that includes the plugin to quickly build a test program apcmp "/test/TestSuite.amos" inclib
;apcmp "aqua_test_plugin.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

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