<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>
Date   : Mon, 03 Aug 2009 01:40:13 +0100
From   : jgh@... (Jonathan Graham Harston)
Subject: RFC: BBC Sockets Networking API

        Request For Comments - Proposed BBC IP Networking API
        -----------------------------------------------------
 
Updated proposed Sockets networking API.
 
Incorporating thse comments:
* Doesn't have to be specifically Ethernet, can be any IP network
* Socket number can be an opaque 8-bit number
* Internet events
* Resolver API
* NFS-style API
 
* Doesn't have to be specifaclly Ethernet, can be any IP network.
Renamed API as IP Networking API.
 
* Socket number can be an opaque 8-bit number.
A 32-bit socket number implies 4 billion sockets can be open at any time.
Even if the socket number was actually an address of a socket block, it
would be memory in the IP networking workspace, so doesn't need to be a
full 32-bit number. An 8-bit number, as with NFS receive blocks, is
adequate for 255 open sockets. Also, an 8-bit number more easilt fits into
the control block at X%?3, filling in what was previously listed as
"unused". Also, an 8-bit number makes implementing Events easier, see next.
 
* Internet events
Event number 19, X=subcode, Y=socket number. As with ANFS receive events,
will need its own enable/disable code, as the MOS *fx13/14 only deals with
events 0-9.
 
* Resolver API
There's nothing in my PRMs about resolver SWIs. Doing a websearch for
DNSResolver only finds a block of SWIs calls Resolver, and searching for,
eg DNSResolver_Start finds no matches as suggests Resolver matches. Anyway,
even without the documentaion, it's easy enough to allocate 64 subcalls to
match the 64 [DNS]Resolver subcalls.
 
* NFS-style API
As with the DNS Resolver, to do a full IP transaction just using sockets
requires several calls and checks, eg to transmit a datagram you have to
open a socket, bind it, write to it and then close it, whereas the NFS API
gives you eg Net_Tx(Stn%,Ctrl%,Port%,Addr%,Len%,RAddr%) in one go.
 
Also, to allow patching of Econet to let NetFS (ie BBC NFS) pass calls to
IP, there needs to be a call that 'looks like' the control blocks that NFS
passes on to Econet.
 
With appropriate programming (eg using the Net library at mdfs.net/blib)
station numbers (network addresses) are already held as 32-bit numbers, so
is transparently transfered to IPv4 netwworking by just rebuilding code
with a new library.
 
For example, A%=FNNet_RxRead(rxnum%):Stn%=X%!3 sets Stn% to &0000<nn><ss>
and program code will transparently deal with what's effectively
0.0.net.stn just as well as one.two.three.four. Effectively, a 2-byte
Econet address is embedded in a 4-byte IPv4 address in the same way that a
4-byte IPv4 address is embedded in a 16-byte IPv6 address.
 
In fact, checking through my TALK (netchat) and MUGINS (multi-user network
game) I can't see anything that would stop them working over IP. Both
work correctly on A5000s with Ethernet interfaces. Anybody taking Econetted
RISC OS machines to 'udd in September?
 
IP Networking API
On entry: A%=192, X%=control block, Y%=X%DIV256
          X%?0  = send block length
          X%?1  = receive block length
          X%?2  = command - same as RISC OS SWI Socket_ command number
          X%?3  = socket
          X%!4  =>data
          X%!8  = data length
          X%!12 = flags
          X%!16 =>IP address
          X%!20 = IP address length, if zero, X%!16 = IPv4 address
 
On exit:  If X%?2 unchanged - call unsupported or no handler present.
          X%?3 = returned socket or result
          X%!4 onwards: any returned data
          Memory pointed to by X%!4 on entry may be modified
 
Commands passed in X%?2 are those in the RISC OS Socket_ SWIs, that is:
 
 &00 Socket_Creat       X%?3=domain, X%!4=type,  X%!8=protocol
 &01 Socket_Bind        X%?3=sock, X%!4=name,    X%!8=namelen
 &02 Socket_Listen      X%?3=sock, X%!4=backlog
 &03 Socket_Accept      X%?3=sock, X%!4=addr,    X%!8=len
 &04 Socket_Connect     X%?3=sock, X%!4=name,    X%!8=namelen
 &05 Socket_Recv        X%?3=sock, X%!4=buf,     X%!8=len,  X%!12=flags
 &06 Socket_Recvfrom    X%?3=sock, X%!4=buf,     X%!8=len,  X%!12=flags,
X%!16=from, X%!20=fromlen
 &07 Socket_Recvmsg     X%?3=sock, X%!4=msg,     X%!8=flags
 &08 Socket_Send        X%?3=sock, X%!4=msg,     X%!8=len,  X%!12=flags
 &09 Socket_Sendto      X%?3=sock, X%!4=msg,     X%!8=len,  X%!12=flags,
X%!16=to, X%!20=tolen
 &0A Socket_Sendmsg     X%?3=sock, X%!4=msg,     X%!8=flags
 &0B Socket_Shutdown    X%?3=sock, X%!4=how
 &0C Socket_Setsockopt  X%?3=sock, X%!4=level,  X%!8=optname, X%!12=optval,
X%!16=optlen
 &0D Socket_Getsockopt  X%?3=sock, X%!4=level,  X%!8=optname, X%!12=optval,
X%!16=optlen
 &0E Socket_Getpeername X%?3=sock, X%!4=name,   X%!8=namelen
 &0F Socket_Getsockname X%?3=sock, X%!4=name,   X%!8=namelen
 &10 Socket_Close       X%?3=sock
 &11 Socket_Select      X%?3=nfds, X%!4=readfds, X%!8=writefds,
X%!12=exceptfds, X%!16=timeout
 &12 Socket_Ioctl       X%?3=sock, X%!4=request, X%!8=argp
 &13 Socket_Read        X%?3=sock, X%!4=buf,     X%!8=num
 &14 Socket_Write       X%?3=sock, X%!4=buf,     X%!8=num
 &15 Socket_Stat        X%?3=sock, X%!4=buf
 &16 Socket_Readv       X%?3=sock, X%!4=iov,     X%!8=iovcnt
 &17 Socket_Writev      X%?3=sock, X%!4=iov,     X%!8=iovcnt
 
The following is a BASIC Sockets library:
 
REM > BLib.Socket
DEFFNSocket_Open(S%, X%!4, X%!8):A%=0
DEFFNSocket_Bind(S%, X%!4, X%!8):A%=1
DEFFNSocket_Listen(S%, X%!4):A%=2
DEFFNSocket_Accept(S%, D%, L%):A%=3:X%!4=D%:X%!8=L%
DEFFNSocket_Connect(S%, X%!4, X%!8):A%=4
DEFFNSocket_Close(S%):A%=16
!X%=&1818:X%?2=A%:X%?3=S%:A%=192:CALL &FFF1:=X%?3
:
DEFFNSocket_Read(S%, X%!4, X%!8):A%=19
DEFFNSocket_Write(S%, X%!4, X%!8):A% 
!X%=&1818:X%?2=A%:X%?3=S%:A%=192:CALL &FFF1:=X%!8
 
IP Events
Need a suitable call to enable/disable IP events. By default, events are
disabled. Could start at the top of the IP subcall numbers, and use subcall
number 63 downwards, unless something like the Socket_SetOpt call would be
more appropiate. A lot of the documentation I have refers to defined
values (eg SO_REUSEADDR), and without checking a suitable header file, I'm
not sure of their exact values.
 
When enabled, the following events occur:
 
A=&13, X=1, Y=socket
  Socket Y has input waiting to be read
A=&13, X=2, Y=socket
  Socket Y has out-of-band data arrived (is this a data overrun?)
A=&13, X=3, Y=socket
  Socket Y's connection has been broken
 
DNS Resolver API
On entry: A%=192, X%=control block, Y%=X%DIV256
          X%?0  = send block length
          X%?1  = receive block length
          X%?2  = command - &40 + RISC OS SWI Resolver_ command number
          X%?3  = ?
          X%!4  = ?
          X%!8  = ?
 
On exit:  If X%?2 unchanged - call unsupported or no handler present.
 
Econet hooks to IP
On entry: A%=&18, X%=control block, Y%=X%DIV256
          Control block as for OSWORD &10, Network Transmit
 
On entry: A%=&19, X%=control block, Y%=X%DIV256
          Control block as for OSWORD &11, Network Receive
 
OSWORD numbers chosen to be the NFS/Econet numbers + &08.
 
These calls are passed on from a patched NFS to transmit to or listen from
reception from IP via AUN UDP datagrams. The handler should update the
control block, which will be in Econet/NFS's workspace, and so is polled by
the usual Net_TxPoll, Net_RxPoll OSBYTEs.
 
This needs a method to map the Econet net numbers to appropriate IP
addresses. AUN specified net &80+ as mapping to an IP net, eg Econet
128.xxx maps to IP aaa.bbb.ccc.xxx. It will need suitable defaults (maybe
in CMOS RAM?) and commands to set/change/read them.
 
eg *AUNMap 128 192.168.10
   *AUNMap 128.254 192.168.10.2
   *Configure AUNMap 128 192.168.10   ...?
 
Econet-style IP tansmit/receive calls
It's 01:30, I've been typing away since about 18:00 and my email server
goes off-line at 02:00, so I'll send what I've typed up so far. Sometime
over the next day I'll write up something to implement:
 
  DEFFNIP_Tx(Stn%,Ctrl%,Port%,Addr%,Len%,RAddr%)
  DEFFNIP_TxCount(Stn%,Ctrl%,Port%,Addr%,Len%,RAddr%,Try%,Delay%)
  DEFFNIP_RxOpen(Stn%,Port%,Addr%,Len%)
  DEFFNIP_Rx(RxNum%)
  DEFFNIP_RxRead(RxNum%)
DEFPROCIP_RxKill(RxNum%)
 
-- 
J.G.Harston - jgh@...                - mdfs.net/User/JGH
BBC BASIC for Windows and Internationalisation
   See http://mdfs.net/Software/BBCBasic/Windows/ProgTips
<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>