Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_3_19910112
-
mit/monitor/mnetwk.mac
There are no other files named mnetwk.mac in the archive.
;[MIT-XX]PS:<BERLIN.M5>MNETWK.MAC.5, 28-Feb-83 17:12:35, Edit by BERLIN
;3032 ISI merge
;<BERLIN.M5>MNETWK.MAC.4, 30-Aug-82 21:42:46, Edit by BERLIN
;1017 Add NETHST GETAB
;[BBNF]<TAPPAN.NEW>MNETWK.MAC.13, 30-Jul-82 09:18:10, Edit by: TAPPAN
; Fix HSTCK0 to work with Non-NCP network addresses (refuse
; to permit connection)
; bug fix HSTLUK
;REL5:<TAPPAN.NEW>MNETWK.MAC.5 15-Jun-82 13:49:42, Edit by TAPPAN
; Merge ISI NTSIBE code
; REL5 merges
; Changed FLINK -> FNLINK to keep up with DEC
; Call NVTDTT instead of NVTDET
; Change order of searches (IMPPAR before PROLOG)
;<TAPPAN.4>MNETWK.MAC.2, 18-Feb-82 18:49:33, Edit by TAPPAN
; Use host address instead of net number for FNDNCT
;<TAPPAN.4>MNETWK.MAC.2, 22-Oct-81 18:46:01, Edit by TAPPAN
;100 moved .ATNVT to JSYSF, entry point at AATNVT for
;NCP NVT's
;<BBN-4-MONITOR>MNETWK.MAC.3, 3-Aug-81 11:18:44, Edit by TAPPAN
; rewrote TSTEX0,TSTEX1 so they can be used no matter what original section was
;<TAPPAN.4>MNETWK.MAC.6, 4-Sep-80 12:36:38, Edit by TAPPAN
; Moved Link and socket tables to ANBSEC
;<TAPPAN.4>MNETWK.MAC.1, 2-Jul-80 12:48:41, Edit by TAPPAN
; Remove HSTINI and related stuff to MNETDV.MAC since thats
; really network independent
;[BBNF]<TCP-BBN-4-MONITOR>NETWRK.MAC.4004, 6-May-80 16:33:34, Ed: PLUMMER
;<BBN-4-MONITOR>NETWRK.MAC.6, 24-Jan-80 16:57:36, EDIT BY JBORCHEK
;<BBN-4-MONITOR>NETWRK.MAC.6, 19-Nov-79 21:16:36, EDIT BY JBORCHEK
;FIX TIPS LOSING NETWORK CONNECTIONS
;
; Many changes betwixt
;
;<4.MONITOR>NETWRK.MAC.2, 29-Jan-78 16:59:49, Edit by BORCHEK
;FIX DIR NET:<*> FROM HANGING JOB. CHECK AT NETSET FOR <*>
SEARCH IMPPAR,PROLOG,MNTPAR,MACSYM,MONSYM
TTITLE MNETWK
;;; Network device stuff for multinet
ASCIZ /
MNETWK
COPYRIGHT (C) 1980,1981,1982 BOLT BERANEK and NEWMAN INC.
/
; Macros to turn imp on and off
DEFINE NCPON<CALL ULKNCP>
DEFINE NCPOFF<CALL LCKNCP>
; Local accumulators
DEFAC (UNIT,Q1) ;PSEUDO-UNIT NUMBER
DEFAC (IOS,Q2) ;STATUS FLAGS (FROM NETSTS(UNIT))
DEFAC (HN,Q3)
DEFAC (STS,P1)
DEFAC (JFN,P2)
DEFAC (PTR,P3)
DEFAC (DEV,P4)
DEFAC (F1,P5)
;PARAMETERS
NLNKBW==<LLINK+^D35>/^D36 ;LENGTH OF LINK BITTABLE
CHKINT==^D30000 ; Do a connection hung check this often
; NCP DATA CLUSTER
DEFSTR ANFHS,NETHST,35,36 ;FOREIGN HOST
DEFSTR ANLNK,NETAWD,8,9 ;LINK
DEFSTR ANCLKS,NETAWD,23,6 ;TIME-OUT COUNTDOWN
DEFSTR ANINPI,NETFRK,5,6 ;INS/INR PSI CHAN
DEFSTR ANFSPI,NETFRK,17,6 ;FSM PSI CHAN
DEFSTR ANFSM,NETSTS,3,4 ;FSM STATE
DEFSTR ANBSIZ,NETSTS,17,6 ;BIT STREAM BYTE SIZE
DEFSTR ANPVST,NETSTS,35,16 ;PREVIOUS 4 STATES
MSGALL==2 ;DESIRED MESSAGE ALLOCATION LEVEL
;FLAGS IN NETSTS
FLG(BFSND,L,IOS,020000) ;BUFFERED SEND MODE
FLG(ERRB,L,IOS,010000) ;ERROR HAS OCCURRED
FLG(EOTF,L,IOS,004000) ;END OF TRANSMISSION FLAG
FLG(SVCIF,L,IOS,002000) ;SERVICE INTERRUPTION IN PROGRESS
FLG(CLZF,L,IOS,001000) ;CONNECTION IS BEING CLOSED
FLG(DEDF,L,IOS,000400) ;HOST IS DEAD
FLG(PROGF,L,IOS,000200) ;SET IF PROGRAM IS WATCHING THIS CONNECTION
FLG(ALLFF,L,IOS,000100) ;ALLOCATION RESYNC HAS BEEN DONE
FLG(LINKF,R,IOS,400000) ;LINK TABLE INDEX VALID
; BBN socket numbers description
; A socket number is a 32-bit number which in conjunction with
; A host number specifies one end of a connection
; For bbn sockets, the 32 bit field is divided in 3 parts:
; The high 17 bits is used as follows:
; if 0: then this is a system socket
; if <100000 then the number is a bbn user number and the socket is
; is called a user socket
; if >99999 then the number is tss job-number plus 100000, and the
; socket is called a job socket
; A job socket is analogous to a temporary file and is guaranteed to
; Be unique to that job. a user socket is analogous to a regular file
; And is guaranteed to be unique to that user. a system socket is
; For use as agreed upon by members of the network for such purposes
; As inter system communication, memo-distribution etc.
; The next 14 bits are an arbitrary number which may be defaulted
; To the jfn associated with the socket or specified by the name field
; Of the file name string. the low order bit is determined by
; The gender of the socket. a socket opened for for writing
; Will have this bit equal to one. a socket opened for reading will
; Have this bit equal to zero.
; Network dispatch table
SWAPCD
NETDTB::DTBDSP (NETSET) ;DIRECTORY SETUP
DTBDSP (NETNAM) ;NAME LOOKUP
DTBDSP (NETEXT) ;EXTENSION LOOKUP
DTBDSP (NETVER) ;VERSION LOOKUP
DTBBAD (DESX9) ;PROTECTION INSERT
DTBBAD (DESX9) ;ACCOUNT INSERT
DTBBAD (DESX9) ;STATUS INSERT
DTBDSP (NETOPN) ;OPEN
DTBDSP (NETSQI) ;BYTE INPUT
DTBDSP (NETSQO) ;BYTE OUTPUT
DTBDSP (NETCLZ) ;CLOSE
DTBBAD (DESX9) ;RENAME
DTBBAD (DESX9) ;DELETE
DTBBAD (DESX9) ;DUMP
DTBBAD (DESX9)
DTBBAD (DESX9) ;MOUNT
DTBBAD (DESX9) ;DISMOUNT
DTBBAD (DESX9) ;INITIALIZE
DTBDSP (NETMTP) ;MTOPR
DTBDSP (NETGST) ;GET STATUS
DTBDSP (NETSST) ;SET STATUS
DTBSKP ;RECORD OUT
DTBDSP (RFTADN) ;READ TAD
DTBDSP (SFTADN) ;SET TAD
DTBDSP (BIOINP) ;SET JFN FOR INPUT
DTBDSP (BIOOUT) ;SET JFN FOR OUTPUT
DTBBAD (GJFX49) ;CHECK ATTRIBUTE
DTBLEN==:.-NETDTB ;GLOBAL LENGTH OF DISPATCH TABLE
; Network lock and unlock
LCKNCP::NOINT
CSKED
LOCK NCPLCK,<JRST LCKNC1>
LCKNC2: MOVE CX,0(P) ; Get PC
HRL CX,FORKX ; And fork
MOVEM CX,NCPLLK ; Save
RET
LCKNC1: ECSKED
OKINT
PUSH P,T1
MOVEI T1,NCPLKT
MDISMS
POP P,T1
JRST LCKNCP
RESCD
NCPLKT: SKIPL NCPLCK
JRST 0(T4)
JRST 1(T4)
;;; Convert host number in AC1 to new format
CVNHST::CAMN T1,[-1] ;IF -1 USE LOCAL HOST NUMBER
MOVE T1,DEFADR ; Default local host
AND T1,[HSTMSK] ;CUT DOWN TO SIZE
TLNE T1,37700
RET
ANDI T1,377
TRZE T1,100 ;SET THE HOST BITS
TRO T1,200000
TRZE T1,200
TRO T1,400000
IOR T1,NETFLD ;Add default network number
RET
; convert host number in AC1 to old format
CVOHST::CAMN T1,[-1] ;NO HOST?
JRST CVOHS1 ;RETURN 777
TDZE T1,[740077,,177700];CHECK TO SEE IF FITS IN OLD FORMAT
MOVEI T1,400 ;RETURN 400
TRZE T1,200000 ;SET THE HOST BITS
TRO T1,100
TRZE T1,400000
TRO T1,200
CVOHS1: ANDI T1,777
RET
SWAPCD
ULKNCP::UNLOCK NCPLCK
ECSKED
OKINT
RET
; Initialize network stuff
NETINI::SE1CAL ;ENTER SECTION 1 FOR THIS ROUTINE
MOVEI T1,NETSTS ; Point to a table
SETSEC T1,ANBSEC ; In this section
SETZM 0(T1) ; Clear first word
MOVE T2,[XWD NETSTS,NETSTS+1]
BLT T2,NSKT-1(T1) ; Clear this far
SETZM NETCNC
SETZM FUNNYC
MOVE T1,[ANBSEC,,NTBUFS]
MOVEM T1,NETFRE ;INITIAL FREE LIST
MOVEI T2,NNTBFS ;SIZE OF BUFFER AREA
IDIV T2,MAXWPM ;CONVERT TO NUMBER OF BUFFERS
MOVEM T2,NETFRE+2 ;FREE SPACE LEFT IN BUFFER AREA
MOVEM T1,NETFRE+3 ;START OF BUFFER AREA
IMUL T2,MAXWPM ;CONVERT TO WORDS
ADDI T1,-1(T2) ;END OF BUFFER AREA
MOVEM T1,NETFRE+4
;INITIALIZE FREE LIST INTO ITEMS OF MAXWPM EACH
IDIV T2,MAXWPM ;NUMBER OF BUFFERS IN REGION
MOVE T3,[ANBSEC,,NTBUFS];SET UP C TO POINT TO NET BUFFERS
NETIN2: MOVE T1,T3 ;COPY C INTO A
ADD T3,MAXWPM ;RH(T3) POINTS TO NEXT BUFFER
HRLOM T3,0(T1) ;STORE THAT IN LEFT HALF IN CURRENT BUFFER
SOJG T2,NETIN2 ;DO ANOTHER
HRRZS 0(T1) ;LAST ITEM POINTER IS 0
SETOM NETFRE+1 ;NETWORK BUFFER LOCK
SETOM NCPLCK
RET
; Prepare to lookup network names
NETSET: TQNE <STEPF> ;WANT TO STEP?
RETBAD (GJFX17) ;YES. CAN'T DO IT
NOINT ;PREVENT INTS
JRST SK2RET ;AND SAY IT IS SET
; Name lookup routine
NETNAM: JUMPE T1,NAMBAD ; *. -- failure
HRLI T1,(<POINT 7,0,35>); Make lookup pointer into byte pointer
CALL NAMDEC ; Decode name
JRST NAMBAD ; Bad syntax
OKRET: TQNE <UNLKF>
JRST SK2RET
OKINT
JRST SK2RET
NAMBAD: MOVEI T1,GJFX18
JRST ERRET ; Error return
ERRET: OKINT
RET
; Extension lookup routine
NETEXT: JUMPE T1,NAMBAD ; .* -- failure
HRLI T1,(<POINT 7,0,35>); Make lookup pointer into byte pointer
CALL EXTDEC ; Decode extension to check syntax
JRST EXTBAD ; Bad syntax
JRST OKRET ; Success
EXTBAD: MOVEI T1,GJFX19
JRST ERRET
; Version lookup
NETVER: HRRES T1 ; Extend sign
CAIL T1,^D100000 ; If geq 100000
JRST NETVR1 ; Use job related socket
HLLZ T1,JSBSDN ; Get structure
LSH T1,-6
ADD T1,JSBSDN ; Add in directory
ANDI T1,177777 ; Clear junk
NETVR1: TQNE <UNLKF>
RETSKP
OKINT
RETSKP
; Decode extension string
; Called both at gtjfn and openf to decode extension string into
; Foreign socket number and host number
EXTDEC: MOVE T4,T1
ILDB T4,T4
JUMPE T4,[SETOB T1,T2
RETSKP]
MOVE T3,T1 ;GET SCRATCH POINTER
SETZ T4, ;ASSUME NO - FOUND
EXTDE1: ILDB T2,T3 ;GET A BYTE
CAIN T2,"-" ;SAVE LAST - FOUND
MOVE T4,T3
JUMPN T2,EXTDE1 ;DO WHOLE STRING
JUMPE T4,R ;NO - MEANS ERROR
DPB T2,T4 ;END HOST WITH NUL
CALL HSTLUK ;LOOKUP HOST
MOVEI T3,"-" ;RESTORE THE -
DPB T3,T1
JUMPG T2,R ;NO HOST FOUND
MOVEI T3,10 ;GET OCTAL SOCKET NUMBER
NIN
RET
MOVE T1,T4
RETSKP
HSTLUK::SAVEPQ ;GET SOME ROOM
MOVE UNIT,T1 ;SAVE POINTER
MOVEI T3,10
NIN ;TRY TO GET A NUMBER
JRST HSTLKI ;TRY A NAME
MOVE UNIT,T1 ;SAVE UPDATED POINTER
MOVE T1,T2
CALL CVNHST
MOVE T4,T1 ;RETURN HOST NUMBER
MOVE T1,UNIT ;AND UPDATED POINTER
SETZ T2, ;HOST NUMBER FOUND
RET
HSTLKI: HRLZ T2,MHOSTS ;SCAN THE TABLE
PUTSEC STS,MNTSEC ; In this section
HSTLK0: MOVE T1,UNIT ;DO NAME POINTER
IFNKA <
LOAD T4,HSTNMP,(STS)
ADD T4,[XWD MNTSEC,HSTNAM] ; Point to the table
MOVE T3,[<POINT 7,0>!1B12] ; Make extended pointer
>
IFKA <
LOAD T3,HSTNMP,(STS)
ADD T3,[POINT 7,HSTNAM]
>
HSTCMP: ILDB IOS,T1 ;COMPARE A STRING
ILDB HN,T3
SKIPN IOS
JUMPE HN,[LOAD T4,HSTIDX,(STS)
SETSEC T4,MNTSEC
MOVE T4,HOSTNN(T4)
HRR T2,STS ; Save index
RET]
CAIN IOS,(HN)
JRST HSTCMP
AOS STS ; Point to next slot in table
AOBJN T2,HSTLK0 ;STEP TO NEXT HOST
SETZ T4, ;NO HOST FOUND
RET
; Decode name string
; Called both at gtjfn and openf to decode name string into
; Local socket number
NAMDEC: MOVEI T3,10 ; Perhaps this should be decimal?
NIN ; Convert to a number
JRST NAMDE1 ; Failure: no number there
LDB T3,T1 ; Get terminator
CAIE T3,"#" ; If not number sign
JRST NAMDE2 ; Then ordinary
MOVE T3,CAPMSK ; Else system socket
TRNN T3,SC%WHL!SC%OPR!SC%NAS;MUST BE WHEEL, OPR, OR
; HAVE ABSOLUTE SOCKET CAPABILITY
RET ; Else fail
ILDB T3,T1 ; Get next ch
TDZA T1,T1 ; Zero for high 17 bits
NAMDE2: HRRZ T1,FILVER(JFN) ; Use filver for high 17 bits
JUMPN T3,R ; String too long
SKIPE T1
ANDI T2,77777 ; If not system socket, retain 15 bits
TRZ T2,1 ; Clear gender
ROT T1,^D15
IOR T1,T2
RETSKP
NAMDE1: MOVE T2,JFN ; Default to jfn
IDIVI T2,MLJFN ; Get the jfn
LSH T2,1 ; Jfn will end up lsh'ed 1
LDB T3,T1
JRST NAMDE2
NETDED::MOVE T1,NETSTS(UNIT) ; GET STATUS
TXNE T1,DEDF+EOTF ; HOST DEAD OR DONE
RET
RETSKP
NETHLK::LOAD T1,ANFHS,(UNIT) ; HOST
LOAD T2,ANLNK,(UNIT) ; LINK
RET
; Open network file
NETOPN: TQNE <XCTF,RNDF>
JRST ILLACC ; Illegal to access in append or xct
TQNE <READF>
TQNN <WRTF>
TQNN <READF,WRTF>
JRST ILLACC ; Must be only one of read or write
LDB T1,PBYTSZ
CAIN T1,^D8 ; Check for 8 32 or 36 bit bytes
TRNA
CAIN T1,^D32
TRNA
CAIN T1,^D36
TRNA
JRST [ MOVEI T1,SFBSX2
RET] ; Bad byte size
HLRZ T1,FILNEN(JFN)
HRLI T1,(<POINT 7,0,35>)
CALL NAMDEC ; Decode name
JRST ILLACC ; Can only happen if wheel lost
TQNE <WRTF>
TROA T1,1 ; If writing set gender bit for local
TRZ T1,1 ; Else clear it
PUSH P,T1 ; Save for later
HRRZ T1,FILNEN(JFN)
HRLI T1,(<POINT 7,0,35>)
CALL EXTDEC ; Decode extension
JRST ILLACC ; Fail
TQNE <READF>
TROA T2,1 ; If reading set gender bit for forskt
TRZ T2,1 ; Else clear
POP P,T3
LDB T4,PBYTSZ ; Get file byte size
JUMPL T1,OPNLSN ; No foreign socket, do a listen
CALL CONNECT ; Connect
RET
TQZ <WNDF>
NETOP1: HRLM UNIT,FILSKT(JFN) ;REMEMBER UNIT NUMBER
SETZ IOS, ; Clear status bits
LDB T1,[POINT 4,STS,35]
CAIE T1,5 ; In modes 5
CAIN T1,7 ; Or 7
TQO <BFSND> ; DO BUFFERED TRANSMISSION
IORB IOS,NETSTS(UNIT) ; Set it in status word
MOVEI T1,^D36
LDB T2,PBYTSZ
IDIV T1,T2 ; Get bytes per WORD
XCTBU [LDB T3,[POINT 6,2,17]];GET DESIRED SIZE OF BUFFER
IMUL T1,T3 ; DESIRED BYTES
HRLM T1,NETBUF(UNIT) ; Gives bytes per buffer
SETZM FILBYN(JFN) ; About to reference byte 0 of buffer
SETZM FILOFN(JFN) ; NEXT BYTE TO XMIT = 0
TQO <SIZF> ; CANNOT CHANGE BYTE SIZE
TQOE <WNDF> ; NO BUFFER YET. ALSO IF LISTEN
RETSKP ; Return immediately
LDB T1,[POINT 4,STS,35]
CAIE T1,6 ; Also in modes 6
CAIN T1,7 ; And 7
RETSKP ; Return immediately
LOAD T1,ANFSM,(UNIT) ; No. get current state
CAIN T1,RFCS ; Will usually be rfcs
CALL WATNOT ; If so, wait for it to not be
LOAD T1,ANFSM,(UNIT) ; Get state
MOVE IOS,NETSTS(UNIT)
TQNN <EOTF> ; IF LEFT OPND
CAIN T1,OPND ; OR STILL OPENED
RETSKP ; THEN SUCCEED
MOVX T2,PROGF
ANDCAM T2,NETSTS(UNIT) ; Program not watching
CALL NETCLD ; FSM close
TQNE <ERRB> ; ERRB REMEMBERS BAD BYTE SIZE
SKIPA T1,[OPNX22] ; MAKE THAT THE ERROR CODE
MOVEI T1,OPNX21 ; ELSE IT WAS REJECTED
RET ; And give bad return
OPNLSN: CALL LISTEN
RET ; Can't listen
TQO <WNDF> ; TO REMEMBER THAT THIS WAS A LISTEN
JRST NETOP1 ; First bin/out is accept
ILLACC: MOVEI T1,OPNX14
RET
; Wait for fsm to leave state given in a
WATNOT: HRLI T1,NOTTST ; TEST ROUTINE ADDRESS
WATNO1: HRRZ T2,UNIT ; COMPUTE SCHEDULER TEST ARGUMENT
ROT T2,-9
MOVSS T1
IOR T1,T2
MDISMS
RET
; Wait for fsm to enter a particular state
WATFOR: HRLI T1,WATTST
JRST WATNO1
RESCD
NOTTST: SE1ENT ; Enter section 1
LDB T2,[POINT 9,T1,26] ; EXTRACT UNIT
SETSEC T2,ANBSEC ; Point into proper section
ANDI T1,777 ; AND STATE TO TEST AGAINST
LOAD T3,ANFSM,(T2) ; GET CURRENT STA(E
CAMN T1,T3 ; IS IT THE SAME
JRST WATTS1 ; YES, MAKE OTHER TESTS
;;; TSTEX1 - exit multisection test, with skip return
TSTEX1::
AOS T4 ; increment return address
TSTEX0:: ; Exit with non-skip return
TLZ T4,-40 ; clear any program flags
JRST @T4 ; and back from the test
;;; SCHEDULER TEST WAITING FOR CONNECTION TO GET TO A STATE
WATTST: SE1ENT ; Enter section 1
LDB T2,[POINT 9,T1,26] ; EXTRACT UNIT
SETSEC T2,ANBSEC ; Point to proper section
ANDI T1,777 ; AND STATE
LOAD T3,ANFSM,(T2) ; GET CURRENT STATE
CAMN T3,T1 ; SAME?
JRST TSTEX1 ; return good
WATTS1: MOVE T3,FKINT(HN) ; Look for deferred interrupts
TLNN T3,(1B1)
JRST TSTEX0 ; bad
SETZ T3,
STOR T3,ANCLKS,(T2) ; Set clock to zero to hasten time-out
JRST TSTEX0 ; return
;;; SCHEDULER TEST FOR BIT ALLOCATION
;;; CONNECTION NUMBER IN T1
BALTST: SE1ENT ; Enter section 1
SETSEC T1,ANBSEC ; Right section
LOAD T2,ANBSIZ,(T1) ;GET BIT STREAM BYTE SIZE
LOAD T3,LTIDX,(T1) ;GET LINK TABLE INDEX
SETSEC T3,ANBSEC ; In the right section
SKIPN IMPLT4(T3) ;SKIP IF NEITHER MSG ALLOC OR BUFFER
JRST BALTS1
CAMG T2,NETBAL(T1) ;MSG OK, HOW ABOUT BITS?
JRST TSTEX1 ; Exit good
BALTS1: MOVE T3,NETSTS(T1) ;GET STATUS INFO
TXNE T3,DEDF+EOTF ;ALLOC BAD. BUT IF DEAD..STILL OK
JRST TSTEX1 ; Exit good
JRST TSTEX0 ; Flunk
SWAPCD
; Close network file
NETCLZ: HLRZ UNIT,FILSKT(JFN)
SETSEC UNIT,ANBSEC ; Place in proper section
TQNN <WNDF> ; IF NO BUFFER EVER ASSIGNED
TQNN <WRTF> ; OR IF READING
JRST NETCL1 ; Then skip the following
CALL DMPBUF ; Dump last buffer
JRST NETCLW ; NOT ALL SENT. GO WAIT.
NETCL1:
REPEAT 0,<
TQNE <ERRF> ; ANY FINAL ERRORS
JRST [ MOVEI T1,IOX5
RET] ; DON'T CLOSE IF ANY UN-HANDLED ERRORS
>
HRROS FILSKT(JFN) ; IN CASE JFN RE-OPENED, SET UNIT TO -1
SETOM NETFRK(UNIT)
HRRZ T2,NETBUF(UNIT) ;GET BUFFER ADDRESS
JUMPE T2,NETCL3 ;IS THERE A BUFFER
MOVEI T1,JSBFRE ;THIS IS ALSO THE BLOCK TO FREE
CALL RELFRE ;YES. RELEASE IT
NETCL3: CALL NETCLD ; FSM close
UMOVE T1,1
TDNN T1,[1,,400000]
TLNN T1,(1B1)
JRST NETCL2 ; Return immediately if no bit 1
LOAD T2,ANFSM,(UNIT)
MOVEI T1,FREE
CAIE T2,FREE
CALL WATFOR
NETCL2: MOVX T1,PROGF
ANDCAM T1,NETSTS(UNIT) ; No program wants this any more
RETSKP
NETCLD: TQNN <WRTF> ; IF NOT SENDING
SKIPA T1,[CLZR] ; THEN DO CLZR
MOVEI T1,CLZS ; ELSE do clzs
CALLRET DOFSM
NETCLW: MOVEI T2,<^D5*^D60*^D1000>/CHKINT ; 5 MINUTES OF TICKS
STOR T2,ANCLKS,(UNIT)
MOVX IOS,CLZF
IORB IOS,NETSTS(UNIT)
MDISMS
JRST NETCLZ ; AND GO TRY AGAIN
; Close nvt
NVTCLZ::MOVE T1,LSKT(UNIT)
TRNN T1,1
SKIPA T1,[CLZR]
MOVEI T1,CLZS
CALLRET DOFSM
; Network mtopr routines
NETMTP: TQNN <OPNF> ;CHECK TO SEE IF OPENED
RETBAD (CLSX1) ;NOT OPENED
HLRZ UNIT,FILSKT(JFN)
SETSEC UNIT,ANBSEC ; In proper section
MOVE IOS,NETSTS(UNIT)
CAIG T2,26
CAIGE T2,20
RETSKP ; ANYTHING ELSE IS A NOP
JRST .+1-20(T2)
JRST NETACP
JRST NETDMP
JRST SNDINT
JRST ABTCON
JRST NETINT
JRST NETRDY
JRST NETFAL
NETACP: LOAD T2,ANFSM,(UNIT)
MOVEI T1,ACPT
CAIN T2,RFCR
CALL DOFSM
RETSKP
NETDMP: TQNE <BFSND> ;SENDING BY BUFFER?
TQNN <WRTF> ;AND A SEND CONNECTION?
RETSKP ;NO, A NOP
TQNE <WNDF> ;YES. BUFFER SET UP?
RETSKP ;NO, NOTHING TO SEND
CALL DMPBUF
JRST WATXXX
RETSKP
SNDINT: LOAD T1,ANFHS,(UNIT)
LOAD T2,ANLNK,(UNIT)
MOVE T4,LSKT(UNIT)
TRNE T4,1
SKIPA T4,[IMPINS]
MOVEI T4,IMPINR
NCPOFF
LOAD T3,ANFSM,(UNIT)
CAIN T3,OPND
CALL (T4)
NCPON
RETSKP
; WAIT FOR READY TO SEND AT LEAST ONE BYTE
ABTCON: MOVE T1,CAPENB
TXNN T1,SC%NWZ
JRST [ MOVEI T1,NTWZX1 ; NOT A NET WIZARD. FAIL.
RET]
CALL SKTDWN
RETSKP
NETRDY: TQNN <WRTF> ; RECEIVE OR SEND?
JRST NETRD1 ; RECEIVE. SEND ALLOCATES OUT
LOAD T1,LTIDX,(UNIT) ;GET LINK TABLE INDEX
SETSEC T1,ANBSEC
CALL PKCHK ; GET BYTES THAT CAN BE SENT
JUMPE T2,[CALL WATBAL ; COMPUTE ACTIVATION TEST
JRST WATXXX] ; AND WAIT
CALL PKULCK
RETSKP
NETFAL: TQNN <WRTF> ; (ISI) Check for read
NETRD1: TQNN <WNDF> ;HAS ALLOCATION ALREADY BEEN SENT?
RETSKP
CALL FIRSTI ;NO. SEND IT OUT.
RET ;PASS ON DOWN BLOCK
RETSKP
NETINT: UMOVE T2,3
HRR T2,FORKX ; REMEMBER THIS FORK, AND USER'S
MOVEM T2,NETFRK(UNIT) ; REQUESTED PI CHANNELS
RETSKP
; HERE WHEN A FORK IS KILLED, TO FORGET THE PSI INFO
NETKFK::SE1CAL ; Place us in section 1
SAVEQ
PUTSEC UNIT,ANBSEC ; Put UNIT in right section for tables
MOVEI HN,NSKT ; Counter
NETKF1: HRRE IOS,NETFRK(UNIT)
CAMN IOS,FORKX
SETOM NETFRK(UNIT)
AOS UNIT ; Increment pointer
SOJG HN,NETKF1
RET ; And return
; HERE FROM LOGOUT CODE TO RELEASE JOB-WIDE NET RESOURCES
NETLGO::SETO T1,0 ;RELEASE ALL SPECIAL QUEUES
RELSQ
RET ; THAT'S ALL
; SKIP IF NET INPUT BUFFER EMPTY
; Called ONLY when DEV = NETDTB
NTSIBE::
MOVEI T1,^D60 ; Try for file lock upto 60 times..
NOINT ;
AOSE FILLCK(JFN) ;
SOJGE T1,[OKINT ;
PUSH P,T1 ;
MOVEI T1,^D1000 ;
DISMS ;
POP P,T1 ;
JRST .-2] ;
JUMPL T1,[OKINT ;
SETZ T1, ; No input
RETSKP] ;
HLRZ UNIT,FILSKT(JFN)
SETSEC UNIT,ANBSEC
TQNE <WNDF> ; Are buffers established?
JRST NTSIBA ; no, try to do so, no input until then!
LOAD T1,LTIDX,(UNIT) ;GET LINK TABLE INDEX
SETSEC T1,ANBSEC
MOVSI T2,777777
TDNN T2,IMPLT4(T1)
TDNE T2,IMPLT3(T1)
JRST NTSIBB ; Raw input available
NTSIB2: SETZ T1, ; Say no input available
AOS 0(P) ;
NTSIB1: TQZ <BLKF> ; Don't leave with this set!
MOVEM STS,FILSTS(JFN) ; Remember any status change!
SETOM FILLCK(JFN) ; Free lock!
OKINT ;
RET ; Return count to user
NTSIBA: CALL FIRSTI ; Try to initialize our buffers, send allocate
JRST NTSIB2 ; can't, don't block, return immediately!
NTSIBB: SKIPLE T1,FILCNT(JFN) ; If our file buffer contains any input,
JRST NTSIB1 ; return how much
CALL LODBUF ; Check with IMPDV for recent arrivals
JRST NTSIB2 ; nothing, don't block, return immediately
TQNE <EOFF> ; If end-of-file,
JRST NTSIB2 ; say no input
AOS T1,FILCNT(JFN) ; Since we are not taking a byte (LODBUF
JRST NTSIB1 ; thought we would), increment the count
; Network file sequential byte input
NETSQI: HLRZ UNIT,FILSKT(JFN)
SETSEC UNIT,ANBSEC
MOVE IOS,NETSTS(UNIT)
TQNN <WNDF>
JRST NTSQI1
CALL FIRSTI ; Wait for listen set up buffers etc.
RET ;PASS ON DOWN BLOCK
NTSQI1: SOSL FILCNT(JFN)
JRST NTSQI2
CALL LODBUF ; Get another bufferful
RET ;PASS ON DOWN BLOCK
NTSQI2: TQNE <EOFF>
RET
ILDB T1,FILBYT(JFN)
AOS FILBYN(JFN)
RET
LODBUF: MOVX IOS,ERRB
TDNE IOS,NETSTS(UNIT)
TQO <ERRF>
ANDCAB IOS,NETSTS(UNIT)
MOVE T3,NETBUF(UNIT) ;GET ADDRESS OF BUFFER
HLL T3,FILBYT(JFN) ;GET THE BYTE SIZE
TLZ T3,770000 ;SET AT END OF FIRST WORD
TLNN T3,700 ;36 BIT MODE?
TLO T3,40000 ;NO GET BYTE OFFSET RIGHT
MOVEM T3,FILBYT(JFN) ;SAVE BYTE POINTER
HLRZ T4,NETBUF(UNIT) ;GET BUFFER SIZE
LOAD T1,LTIDX,(UNIT) ;GET LINK TABLE INDEX
SETSEC T1,ANBSEC
CALL UPMSG ;UNPACK MESSAGE(S) INTO BUFFER
JRST [MOVX IOS,EOTF ;GET END OF FILE FLAG
TDNE IOS,NETSTS(UNIT) ;IS IT SET FOR THIS CONNECTION
JRST [ TQO <EOFF> ;YES SET FOR THIS JFN
RETSKP] ;AND RETURN
JRST WATXXX] ;BACK OUT AND WAIT THEN START OVER
HLRZ T2,NETBUF(UNIT) ;GET BUFFER SIZE IN BYTES
SUB T2,T4 ;BYTES LOADED
MOVEM T2,FILCNT(JFN) ;SET BYTES IN BUFFER FOR THIS JFN
ADDM T2,FILLEN(JFN) ;UPDATE NUMBER OF BYTES ON THIS CONN.
LOAD T4,ANBSIZ,(UNIT) ;GET BYTE SIZE
IMUL T4,T2 ;BITS RECEIVED
ADDM T4,NETBTC(UNIT) ;KEEP COUNT OF BITS RECEIVED
MOVN T2,T4 ;GET NEGATIVE OF BITS RECIEVED
ADDM T2,NETBAL(UNIT) ;DEBIT ALLOCATION FOR MESSAGE RECEIVED
CALL NETRAL ;RE-ALLOCATE IF NEEDED
SOSGE FILCNT(JFN) ;DID WE GET ANYTHING?
JRST LODBUF ;NO BYTES GO TRY AGAIN
RETSKP
NETRAL::NCPOFF ; PREVENT CONFUSION
MOVE IOS,NETSTS(UNIT)
TQNE <EOTF,DEDF>
JRST NETRAX ; DON'T BOTHER IF DEAD OR DONE
STKVAR<NETRBA,NETRMA>
MOVE T4,NETDAL(UNIT) ; GET DESIRED BIT ALLOCATION
MOVE T2,T4
ASH T2,-1 ; HALVE
MOVEM T2,NETRBA
MOVEI T3,MSGALL ; DESIRED LEVEL OF MSG ALLOC
MOVE T2,T3
ASH T2,-1 ; HALVE
MOVEM T2,NETRMA
LOAD T2,LTIDX,(UNIT) ; GET LINK TABLE INDEX
SETSEC T2,ANBSEC
HRRZ T2,IMPLT4(T2) ; OUTSTANDING MSG ALLOC
SUB T3,T2 ; NEEDED INCREMENT
SUB T4,NETBAL(UNIT) ; NEEDED INCREMENT
LOAD T1,ANFHS,(UNIT)
LOAD T2,ANLNK,(UNIT)
CAMGE T4,NETRBA ; IF GREATER THAN HALF
CAML T3,NETRMA ; FOR EITHER ONE
CALL IMPALL ; THEN SEND AN ALLOCATE
NETRAX: NCPON
RET
FIRSTI: CALL FRSTIO ; SET UP BUFFER
RET ;PASS ON DOWN BLOCK
JUMPG T2,FRSTI1 ; BUFFER SPECIFIED. USE FOR ALLOCATION
PUSH P,T1
MOVE T1,MAXBPM ; MAXIMUM BITS IN A MESSAGE
LOAD T2,ANBSIZ,(UNIT) ; CONNECTION BYTE SIZE
IDIV T1,T2 ; BYTES
IMULI T1,MSGALL ; TIMES MESSAGE ALLOCATION
POP P,T2 ; THAT PLUS FILE BUFFER BYTES
ADD T2,T1 ; IS WHAT TO USE
FRSTI1: LOAD T4,ANBSIZ,(UNIT) ; GET BYTES SIZE
IMUL T4,T2 ; BITS IN BUFFERS
MOVEM T4,NETDAL(UNIT) ; SAVE DESIRED LEVEL
CALL NETRAL ; SEND ALLOCATE AS NEEDED
RETSKP
WATLSN: LOAD T1,ANFSM,(UNIT) ; Get state of this connection
CAIN T1,OPND
RETSKP
CAIN T1,RFCR
JRST [ MOVEI T1,ACPT
CALL DOFSM
RETSKP]
CAIN T1,RFCS ; If still waiting for rfc
JRST WATLS1 ; Continue waiting
CAIE T1,LSNG
JRST [ MOVX IOS,EOTF
TDNE IOS,NETSTS(UNIT)
RETSKP ; Null file sent
MOVX IOS,ERRB!EOTF ; Connection never actually opened
IORB IOS,NETSTS(UNIT)
RETSKP]
WATLS1: HRRZ T2,UNIT ;GET UNIT
ROT T2,-9 ;PUT IN BITS 0-8
HRLI T1,NOTTST ;TEST ROUTINE ADDRESS,,STATE
MOVSS T1 ;STATE TO WAIT FOR,,TEST ROUTINE ADDRESS
IOR T1,T2 ;UNIT/STATE,,TEST ROUTINE
TQO <BLKF> ;BLOCK FOR STATE CHANGE
RET
WATXXX: TQO <BLKF> ;TELL LOWER LEVEL TO BLOCK
RET
; Network file sequential byte output
NETSQO: HLRZ UNIT,FILSKT(JFN)
SETSEC UNIT,ANBSEC
MOVE IOS,NETSTS(UNIT)
TQNE <DEDF,ERRB>
TQO <ERRF>
TQNE <DEDF,EOTF>
RET
PUSH P,T1
TQNN <WNDF>
JRST NTSQO4
CALL FIRSTO
JRST [POP P,0(P) ;CLEAN UP STACK
RET] ;PASS ON DOWN BLOCK
NTSQO4: TQNE <BFSND> ; IMMEDIATE SEND?
JRST NTSQO1 ; No
LOAD T1,LTIDX,(UNIT) ;GET LINK TABLE INDEX
SETSEC T1,ANBSEC
CALL PKCHK ; HOW MANY BYTES CAN WE SEND?
POP P,T3
JUMPE T2,NTSQO3 ; NOT ENOUGH
CALL PKBYT
TRN
LOAD T1,ANBSIZ,(UNIT)
ADDM T1,NETBTC(UNIT)
MOVNS T1
ADDM T1,NETBAL(UNIT)
MOVEI T1,<^D2*^D60*^D1000>/CHKINT
STOR T1,ANCLKS,(UNIT) ; RESET CLOCK TO TWO MINUTES
RET
NTSQO1: SOSL FILCNT(JFN)
JRST NTSQO2
CALL DMPBUF
JRST [POP P,T3 ;CLEAN UP STACK
JRST WATXXX] ; Can't dump now, wait
NTSQO2: AOS FILBYN(JFN)
POP P,T1
IDPB T1,FILBYT(JFN)
RET
NTSQO3: CALL WATBAL ;WAIT FOR BITS AND A MSG TO BE ALLOCATED
JRST WATXXX ; ..
DMPBUF: MOVX IOS,ERRB ;GET ERROR HAS OCCURED FLAG
TDNE IOS,NETSTS(UNIT) ;HAS ERROR OCCURED?
TQO <ERRF> ;YES. INDICATE IT FOR THE JFN
ANDCAB IOS,NETSTS(UNIT) ;CLEAR ERROR FLAG FOR CONNECTION
MOVE T4,FILOFN(JFN) ;GET CURRENT OUTPUT POINT
CAML T4,FILBYN(JFN) ;DONE?
JRST DMPDUN ;YES
TQNE <EOTF,DEDF> ;END OF FILE OR DEAD HOST
JRST [ TQO <ERRF> ;YES. SET ERROR FOR JFN
SETZM FILBYT(JFN) ;ZERO BYTE POINTER
SETZM FILBYN(JFN) ;BYTE COUNT
SETZM FILOFN(JFN) ;AND CURRENT POSITION IN FILE
HRLOI T1,377777 ;AND SET NUMBER OF BYTES TO INFINITY
MOVEM T1,FILCNT(JFN)
RETSKP]
LOAD T1,LTIDX,(UNIT) ;GET LINK TABLE INDEX
SETSEC T1,ANBSEC
CALL PKCHK ;HOW MANY BYTES CAN WE SEND?
JUMPE T2,WATBAL ;NONE, WAIT
MOVE T4,FILBYN(JFN) ;GET BYTE COUNT
SUB T4,FILOFN(JFN) ;GET NUMBER OF BYTES IN BUFFER
CAML T4,T2
MOVE T4,T2 ;TAKE MIN OF THE TWO
MOVE T3,NETBUF(UNIT) ;GET BUFFER ADR
HLL T3,FILBYT(JFN) ;GET BYTE SIZE
TLZ T3,770000 ;END OF FIRST WORD
TLNN T3,700 ;36 BIT MODE?
TLO T3,40000 ;NO GET BYTE OFFSET RIGHT
MOVE T1,FILOFN(JFN) ;GET BYTE OFFSET
TLNE T3,6700 ;8 BIT?
JRST DMPBF1 ;NO
IDIVI T1,4 ;GET WORDS TO ADJUST IN T1
HRRZS T3 ;WE WILL ADD IN THE PROPER LH
ADD T3,[041000,,0 ;CASE 0. POINT TO PREVIOUS WORD
341000,,1 ;SO PKMSG WILL DO A BLT
241000,,1 ;OTHERS CASES USE STD. PTR
141000,,1](T2)
DMPBF1: ADDI T3,(T1) ;DO WORD OFFSET
LOAD T1,LTIDX,(UNIT) ;GET LINK TABLE INDEX
SETSEC T1,ANBSEC
PUSH P,T4 ;SAVE COUNT WE ARE ASKING FOR
CALL PKMSG ;GO PACK MESSAGE AND SEND IT
POP P,T4 ;GET BYTE COUNT BACK
ADDM T4,FILOFN(JFN) ;UPDATE BYTE COUNT OF BUFFER
LOAD T3,ANBSIZ,(UNIT) ;GET BYTE SIZE
IMUL T4,T3 ;GIVES BITS JUST SENT
ADDM T4,NETBTC(UNIT) ;KEEP COUNT OF BITS SENT
MOVNS T4 ;GET NEGATIVE OF BITS SENT
ADDM T4,NETBAL(UNIT) ;UPDATE BIT ALLOCATION
MOVEI T1,<2*^D60*^D1000>/CHKINT
STOR T1,ANCLKS,(UNIT) ;RESET CLOCK FOR THIS CONNECTION
JRST DMPBUF ;GO CHECK FOR ERRORS
DMPDUN: SETZM FILBYN(JFN) ;ZERO BYTE COUNT FOR BUFFER
SETZM FILOFN(JFN) ;ZERO CURRENT OUTPUT POINT
MOVE T1,NETBUF(UNIT) ;GET ADDRESS OF BUFFER
HLL T1,FILBYT(JFN) ;GET THE BYTE SIZE
TLZ T1,770000 ;SET AT END OF FIRST WORD
TLNN T1,700 ;36 BIT MODE?
TLO T1,40000 ;NO GET BYTE OFFSET RIGHT
MOVEM T1,FILBYT(JFN) ;SAVE BYTE POINTER
HLRZ T1,NETBUF(UNIT) ;GET BUFFER SIZE
SUBI T1,1 ;DECREMENT IT BY ONE
MOVEM T1,FILCNT(JFN) ;AND SAVE IT AS BYTES IN BUFFER
RETSKP
WATBAL: LOAD T1,LTIDX,(UNIT) ;GET LINK TABLE INDEX
SETSEC T1,ANBSEC
CALL PKULCK ;UNLOCK CONNECTION TOO
MOVEI T1,BALTST ;GET ADDRESS OF TEST ROUTINE
HRL T1,UNIT ;AND UNIT TO WAIT ON
RET
FIRSTO: TQNN <BFSND> ; BUFFERED?
JRST [ CALL WATLSN ; NO, WAIT FOR CONNECTION TO OPEN
RET ;PASS ON DOWN BLOCK
TQZ <WNDF>
RETSKP]
CALL FRSTIO ; YES, SET UP BUFFER ETC
RET ;PASS ON DOWN BLOCK
RETSKP
;FRSTIO - SET UP BUFFER IN JSB FREE SPACE
;ACCEPTS UNIT/ NETWORK PSEUDO UNIT NUMBER
;RETURNS +1 FAILURE
; +2 SUCCESS
; RH NETBUF(UNIT) HAS BUFFER ADDRESS
FRSTIO: CALL WATLSN ; Wait for connection complete
RET ; Pass on down block
STKVAR <FRSTBY,FRSTBF>
MOVEI T1,^D36 ; Bits per word
LOAD T3,ANBSIZ,(UNIT) ; Connection byte size
IDIV T1,T3 ; Connection bytes per word
IMUL T3,T1 ; Used bits per word
MOVE T2,MAXBPM ; Max bits per net message
IDIVM T2,T3 ; Max words per net message
MOVEI T1,^D36 ; Bits per machine word
LDB T2,PBYTSZ ; File byte size
IDIVM T1,T2 ; File bytes per word
MOVEM T2,FRSTBY ; Save file bytes per word
HLRZ T1,NETBUF(UNIT) ; Desired bytes per buffer
IDIV T1,T2 ; Number of words needed
SKIPE T1 ; If zero
CAML T1,T3 ; Or bigger than max
MOVE T1,T3 ; Use max
MOVEM T1,FRSTBF ; Save bytes per buffer
AOS T2,T1 ; Plus header
CALL ASGJFR ;ASSIGN A PAGE IN JOB AREA
JRST [TQO <ERRF> ;INDICATE AN ERROR
RETBAD] ;RETURN
HRRM T1,NETBUF(UNIT) ;SAVE BUFFER ADDRESS
MOVE T3,FRSTBF ;GET SIZE AVAILABLE FOR BUFFER
MOVE T1,FRSTBY ;GET BYTES/WORD BACK
IMUL T1,T3 ;CALCULATE BYTES BUFFER WILL HOLD
HLRZ T2,NETBUF(UNIT) ;RETURN AS VALUE
HRLM T1,NETBUF(UNIT) ;REAL BYTES PER BUFFER
TQZ <WNDF>
RETSKP
;100 Begin modification
; Attach sockets to pty
; Call: 1 (u) ; Receive jfn of opened network connection
; 2 (u) ; Send jfn of opened network connection
; CHKJFN done on (1)
; JRST AATNVT from .ATNVT
; Returns
; +1 ; Cannot attach
; +2 ; Ok. the jfns are released, ac 1 has line number of
; ; Attached pty.
AATNVT::STKVAR <ATUNTS,ATRCJF,ATNDAD>
;100 End modification
MOVEI T1,ATNX2 ; Error code if test skips
TQNE <READF> ; MUST BE OPENED FOR READING
CALL CHKATP ; Check for dev=net, open, no buffer
JRST ATPER1 ; Failed one of the above
HLRZ UNIT,FILSKT(JFN)
SETSEC UNIT,ANBSEC
MOVEM UNIT,ATUNTS ;SAVE DEV AND JFN
MOVEM JFN,ATRCJF
UMOVE JFN,2 ; Get send jfn
CALL CHKJFN ; Check it
JRST ATPER2 ; Must also be a real jfn
JRST ATPER2
JRST ATPER2
MOVEI T1,ATNX2 ; Becomes atNx8 at atper3
TQNE <WRTF> ; THIS ONE MUST BE FOR WRITING
CALL CHKATP ; And dev=net, open, no buffer
JRST ATPER3 ; Failed above tests
HLRZ UNIT,FILSKT(JFN)
SETSEC UNIT,ANBSEC
LOAD T1,ANFSM,(UNIT)
CAIN T1,RFCS
CALL WATNOT ; Wait for response from foreign host
MOVEI T1,ATNX12 ; Error code for refused send
LOAD T2,ANFSM,(UNIT) ; Now get state
CAIE T2,OPND ; If not opnd
JRST ATPER4 ; Then fail
HRLM UNIT,ATUNTS ;SAVE SEND JFN IN LEFT HALF
HRRZ UNIT,ATUNTS ;SWITCH TO RECEIVE CONNECTION
SETSEC UNIT,ANBSEC
LOAD T1,ANFSM,(UNIT) ; Get its state
CAIN T1,RFCS
CALL WATNOT ; Wait for response from foreign host
MOVEI T1,ATNX6 ; Error code for refused receive
LOAD T2,ANFSM,(UNIT)
CAIE T2,OPND ; If not opnd
JRST ATPER4 ; Then fail
NCPOFF
LOAD T1,ANFSM,(UNIT)
CAIE T1,OPND
JRST [ MOVEI T1,ATNX6
JRST ATPERZ]
HLRZ UNIT,ATUNTS ;GET SEND UNIT
SETSEC UNIT,ANBSEC
LOAD T1,ANFSM,(UNIT)
CAIE T1,OPND
JRST [ MOVEI T1,ATNX12
JRST ATPERZ]
UMOVE 1,1 ; GET OPTION FLAGS
HRR T1,ATUNTS ;SET UP ARGS, RECEIVE UNIT IN 1
HLRZ T2,ATUNTS ;SEND UNIT IN 2
CALL ASNNVT ; Assign NVT to these units
JRST [ MOVEI T1,ATNX13 ; Can't, no pty's
JRST ATPERZ]
MOVEM T2,ATNDAD ;SAVE ADDRESS OF DYNAMIC DATA
HRRZ UNIT,ATUNTS ;RECIEVE UNIT
SETSEC UNIT,ANBSEC
MOVX T3,PROGF
ANDCAM T3,NETSTS(UNIT) ; PROGRAM NO LONGER LOOKING
HRRM T1,NETBUF(UNIT) ; Store pty number here
HLRZ UNIT,ATUNTS ;SEND UNIT
SETSEC UNIT,ANBSEC
ANDCAM T3,NETSTS(UNIT) ; NOT HERE EITHER
HRRM T1,NETBUF(UNIT) ; Also here
NCPON
IORI T1,400000 ; Convert pty to tty designator
UMOVEM T1,1 ; Return to user
CALL RELJFN ; Release send jfn
MOVE JFN,ATRCJF
CALL RELJFN ; And receive jfn
HRRZ UNIT,ATUNTS ;GET RECIEVE UNIT
SETSEC UNIT,ANBSEC
MOVE T2,ATNDAD ;GET ADDRESS OF DYNAMIC DATA
CALL NVTRAL ;GO REALLOCATE
MOVE T2,ATNDAD ;GET ADDRESS OF DYNAMIC DATA
CALL ULKTTY ;UNLOCK DATA BASE
SMRETN ;RETURN SKIPPING
; Check validity of jfn for atpty
CHKATP: MOVEI T1,ATNX3 ; Receive not open
TQNN <OPNF> ; IS IT OPEN?
RET ; NO
HRRZ T2,DEV
MOVEI T1,ATNX4
CAIE T2,NETDTB
RET
MOVEI T1,ATNX5
TQNN <WNDF>
RET
RETSKP
ATPERZ: NCPON
JRST ATPER4
ATPER2: MOVEI T1,ATNX7 ; Bad send jfn
JRST ATPER5
ATPER3: ADDI T1,ATNX7-ATNX1 ; Convert receive errors to send errors
ATPER4: CALL UNLCKF
ATPER5: MOVE JFN,ATRCJF ;GET RECIEV JFN
MOVE STS,FILSTS(JFN)
ATPER1: CALL UNLCKF
JRST MRETNE ; Save error return in ac1
ATPER0: MOVEI T1,ATNX1 ; Bad receive jfn
JRST MRETNE
; Convert jfn to absolute network socket number
; Call: 1 ; Jfn
; CVSKT
; Returns
; +1 ; Error
; +2 ; Ok, in 2 the absolute socket number
.CVSKT::MCENT
MOVE JFN,T1
CALL CHKJFN
RETERR (CVSKX1)
RETERR (CVSKX1)
RETERR (CVSKX1)
CAIE PTR,NETDTB
RETERR (CVSKX1,<CALL UNLCKF>)
HLRZ T1,FILNEN(JFN)
HRLI T1,(<POINT 7,0,35>)
CALL NAMDEC
RETERR (CVSKX2,<CALL UNLCKF>)
CALL UNLCKF
UMOVEM T1,2
JRST SKMRTN
;ROUTINE TO PRODUCE THE OLD HOSTN TABLE
GHOSTN::SETSEC T2,MNTSEC ; Point into right section
LOAD T4,HSTIDX,(T2) ;GET INDEX
SETSEC T4,MNTSEC
MOVE T1,HOSTNN(T4) ;GET THE HOST NUMBER
CALL CVOHST ;CONVERT TO OLD FORMAT
MOVE T3,HSTSTS(T4) ;GET HOST STATUS
ANDI T3,777000 ;GET THE RIGHT BITS
IORI T1,(T3) ;BUILD LH
SKIPGE HOSTN(T2) ;NICKNAME?
TXO T1,HS%NCK
MOVSI T1,(T1)
LOAD T3,HSTNMP,(T2) ;GET THE NAME POINTER
HRRI T1,(T3)
RET
;ROUTINE TO PRODUCE THE OLD NETAWD TABLE
GNTAWD::SETSEC T2,ANBSEC
LOAD T1,ANFHS,(T2) ;GET THE HOST NUMBER
CALL CVOHST ;CONVERT TO OLD FORMAT
MOVSI T1,(T1) ;HOST NUMBER TO LH
MOVE T3,NETAWD(T2) ;GET REST OF WORD
TLZ T3,777 ;CLEAR OUT SLOT FOR HOST
IOR T1,T3 ;PUT IT TOGETHER
RET
;ROUTINE TO PRODUCE OLD IMPHRT GETAB TABLE.
GTBHRT::SAVEQ ;NEED SOME ACS
HRRZ UNIT,T2 ;GET INDEX
IMULI UNIT,^D36 ;CONVERT TO 1ST HOST NUMBER
HRLI UNIT,-^D36 ;LOOP COUNTER
SETO IOS, ;SET TO ALL UP
GTBHR1: ROT IOS,1 ;MAKE ROOM FOR NEXT BIT
HRRZ T1,UNIT ;GET NEXT HOST NUMBER
CAIL T1,400 ;OUT OF RANGE
JRST GTBHR2
CALL CVNHST ;CONVERT TO NEW FORMAT
CALL HSTHSH ;LOOKUP HOST INDEX
TRNA ;NOT THERE SO NOT UP
SKIPL HSTSTS(T2) ;UP?
GTBHR2: TXZ IOS,1 ;NO, CLEAR BIT
AOBJN UNIT,GTBHR1 ;LOOP FOR ALL 36 HOSTS IN THIS WORD
MOVE T1,IOS ;RETURN WORD FOR GETAB
RET
;ROUTINE TO PRODUCE OLD HSTSTS GETAB TABLE.
GTBHSS::SAVEQ ;NEED WORK SPACE
HRRZ IOS,T2 ;GET INDEX
LSH IOS,1 ;TURN INTO HOST NUMBER
MOVE T1,IOS ;HOST N
CALL GTBHSH ;GET RIGHT STATUS
HLLZ UNIT,T1 ;RESULT FOR HOST N IN LEFT HALF
AOS T1,IOS ;HOST N+1
CALL GTBHSH ;GET RIGHT STATUS
HLR UNIT,T1 ;RESULT FOR HOST N+1 IN RIGHT HALF
MOVE T1,UNIT ;RETURN WORD FOR GETAB
RET
GTBHSH: CALL CVNHST ;CONVERT TO NEW FORMAT
CALL HSTHSH ;LOOKUP HOST INDEX
JRST RFALSE ;NO SUCH HOST, RETURN 0
SKIPL T1,HSTSTS(T2) ;UP?
TXOA T1,<1B0+1B1> ;SET VALID AND DEAD BITS
MOVX T1,<1B0> ;OTHERWISE JUST SET VALID
RET
;GTNCP RETURNS A TABLE OF DATA FOR AN NCP CONNECTION
.GTNCP::MCENT
SKIPL T1 ;CHECK RANGE OF FUNCTION
CAIL T1,GTNMAX
RETERR (ARGX02) ;BAD FUNCTION NUMBER
XCT GTNDSP(T1) ;DO FUNCTION
GTNCPX: SETSEC UNIT,ANBSEC ; Point it to right section
SKIPL UNIT ;GET THE INDEX
CAML UNIT,[XWD ANBSEC,NSKT] ; value to large?
RETERR (GTJIX1) ;BAD INDEX
UMOVE T3,3 ;GET AC3 AND AC4 FROM USER
UMOVE T4,4
GTNCPL: HRRZ T1,T4 ;OUT OF THINGS?
CAIL T1,NCPLEN
JRST GTNCLX ;YES
XCT NCPTAB(T1) ;LOAD DATA WORD
UMOVEM T1,(T3) ;RETURN TO USER
AOJ T3,
AOBJN T4,GTNCPL ;LOOP
GTNCLX: UMOVEM T4,4 ;UPDATE COUNTER
JRST SKMRTN
NCPTAB: HRRZ T1,UNIT ;(00)NCP UNIT
LOAD T1,ANFHS,(UNIT) ;(01)FOREIGN HOST
MOVE T1,LSKT(UNIT) ;(02)LOCAL SOCKET
MOVE T1,FSKT(UNIT) ;(03)FOREIGN SOCKET
LOAD T1,ANFSM,(UNIT) ;(04)FINITE STATE
LOAD T1,ANLNK,(UNIT) ;(05)LINK
CALL [ HRRZ T1,NETBUF(UNIT) ;(06)RETURN NVT IF
CAIGE T1,1000 ;THERE IS ONE
JUMPN T1,R
JRST RTRUE]
LOAD T1,ANBSIZ,(UNIT) ;(07)BYTE SIZE OF CONNECTION
CALL [ LOAD T1,LTIDX,(UNIT) ;(10)MSG ALLOC
SETSEC T1,ANBSEC
HRRZ T1,IMPLT4(T1)
RET]
MOVE T1,NETBAL(UNIT) ;(11)BIT ALLOC
MOVE T1,NETDAL(UNIT) ;(12)DESIRED ALLOC
MOVE T1,NETBTC(UNIT) ;(13)BITS XFERRED
HLRZ T1,NETBUF(UNIT) ;(14)BYTES/BUFFER
LOAD T1,ANCLKS,(UNIT) ;(15)TIMEOUT
MOVE T1,NETSTS(UNIT) ;(16)STATUS OF CONN
NCPLEN==.-NCPTAB
GTNDSP: JRST GTNSIZ ;(00)GET TABLE SIZE
HRRZ UNIT,T2 ;(01)INDEX GIVEN
JRST GTNNVI ;(02)INPUT NVT
JRST GTNNVO ;(03)OUTPUT NVT
JRST GTNJFN ;(04)JFN
GTNMAX==.-GTNDSP ;NUMBER OF FUNCTIONS
GTNSIZ: MOVSI T2,-NSKT ;-LENGTH,,1ST INDEX
UMOVEM T2,2 ;RETURN TO USER
MOVE T3,NVTPTR ;-# NVTS,,1ST NVT
UMOVEM T3,3
JRST SKMRTN ;DONE
GTNJFN: MOVE JFN,T2 ;CHECK THE JFN
CALL CHKJFN
RETERR (GTNCX1)
RETERR (GTNCX1)
RETERR (GTNCX1)
HLRZ UNIT,FILSKT(JFN) ;GET THE UNIT
CALL UNLCKF
CAIE PTR,NETDTB ;MAKE SURE IS NET:
RETERR (GTNCX1)
JRST GTNCPX ;REJOIN MAIN CODE
GTNNVI: SKIPA UNIT,[NVTIPU] ;GET INPUT UNIT
GTNNVO: MOVEI UNIT,NVTOPU ;USE OUTPUT UNIT
CAIN T2,.CTTRM ;WANT CONTROLLING TTY?
MOVE T2,CTRLTT ;YES
ANDI T2,377777 ;CLEAR 400000
CALL NVTCHK
RETERR (GTNCX2) ;BAD NVT
CALL (UNIT) ;CALL ROUTINE
SETO UNIT, ;CATCH ERROR AS BAD UNIT
CALL ULKTTY ;UNLOCK TTY DATA BASE
JRST GTNCPX ;REJOIN MAIN CODE
; Flush host
.FLHST::MCENT
MOVEI T2,SC%WHL!SC%OPR
TDNN T2,CAPENB
ITERR (WHELX1)
CALL CVNHST ;CONVERT HOST NUMBER
CALL HSTDED
CALL IMSRST
JRST MRETN
; Set local host number routine. Takes old or new style number.
; Sets to new style, and puts it in NLHOST.
STHSTJ:: ITERR() ; No longer a valid function, no-one should be using this
; Get net status
NETGST: HLRZ UNIT,FILSKT(JFN)
SETSEC UNIT,ANBSEC
LOAD T1,ANFHS,(UNIT)
CALL CVOHST ; Convert to old host format
UMOVEM T1,3
HLLZ T1,NETSTS(UNIT)
MOVE T2,FSKT(UNIT)
UMOVEM T2,4
; Set net status
NETSST: RET
; The following code and tables PROVIDE a finite state machine
; Implementation of the transitions and actions produced by various
; Events associated with a connection
; Assumed are that unit indexes the proper local socket
; Events are numbered as follows
RRFC==0 ; Received an rfc
CLSR==1 ; Cls for a receive socket
CLSS==2 ; Cls for a send socket
CLZR==3 ; Close done on a receive socket
CLZS==4 ; Close done on a send socket
ACPT==5 ; Program issued an accept
CONN==6 ; Program issued a connect
LISN==7 ; Program issued a listen
RRFN==10 ; Received a rfnm with no more data outstanding
HUNG==11 ; Time out event (happens 2 minutes after last dofsm)
RRFB==12 ; RECEIVED RFC WITH NON-MATCHING BYTE SIZE
; Actions are numbered as follows
ANOP==0 ; No operation
AFNY==1 ; No operation (unexpected event)
ACLS==2 ; Send cls
ARFC==3 ; Send rfc
AOPB==4 ; Send rfc and open link
AOPL==5 ; Open link
ACLL==6 ; Close link
ACLO==7 ; Close link and send cls
AEOR==10 ; END OF RECEIVE
AEOS==11 ; END OF SEND
AES1==12 ; END OF SEND WHEN ABORTED BY FOREIGN HOST
AABT==13 ; CONNECTION ABORTED BY FAR END
ACKA==14 ; CHECK ALLOCATION
; States are numbered as follows
DEAD==0 ; Never used
CLZD==1 ; Closed
PNDG==2 ; Pending. rfc received while closed
LSNG==3 ; Listening. listen issued while closed
RFCR==4 ; Rfc received while listening
CLW1==5 ; Close wait alternate. clzr from opnd
RFCS==6 ; Rfc sent
OPND==7 ; Opened
CLSW==10 ; Waiting for a cls
DATW==11 ; Waiting for all data to be sent
RFN1==12 ; Waiting for last rfnm
CLZW==13 ; Waiting for program close
RFN2==14 ; Waiting for rfnm after clss
NUSE==15 ; THIS STATE NO LONGER USED
FREE==16 ; Not in use
; The following table of byte pointers is used to get to the next state
; Given the current state and the event
; This table is indexed by event, the table addressed by this table
; Is indexed by old state
RADIX ^D10
QQ==3
CBPFSM: REPEAT 9,<
POINT 4,NXTSTT(T2),QQ
QQ==QQ+4>
QQ==3
REPEAT 9,<
POINT 4,NXTSTT+1(T2),QQ
QQ==QQ+4>
; Following table of pointers is used to get the action to be taken
; Given the current state and the event
; This table is indexed by event, the table addressed by this table
; Is indexed by old state
QQ==3
CBAFSM: REPEAT 9,<
POINT 4,ACTION(T2),QQ
QQ==QQ+4>
QQ==3
REPEAT 9,<
POINT 4,ACTION+1(T2),QQ
QQ==QQ+4
>
; This is the transition table
; Each word contains the new state for a given old state
; Successive bytes are used for different events
; Event rrfc clsr clss clzr clzs acpt conn lisn rrfe hung rrfb old state
NXTSTT:
BYTE (4)DEAD,DEAD,DEAD,DEAD,DEAD,DEAD,DEAD,DEAD,DEAD,DEAD,DEAD ; Dead
BYTE (4)PNDG,CLZD,CLZD,CLZD,CLZD,CLZD,RFCS,LSNG,CLZD,CLZD,CLZD ; Clzd
BYTE (4)PNDG,FREE,FREE,PNDG,PNDG,PNDG,OPND,RFCR,PNDG,CLW1,PNDG ; Pndg
BYTE (4)RFCR,LSNG,LSNG,FREE,FREE,LSNG,LSNG,LSNG,LSNG,LSNG,CLSW ; Lsng
BYTE (4)RFCR,CLZW,CLZW,CLW1,CLW1,OPND,RFCR,RFCR,RFCR,RFCR,RFCR ; Rfcr
BYTE (4)CLW1,FREE,FREE,CLW1,CLW1,CLW1,CLW1,CLW1,CLW1,FREE,CLW1 ; Clw1
BYTE (4)OPND,CLZW,CLZW,CLW1,CLW1,RFCS,RFCS,RFCS,RFCS,CLSW,CLSW ; Rfcs
BYTE (4)OPND,CLZW,RFN2,CLW1,DATW,OPND,OPND,OPND,OPND,OPND,OPND ; Opnd
BYTE (4)CLSW,CLZW,CLZW,CLW1,CLW1,CLSW,CLSW,CLSW,CLSW,CLZW,CLSW ; Clsw
BYTE (4)DATW,DATW,RFN1,DATW,DATW,DATW,DATW,DATW,CLW1,CLW1,DATW ; Datw
BYTE (4)RFN1,RFN1,RFN1,RFN1,RFN1,RFN1,RFN1,RFN1,FREE,FREE,RFN1 ; Rfn1
BYTE (4)CLZW,CLZW,CLZW,FREE,FREE,CLZW,CLZW,CLZW,CLZW,CLZW,CLZW ; Clzw
BYTE (4)RFN2,RFN2,RFN2,RFN1,RFN1,RFN2,RFN2,RFN2,CLZW,CLZW,RFN2 ; Rfn2
BYTE (4)NUSE,NUSE,NUSE,NUSE,NUSE,NUSE,NUSE,NUSE,NUSE,NUSE,NUSE ; Nuse
BYTE (4)FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE ; Free
; This is the action table
; It is referenced the same as the transition table
; Event rrfc clsr clss clzr clzs acpt conn lisn rrfe hung rrfb old state
ACTION:
BYTE (4)AFNY,AFNY,AFNY,AFNY,AFNY,ANOP,AFNY,AFNY,AFNY,ANOP,AFNY ; Dead
BYTE (4)ANOP,AFNY,AFNY,AFNY,AFNY,ANOP,ARFC,ANOP,AFNY,ANOP,AFNY ; Clzd
BYTE (4)AFNY,ACLS,ACLS,AFNY,AFNY,ANOP,AOPB,ANOP,AFNY,ACLS,AFNY ; Pndg
BYTE (4)ANOP,AFNY,AFNY,ANOP,ANOP,ANOP,AFNY,AFNY,AFNY,ANOP,ACLS ; Lsng
BYTE (4)AFNY,ACLS,ACLS,ACLS,ACLS,AOPB,AFNY,AFNY,AFNY,ANOP,AFNY ; Rfcr
BYTE (4)AFNY,ACLL,ACLL,AFNY,AFNY,ANOP,AFNY,AFNY,AFNY,ACLL,AFNY ; Clw1
BYTE (4)AOPL,ACLS,ACLS,ACLS,ACLS,ANOP,AFNY,AFNY,AFNY,ACLS,ACLS ; Rfcs
BYTE (4)AFNY,AEOR,AES1,ACLS,AEOS,ANOP,AFNY,AFNY,AFNY,ACKA,AFNY ; Opnd
BYTE (4)ANOP,ANOP,ANOP,ANOP,ANOP,ANOP,AFNY,AFNY,AFNY,ANOP,AFNY ; Clsw
BYTE (4)AFNY,AFNY,AES1,AFNY,AFNY,ANOP,AFNY,AFNY,ACLS,ACLS,AFNY ; Datw
BYTE (4)AFNY,AFNY,AFNY,AFNY,AFNY,ANOP,AFNY,AFNY,ACLO,ACLO,AFNY ; Rfn1
BYTE (4)AFNY,AFNY,AFNY,ACLL,ANOP,ANOP,AFNY,AFNY,AFNY,ANOP,AFNY ; Clzw
BYTE (4)AFNY,AFNY,AFNY,ANOP,ANOP,ANOP,AFNY,AFNY,ACLO,ACLO,AFNY ; Rfn2
BYTE (4)AFNY,AFNY,AFNY,AFNY,AFNY,AFNY,AFNY,AFNY,AFNY,AFNY,AFNY ; Nuse
BYTE (4)AFNY,AFNY,AFNY,ANOP,ANOP,AABT,AFNY,AFNY,AFNY,ANOP,AFNY ; Free
;DISPATCH TABLE FOR ACTIONS
;ROUTINES ARE CALLED EFFECTIVELY BY CALL @ACTAB(ACTION#)
ACTAB: IFIW!R ;NOP
IFIW!FUNNY ;UNEXPECTED EVENT
IFIW!SNDCLS ;SEND CLS
IFIW!SNDRFC ;SEND STR OR RTS
IFIW!NETOPB ;SNED RFC AND OPEN LINK
IFIW!NETOPL ;OPEN LINK
IFIW!NETCLL ;CLOSE LINK
IFIW!NETCLB ;CLOSE LINK AND SEND CLS
IFIW!DOEOR ;FINISH UP INPUT
IFIW!DOEOS ;FINISH UP OUTPUT
IFIW!DOES1 ;END OF SEND IF TRANSMISSION ABORTED
IFIW!DOABT ;ACCEPT ON ABORTED CONNECTION
IFIW!CKALL ;ALLOCATIN CHECK FOR OPENED CONN
RADIX 8
;UNEXPECTED EVENT
; T1/ EVENT
; UNIT/ UNIT INDEX
FUNNY: HLL T1,NETSTS(UNIT) ;GET STATUS
LOAD T2,ANFHS,(UNIT) ;GET FOREIGN HOST
MNTBUG(INF,NCPFUN,<NCP FSM RECEIVED FUNNY INPUT>,<<T1,D>,<T2,D>,<UNIT,D>>)
AOS FUNNYC ;COUNT THEM
MOVE T1,T2
SETZ T2,
JRST NCPERR ;AND SEND TYPE 0 ERR
; ACCEPTED AN ABORTED REQUEST
DOABT: MOVX IOS,EOTF ; SET FLAG TO CAUSE ERROR
IORB IOS,NETSTS(UNIT) ; IN STATUS WORD
RET
; CHECK ALLOCATION
CKALL: MOVE T1,LSKT(UNIT)
TRNN T1,1 ; SEND SOCKET?
RET ; NO. DO NOTHING
TQNE <ALLFF> ; Allocation failure??
TQNN <CLZF> ; BEING CLOSED?
JRST CKALL1 ; NO, IGNORE
TQO <ERRB,EOTF> ; SIGNAL ERROR, AND STOP TRANSMISSION
HLLM IOS,NETSTS(UNIT)
RET
CKALL1: LOAD T1,LTIDX,(UNIT) ;GET LINK TABLE INDEX
SETSEC T1,ANBSEC
LOAD T2,ANBSIZ,(UNIT)
CAMG T2,NETBAL(UNIT) ; SUFFICIENT BIT ALLOCATION?
SKIPN IMPLT4(T1) ; AND MESSAGE SPACE?
JRST CKALL2 ; NO
TQZ <ALLFF>
HLLM IOS,NETSTS(UNIT)
RET
CKALL2: LOAD T1,LTIDX,(UNIT) ;GET LINK TABLE INDEX
SETSEC T1,ANBSEC
CALL IMPSYN ; RESYNC ALLOCATION
MOVX IOS,ALLFF
IORB IOS,NETSTS(UNIT) ; REMEMBER WE DID THIS ONCE
RET
; END OF SEND
DOES1: CALL DOEOS
CALLRET IMPABL ; FLUSH QUEUED MESSAGES
DOEOS: MOVX IOS,EOTF
IORB IOS,NETSTS(UNIT)
LOAD T1,LTIDX,(UNIT) ;GET LINK TABLE INDEX
SETSEC T1,ANBSEC
CALLRET IMPSDB ; SET DONE BIT IN LINK TABLE
; End of receive
DOEOR: CALL SNDCLS
HRRZ T2,NETBUF(UNIT)
JUMPE T2,DOEOS
CAIL T2,1000
JRST DOEOS
CALL DOEOS ; DO SAME AS END OF SEND
NCPON ; NCP BACK ON SO NVTDET CAN USE IT
EORNV0: HRRZ T2,NETBUF(UNIT) ; PICK UP LINE NUMBER
JUMPE T2,EORNV1 ;ALREADY GONE
PUSH P,UNIT
CALL LCKDVL ;LOCK DEVICE LOCK, GO NOINT
CALL NVTDTT
JRST EORNV2 ;FAILURE
EORNV3: UNLOKK DEVLKK ;UNLOCK THE DEVICE LOCK
OKINT ;DEVLKK WENT NOINT
POP P,UNIT
EORNV1: NCPOFF ; BACK OFF SO CALLER IS NOT CONFUSED
RET
EORNV2: TXZN T1,1B0 ;WAIT OR ERROR?
JRST [ MNTBUG (INF,NETDET,<NVTDET: COULD NOT CLOSE NVT>,<<T1,D>>)
JRST EORNV3] ;GO CLEAN UP
UNLOKK DEVLKK ;UNLOCK THE DEVICE LOCK
OKINT ;DEVLKK WENT NOINT
POP P,UNIT
HRL T1,NETBUF(UNIT) ;GET TTY NUMBER
MDISMS ;WAIT UNTIL DEALLOCATE IS POSSIBLE
JRST EORNV0 ;GO TRY AGAIN
; Close link
NETCLL: LOAD T1,LTIDX,(UNIT) ; Get link table index
SETSEC T1,ANBSEC
TQZE <LINKF> ; Link setup?
CALL IMPCLL
MOVEM IOS,NETSTS(UNIT) ; Store status
RET
NETCLB: CALL NETCLL
SNDCLS: LOAD T1,ANFHS,(UNIT) ; Get foreign host
MOVE T2,LSKT(UNIT) ; And local socket
MOVE T3,FSKT(UNIT) ; And foreign socket
TQNN <DEDF>
CALL IMPCLS ; Send the control message
RET
; OPEN LINK
NETOPL: LOAD T1,ANFHS,(UNIT)
LOAD T2,ANLNK,(UNIT)
LOAD T3,ANBSIZ,(UNIT)
MOVE T4,LSKT(UNIT)
TRNE T4,1 ; Send socket?
JRST NETOPS ; Yes, open send link
CALL IMPOPL ; No, open a receive link
SKIPA
NETOPS: CALL IMPOPS ; Open a send link
STOR T1,LTIDX,(UNIT) ; Keep the link index
MOVX IOS,LINKF ; Mark valid link table index
IORB IOS,NETSTS(UNIT)
RET
; Send rfc and open link
NETOPB: CALL NETOPL
; Send rfc
SNDRFC: TQNE <DEDF>
RET
LOAD T1,ANFHS,(UNIT) ; Get foreign host
MOVE T2,LSKT(UNIT) ; And local socket
MOVE T3,FSKT(UNIT)
LOAD T4,ANBSIZ,(UNIT) ; Byte size
TRNE T2,1
JRST IMPSTR
LOAD T4,ANLNK,(UNIT)
JRST IMPRTS ; Send control message
; This here is the main fsm routine
DOFSM: MOVE IOS,NETSTS(UNIT)
TQNN <DEDF>
JRST DOFSMA
CALL DOFSMA
LOAD T1,ANFSM,(UNIT)
DOFSMB: PUSH P,T1
MOVEI T1,HUNG
CALL DOFSMA
LOAD T1,ANFSM,(UNIT)
POP P,T2
CAME T1,T2
JRST DOFSMB
RET
DOFSMA: NCPOFF ; Allow no control messages while here
MOVEI T2,<2*^D60*^D1000>/CHKINT ; Time out in 2 minutes
STOR T2,ANCLKS,(UNIT)
LOAD T2,ANFSM,(UNIT) ; Get old state
MOVE T4,T2 ; Save old state
LSH T2,1 ; Two words per old state
LDB T3,CBPFSM(T1) ; Get new state
STOR T3,ANFSM,(UNIT)
LDB T2,CBAFSM(T1) ; Get action
CAME T3,T4 ; State changed?
CALL STCPSI ; GENERATE STATE CHANGE PSI
MOVE IOS,NETSTS(UNIT) ; Get current status
CALL @ACTAB(T2) ; Call action routine
NCPON
RET
; Generate state change PSI
STCPSI: SAVET
LOAD T1,ANPVST,(UNIT) ; Save previous 4 states
LSH T1,4
IOR T1,T4
STOR T1,ANPVST,(UNIT) ; Save previous state
HRRE T1,NETFRK(UNIT)
JUMPL T1,R ; No fork for interrupts
LOAD T2,ANFSPI,(UNIT) ; Get psi channel
CAIL T2,^D36
RET
EXCH T1,T2
CALLRET PSIRQ
; Make a socket or find existing one
GETSKT: TDZA T4,T4
MAKSKT: SETO T4,
PUSH P,T4
PUSH P,T1 ; Save foreign host
PUSH P,T2 ; Save foreign socket
PUSH P,T3 ; Save local socket
MOVE UNIT,T3
XOR UNIT,T2
TRNN UNIT,1 ; Homosexual?
JRST MAKSKX ; Yes, go tell Anita
ROT T3,-4
MOVS UNIT,T3
IMULI T3,123431
XOR UNIT,T3 ; Randomize from local socket
LSH UNIT,-1
MULI UNIT,NSKT ; Initial probe
MOVEI T4,NSKT
SETO T3,
NCPOFF
SETSEC UNIT,ANBSEC
MAKSKL: LOAD T1,ANFSM,(UNIT) ; Get state of this socket
CAIE T1,FREE
CAIN T1,DEAD
JRST MAKSK1
CAIN T1,CLZW ; WAITING FOR USER TO CLOSE?
JRST MAKSKN ; YES. DON'T PICK THIS ONE
MOVE T2,LSKT(UNIT) ; What local socket is this for?
CAME T2,(P)
JRST MAKSKN ; Not the one we're after, try next
SKIPGE -2(P)
JRST MAKSK6
LOAD T2,ANFHS,(UNIT)
MOVE T1,FSKT(UNIT)
JUMPL T2,[SKIPN -3(P) ; Was getskt called?
JRST MAKSKN ; Yes, getskt called
POP P,T3 ; Makskt...suceed
JRST MAKSKF]
CAMN T2,-2(P)
CAME T1,-1(P)
JRST MAKSKN ; Foreign host or socket doesn't match
AOS -4(P) ; EVERYTHING MATCHES. SKIP RETURN
NCPON
JRST MAKSKV ; NCPON, POP STACK
MAKSK6: POP P,T3
SUB P,BHC+3
MOVE T2,FSKT(UNIT)
LOAD T1,ANFHS,(UNIT)
NCPON
RETSKP
MAKSKN: SOJLE T4,MAKSKE ; Full, error
SOS UNIT ; Loop back for next slot
TRNN UNIT,100000 ; Past start of table?
JRST MAKSKL ; No, loop some more
ADDI UNIT,NSKT ; Point to end of table
JRST MAKSKL
MAKSK1: SKIPGE T3
MOVE T3,UNIT ; Save where it's at
CAIE T1,DEAD
JRST MAKSKN ; Space keeper, test next
MAKSK5: SKIPN -3(P)
JRST MAKSKR
MOVE UNIT,T3
SETZM NETHST(UNIT)
SETZM NETSTS(UNIT)
SETZM NETBUF(UNIT)
SETZM NETAWD(UNIT)
SETZM NETBAL(UNIT)
SETZM NETBTC(UNIT)
SETOM NETFRK(UNIT)
MOVEI T1,CLZD
STOR T1,ANFSM,(UNIT) ; Set its state to be closed
POP P,T3
MOVEM T3,LSKT(UNIT)
MAKSKF: MOVE T1,-1(P) ; Foreign host
MOVE T2,LSKT(UNIT)
TRNE T2,1 ; Receive?
JRST MAKSKQ
CALL ASNLNK ; Assign link for that host
JRST [ LOAD T1,ANFSM,(UNIT)
MOVEI T2,FREE
CAIN T1,CLZD ; Just created?
STOR T2,ANFSM,(UNIT) ; Yes, delete it
PUSH P,LSKT(UNIT)
JRST MAKSKR] ; And fail
MAKSKQ: POP P,T2 ; Common for old and new
MOVEM T2,FSKT(UNIT)
POP P,T1
STOR T1,ANFHS,(UNIT)
SUB P,BHC+1
NCPON
RETSKP
MAKSKE: JUMPGE T3,MAKSK5
TDZA T1,T1 ; FULL
MAKSKR: MOVEI T1,4 ; NON-EXISTENT
NCPON
SKIPA ; RETURN 0 OR FOUR ERROR CODE
MAKSKX: MOVEI T1,3 ; BAD PARAMETERS
MOVEM T1,-1(P) ; STORE ERROR CODE
MAKSKV: POP P,T3
POP P,T2
POP P,T1
SUB P,BHC+1
RET
; Assign link number for this connection
ASNLNK: SAVET
MOVEI T4,1(P) ; Where bits will be
PUSH P,[<1B<FNLINK>-1>_1+1]
REPEAT NLNKBW-2,<PUSH P,[-1]>
PUSH P,[-<1B<LLINK-<^D36*<NLNKBW-1>>>>]
PUSH P,UNIT ; Preserve unit
PUSH P,T1
PUTSEC UNIT,ANBSEC
MOVEI HN,NSKT
ASNLNL: LOAD T1,ANFSM,(UNIT)
CAIE T1,FREE
CAIN T1,DEAD
JRST ASNLNN
LOAD T1,ANFHS,(UNIT)
CAME T1,0(P) ; Check all connection to this host
JRST ASNLNN ; Get next
MOVE T1,LSKT(UNIT)
TRNE T1,1 ; Only receive connections
JRST ASNLNN
LOAD T1,ANLNK,(UNIT) ; Get link assigned
IDIVI T1,^D36 ; Separate word and bit
MOVE T2,BITS(T2) ; Get the bit
ADD T1,T4
ANDCAM T2,0(T1) ; Clear bits for links in use
ASNLNN: AOS UNIT
SOJG HN,ASNLNL ; Loop thru all connections
HRLI T4,-NLNKBW ; Prepare to look at all bits
SETZ T3,
ASNLNC: MOVE T1,0(T4)
JFFO T1,ASNLNF
ADDI T3,^D36
AOBJN T4,ASNLNC
POP P,T1 ; Failed. Must clean stack before returning
POP P,UNIT
SUB P,BHC+NLNKBW
RET
ASNLNF: ADD T2,T3
POP P,T1
POP P,UNIT
STOR T2,ANLNK,(UNIT)
SUB P,BHC+NLNKBW
RETSKP
; Do a listen (openf for file with no foreign host/socket)
LISTEN: CALL HSTCHK
RET
PUSH P,T4 ; Save byte size
CALL MAKSKT ; Make a socket
JRST [ POP P,T4
MOVEI T1,OPNX10
RET] ; No room
MOVEI T1,LISN
JRST CONNE1
; Do a connect (openf for file with foreign host/socket specified)
CONNEC: CALL HSTCHK
RET
PUSH P,T4 ; Save byte size
CALL MAKSKT ; Make a socket or find existing one
JRST [ POP P,T4
MOVEI T1,OPNX10
RET] ; No room
MOVEI T1,CONN
CONNE1: NCPOFF
LOAD T2,ANFSM,(UNIT)
CAIN T2,CLZD ; Received any rfc here?
JRST CONNE2 ; No
CAIN T2,PNDG ; Same question
JRST CONNE3 ; Yes
MOVEI T1,OPNX9 ; Already in use
POP P,T4
NCPON
RET
CONNE2: MOVX T4,PROGF
IORM T4,NETSTS(UNIT) ; Mark as attached to program
NCPON
POP P,T4 ; My choice of byte size
STOR T4,ANBSIZ,(UNIT) ; Set byte size
CALL DOFSM ; Send rfc etc
RETSKP
CONNE3: TRNE T3,1 ; Are we sender?
JRST CONNE2 ; Also our choice
LOAD T4,ANBSIZ,(UNIT) ; Get his byte size
CAMN T4,0(P) ; Does byte size agree?
JRST CONNE2 ; Yes, same as if my choice
NCPON
MOVEI T1,HUNG ; Flush his connection attempt
CALL DOFSM
POP P,T4
MOVEI T1,OPNX22 ; Bad byte size error
RET
;;; HSTCHK - Check if host is available
;;; Called with T1 - 32 bit host number
;;; Returns+1 if host cannot be reached, error number in T1
;;; +2 if successful
;;;
HSTCHK::
JUMPL T1,RSKP ; ALWAYS OK IF LISTEN
CALL HSTCK0 ; CHECK THE HOST
JRST [ MOVE T1,0 ; Get error number
RET] ; AND ERROR RETURN
JRST RSKP ; UP AND READY
;;;
;;; HSTCK0 - Work routine for above, returns +2 if host is up,
;;; else +1 with error number in 0
;;;
HSTCK0: SAVET
SAVP1 ; (STS)
MOVE T2,T1 ; Save host number here
CALL FNDNCT ; Check if that net is up
JRST [ MOVEI 0,OPNX19 ; Down, can't do anything
RET] ; Return
LOAD T1,NTTYP,(STS) ; Get network type
CAIE T1,NT.NCP ; NCP traffic work?
JRST [ MOVEI 0,OPNX19 ; No
RET]
REPEAT 0,<
MOVE T1,NTNET(P1) ; Get network number for this interface
CAIN T1,^D10 ; ARPANET?
JRST [ MOVE T1,CAPMSK ; Get possible capabilities
TXNE T1,SC%WHL+SC%OPR+SC%ANA ; WHEEL, OPER, or ARPA
JRST .+1
MOVEI 0,WHELX1 ; Insufficent capabilities
RET]
>
MOVE T1,T2 ; Get back to normal AC
LDB T2,[POINT 8,T1,19]
CAIL T2,FKHOST
JRST HSTCKX ; Fake hosts are down
CALL HSTHSH ; Get the host index
JRST RSKP ; No room, try anyway
SKIPGE HSTSTS(T2) ; Up?
RETSKP ; Yes
PUSH P,T2
CALL IMSRST ; Reset him
POP P,T2
MOVEI T3,^D10 ; Wait 5 sec
HSTCK1: MOVEI T1,^D500 ; Wait
DISMS
SKIPGE HSTSTS(T2) ; Up?
RETSKP
SOJG T3,HSTCK1
HSTCKX: MOVEI 0,OPNX20 ; Host is down
RET
; Routines to call when control messages are received
; Receive cls
; Reccls(fhost,fskt,lskt)--nil
RECCLS::CALL GETSKT ; Get the socket entry
JRST NCPERR
RECCL1: MOVE T2,LSKT(UNIT)
TRNN T2,1
SKIPA T1,[CLSR]
MOVEI T1,CLSS
CALLRET DOFSM
; RECEIVED INCORRECT MESSAGE
; REPLY WITH ERR
NCPERR: SAVET
SAVEQ
MOVE T3,I8COP ; GET LAST OP CODE
MOVE HN,[I8CAL,,T4] ; COMPLAIN ABOUT LAST CONTROL MESSAGE
BLT HN,HN
CALLRET IMPERR
; Receive str
; Recstr(fhost,fskt,lskt)--nil
RECSTR::PUSH P,T4 ; Save byte size
RCSTR0: CALL MAKSKT
JRST [ POP P,T4
JRST NCPERR]
MOVE T4,0(P)
CALL CHKSKT ; MAKE SURE THIS SOCKET NOT IN USE
JRST RCSTR0 ; IT WAS. DELETED. NOW TRY AGAIN.
LOAD T1,ANFSM,(UNIT) ; What is state of this connection
CAIE T1,CLZD ; If not clzd
JRST [ LOAD T4,ANBSIZ,(UNIT) ; Then get user's byte size
CAMN T4,0(P) ; If not the same
JRST .+1
MOVEI T1,RRFB ; RECEIVED BAD BYTE SIZE
CALL DOFSM
MOVX T1,ERRB
IORM T1,NETSTS(UNIT)
POP P,T4
RET]
POP P,T4
STOR T4,ANBSIZ,(UNIT)
MOVEI T1,RRFC
CALL DOFSM
MOVE T1,UNIT
LOAD T2,ANLNK,(UNIT)
RET
CHKSKT: SAVET
LOAD T1,ANFSM,(UNIT) ; GET STATE
CAIE T1,RFCS ; STATES WHERE RFC IS EXPECTED
CAIN T1,CLZD
RETSKP
CAIN T1,LSNG
RETSKP
CALLRET SK2DWN ; KILL THE OLD ONE
CHKLNK: SAVET
STKVAR<CHKLLK,CHKLHS>
MOVEM T1,CHKLHS
MOVEM T4,CHKLLK
PUTSEC UNIT,ANBSEC
MOVEI HN,NSKT
CHKLK1: LOAD T2,ANLNK,(UNIT) ; GET THE LINK
LOAD T3,ANFHS,(UNIT) ; AND HOST
CAMN T2,CHKLLK
CAME T3,CHKLHS
JRST CHKLK2
MOVE T2,LSKT(UNIT)
TRNN T2,1
JRST CHKLK2 ; SKIP SEND CONNECTIONS
LOAD T2,ANFSM,(UNIT) ; LINK-HOST MATCHES. GET STATE
CAIE T2,DEAD
CAIN T2,FREE
JRST CHKLK2
CAIE T2,CLZD
CAIN T2,RFCS
JRST CHKLK2
CAIE T2,LSNG
CAIN T2,CLZW
JRST CHKLK2
CALL SK2DWN
CHKLK2: AOS UNIT ; Increment socket pointer
SOJG HN,CHKLK1
RET
; Receive rts
; Recrts(fhost,fskt,lskt,link)
RECRTS::CALL CHKLNK ; CHECK AND DELETE ANY MATCHING LINKS
PUSH P,T4 ; SAVE LINK
CALL MAKSKT ; MAKE SOCKET TABLE ENTRY
JRST [ POP P,T4 ; FAILED, SEND ERR
JRST NCPERR]
POP P,T4 ; RESTORE LINK
CALL CHKSKT ; MAKE SURE NO DUPLICATES
JRST RECRTS ; PREVIOUS CONNECTION CLOSED. TRY AGAIN
STOR T4,ANLNK,(UNIT)
MOVEI T1,RRFC
CALLRET DOFSM
; Receive rfnm
RCFRFN::MOVEI T1,RRFN
CALLRET DOFSM
; Receive ins/inr
RECINR::
RECINS::LOAD T2,ANINPI,(UNIT)
LOAD T1,ANFSM,(UNIT)
CAIGE T2,^D36 ; RETURN IF CHANNEL IS 77 OCTAL
CAIE T1,OPND
RET
HRRZ T1,NETBUF(UNIT)
SKIPE T1
CAIL T1,1000
TRNA
RET
HRRE T1,NETFRK(UNIT)
JUMPL T1,R
EXCH T1,T2
CALLRET PSIRQ
; INITIATE SERVICE INTERRUPTION (HOST DEAD)
SVCINT::MOVX IOS,SVCIF
IORB IOS,NETSTS(UNIT)
CALLRET STCPSI ; GENERATE STATE CHANGE PSI
; TERMINATE SERVICE INTERRUPTION
SVCRST::MOVX IOS,SVCIF
ANDCAB IOS,NETSTS(UNIT)
CALLRET STCPSI
;;; Receive reset message
RECRST::CALL NETHDN
JRST IMPRRP
;;; Kill all connection -- net is down
;;; P1 -- NCT for the network
NETDWN::MOVEI HN,NSKT
PUTSEC UNIT,ANBSEC ; Place pointer to right section
NETDWL: MOVE T1,NETHST(UNIT) ; Get the host for this one
CALL NETCMP ; Same net?
SKIPA ; No
CALL SKTDWN
AOS UNIT ; Point to next
SOJG HN,NETDWL ; Loop
RET ; And return
;;; Periodic check of all connections for time-out
CONNCK::PUTSEC UNIT,ANBSEC
MOVEI HN,NSKT
CONCKL: LOAD T1,ANFSM,(UNIT) ;Get connection state
CAIE T1,DEAD ; Is this an active connection?
CAIN T1,FREE ; ?
JRST CONCKN ; No, try next
MOVX T1,DEDF ; is it alive?
TDNE T1,NETSTS(UNIT) ; ?
JRST CONCK1 ; No, hang it
LOAD T2,ANCLKS,(UNIT) ; else count down clock
SOS T2 ; ..
STOR T2,ANCLKS,(UNIT) ; ..
JUMPG T2,CONCKN ; and on to next if it hasn't counted down
CONCK1: MOVEI T1,HUNG
CALL DOFSM
CONCKN: AOS UNIT ; INCREMENT POINTER
SOJG HN,CONCKL
MOVEI T1,CHKINT ; Get check interval
ADD T1,TODCLK
MOVEM T1,NETTIM
;3032 RET
callret ntdset ;3032 fix up IMPTIM and return with todclk
; Host has died
NETHDN::PUTSEC UNIT,ANBSEC
PUSH P,T2
MOVEI T2,NSKT
PUSH P,T1
NETHDL: LOAD T1,ANFSM,(UNIT)
CAIE T1,FREE
CAIN T1,DEAD
JRST NETHDX
LOAD T1,ANFHS,(UNIT)
CAMN T1,(P)
CALL SKTDWN
NETHDX: AOS UNIT ; Increment pointer
SOJG T2,NETHDL ; And loop through all
POP P,T1
POP P,T2
RET
SK2DWN::HRRZ T2,NETBUF(UNIT)
CALL NVTCHK ; AN NVT?
JRST SKTDWN ; NO, TREAT NORMALLY
PUSH P,UNIT
PUSH P,T2
CALL SKTDWN
MOVE T2,0(P)
CALL NVTIPU ;GET INPUT UNIT
TRNA ;NO UNITS FOR THIS LINE
CALL SKTDWN ; CLOSE THE OTHER HALF
POP P,T2 ;GET ADDRESS OF DYNAMIC DATA FOR TTY
CALL ULKTTY ;UNLOCK DATA BASE
POP P,UNIT
RET
SKTDWN: LOAD T1,ANFSM,(UNIT) ; GET STATE
CAIN T1,LSNG ; IF LSNG
RET ; IGNORE
MOVX T2,ERRB!DEDF
IORM T2,NETSTS(UNIT)
CAIE T1,CLSW ; IF WAITING FOR CLOSE,
CAIN T1,CLW1
CALL SKTDW2 ; PRETEND ONE HAPPENED.
CAIE T1,RFCR
CAIN T1,OPND ; If opnd
SKTDW2: CALL RECCL1 ; Simulate receipt of cls
MOVEI T1,HUNG
CALLRET DOFSM
;;;
;;; The following routines simulate various NCP Getab tables
;;; (since the data is now in ANBSEC they can't be accesed directly
;;;
;;; GNTRDY - Get the NETRDY table
;;; attempts to find the data from the NCT for the primary network
;;;
GNTRDY::
MOVE T1,DEFADR ; get primary address
CALL NETNCT ; Find an NCT for it
RETERR() ; Error
MOVE T1,@GNTAB(T2) ; get an entry
RET ; And return
;;; Indirect table for deriving the data
GNTAB: IFIW!<STS>B17+NTRDY ; NETRDY From the NCT
IFIW!<STS>B17+NETON ; As NETON
IFIW+NETENT ; NETENT has its own cell
IFIW+BHC ; NCPUPT (wrong data but)
IFIW+IGDMSG ; Last Imp going down message
IFIW!<STS>B17+NTXDNT ; Last ready line drop
IFIW!<STS>B17+NTXUPT ; last ready line up time
IFIW+IGDTIM ; Last imp going down message time
;;; GHTSNM - get a word form the HSTNAM Table
;;;
GHSTNM::
SETSEC T2,MNTSEC ; Point to right sction
MOVE T1,HSTNAM(T2) ; get entry
RET
;;; GNTLSK,GNTFSK,GNTBAL,GNTSTS,GNTBUF,GNTBTC
;;; Get entries from various NCP tables
GNTLSK::
SETSEC T2,ANBSEC
MOVE T1,LSKT(T2)
RET
;1017 Begin addition
GNTHST::
SETSEC T2,ANBSEC
MOVE T1,NETHST(T2)
RET
;1017 End addition
GNTFSK::
SETSEC T1,ANBSEC
MOVE T1,FSKT(T2)
RET
GNTBAL::
SETSEC T2,ANBSEC
MOVE T1,NETBAL(T2)
RET
GNTSTS::
SETSEC T2,ANBSEC
MOVE T1,NETSTS(T2)
RET
GNTBUF::
SETSEC T2,ANBSEC
MOVE T1,NETBUF(T2)
RET
GNTBTC::
SETSEC T2,ANBSEC
MOVE T1,NETBTC(T2)
RET
;;; GIMLT1-4, Get from the link tables IMPLT1-4
GIMLT1::
SETSEC T2,ANBSEC
MOVE T1,IMPLT1(T2)
RET
GIMLT2::
SETSEC T2,ANBSEC
MOVE T1,IMPLT2(T2)
RET
GIMLT3::
SETSEC T2,ANBSEC
MOVE T1,IMPLT3(T2)
RET
GIMLT4::
SETSEC T2,ANBSEC
MOVE T1,IMPLT4(T2)
RET
TNXEND
END