// PupRTP.bcpl -- Rendezvous/Termination Protocol
// companion module is PupRTPOpenClose.bcpl
// This module contains the 'main line' code.
// Copyright Xerox Corporation 1979, 1981

// last modified October 29, 1981  4:57 PM by Taft

get "Pup0.decl"
get "Pup1.decl"
get "PupRTPInternal.decl"

external
[
// outgoing procedures
RTPSocketProcess; RTPFilter; DefaultOtherPupProc

// incoming procedures
BuildAbort; RTPHandleUncommonPup; RTPFSM
CompletePup; SetPupDPort; SetPupID
Block; TimerHasExpired; Dequeue; ReleasePBI; MultEq

// incoming statics
ndbQ

// outgoing statics
rtpStackSize; defaultTimeout
]

static
[
rtpStackSize = defaultRTPStackSize
defaultTimeout = defaultDefaultTimeout
]

//----------------------------------------------------------------------------
let RTPSocketProcess(ctx) be
//----------------------------------------------------------------------------
// a copy of this process gets fired up for each RTP socket created
[
let soc = ctx>>RTPCtx.socket

   [ // repeat
   ctx>>RTPCtx.unclean = true
   while soc>>RTPSoc.iQ.head ne 0 do
      [
      let pbi = Dequeue(lv soc>>RTPSoc.iQ)
      switchon pbi>>PBI.pup.type into
         [
         case typeRFC:
         case typeEnd:
         case typeEndReply:
         case typeAbort:
         case typeError:
            // Pup type known about by RTP, though it may also be of interest
            // to higher-level handler.  RTPHandleUncommonPup returns true if
            // it has disposed of pbi, false if the pbi is to be handed to
            // the higher-level handler.  (This arrangement minimizes stack
            // usage when the higher-level handler is called.)
            if RTPHandleUncommonPup(soc, pbi) then loop
            endcase
         ]

      // surviving pups are passed up to higher level guy
      (soc>>RTPSoc.rtpOtherPupProc)(pbi)
      ]

   if TimerHasExpired(lv soc>>RTPSoc.rtpTimer) then RTPFSM(soc, TIMO)
   if TimerHasExpired(lv soc>>RTPSoc.rtpOtherTimer) then
      (soc>>RTPSoc.rtpOtherTimerProc)(soc)

   ctx>>RTPCtx.unclean = false
   Block()
   ] repeat
]

//----------------------------------------------------------------------------
and RTPFilter(pbi, checkFrnPort, checkID) = valof
//----------------------------------------------------------------------------
[
let soc = pbi>>PBI.socket
if pbi>>PBI.pup.dPort.host eq 0 then resultis false  //broadcast
if checkFrnPort then
   [  // if the foreign net in the socket is zero and the identity
      // of net zero has become known since we opened the socket,
      // set the socket's foreign net to be the real net number.
   if soc>>PupSoc.frnPort.net eq 0 then
      soc>>PupSoc.frnPort.net = (ndbQ!0)>>NDB.localNet
   unless MultEq(lv pbi>>PBI.pup.sPort, lv soc>>RTPSoc.frnPort, lenPort) do
      resultis false
   ]
resultis checkID? MultEq(lv pbi>>PBI.pup.id, lv soc>>RTPSoc.connID), true
]

//----------------------------------------------------------------------------
and DefaultOtherPupProc(pbi) be ReleasePBI(pbi)
//----------------------------------------------------------------------------