Expand documentation suite: 30+ articles enriched with diagrams, code examples, and hardware details

Graphics: text_fonts (bitmap layout, styles), sprites (DMA, multiplexing), gfx_base (chipset detection), rastport (draw modes, clipping), ham_ehb (mermaid fixes), display_modes (HAM palettes)

Devices: scsi (per-model interfaces, Gayle limits, CD-ROM, native vs vendor drivers), console (ANSI sequences, CON:/RAW:), parallel (CIA registers, pinout), timer (resource exhaustion), gameport (quadrature, XOR state)

Libraries: workbench (WBStartup, AppWindow/Icon/MenuItem), rexxsyslib (ARexx port hosting, command parsing), diskfont (font directory, colour fonts), keymap (rawkey codes, dead keys), locale (catalogue system, date formatting), layers (ClipRect, refresh types), utility (TagItem chains), icon (DiskObject, ToolTypes), iffparse (IFF structure, ByteRun1), expansion (Zorro AutoConfig)

Networking: tcp_ip_stacks (major rewrite - Amiga vs Unix architecture, SANA-II pipeline, PPP/SLIP dial-up, Ethernet cards, MiSTer), bsdsocket (pure API ref), sana2 (buffer hooks, driver requirements), protocols (all code examples). Deduplicated overlap between the three files.

Toolchain: debugging (Enforcer patterns, SnoopDOS, GDB remote, kprintf checklist), sasc (pragma encoding, __saveds idioms), stormc (NEW - StormC IDE, C++, PowerPC)

References: error_codes (DOS, Exec, trackdisk, Intuition error tables)
Driver development: rtg_driver (Native driver analysis, P96 tuning)

All 22 README indexes updated. Root README synced with stormc.md entry.
This commit is contained in:
Ilia Sharin 2026-04-23 21:37:26 -04:00
parent 0ded078134
commit f61c26b542
38 changed files with 6402 additions and 1065 deletions

View file

@ -1,67 +1,245 @@
[← Home](../README.md) · [Networking](README.md)
# Protocol Implementation — DHCP, DNS, HTTP
# Protocol Implementation — DNS, TCP, UDP, WaitSelect
## Overview
With `bsdsocket.library` providing a BSD-compatible API, standard network protocols can be implemented using familiar patterns adapted for the Amiga's single-address-space, library-based architecture.
Working code examples for common network protocols on AmigaOS using [bsdsocket.library](bsdsocket.md). See [TCP/IP Stacks](tcp_ip_stacks.md) for the architecture that makes this possible and how it differs from Unix.
> [!NOTE]
> Amiga socket functions are **library calls** (via `bsdsocket.library`), not system calls. You must `OpenLibrary("bsdsocket.library", ...)` before using any socket function. Use `CloseSocket()` instead of `close()`, and `Errno()` instead of `errno`.
---
## DNS Resolution
```c
/* gethostbyname — provided by bsdsocket.library: */
struct Library *SocketBase = OpenLibrary("bsdsocket.library", 4);
if (!SocketBase) return;
struct hostent *he = gethostbyname("www.amiga.org");
if (he) {
struct in_addr addr = *(struct in_addr *)he->h_addr;
Printf("IP: %s\n", Inet_NtoA(addr.s_addr));
if (he)
{
struct in_addr addr;
CopyMem(he->h_addr, &addr, sizeof(addr));
Printf("Host: %s\n", he->h_name);
Printf("IP: %s\n", Inet_NtoA(addr.s_addr));
/* May have multiple addresses: */
char **p;
for (p = he->h_addr_list; *p; p++)
{
CopyMem(*p, &addr, sizeof(addr));
Printf(" Addr: %s\n", Inet_NtoA(addr.s_addr));
}
}
else
{
Printf("DNS lookup failed\n");
}
CloseLibrary(SocketBase);
```
---
## HTTP Client (Minimal)
## TCP Client
```c
struct Library *SocketBase = OpenLibrary("bsdsocket.library", 4);
if (!SocketBase) return;
LONG sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) { Printf("socket() failed\n"); goto out; }
struct hostent *he = gethostbyname("www.example.com");
if (!he) { Printf("DNS failed\n"); goto close; }
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(80);
CopyMem(he->h_addr, &sa.sin_addr, he->h_length);
connect(sock, (struct sockaddr *)&sa, sizeof(sa));
if (connect(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0)
{
Printf("connect failed: %ld\n", Errno());
goto close;
}
/* Send HTTP request: */
char req[] = "GET / HTTP/1.0\r\nHost: www.example.com\r\n\r\n";
send(sock, req, strlen(req), 0);
char buf[8192];
LONG total = 0, n;
while ((n = recv(sock, buf + total, sizeof(buf) - total - 1, 0)) > 0)
total += n;
buf[total] = 0;
Printf("%s\n", buf);
/* Receive response: */
char buf[4096];
LONG n;
while ((n = recv(sock, buf, sizeof(buf) - 1, 0)) > 0)
{
buf[n] = 0;
Printf("%s", buf);
}
CloseSocket(sock);
close:
CloseSocket(sock);
out:
CloseLibrary(SocketBase);
```
---
## DHCP Overview
## TCP Server
DHCP on Amiga is typically handled by the TCP/IP stack itself (Roadshow, Miami) or an external client (AmiTCP + `dhclient`). The sequence is standard:
```c
LONG listenSock = socket(AF_INET, SOCK_STREAM, 0);
1. `DHCPDISCOVER` — broadcast on port 67
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(8080);
sa.sin_addr.s_addr = INADDR_ANY;
bind(listenSock, (struct sockaddr *)&sa, sizeof(sa));
listen(listenSock, 5);
Printf("Listening on port 8080...\n");
while (running)
{
struct sockaddr_in clientAddr;
LONG addrLen = sizeof(clientAddr);
LONG clientSock = accept(listenSock,
(struct sockaddr *)&clientAddr,
&addrLen);
if (clientSock >= 0)
{
Printf("Connection from %s\n",
Inet_NtoA(clientAddr.sin_addr.s_addr));
char response[] = "HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n\r\n"
"<h1>Hello from Amiga!</h1>\n";
send(clientSock, response, strlen(response), 0);
CloseSocket(clientSock);
}
}
CloseSocket(listenSock);
```
---
## UDP Datagram
```c
LONG udpSock = socket(AF_INET, SOCK_DGRAM, 0);
/* Send: */
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = htons(9999);
dest.sin_addr.s_addr = inet_addr("192.168.1.255");
char msg[] = "Hello UDP";
sendto(udpSock, msg, strlen(msg), 0,
(struct sockaddr *)&dest, sizeof(dest));
/* Receive: */
char buf[1024];
struct sockaddr_in from;
LONG fromLen = sizeof(from);
LONG n = recvfrom(udpSock, buf, sizeof(buf), 0,
(struct sockaddr *)&from, &fromLen);
buf[n] = 0;
Printf("From %s: %s\n", Inet_NtoA(from.sin_addr.s_addr), buf);
CloseSocket(udpSock);
```
---
## WaitSelect — Combined Socket + GUI Event Loop
The key pattern for responsive Amiga network applications. `WaitSelect` simultaneously waits on sockets **and** Exec signals (windows, ARexx, timers) — no threads needed:
```c
/* Set up signal masks: */
ULONG winSig = 1 << window->UserPort->mp_SigBit;
ULONG ctrlSig = SIGBREAKF_CTRL_C;
fd_set readFDs;
struct timeval tv;
BOOL running = TRUE;
while (running)
{
FD_ZERO(&readFDs);
FD_SET(sock, &readFDs);
tv.tv_secs = 1;
tv.tv_micro = 0;
ULONG sigmask = winSig | ctrlSig;
LONG result = WaitSelect(sock + 1, &readFDs, NULL, NULL,
&tv, &sigmask);
/* Socket data ready? */
if (result > 0 && FD_ISSET(sock, &readFDs))
{
LONG n = recv(sock, buffer, sizeof(buffer), 0);
if (n > 0)
{
/* process network data */
}
else
{
/* connection closed or error */
running = FALSE;
}
}
/* Window event? */
if (sigmask & winSig)
{
struct IntuiMessage *imsg;
while ((imsg = (struct IntuiMessage *)GetMsg(window->UserPort)))
{
switch (imsg->Class)
{
case IDCMP_CLOSEWINDOW:
running = FALSE;
break;
/* ... handle other IDCMP events ... */
}
ReplyMsg((struct Message *)imsg);
}
}
/* Ctrl-C? */
if (sigmask & ctrlSig)
{
Printf("*** Break\n");
running = FALSE;
}
}
```
> [!TIP]
> `WaitSelect` eliminates the need for multi-threading in most Amiga network apps. A single event loop handles sockets, GUI, timers, and ARexx simultaneously — simpler and safer than threads in a non-protected memory environment.
---
## DHCP
DHCP is handled by the TCP/IP stack, not by applications. See [TCP/IP Stacks](tcp_ip_stacks.md) for configuration. The standard sequence is:
1. `DHCPDISCOVER` — stack broadcasts on port 67
2. `DHCPOFFER` — server responds with IP offer
3. `DHCPREQUEST` — client accepts
4. `DHCPACK` — server confirms; lease begins
For MiSTer/FPGA cores with custom SANA-II drivers, DHCP is handled automatically once the SANA-II driver is online and the stack is configured for `IPTYPE=DHCP`.
3. `DHCPREQUEST` — stack accepts
4. `DHCPACK` — server confirms; interface is configured
---
## References
- [bsdsocket.md](bsdsocket.md) — socket API reference
- [tcp_ip_stacks.md](tcp_ip_stacks.md) — stack configuration
- [bsdsocket.md](bsdsocket.md) — API reference and LVO table
- [tcp_ip_stacks.md](tcp_ip_stacks.md) — stack architecture and configuration
- [sana2.md](sana2.md) — SANA-II driver layer