%begin; !Opaque: program to use ether station's transparent mode

%option "-low"
%include "inc:fs.imp"
%include "inc:util.imp"
%include "inc:chario.imp"

%recordformat eaf(%byte station,port,%integer z)
%recordformat epf(%record(eaf)dest,source,%byte type,seq,
                  %bytearray data(0:531))
%integer pos=0
%integer us
%integer packetlength
%record(epf)packet

%routine suck
  packetlength = etherread(0,byteinteger(addr(packet)),sizeof(packet))
%end

%routine blow(%integer packetlength)
  etherwrite(0,byteinteger(addr(packet)),packetlength)
%end

%routine swap addresses
%record(eaf)temp
  temp = packet_source
  packet_source = packet_dest
  packet_dest = temp
%end

%routine show(%integer x)
  newline %and pos=0 %if pos>=77
  %if ' '<=x<='~' %start
    printsymbol(x); printsymbol('_')  %and pos = pos+1 %if x='_'
  %else
    printsymbol('_'); phex2(x); pos = pos+2
  %finish
  pos = pos+1
%end

%routine print address(%record(eaf)%name a)
%integer i
  phex2(a_station); printsymbol('.'); phex2(a_port)
  printsymbol('-') %and phex(a_z) %unless a_z=0
%end

%routine handle receiver
%integer i
  suck
  %if packet_type&128=0 %start; !data packet, so acknowledge it
    packet_type = packet_type!!128; swap addresses
    blow(14)
    packet_type = packet_type!!128; swap addresses
  %finish
  printstring("From "); print address(packet_source)
  printstring(" to "); print address(packet_dest)
  space; phex2(packet_type); phex2(packet_seq); space
  phex4(packetlength-14)
  %if packet_type&128=0 %start
    newline; pos = 0
    show(packet_data(i)) %for i = 0,1,packetlength-15
    newline %unless pos=0
  %else
    printstring(" - (Ack)"); newline
  %finish
%end

%routine handle keyboard
%owninteger ds=16_72,dp=0,sp=3,ty=1,seq=0
%integer x
  readsymbol(x)
  %returnif x=nl
  x = x!32
  %if x='e' %start
    ethc = 15; twait
    etheropen(lsap,rdte<<8+rsap)
    %stop
  %finish
  %if x='s' %start
    ds = rhex
  %elseif x='p'
    dp = rhex
  %elseif x='f'
    sp = rhex
  %elseif x='t'
    ty = rhex
  %elseif x='q'
    seq = rhex
  %elseif x=':'
    packet_source_z = 0; packet_dest_z = 0
    packet_source_station = us; packet_source_port = sp
    packet_dest_station = ds; packet_dest_port = dp
    packet_type = ty; packet_seq = seq; seq = seq+1
    packetlength = 0
    %cycle
      x = nextsymbol; %exitif x=nl
      skipsymbol
      %if x='_' %start
        %if nextsymbol='_' %then skipsymbol %else x = rhex
      %finish
      packet_data(packetlength) = x
      packetlength = packetlength+1
    %repeat
    blow(packetlength+14)
  %else
    printstring("s - set dest station"); newline
    printstring("p - set dest port"); newline
    printstring("f - (from) set source port"); newline
    printstring("t - set packet type"); newline
    printstring("q - set sequence number"); newline
    printstring(": - send data (_rhex)"); newline
    printstring("e - exit"); newline
  %finish
  readsymbol(x) %until x=nl
%end

us = etherstation
ethc = 2; twait
prompt("")

%cycle
  handlereceiver %if dtx#0
  handlekeyboard %if probesymbol(nl)
%repeat

%endofprogram
