File [Indigo]<AltoSource>PUPSOURCES.DM!3>PupBSPOpenClose.bcpl

// PupBSPOpenClose.bcpl -- Byte Stream Protocol
// Companion files are PupBSPProt, PupBSPStreams and PupBSPa
// This module contains infrequently executed code which can swap
// without affecting performance.
// Copyright Xerox Corporation 1979, 1980, 1981
// Last modified October 29, 1981 5:22 PM by Taft
get "Pup.decl"
get "PupRTPInternal.decl"
external
[
// outgoing procedures
CreateBSPStream; CloseBSPSocket; BSPPutInterrupt; BSPHandleUncommonPup
// incoming procedures
BSPPupProc; BSPTimerProc; BSPForceOutput; BSPPrepareIPBI; BSPGetCleanup
BSPGetByte; BSPPutByte; BSPEndofs; BSPErrors; BSPCloses; SearchTQ
CloseRTPSocket; RTPFilter; RTPFSM; CloseLevel1Socket; SetTimeout
ReleasePBI; GetPBI; CompletePup; SetPupID; AppendStringToPup; MultEq
Noop; Zero; SetBlock; MoveBlock; SysErr; DoubleIncrement; DoubleDifference
SetTimer; TimerHasExpired; Block; Dismiss; Min
FlushQueue
// outgoing statics
lBSPSoc; offsetBSPStr
// incoming statics
defaultTimeout
]
static
[
lBSPSoc = lenBSPSoc
offsetBSPStr = offset BSPSoc.bspStr/16
]
//----------------------------------------------------------------------------
let CreateBSPStream(soc) = valof
//----------------------------------------------------------------------------
[
// initialize BSP socket
unless soc>>BSPSoc.state eq stateOpen % soc>>BSPSoc.state eq stateEndIn do
 resultis 0
Zero(soc+lenRTPSoc, lenBSPSoc-lenRTPSoc)
for i = 0 to 5 do
 MoveBlock(soc + (table
 [
 offset BSPSoc.userByteID/16
 offset BSPSoc.rcvByteID/16
 offset BSPSoc.rcvIntID/16
 offset BSPSoc.xmitIntID/16
 offset BSPSoc.xmitByteID/16
 offset BSPSoc.lastAckID/16
 ])!i, lv soc>>BSPSoc.connID, 2)
SetTimer(lv soc>>BSPSoc.bspTimer, 0)
SetTimer(lv soc>>BSPSoc.inactivityTimer, inactivityTimeout)
soc>>BSPSoc.bspOtherPupProc = soc>>BSPSoc.bspPupProc
soc>>BSPSoc.bspPupProc = BSPPupProc
soc>>BSPSoc.bspTimerProc = BSPTimerProc
soc>>BSPSoc.aDataTimeout = initialADataTimeout
soc>>BSPSoc.maxPupAlloc = Min(soc>>BSPSoc.maxOPBI, initialMaxPupAlloc)
// initialize BSP stream
let str = soc+offsetBSPStr
SetBlock(str, SysErr, lST)
str>>BSPStr.gets = BSPGetByte
str>>BSPStr.puts = BSPPutByte
str>>BSPStr.close = BSPCloses
str>>BSPStr.endof = BSPEndofs
str>>BSPStr.error = BSPErrors
resultis str
]

//----------------------------------------------------------------------------
and CloseBSPSocket(soc, timeout; numargs na) = valof
//----------------------------------------------------------------------------
[
if na le 1 then timeout = defaultTimeout
if soc>>BSPSoc.state eq stateOpen % soc>>BSPSoc.state eq stateEndIn then
 [ // wait til all queued output has been acknowledged
 BSPForceOutput(soc)
 let timer = nil; SetTimer(lv timer, timeout)
 while soc>>BSPSoc.unAckedPups ne 0 % soc>>BSPSoc.interruptOut do
 [
 BSPFlushInput(soc) // flush waiting input
 switchon soc>>BSPSoc.state into
 [
 case stateOpen: case stateEndIn:
 unless TimerHasExpired(lv timer) endcase
 default:
 timeout = 0; break // timed out or aborted
 ]
 Dismiss(1)
 ]
 ]
// close the socket, flushing BSP input while waiting
soc>>BSPSoc.bspTimerProc = BSPInputSuckerUpper
BSPInputSuckerUpper(soc)
timeout = CloseRTPSocket(soc, timeout)
// wait til all owned pbi's have returned before destroying socket
soc>>BSPSoc.bspPupProc = ReleasePBI // turn off input
soc>>BSPSoc.bspTimerProc = Noop
if soc>>BSPSoc.oPBI ne 0 then ReleasePBI(soc>>BSPSoc.oPBI)
while soc>>BSPSoc.numOPBI ne soc>>BSPSoc.maxOPBI do
 [ FlushQueue(lv soc>>BSPSoc.bspTQ); Dismiss(1) ]
FlushQueue(lv soc>>BSPSoc.bspIQ)
CloseLevel1Socket(soc)
resultis timeout ne 0
]
//---------------------------------------------------------------------------
and BSPFlushInput(soc) be
//---------------------------------------------------------------------------
// called via BSPTimerProc entry to flush input during RTP close
[
let ec = BSPPrepareIPBI(soc, 0)
unless ec eq 0 % ec eq ecMarkEncountered return
BSPGetCleanup(soc)
] repeat
//---------------------------------------------------------------------------
and BSPInputSuckerUpper(soc) be
//---------------------------------------------------------------------------
// called via BSPTimerProc entry to flush input during RTP close
[
BSPFlushInput(soc)
SetTimer(lv soc>>BSPSoc.bspTimer, 10)
]

//---------------------------------------------------------------------------
and BSPPutInterrupt(soc, code, string, timeout; numargs na) = valof
//---------------------------------------------------------------------------
[
if na ls 4 then timeout = -1
let timer = nil; SetTimer(lv timer, timeout)
 [
 switchon soc>>BSPSoc.state into
 [
 case stateOpen: case stateEndIn:
 unless timeout ge 0 & TimerHasExpired(lv timer) endcase
 default:
 resultis false // bad state or timed out
 ]
 if soc>>BSPSoc.numTPBI ne 0 & soc>>BSPSoc.numOPBI ne 0 &
 not soc>>BSPSoc.interruptOut then break
 Block()
 ] repeat
let pbi = GetPBI(soc)
pbi>>PBI.pup.words↑1 = code
AppendStringToPup(pbi, 3, string)
SetPupID(pbi, lv soc>>BSPSoc.xmitIntID)
pbi>>PBI.queue = lv soc>>BSPSoc.bspTQ // keep pbi around
CompletePup(pbi, typeInterrupt)
soc>>BSPSoc.interruptOut = true
SetTimeout(soc)
resultis true
]

//---------------------------------------------------------------------------
and BSPHandleUncommonPup(soc, pbi) be
//---------------------------------------------------------------------------
// Called from BSPPupProc for Interrupt, InterruptReply, and End.
// Always disposes of pbi.
[
let passedSourceFilter = RTPFilter(pbi, true, false)
switchon pbi>>PBI.pup.type into
 [
 case typeInterruptReply:
 if passedSourceFilter &
 MultEq(lv pbi>>PBI.pup.id, lv soc>>BSPSoc.xmitIntID) &
 soc>>BSPSoc.interruptOut then
 [
 let npbi = SearchTQ(soc, true) // Find interrupt on TQ
 if npbi ne 0 then
 [
 DoubleIncrement(lv soc>>BSPSoc.xmitIntID, 1)
 soc>>BSPSoc.interruptOut = false
 ReleasePBI(npbi)
 ]
 // If we can't find it, we must be retransmitting it now,
 // so just pretend the reply was lost and rely on the
 // retransmission to elicit a new reply
 ]
 endcase
 case typeInterrupt:
 if passedSourceFilter then
 [
 let d = DoubleDifference(lv soc>>BSPSoc.rcvIntID,
 lv pbi>>PBI.pup.id)
 test d eq 0
 ifso
 [ // This is a new interrupt so update id
 DoubleIncrement(lv soc>>BSPSoc.rcvIntID, 1)
 soc>>BSPSoc.interruptIn = true
 (soc>>BSPSoc.bspOtherPupProc)(pbi) //pass it on
 ]
 ifnot ReleasePBI(pbi)
 if d ule 1 then
 [ // Generate InterruptReply for cases 0 and 1
 pbi = GetPBI(soc, true)
 if pbi ne 0 then
 [
 SetPupID(pbi, lv soc>>BSPSoc.rcvIntID)
 DoubleIncrement(lv pbi>>PBI.pup.id, -1)
 CompletePup(pbi, typeInterruptReply, pupOvBytes)
 ]
 ]
 return // pbi already released
 ]
 endcase
 case typeEnd:
 // Already filtered by RTP.
 // If stream is idle then close connection immediately; otherwise
 // await local close.
 if soc>>BSPSoc.oPBI eq 0 & soc>>BSPSoc.unAckedPups eq 0 &
 not soc>>BSPSoc.interruptOut & soc>>BSPSoc.unReadPups eq 0 then
 RTPFSM(soc, CLSN)
 endcase
 ]
// above code should return before here if pbi is already disposed of
ReleasePBI(pbi)
]

AltStyle によって変換されたページ (->オリジナル) /