Socket Primitives

The file SOCKETS\SOCKPRIM.FTH contains primitives for the sockets layers.

: GetSocketError        \ -- ErrorCode
Return the last socket error code.

: SetSocketError        \ ErrorCode --
Set the last socket error code.

: ClrSocketError        \ --
Clear the last socket error code.

MAXSOCKETS cells equ SOCKLIST_LEN       \ -- size
The size of the sockets array.

SOCKLIST_LEN buffer: socket_list        \ -- addr
The static sockets array.

equ socket_list_last    \ -- addr
The address of the last entry in the socket list.

: initsockets   \ --
Initialise the socket list.

0 value NextSock#       \ -- socknum
Returns the next socket number to be used. This value is is ranged 0..n-1, not 1..n.

: +Sock#        \ --
Step to the next socket number, wrapping as required.

: NextSockEntry \ -- addr
Return the socket list entry address for NextSock#.

: add_hsocket   \ *socket -- HSOCKET|0
See if we can get a socket handle.

: sub_hsocket   \ *socket --
If the given socket address is in the table, mark its socket as unused. If the socket has already been removed, no action is taken.

: get_socket_addr       \ HSOCKET -- addr|0
Given a socket handle, return the socket address, or 0 if the socket is not in use.

: get_socket_inq        \ HSOCKET -- *q|0 ;
Return the socket's input queue.

: get_socket_outq       \ HSOCKET -- *q|0 ;
Return the socket's output queue.

: find_hsocket_port     { ip pcol port | hs *sk -- hsocket|0 }
Find a socket handle with matching IP, protocol and port.

: (find_hsocket_tcpport)        { ips ps ipd pd | hs *sk -- hsocket|0 }
Find a socket handle with matching IP and protocol and port

: find_hsocket_tcpport  { ips ps ipd pd | hs *sk -- hsocket|0 }
Find a socket handle with matching IP and protocol and port.

: WaitForIpAddress      \ --
Waits until we have a valid IP Address, i.e. one that is not 0.0.0.0.

: numsockets    { | res -- numsockets }
Count the number of socket handles in use.

: RebindAllSockets      { ip -- }
Rebind sockets to new local IP address.

Ephemeral ports

Ephemeral ports are port numbers allocated by TCP/IP when you make a connection. These are in a range which does not conflict with the "well known" ports. Each socket connection uses a different port number which allows TCP to identify multiple connections from one machine to the same port on another machine.

#6000 equ FirstPortNumber       \ -- n
First ephemeral port number. Moved to PNconfig.fth.

#9000 equ LastPortNumber        \ -- n
Last+1 ephemeral port number. Moved to PNconfig.fth.

variable LastPortUsed   \ -- addr
Holds the last ephemeral port number used.

: (GetFreePort) \ -- port
Get a free port number; the free port numbers count up.

: GetFreePort   \ *socket -- port#
Get an ephemeral port for a socket.

TCP control block creation and deletion

: FlushQ        \ queue --
Flush the contents of a queue, return them to the free queue, and FREE the queue itself. If queue=0, no action is taken.

: freeConnQ     \ *cb --
Free up any outstanding items on the connection queue.

: DiscardTcpTcb \ *cb --
Free-up all resources in the TCP control block, and then free the control block itself.

: MakeTcpCb     \ -- addr|0
Create a new TCP control block from the heap. On error, zero is returned.

: skTCP?        \ *sk -- flag
Returns true if the socket protocol is TCP.

: FreeupSocket  \ *sk --
Frees up all allocated memory for a socket. *sk is assumed to be valid.

: ?BadSocket    \ *sk x flag -- *sk x | -- 0 and exit caller
A factor used by SOCKET for error recovery. If flag is non-zero, x is discarded, the socket is freed, and exit is from the calling word.

: socket        \ address-family socket-type proto-group -- hs|0
Create a new socket of the given characteristics, returning the new socket number (1..n) on success, or zero for failure. DO NOT CHANGE the return of INVALID_SOCKET=zero for failure!