SLIB API Reference - the SINTRAN socket library¶
SLIB is ND's socket library for TCP and UDP programs on SINTRAN III. It is product
ND-211566. It ships with the COSMOS TCP/IP gateway, and it is written for PLANC. This page
lists every call, record, constant and status code, taken from the two files ND ships:
(TCP-IP)SLIB:IMPT and (TCP-IP)SLIB:DEFS. The descriptions come from ND's manual,
ND-860372 SINTRAN SLIB Programmer's Guide.
Each call is marked with one of three labels:
- Run means it ran on SINTRAN III VSX/500 M with COSMOS TCP/IP D02 and SLIB B01, in one of the echo servers.
- Manual means it comes from ND-860372 and has not yet run here.
- Declared means
SLIB:IMPTdeclares it, but ND-860372 has no page for it.
Only PLANC can use SLIB directly. See Which languages can use SLIB before planning a program in any other language.
How to write and build a program is in PLANC-TCP-UDP-SOCKETS.md. How to run the stack itself is in RUNNING-TCPIP-ON-RETROCORE.md.
Which languages can use SLIB¶
SLIB is a PLANC library. PLANC is the only language ND documents it for. Read this before planning a TCP or UDP program in any other language.
What ND's own material says:
- The manual calls itself "the PLANC interface of the SINTRAN Socket Library", and says "ND Socket Library is a programming interface (PLANC)" (ND-860372, the preface and section 1.3). Its required knowledge is "programming experience in PLANC". It has no chapter, example or file list for any other language.
- The interface ND ships is two PLANC source files,
SLIB:IMPTandSLIB:DEFS, which a program includes when it is compiled (section 1.4). The D02 distribution has no interface files for FORTRAN, C, Pascal, COBOL, MAC or any other language. Checked against the full file list of the D02TCP-IPuser. - A program that uses SLIB is linked with the PLANC run-time libraries (section 1.4).
- The D02 distribution has SLIB for the ND-100 only (
SLIB-NRE-1B/2B-B01,SLIB-REE-1B/2B-B01). The manual listsSLIB-500-A00:BRFfor the ND-500 and ND-5000, but that file is not in D02.
What that means, language by language:
| Language | Can it use SLIB? | Status |
|---|---|---|
| PLANC | yes, directly | documented by ND, and run here: every echo server and the Finger server |
| MAC | only through a small PLANC helper whose routines are declared STANDARD; MAC calls the helper and the helper calls SLIB |
run here: ECHOMA. The result is not a pure MAC program. See MAC-COOKBOOK.md section 11 |
| MAC, calling SLIB directly | no ND document describes it. It would mean building PLANC's own call and stack layout by hand | not documented, not tried |
| FORTRAN | a STANDARD PLANC routine uses the FORTRAN calling sequence (ND-60.145.7 appendix F.1), so the same kind of helper should be callable from FORTRAN |
not tried |
| C, Pascal, COBOL, BASIC | nothing in ND-860372 or the D02 distribution | not documented, not tried |
Without SLIB, a program would have to talk to the TCP/IP software the way SLIB does underneath. That protocol is not documented in ND-860372 and has not been worked out here.
1. The files¶
All of them are under user TCP-IP on a pack with the D02 gateway installed. They are
also in this repository, in
Installation/Communication/TCP/x/D02-gateway-and-clients/TCP-IP/.
| File | What it is |
|---|---|
SLIB:DEFS |
Types, constants, status codes, and the SLSzWorkArea calculation. $INCLUDE it. |
SLIB:IMPT |
The IMPORT declarations of every call. $INCLUDE it after SLIB:DEFS. |
SLIB-NRE-1B-B01:BRF |
Non-reentrant half of the library, 1-bank programs. |
SLIB-REE-1B-B01:BRF |
Reentrant half, 1-bank programs. Load both halves. |
SLIB-NRE-2B-B01:BRF, SLIB-REE-2B-B01:BRF |
The same for 2-bank programs. |
SLIB:DEFS does not compile with PLANC-100-F00. One line uses the word UNSIGNED,
and F00 is the newest ND-100 PLANC compiler in the archive. It stops at that line. The echo-server
folder holds SLIBF00.DEFS. It is ND's file
with that one word removed, and its header says exactly what changed. Copy it to the pack as
SLIBF00:DEFS and include that instead. SLIB:IMPT compiles as ND ships it.
Do not copy numbers out of the printed manual. The manual describes SLIB A00, and the
pack has B01. B01 adds status codes 20254-20258 and has larger work areas.
SLIB:DEFS works out SLSzWorkArea for you.
2. Starting SLIB¶
SLinit - Run¶
ROUTINE VOID, INTEGER (INTEGER ARRAY POINTER, SLmaxima, SLrvvp, INTEGER, INTEGER POINTER) : SLinit
SLinit(ADDR workArea, maxima, NIL, SLMainTaskStackSize, NIL) =: status
This must be the first SLIB call. The program supplies SLIB's work area, a module-level
INTEGER ARRAY of SLSzWorkArea words. SLIB keeps pointers into it for as long as the
program runs.
SLSzWorkArea is calculated inside SLIB:DEFS from five constants. The program must
declare these five before it includes the file:
CONSTANT SLMaxPorts = 1 % must be 1 (ND-860372 p.38)
CONSTANT SLMaxSockets = 10
CONSTANT SLMaxSLFork = 1
CONSTANT SLSubTaskStackSize = 1
CONSTANT SLMainTaskStackSize = 1
The SLmaxima record:
| Field | Type | Value used in the samples | Meaning |
|---|---|---|---|
max_nports |
INTEGER | SLMaxPorts |
ports (TCP, UDP ...) |
max_nsockets |
INTEGER | SLMaxSockets |
sockets |
max_debug |
BOOLEAN | FALSE |
debug printing |
max_debfd |
INTEGER | 1 |
file number for the debug printing |
max_AUserDatap |
INTEGER POINTER POINTER | NIL |
address of a user data pointer |
max_nsallocmsg |
INTEGER | 6 |
small messages reserved |
max_nballocmsg |
INTEGER | 0 |
big messages reserved |
max_nxballocmsg |
INTEGER | 0 |
huge messages reserved |
max_tcpdev |
INTEGER | SLDominoPioc |
which TCP device, see below |
max_nsallocmsg + max_nballocmsg must not be more than max_nsockets (ND-860372 p.39).
Otherwise SLinit returns 20234 SLEinval. This was measured: 4 sockets with 6 small
messages failed exactly that way, and 10 sockets work.
max_tcpdev picks the network controller:
| Constant | Value | Meaning |
|---|---|---|
SLDominoPioc |
-1 | Ethernet-III (DOMINO) first, then Ethernet II (PIOC). Run. |
SLPiocDomino |
-2 | Ethernet II first, then Ethernet-III |
SLDominoOnly |
-3 | Ethernet-III only |
SLPiocOnly |
-4 | Ethernet II only |
0..3 |
one Ethernet II controller by number (manual) |
Tasks and sleeping¶
| Call | Declaration | Status |
|---|---|---|
SLfork |
INTEGER (SLrvvp, INTEGER, INTEGER POINTER) |
Manual 7.7. Starts a subtask; limited by SLMaxSLFork. |
SLexit |
VOID |
Manual 7.6. Ends the current task. |
SLsleep |
VOID (INTEGER4 nsec, INTEGER4 eventMask, INTEGER4 WRITE actualEvents) |
Manual 7.23. Sleeps up to nsec seconds or until an event in the mask; -1 = any event. actualEvents is 0 on a timeout. |
SLsleepShort |
VOID (INTEGER4) |
Declared only. |
SLsetOwnEvent |
VOID (INTEGER4) |
Manual 7.21. Wakes a task sleeping on its own events. |
3. Sockets¶
Every call below returns an INTEGER status: SLEok (0) or a code from section 6. Errors
come back as that number, never as a skip return, so compare with SLEok.
| Call | Declaration | Status | Notes |
|---|---|---|---|
SLsocket |
INTEGER (INTEGER domain, INTEGER type, INTEGER protocol, SLsockid WRITE) |
Run (stream and datagram) | domain must be AF_inet, and type must be SOCK_stream (TCP) or SOCK_dgram (UDP). protocol 0 picks the default. The socket id is never 0. |
SLbind |
INTEGER (SLsockid, SLsockaddr) |
Run | Pass an SLin_sockaddr. Address 0 (in_l1 = 0) means any local address. This was measured: the listener shows as 0.0.0.0 port 7 in NETSTAT a and takes connections. |
SLlisten |
INTEGER (SLsockid, INTEGER backlog) |
Run with backlog 1 | TCP only. |
SLaccept |
INTEGER (SLsockid, SLsockid WRITE, SLsockaddr) |
Run | Waits for a connection. It writes the peer's address and port into the third argument, although that argument is not declared WRITE. |
SLconnect |
INTEGER (SLsockid, SLsockaddr) |
Manual 7.5 | TCP client side. |
SLsend |
INTEGER (SLsockid, BYTE POINTER buf, INTEGER len, INTEGER flags, INTEGER WRITE sent) |
Run | Connected sockets only. flags must be 0. sent can be less than len, so loop until it is all sent. |
SLrecv |
INTEGER (SLsockid, BYTE POINTER buf, INTEGER len, INTEGER flags, INTEGER WRITE got) |
Run | Connected sockets only. flags must be 0. When the peer closes, it returns SLEok with got = 0 (manual and measured). A second read after that gives SLEnotconn. |
SLsendTo |
INTEGER (SLsockid, BYTE POINTER, INTEGER, INTEGER, SLin_sockaddr POINTER to, INTEGER WRITE sent) |
Run | UDP. Pass ADDR peer. |
SLrecvFrom |
INTEGER (SLsockid, BYTE POINTER, INTEGER, INTEGER, SLin_sockaddr POINTER from, INTEGER WRITE got) |
Run | UDP. Writes the sender's address and port into from, which may be NIL. |
SLsendV |
INTEGER (SLsockid, Sliov POINTER, INTEGER, INTEGER WRITE) |
Declared | Gather-send from a list of buffers (record sliov). |
SLsense |
INTEGER (SLsockid, INTEGER WRITE) |
Manual 7.19 | Checks the input queue. |
SLshutdown |
INTEGER (SLsockid, INTEGER how) |
Manual 7.22 | Shuts down one direction. |
SLclose |
INTEGER (SLsockid) |
Run | |
SLgetsockname |
INTEGER (SLsockid, SLsockaddr WRITE) |
Manual 7.10 | |
SLgetpeername |
INTEGER (SLsockid, SLsockaddr WRITE) |
Manual 7.9 | |
SLgetOption |
INTEGER (SLsockid, INTEGER level, INTEGER WRITE, BYTE POINTER, INTEGER) |
Manual 7.8 | |
SLsetOption |
INTEGER (SLsockid, INTEGER level, INTEGER opt, BYTE POINTER, INTEGER) |
Manual 7.20 | Level sol_socket (-1); options in section 5. |
SLioctl |
INTEGER (SLsockid, INTEGER request, SLiocArg POINTER, INTEGER size) |
Run (SLiocNBIO) |
Requests in section 5. |
ND-100 rule for receive buffers. On the ND-100 the buffer given to SLrecv must start on
a word boundary (ND-860372 7.15). ADDR ( buf ( 0 ) ) of a module-level BYTES array does.
Blocking. ND's own server, TCCOM, sets each accepted socket to blocking mode with
SLioctl(sock, SLiocNBIO, ADDR arg, SIZE(arg)) and arg.SLiocNumber = 0. The samples do the same.
An SLaccept on a listener that is not blocking returns 20253 SLEwouldblock when no
client is waiting.
Do not poll with a SINTRAN sleep. SLIB takes in new data only inside its own calls. A
non-blocking SLrecv loop that sleeps with SuspendProgram (MN104) between tries got the
first segment of a query and never the second, although the card had acknowledged it.
Measured with Windows finger.exe, which sends a name and its CR LF separately. For a
read with a timeout, use a blocking SLrecv and the no-activity timer (SLiocSNOACT,
section 5); the Finger server does this.
4. Names, addresses and byte order¶
| Call | Declaration | Status |
|---|---|---|
SLhtonl, SLntohl |
INTEGER4 (INTEGER4) |
Declared. The ND-100 is big-endian, so network order is its own order. Port 7 was stored straight into sin_port and worked. |
SLhtons, SLntohs |
INTEGER2 (INTEGER2) |
Declared; as above. |
SLinNetAddr |
INTEGER (BYTES, SLinaddr WRITE) |
Manual ch. 9. Turns dotted text into an address. It is imported under the name SLINNETADD. |
SLgHbyName, getHbyName |
SLhostent POINTER (BYTES) |
Manual ch. 8. Looks a host up by name in AIP-HOSTS. ND's TCCOM uses this to bind to its own address. |
SLgHbyAddr, getHbyAddr |
SLhostent POINTER (SLinaddr) |
Manual ch. 8. |
SLgetHent, SLsetHent, SLendHent |
Manual ch. 8. Walk the hosts file. | |
SLgetNent, SLsetNent, SLendNent, SLgNbyName, SLgNbyAddr |
Manual ch. 8. The networks file. | |
SLgPent, SLsetPent, SLendPent, SLgPbyName, SLgPbNumber |
Manual ch. 8. The protocols file. | |
SLgetSent, SLsetSent, SLendSent, SLgSbyName, SLgSbyPort |
Manual ch. 8. The services file. |
The address records (SLIB:DEFS)¶
TYPE SLinaddr = RECORD PACKED % an internet address
SLu_char : in_b1, in_b2, in_b3, in_b4 % the four bytes, in_b1 first: 192.168.199.40
SLu_short: in_w1 = in_b1
SLu_short: in_w2 = in_b3
SLu_long : in_l1 = in_b1 % all four bytes as one number; 0 = any address
ENDRECORD
TYPE SLsockaddr = RECORD % the general part
SLu_short: sa_family MOD 2 % AF_inet
ENDRECORD
TYPE SLin_sockaddr = SLsockaddr RECORD % an internet socket address
SLu_short: sin_port MOD 2 % port number
SLinaddr : sin_addr MOD 2
ENDRECORD
SLsockid is an INTEGER. Declare an SLin_sockaddr and pass it wherever a call wants an
SLsockaddr, because the record extends it.
5. Constants¶
Address families. Only AF_inet = 2 is implemented (ND-860372 7.24). SLIB:DEFS also
defines AF_unspec 0 to AF_max 15.
Socket types. SOCK_stream = 1 (TCP) and SOCK_dgram = 2 (UDP) are the two the manual
allows. SOCK_raw 3, SOCK_rdm 4 and SOCK_seqpacket 5 are defined but not supported.
Socket options (SLsetOption, level sol_socket = -1):
| Constant | Value | Meaning |
|---|---|---|
SO_debug |
1 | record debug information |
SO_reuseaddr |
4 | allow reuse of a local address |
SO_keepalive |
8 | keep connections alive |
SO_linger |
64 | wait on close while data is queued |
SO_dontlinger |
128 | the opposite of SO_linger |
SLioctl requests, and the record each one takes:
| Constant | Value | What it does | Record |
|---|---|---|---|
SLiocNBIO |
1 | non-blocking on (1) or off (0). Run. | SLiocINT (SLiocNumber, INTEGER4) |
SLiocSNOACT, SLiocGNOACT |
2, 3 | set / get the no-activity timer. SNOACT run: seconds in bits 31-16, bit 1 = signal the application, bit 0 = signal the peer; with bit 1 a blocking SLrecv returns 20249 SLEtimedout after that many idle seconds. ND's default is 600 s with bit 0 |
SLiocINT |
SLiocSOEV |
4 | set event bits for the socket (used with SLsleep) |
SLiocINT |
SLiocSSEV |
5 | set a routine to call on an event | SLiocRout |
SLiocGActConn |
6 | active connections | SLiocActConn |
SLiocGMbStat |
7 | buffer statistics | SLiocMbStat |
SLiocGNetwork |
8 | network statistics | SLiocNetwork |
SLiocGArpTable |
9 | the ARP table | SLiocArpTable |
SLiocGHwStat |
10 | hardware statistics | SLiocLNMAST |
SLiocGGenInfo |
11 | generation information | SLiocGenInfo |
SLiocGLoad |
12 | load information | |
SLiocSAipAddr |
13 | set the IP address | |
SLiocKill |
14 | kill a connection (what the monitor's KILL does) |
|
SLiocGTimers |
15 | timer information | SLiocTimers |
SLiocDIEV |
16 | stop SLIB waiting for these events | |
SLiocSndQue |
17 | send-queue information | SLiocTSndQue |
SLiocSdelResp |
18 | delay the send response (DOMINO/PIOC only) | |
SLiocAroute, SLiocDroute |
19, 20 | add / delete a route | SLiocRoute |
SLiocAx25, SLiocDx25, SLiocGx25 |
21-23 | X.25 address mapping and statistics | SLiocX25 |
TCPIP-MONITOR is ND's own program built on these requests; its NETSTAT, ARP and KILL
commands show what they return. ND-860372 chapter 4.5 describes the records.
6. Status codes¶
SLEok = SLEnoerror = 0. The error codes are decimal 20225-20258.
| Code | Name | Meaning (ND's comment in SLIB:DEFS) |
|---|---|---|
| 20225 | SLEwksz |
work size error |
| 20226 | SLEptr |
pointer error |
| 20227 | SLEilsid |
illegal socket id |
| 20228 | SLElostPL |
lost contact with the packet level |
| 20229 | SLEconstart |
error when making contact with the packet level |
| 20230 | SLEnospace |
no more space |
| 20231 | SLEnospinmsg |
too little space in message |
| 20232 | SLEslibfatal |
fatal internal SLIB error |
| 20233 | SLEtryagain |
used between SLIB and the protocols |
| 20234 | SLEinval |
argument invalid. Seen from SLinit when the reserved messages were more than max_nsockets. |
| 20235 | SLEprototype |
protocol wrong type for socket |
| 20236 | SLEnoprotoopt |
bad protocol option |
| 20237 | SLEprotonosupport |
protocol not supported |
| 20238 | SLEsocktnosupport |
socket type not supported |
| 20239 | SLEaddrinuse |
address already in use |
| 20240 | SLEaddrnotavail |
cannot assign requested address |
| 20241 | SLEnetdown |
network is down |
| 20242 | SLEnetunreach |
network is unreachable |
| 20243 | SLEnetreset |
network dropped connection on reset |
| 20244 | SLEconnaborted |
software caused connection abort |
| 20245 | SLEconnreset |
connection reset by peer |
| 20246 | SLEisconn |
socket is already connected |
| 20247 | SLEnotconn |
socket is not connected |
| 20248 | SLEshutdown |
cannot send after shutdown |
| 20249 | SLEtimedout |
connection timed out |
| 20250 | SLEconnrefused |
connection refused |
| 20251 | SLEnobufs |
no buffer space available |
| 20252 | SLEunexpected |
unexpected subsystem error |
| 20253 | SLEwouldblock |
the call would have blocked |
| 20254 | SLEhostnotfound |
name lookup: host not found (B01 only) |
| 20255 | SLErestryagain |
name lookup: try again (B01 only) |
| 20256 | SLEnodata |
name lookup: no data (B01 only) |
| 20257 | SLEnorecovery |
name lookup: no recovery (B01 only) |
| 20258 | SLEnoaddress |
name lookup: no address (B01 only) |
ND-860284 COSMOS TELNET-FTP Client User Guide, appendix D, explains 20225-20253 with an operator action for each.
7. Linking¶
Load order for a 1-bank PLANC program, as used by every sample. The order was measured,
and LIST-ENTRIES-UNDEFINED prints nothing after it:
@BRF-LINKER-C01
PROGRAM-FILE "NAME"
LOAD NAME
LIBRARY-MODE ON
LOAD (TCP-IP)SLIB-NRE-1B-B01
LOAD (TCP-IP)SLIB-REE-1B-B01
LOAD MON-CALL-1B-A00
LOAD PLANC-1BANK-F00
LIST-ENTRIES-UNDEFINED
EXIT
ND-860372 section 2 also lists NK-100-1BANK and PLANC-UTILLIB-1B. Neither is needed:
SLIBalready contains the NK routines, so loadingNK-100-1BANKonly prints "Redefinition" lines.- Nothing is left undefined without
PLANC-UTILLIB-1B, and no copy of it is known to exist.