!iso4
! Uni-process implementation of ISO-TL
include "inc:util.imp"
include "ether:iso4.inc"
include "ether:iso.inc"
include "ether:iso4sum"
recordformat list f (record (listf)name next,prev,record (*)name rec)
ownrecord (listf)name tc list == nil
owninteger clock phase=0
recordformat i tc f (record (tcf)userpart,
half lref,rref,integer state,nextin,inlimit,nextout,outlimit,
record (listf)name inpend,outpend)
constinteger max tc = 20
ownrecord (i tc f)namearray tc refs(1:maxtc) == nil(*)
constinteger -
clock bit = 1, {clock phase indicator
cr sent = 2, {TCRQ received from user, CR TPDU sent
cr received = 4, {CR TPDU received
cr indicated = 8, {TCI sent to user
ca sent = 16, {TCRE received from user, CA TPDU sent
ca received = 32, {CA TPDU received
ca confirmed = 64, {TCC sent to user
dr sent = 128, {TDR received from user, DR TPDU sent
dr received = 256, {DR TPDU received
dr indicated = 512 {TDI sent to user
externalstring (*)map heapstring(string (255)s)
string (*)name t
result == nil if s=""
t == string(heapget(length(s)+1))
t = s
result == t
end
halffn new tc ref
integer i
for i = 1,1,maxtc cycle
result = i if tcrefs(i)==nil
repeat
signal 3,4,,"Too many transport connections"
end
externalrecord (tc f)map T ALLOCATE TC REF (string (63) LSAP, RSAP)
! Returns a reference to a (new) connection record.
record (itcf)name tc
record (listf)name cell
half lref
lref = new tc ref
tc == new(tc)
tc = 0
tc_lref = lref
tc_userpart_lsap == heapstring(lsap)
tc_userpart_rsap == heapstring(rsap)
cell == new(cell)
cell_rec == tc
cell_prev == nil
cell_next == tc list
tc list == cell
result == tc_userpart
end
record (listf)map validate tc(record (tcf)name tc)
record (listf)name c
c == tc list
cycle
signal 3,4,,"Invalid TC reference supplied" if c==nil
result == c if c_rec==tc
c == c_next
repeat
end
routine move(integer bytes,bytename from,to)
label nothing
*subq.w #1,bytes
*bmi nothing
loop: *move.b (a0)+,(a1)+
*dbra d0,loop
nothing:
end
routine add parm(byte code,record (parmf)name p,record (tpduf)name t)
bytename source,dest
integer size
source == p_code; source = code
dest == t_byte(t_li+2)
size = length(p_string)+2
move(size,source,dest)
t_li = t_li+size
end
externalroutine T CONNECT REQUEST -
(record (tc f)name REF, string (32) DATA)
! Attempt to make a connection to the remote entity indicated by REF_RSAP,
! with the QOS parameters in REF, and with optional DATA as provided.
record (itcf)name tc
record (tpduf)name tpdu
record (parmf)parm
integer sumpos
tc == validate tc(ref)_rec
signal 3,4,,"TC already connected" unless tc_state=0
tc refs(tc_lref) == tc
tpdu == new(tpdu)
tpdu_li = fhp cr
tpdu_code = cr tpdu
tpdu_sref = tc_lref
tpdu_classopt = class4+extendedformats
unless tc_userpart_lsap==nil start
parm_string = tc_userpart_lsap; add parm(pc cgid,parm,tpdu)
finish
unless tc_userpart_rsap==nil start
parm_string = tc_userpart_rsap; add parm(pc cdid,parm,tpdu)
finish
parm_byte(0) = 1; parm_byte(1) = lmt; add parm(pc size,parm,tpdu)
parm_byte(0) = 1; parm_byte(1) = 1; add parm(pc ver,parm,tpdu)
parm_byte(0) = 2; add parm(pc sum,parm,tpdu); sumpos = tpdu_li
move(length(data),charno(data,1),tpdu_byte(tpdu_li+1)) unless data=""
generate sum(tpdu_li,tpdu_li+1+length(data),sumpos)
tc_state = tc_state!crsent
{now schedule the TPDU for transmission}
end
externalrecord (tc f)map T CONNECT INDICATED -
(string (63) LSAP, integer WAIT)
! If some other end has attempted to establish a connection with the
! caller, identified as LSAP, a reference to a connection record is
! returned. If not, NIL is returned if WAIT=0; otherwise the called
! is suspended.
end
externalroutine T CONNECT RESPONSE -
(record (tc f)name REF, string (32) DATA)
! Either this or T DISCONNECT REQUEST should be called by someone who
! has received a non-NIL result from T CONNECT INDICATED.
end
externalroutine T DISCONNECT REQUEST -
(record (tc f)name REF, string (43) REASON, string (64) DATA)
! Shut down the connection identified by REF, optionally supplying
! an explanatory reason and data.
end
externalintegerfn T CONNECTED -
(record (tc f)name REF, string (*)name REASON, DATA, integer WAIT)
! If the connection is still being negotiated (the other end has not
! yet responded), then the result is 0 (if WAIT=0, otherwise caller
! is suspended) and REASON and DATA are unaffected.
! If the connection has been established, the result is >0, and DATA
! receives the message supplied at the other end via T CONNECT RESPONSE.
! Otherwise the connection has been shut down, the result is <0, and DATA
! and REASON receive information provided by T DISCONNECT REQUEST.
end
externalroutine T EXPEDITED DATA REQUEST -
(record (tc f)name REF, string (16) DATA)
! Sends a quickie (if enabled by negotiation).
end
externalroutine T DATA REQUEST-
(record (tc f)name REF, name WHERE, integer SIZE, byte EOF)
! Passes a TIDU across the interface. SIZE bytes of data, in store at
! WHERE, are transmitted. If EOF#0, this constitutes the last TIDU
! making up a TSDU.
end
externalintegerfn T DATA INDICATED (record (tc f)name REF, integer WAIT)
! If no TSDU has arrived on the connection, the result is 0 (unless
! WAIT#0, in which case the caller is suspended).
! If a DATA unit is available, the result is >0.
! If an EXPEDITED DATA unit is available, or the connection has been
! broken, the result is <0.
end
externalroutine T ACCEPT DATA (record (tc f)name REF, -
name WHERE, integername SIZE, bytename EOF, integer WAIT)
! A pending data unit is copied into store at WHERE. SIZE on entry
! indicates the maximum size of the TIDU the caller is prepared to accept.
! SIZE will be set to the number of bytes actually copied. This will
! be negative if the connection is broken or an EXPEDITED DATA unit
! is pending, or no data is available and WAIT=0. EOF is set if this
! was the last TIDU of a TSDU.
end
externalroutine T ACCEPT EXPEDITED DATA -
(record (tc f)name REF, string (16)name DATA)
! Should only be called when an expedited data unit is known to be there.
end