!**********************************************************
!*                                                        *
!*       RCO ITP to GEC Network Management Module         *
!*                                                        *
!*                       Gecgrab                             *
!*                                                        *
!*           Version    9.3  11 Apr  1983                *
!*                                                        *
!**********************************************************

#options
!* Prep options
!*  b   -   output binary file, else packed hex+compression
!*
!*
%control 1 ;!No record checking.
!*
#if ~i
%include "deimosperm"
#else
%include "b_deimosspecs"
%control x'4001'
#fi
%begin
!*
!**************************
!*                        *
!*    Declarations        *
!*                        *
!**************************

!****** Constintegers ******
!*

!States
%constinteger estb = 2
%constinteger wait data = 1
%constinteger disconnected = 0

!* modes

%constinteger idle = 0
%constinteger sft sent = 1
!estb = 2
%constinteger go sent = 3
%constinteger expect data = 4

%constinteger interact = 0
%constinteger dump = 1
%constinteger hex = 1
%constinteger interp = 2
%include "b_ygatecalls"
%constinteger gatex ser                = 24
%constinteger buffer manager = 17
!Various useful consts etc
%CONSTINTEGER REQUEST BUFFER           =  0
%CONSTINTEGER RELEASE BUFFER           =  1

%constinteger data = 5
%constinteger ack  = 4


!Reasons for grabbing buffers
%constinteger send go = 1
%constinteger send er = 2
%constinteger send ms = 3
%constinteger send sft = 0
%constinteger send connect = 4

!Monitor Calls
%constinteger grotted 2                =  2
%constinteger grotted 4                =  6

!*
!****** End of Constintegers ******
!*


!*
!****** Recordformats ******
!*
%recordformat qf(%record (qf) %name link, %integer count)
%recordformat ts29f(%string (255) s %or %byte octet1 %or %bytearray a(0:255))
%recordformat itpf(%byte cnsl, hb2, hb3, (%string(252) s %or %bytearray a(0:252)))
%recordformat mef(%record (mef) %name link, %byte l,type, %c
       (%bytearray a(0:251) %c
   %or (%string(4) padding, %byte octet1, lcn, fn ,(%bytearray data(0:243) %or %record (itpf) itp %or %record (ts29f) ts29 %or %string (243) ds)) %c
   %or %string(250) s ))
%recordformat pf( %c
    (%byte ser, reply, fn, s1, %record (mef) %name m, %byte gate port, task port) %c
%or (%integer address, d5, %string (3) facility) %c
%or (%byte d6, d7, a1, a2, b1, b2, c1, c2) %c
 %or (%integer type, a, b, c))

%recordformat sidef(%byte proc, state, inputs, outputs, %record (qf) outq)

%ownbyte param, cnsl, mode
%owninteger blocks in

!*
!****** Names ******
!*
%ownrecord (sidef) gec
!*
!****** Records and Recordarrays ******
!*
%constrecord (*) %name null == 0
%ownrecord (pf) p = 0
%owninteger i,logopt, dataopt,buffers held = 0
%ownstring (255) itpbuff

%ownstring (63) address = ""

!*
!****** Routine Specs ******
!*
%routinespec ask for buffer(%record (mef) %name mes, %byte reason)
%routinespec free buffer(%record (mef) %name mes) ;!EXT
%routinespec to gatex(%integer type, flag)
%routinespec do connect(%record (mef) %name mes)
%routinespec handle gec data(%record (pf) %name p)
%routinespec handle ts packet(%byte ser)
#if ~f
%routinespec monitor(%record (pf) %name p, %integer type) ;!EXT
#fi
%routinespec read string(%string (*) %name s)
%routinespec query process
%routinespec send(%record (mef) %name mes, %c
%integer fn)
%routinespec stop(%integer reason)
!*
!****** Others ******
!*
%ownstring(1) snil = ""
%ownstring (4) stopit = "STOP"
%ownstring (3) marker = "*
"
!************************
!*                      *
!*    Main Program      *
!*                      *
!************************
!*
      %on 9 %start;   ! disc full etc.
         selectoutput(0)
         printstring("Disc/directory is full!
")
         -> abo
      %finish

printstring("Gecgrab Running
")
      prompt("Address?"); readstring(address)
      %if address = "" %then address = "18888888888803"

i = map virt(buffer manager, 6, 5)
i = map virt(buffer manager, 5, 4)

      ask for buffer(null, send connect)

%cycle
   p_ser = 0
   poff(p)

      %if 'M' <= int <= 'O' %start
         logopt = int-'O'; int = 0
      %finish

     %if int = 'A' %then to gatex(Disconnect, 1)

   %if int = '?' %start
      query process
#if ~f
      monitor(null, query)
#fi

   %finish
   int = 0

   buffers held = buffers held + 1 %unless p_m == null
   handle ts packet(p_reply)
      %continue

abo:  to gatex(disconnect, 1)
%repeat

!*********************
!*                   *
!*    Routines       *
!*                   *
!*********************



%routine ask for buffer(%record (mef) %name mes, %byte reason)
   !This routine fires off a buffer request to Buffer Manager
   %record (pf) p
   
   %if mes == null %start
      p_ser = buffer manager ;p_reply = own id
      p_fn = request buffer 
      p_c = 0
      ponoff(p)
      buffers held = buffers held+1
      mes == p_m
   %finish


#if m
      %if logopt < 0 %start
         printstring("ask for buffer, call ="); write(reason, 1); newline
      %finish
#fi

      %if reason = send sft %start
         mes_l = 5
         mes_data(0) = x'84' ;mes_data(1) = 3 ;mes_data(2) = 0
         mes_data(3) = param >>8 ;mes_data(4) = param & 255

      %elseif reason = send go
         mes_l = 3
         mes_data(0) = x'82' ;mes_data(1) = 2 ;mes_data(2) = 0

      %elseif reason = send er
         mes_l = 3
         mes_data(0) = 0 ;mes_data(1) = 4 ;mes_data(2) = 0

      %elseif reason = send ms
         mes_l = 3
         mes_data(0) = 0 ;mes_data(1) = 3 ;mes_data(2) = param

      %else %if reason = send connect
         do connect(mes); %return
      %finish

      send(mes, data)

   %return

%end ;!of Buffer Arrived


%routine free buffer(%record (mef) %name mes)
   %record (pf) p
   %if mes == null %then %return ;!No buffer to free
   p_ser = buffer manager ;p_reply = own id
   p_fn = release buffer
   p_m == mes
   buffers held = buffers held - 1
   stop(grotted 2) %if 0 # mes_type # 64
   pon(p)
%end ;!of Free Buffer

      %routine mon mes(%record (mef) %name mes)
         %integer i, j, k, n

         k = mes_l
         write(k, 1);  space;  space
         j = 0
         %cycle i = 0, 1, k-1
               write(mes_data(i), 1)
               j = j+1;   %if j = 20 %then j = 0 %and newline
         %repeat
         newline;   select output(0)
      %end
      %routine to gatex(%integer fn, flag)
         p_ser = gatex ser; p_reply = id
         p_fn = fn; p_s1 = flag
         p_gate port = gec_proc; p_task port = 1
         p_m == null
         pon(p)
#if m
         %if logopt < 0 %start
            printstring("To Gatex, call ="); write(fn, 1)
            printstring(", flag ="); write(flag, 1)
            newline
         %finish
#fi
      %end

      %routine pack(%record(mef) %name mes, %string (*) %name s)
         string(addr(mes_a(mes_l))) = s
         mes_l = mes_l+length(s)+1
      %end


%routine do connect(%record (mef) %name mes)
      %string (3) facn
      %ownstring (5) wind = "W=4/4"

         p_ser = gatex ser; p_reply = id
         p_fn = Connect
         p_s1 = 0
         p_gate port = 0; p_task port = 1
         p_m == mes
         mes_l = 0
         pack(mes, address)
         pack(mes, snil)
         pack(mes, wind)
         pack(mes, snil)
         %if logopt # 0 %start
           printstring("Connect to "); printstring(address)
            newline
         %finish
         pon(p)
%end

#if ~b
      %routine squeeze(%string (*) %name s)
         %integer i, j, n, c
         %owninteger last = 0, pos = 0

         n = length(s)
         %for i = 1, 1, n %cycle
            c = charno(s, i)
            %if c = '0' %start
               last = last+1
            %else
               select output(1)
                  %if last # 0 %start
                     %if last < 5 %start
                        %for j = 1, 1, last %cycle
                           printsymbol('0')
                        %repeat
                        pos = pos+last
                     %else
                        printsymbol('('); write(last, 1)
                        printsymbol(')')
                        pos = pos+5
                     %finish
                     last = 0
                  %finish
                  printsymbol(c); pos = pos+1
                  %if pos > 100 %then newline %and pos = 0
                  select output(0)
               %finish
         %repeat
      %end
#fi

%routine handle gec data(%record (pf) %name p)
   %routinespec pack(%byte char)
   %routinespec packhex(%integer n, places)
   %integer i, m, n, q, l
   %record (mef) %name mes
   mes == p_m

      to gatex(ack, 1);  ! ack the block: NB: Disturbs P
      %if logopt < 0 %then printstring("From Gate ") %and mon mes(mes)

      %if mes_l = 0 %then free buffer(mes) %and %return

      %if mode = sft sent %start
         %if mes_data(1) = 0 %and mes_data(2) = 0 %start
            !Rpos rec'd ok
            ask for buffer(mes, send go) ;mes == null
            printstring("Rpos
")
            mode = go sent

         %else
            printstring("Rneg
")
            mes == null
            mode = idle
            to gatex(Disconnect, 1)


         %finish

      %elseif mode = go sent
         %if logopt # 0 %then printstring("SS
")
         mode = expect data

      %elseif mes_data(0) = 0 %and (mode = estb %or mode = expect data)
         blocks in = blocks in+1
         %if mes_data(1) = 1 %start
            %if blocks in = 6000 %start
               printstring("File too large, stopping
")
               to Gatex(Disconnect, 0)
               mode = idle
               free buffer(mes)
               %return
            %finish

            param = mes_data(2)
            ask for buffer(mes, send ms) ;mes == null
            %if logopt # 0 %start
               printstring("MR"); write(param, 1); newline
            %finish
#if ~b
            squeeze(marker)
#fi
            mode = expect data

         %elseif mes_data(1) = 2
            ask for buffer(mes, send er) ;mes == null
            printstring("ES
")
            mode = idle
            to gatex(Disconnect, 1)

         %else
            printstring("Unkn ?")
            write(mes_data(0), 1) ;write(mes_data(1), 1) ;write(mes_data(2), 1) ;newline

         %finish
      %elseif mode = expect data
         %if mes_data(0) > 127 %then mode = estb %and mes_data(0) = mes_data(0) & 127
         %if dataopt = hex %start
            itpbuff = ""
            q = 1
            %if length(mes_ds) # 0 %start
            l = length(mes_ds)
back:
              select output(1)
               %for i = 1, 1, l %cycle
#if ~b
                  packhex(mes_data(q), 2)
#else
                  printsymbol(mes_data(q))
#fi
                  q = q +1
               %repeat
               select output(0)
               %if mes_l > q %then l = mes_data(q) %and q = q+1 %and -> back
            %finish

         %else
            itpbuff = mes_ds

         %finish

#if ~b
            squeeze(itpbuff)
#fi

         %if logopt < 0 %start
            %if length(itpbuff) > 70 %start
               %cycle i = 1, 1, length(itpbuff)
                  printsymbol(charno(itpbuff, i))
                  newline %if i&63 = 0
               %repeat
           %finish %else printstring(itpbuff)
            newline
         %finish

      %finish

   free buffer(mes)

   %return

   %routine pack(%byte char)
      length(itpbuff) = length(itpbuff) + 1 ;charno(itpbuff, length(itpbuff)) = char
   %end ;!of pack

   %routine packhex(%integer val, d)
   %integer i,j,mask
      %constintegerarray k(0:15) = '0', '1', '2', '3', '4', '5', '6', '7',
                                    '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
      i = val>>4&15; j = val&15
      pack(k(i)); pack(k(j))
   %end ;!of packhex
%end ;!of Handle GEC Data



%routine handle ts packet(%byte ser)
   %record (mef) %name mes
   %integer gate port, task port
   mes == p_m
   task port = p_task port
   gate port = p_gate port
#if m
      %if logopt < 0 %start
         printstring("From Gate; Fn ="); write(p_fn, 1)
         printstring(" flag ="); write(p_s1, 1)
         newline
      %finish
#fi
%if p_fn = accept call %start
      free buffer(mes) %unless mes == null
   cnsl = 0 ;mode = 0 ;gec = 0 
   dataopt = hex
      param = 0
      gec_proc = gate port
      ask for buffer(null, send sft)
      mode = sft sent

%elseif p_fn = data %or p_fn = control data
   gec_inputs = gec_inputs + 1
   handle gec data(p)

%elseif p_fn = disconnect
      free buffer(mes) %unless mes == null
   gec_proc = gate port %if gec_proc = 0
   free buffer(pop(gec_outq)) %while gec_outq_count # 0
   gec_outputs = 0
      printstring("Call Disconnected "); write(p_s1, 1)
      newline
#if ~b
      squeeze(stopit); select output(1); newline
#else
   select output(1); newline
#fi
      %stop


%elseif p_fn = ack
   gec_outputs = gec_outputs - p_s1
      %if gec_outputs > 250 %then gec_outputs = 0


%finish

   %return

%end ;!of Handle TS packet


%routine read string(%string (*) %name s)
%integer i,j
      s = ""
      %cycle
         readsymbol(i)
         %return %if i = nl
         s = s.tostring(i)
      %repeat
%end

%routine query process
   %integer i,j
   %routinespec monside(%record (sidef) %name side)
   printstring("BH=") ;write(buffers held, 1) ;newline
   printstring("CL,IQ:")
   write(cnsl, 1) ;write(mode, 1)
   printstring(" GEC:") ;monside(gec)
   newline
      printstring("Blocks In ="); write(blocks in, 1)
      newline

   %routine monside(%record (sidef) %name side)
      write(side_proc, 2)
      write(side_state, 1)
      write(side_inputs, 1)
      write(side_outputs, 1)
      write(side_outq_count, 1)
   %end ;!of Monside (in Query Processes)
%end ;!of Query Process








%routine send(%record (mef) %name mes, %integer fn)
   %byte q
   %if fn = data %or fn = control data %then gec_outputs = gec_outputs + 1
   p_reply = id
   p_fn = fn
   p_m == mes
   p_gate port = gec_proc
   p_task port = 1
      p_ser = gatex ser
   %unless p_m == null %start
      buffers held = buffers held - 1
      stop(grotted 4) %if 0 # p_m_type # 64
   %finish
   pon(p)
   %return
%end ;!of Send

%routine stop(%integer reason)
   printstring("Gecgrab Stopped") ;write(reason, 1)
#if ~f
   monitor(null, query)
#fi
   %cycle
   %repeat
%end ;!of Stop





%endofprogram