Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_3_19910112 - mit/monitor/tttvdv.mac
There are no other files named tttvdv.mac in the archive.
;[MIT-XX]SSY:<MONITOR.NEW>TTTVDV.MAC.2,  5-Nov-83 17:45:32, Edit by BERLIN
;3051 Add TVRFIL routine to signal tvt buffer refill (from CLYNN and MRC)
;3031 Fix for supdup - cknnvt has a double skip return now!
;#473 Make monitor listen on TCP port 231
; Use DLAYPZ before OPSCA7 instead of ENC/FRCPKT (closed window problem)
;[BBNF]<BBN-5-MONITOR.TCP4>TTTVDV.MAC.2,  2-Jun-82 16:55:54, Edit by RBASCH
; Added new TVSBE1 routine, called instead of TTSOBE from OPSCAN
; and PKTZ00, to check for send-all as well as normal output
;CWL:<403-TCP>TTTVDV.MAC.40303  3-May-82 16:14:41, Edit by CLYNN
; Fix DM option after error loop bug
;<403-TCP>TTTVDV.MAC.7, 23-Apr-82 12:05:15, Edit by TAPPAN
; PREVENT TVTCOB FROM PUTTING STUFF IN THE OUTPUT BUFFER
; IF CONNECTION IS UNUSABLE
;<403-TCP>TTTVDV.MAC.6,  1-Apr-82 12:27:50, Edit by TAPPAN
; Add test of SF%NVT before starting up a TVT LISTEN
;REL5:<MNET-TCP>TTTVDV.MAC.31  7-Feb-82 17:26:05, Edit by RBASCH
;IN TVTOSP, CHECK NEW XOFF BIT TTRXF
;REL5:<MNET-TCP>TTTVDV.MAC.30  5-Feb-82 17:00:37, Edit by RBASCH
;IN TVMSNT, USE SASUBR INSTEAD OF PUSH/POP, AND JRST TO TVMSN1 INSTEAD
;OF TTMSN1 (FOR REL-5)
;<403-TCP>TTTVDV.MAC.40301 29-Jan-82 15:08:58, Edit by CLYNN
; Updated for TCP release 3
;<MNET-TCP>TTTVDV.MAC.6,  5-Jan-82 15:00:31, Edit by TAPPAN
; Release 5 fixes
;<401-TCP>TTTVDV.MAC.88, 13-Oct-81 19:05:00, Edit by CLYNN
; Fix: SNDALL with no TVTs in configuration
;<401-TCP>TTTVDV.MAC.87, 13-Oct-81 09:54:52, Edit by TAPPAN
; Change default retransmittion timeount to 1 second
;[BBNF]<401-TCP>TTTVDV.MAC.86, 14-Aug-81 15:07:00, Ed: CLYNN
; WARNING: Changes are also required to TTNTDV.MAC:
;	after TMSNR1:, before SETZRO TSALP,(T2) insert SETZRO TSALC,(T2)
;	after NVTDT2:, before SETZRO TSALP,(T2) insert SETZRO TSALC,(T2)
; Fix: Zero TSALC when cancelling a SNDALL, TVTOSP returns sum of
; regular & sendall buffers, TVTCLS does a listen if EFP+^D7 & no TVTL,
; Added TVSBE1 to check for sendall characters
;<401-TCP>TTTVDV.MAC.85, 17-Jul-81 12:13:53, Edit by TAPPAN
; experimental re-doing of "when-to-listen" algorithm (to 
; prevent hung listening sockets)
;[BBNF]<401-TCP>TTTVDV.MAC.85, 14-Jul-81 14:33:00, Ed: CLYNN
; Fix: TCB is in INTSEC in TVTDOB, Error code for ABTCON at TVTOP9
;[BBND]<401-TCP>TTTVDV.MAC.84, 29-May-81 13:38:33, Ed: EONEIL
;CHANGED SKIPN TO SKIPL AT TVTOPR
;[BBND]<JDELSIGNORE.MONITOR>TTTVDV.MAC.4, 22-Jan-81 16:29:36, Ed: JDELSIGNORE
;REMOVED OFFSETS FOR LINE ACCOUNTING AND LINE USAGE NUMBERS 41,42

IFNDEF .TVFLG,<.TVFLG==:1>
IFN	.TVFLG,<		; If supporting TCP terminals

IF1 <PRINTX IN TTTVDV PASS 1>
IF2 <PRINTX IN TTTVDV PASS 2>

IFNKA <IFNDEF %%REL,<
	PRINTX % %%REL NOT SET IN PROLOG0.MAC.  %%REL 50 ASSUMED.
	%%REL==50
>>

IFNKA <
  IFLE %%REL-40,<IFE TTNTVT-TTDMVT,<PRINTX ? TVTs require TTNTDV to be included>>
  IFGE %%REL-50,<IFE .NTFLG,<PRINTX ? TVTs require TTNTDV to be included>>
> ; End of IFNKA

IFNKA < IFLE %%REL-40,<	SEARCH	INPAR,TCPPAR >>

IFKA <	SEARCH	PROLOG
	TTITLE TTTVDV
> ; End of IFKA
	SUBTTL	TVT DEPENDENT CODE
COMMENT	!

These routines support TCP Virtual Terminals, which are very similar
to ARPANET NVTs.  They speak "new" TELNET protcol.  TVTs are
operated by the TCP portion of the Internet fork.  This fork
does the listen, etc. and there is no usermode equivalent of
NETSER.  The listen is special in that it is marked as a TVT,
which means that the buffers involved are TTYSRV buffers in
monitor space and not user-supplied buffers in some user's
space.  Further, no PSI are generated for buffer completions.
Allocation (window) is set by the number of bytes available in
the TTY buffers.
TVTs use the TELNET protocol through TCP connections.  Most of the
TELNET code is in TTNTDV and this module uses that code.

 #TVSBE1 ...  4 ...... See if send-all has any output too
 #TVMSNT ...  4 ...... See if send-all should be done
* TVMNTR ...  4 ...... Clear all TVT Send-all requests

  ASNTVT ...  5 ...... Assign a TCP Virtual Terminal
* TVTCSO ...  6 ...... TVT Console start output routine
 #TVTDOB ...  7 ...... TVT Dismiss until output buffer empty routine
 #TVTCOB ...  8 ...... TVT lear output buffer routine

* TVTNCK ...  9 ...... Check for overdue TELNET negotiations on TVTs
* SNDTVT ... 10 ...... Send bytes to TVT
* PRCTVT ... 11 ...... Process bytes received from TVT

* CHKTVT ... 12 ...... Check to see if line is a TVT
* TVTCHK ... 12 ...... Check for TVT and lock line if so.

* TVTISP ... 13 ...... Get number of holes in TVT input buffer
* TVTOSP ... 13 ...... Get number of bytes in TVT output buffer

 #TVTDTS ... 15 ...... Close TCP connection upon carrier-off condition
 #TVTDET ... 15 ...... Detach job from TVT

 #TVTIGA ... 16 ...... Input TELNET Go-Ahead

* TVTOPR ... 17 ...... Main routine to operate TVTs
  LISTEN ... 17 ...... TELNET server listen routine
* TVTOPN ... 18 ...... Handle TVT connection as it is opening
* TVTCLS ... 19 ...... Handle TVT connection as it is closing

  OPSCAN ... 20 ...... Scan all TVTs for possible output
	!

	OPDEF %OPEN% [JSYS 742]		; 'Cause MACRO is finding CALLI nowdays
IFNKA < IFLE %%REL-40,<
;TVT VECTOR TABLE ENTRYS

	RESCD
TTTVVT=.
	TVTLEN			;LENGTH OF DYNAMIC DATA FOR THIS TYPE
	-1			;FIRST LINE OF THIS TYPE/-1 NO LINES
	IFIW!R			;00 - INITALIZATION
	IFIW!R			;01 - RESTART
	IFIW!TVTCOB		;02 - CLEAR OUTPUT BUFFER
	IFIW!R			;03 - SET LINE SPEED
	IFIW!TTRSP2		;04 - READ TTY SPEED
	IFIW!TTSNT2		;05 - SET NON-TERM STATUS
	IFIW!TTRNT1		;06 - READ NON-TERM STATUS
	IFIW!TTSTO5		;07 - REMOVE CHAR FROM OUTPUT BUFFER
	IFIW!TVTPAR		;08 - STPAR JSYS
	IFIW!R			;09 - CHECK PHYSICAL LINE
	IFIW!TTXON2		;10 - XON
	IFIW!TVTDET		;11 - DEASIGN DYNAMIC DATA
	ANDI T1,177		;12 - TTY OUTPUT PARITY OFF
	IFIW!TVTCSO		;13 - START OUTPUT LINE
	IFIW!R			;14 - XOFF
	IFIW!R			;15 - XON
	IFIW!TTCQ1		;16 - EMPTY BUFFER
	IFIW!R			;17 - CARRIER ON
	IFIW!TVTCOF		;18 - CARRIER OFF
	IFIW!TVTDTS		;19 - HANGUP
	IFIW!R			;20 - ^S
	IFIW!TVC7SN		;21 - NO LOGINS
	IFIW!R			;22 - STORE CHARACTER
	IFIW!R			;23 - SEND CHARACTER
	IFIW!TVDAL6		;24 - DEALLOCATE LINE
	IFIW!DLSSX2		;25 - BUFFER OVERFLOW
	IFIW!R			;26 - EMPTY BUFFER
	IFIW!RSKP		;27 - SENDALL TO SINGLE LINE
	IFIW!R			;28 - ENABLE/DISABLE DATASETS
	IFIW!R			;29 - INIT
	IFIW!R			;30 - CLEAR INPUT BUFFER
	IFIW!TVTDOB		;31 - DOBE
	IFIW!TVTIGA		;32 - INPUT GA
	IFIW!TVSET1		;33 -  SET INIT. VALUES FOR A LINE
	IFIW!TVSBE1		;34 - SOBE
	IFIW!TVOBE1		;35 -  WAKEUP IF OUTPUT BUFFER EMPTY
	IFIW!TVMSNT		;36 - SENDALL TO SINGLE LINE
	IFIW!TVMSNT		;37 - SENDALL TO ALL LINES
	JFCL			;38 - ADJUST WAKEUP CLASS
	IFIW!R			;39 - STOP LINE
	IFIW!R			;40 - XOFF RECOGNITION
   IFN <.-TTVTMX>-TTTVVT,<PRINTX %%INVALID DEVICE DEPENDENT TABLE SIZE>
>> ; End of IFLE %%REL-40 ; End of IFNKA
; TVT Block length is same as NVT:

IFNKA <TVTLEN==NVTLEN>

; Routines in TTNTDV which are suitable for TVTs:

IFKA <EXTERN NVTSTD,STADYN,LCKTTY,ULKTTY>
IFNKA < IFLE %%REL-40,<TVSET1==TTSET1>>
TVTPAR==NVTPAR
TVTCOF==NTYCOF
IFNDEF ISI,<IFKA <TVTCOF==NTYCOF>>
IFDEF ISI,<
IFKA <TVTCOF==NVTCOF>
IFKA <RCTOPT==7>
IFKA <WILOPT==10>
> ; End of IFDEF ISI
TVTCHI==TTCHI
IFKA <	TTCOBN==TTCOBI
	TCOBN==TCOBQ
>
IFKA <	INTERN TVTCIB,TVTCOB,TVTDOB,TVTCAP,TVTDET>

IFKA <
	NTTTVT==TVTHI-TVTLO+1
	NVTMO==NEGTMO_^D18
>


; Structure analagous to PTNTO and PTNTI:

IF1 <IFNDEF PTVT,<		; Its also defined in TCPPAR
DEFSTR(PTVT,TTNETW,35,18)	; Holds pointer to a TVT TCB
   >>

IFKA <	; Note: Some of these definitions must parallel those in MIMPDV

DEFSTR TTTYP,TTYPE,35,18	; Terminal type
DEFSTR TCJOB,TTFORK,17,18	; Controlling job number
DEFSTR TIMAX,TTBFRC,26,9	; Max bytes in input buffer
DEFSTR PBRCT,TTBRKC,8,9		; Outstanding BREAKS count
DEFSTR TTOTP,TTFLGS,0,1		; Output active flag
DEFSTR NVSTP,TTNETW,14,3	; Current NVT state
>


; TCP Parameters:

LSNPRT==^D101		;#473 Port TELNET listens on
LSNTMO==^D<5*60>	; Timeout
TVTRXP==0000,,0		; TVT Retransmission parameters

RS	LSNTIM		; temp holder for time to try another listen
IFNKA <
;DOES SKIPE TTOCT(B) AND SKIPE TSALC(B) FOR TVTS
;SKIPS ONLY IF ABSOLUTELY NO CHARS TO BE HANDLED FOR LINE
;ACCEPTS DYN LINE # IN B
;RETURNS TTOCT+TSALC IN T1

TVSBE1::CALL TTSOBE		
	 JRST TVSBE2		;NO SKIP IF NORMAL OUTPUT TO BE DONE
	OPSTR <SKIPN>,TSALC,(B) ;NO SKIP IF SENDALL TO BE DONE
	 RETSKP			;SKIP ONLY IF ABSOLUTELY NO CHARS
TVSBE2:	OPSTR <ADD A,>,TSALC,(B)
	RET			;NO-SKIP, COUNT IN A

;TVMSNT - TEST TO SEE IF SEND ALL SHOULD BE DONE

;	FNCALL OFF TTVT36	One Line
;	FNCALL OFF TTVT37	All Lines

;ACCEPTS:
;	T2/ LINE NUMBER

;RETURNS: +1 DO NOT SEND MESSAGE
;	  +2 SEND MESSAGE

	SWAPCD

TVMSNT:	SASUBR <MSPT,MSLN,MSCT>
	JUMPL T2,R		; return now if no such lines
	CALL LCKTTY		;GET DYNAMIC DATA ADDRESS IF IT EXIST
	JRST TVMSN1		;NO DYNAMIC DATA DO NOT SEND
	SKIPG TTNETW(T2)	;ANY CONNECTIONS?
	JRST TVMSN1		;NO DO NOT SEND MESSAGE
	CALL ULKTTY		;YES UNLOCK TTY DATABASE
	AOS TVTNOF		;INDICATE OUTPUT FOR TVTS
	MOVE T2,MSCT		;GET COUNT OF CHARACTERS IN MESSAGE
	IMULI T2,TMSNTT		;MULTIPLY BY ALLOWABLE TIME PER CHAR.
	ADD T2,TODCLK		;GET TIME MESSAGE TO BE DISCARDED
	MOVEM T2,TVMSTM		;SAVE TIME FOR TCP FORK
	RETSKP			;SEND MESSAGE

TVMSN1:	CALL ULKTTY		;UNLOCK TTY
	RETBAD			;NO DO NOT SEND MESSAGE
;TVMNTR - ROUTINE TO CLEAR ALL TVT SNDALL REQUEST
;Called NOSKED from OPSCAN on TVMSTM timeout set by TVMSNT

	RESCD

TVMNTR::MOVE T3,TVTPTR		;GET AOBJN COUNTER FOR TVT'S
	JRST TMSNR1		; Use code in TTNTDV
REPEAT 0,<
TMSTR1:	SKIPN T2,TTACTL(T3)	;GET ADDRESS OF DYNAMIC DATA
	 JRST TMSTR2		;IF NON-STANDARD BLOCK CHECK
	HRRZ T2,T2		;GET JUST ADDRESS
	JE TTSAL,(T2),TMSTR2	;IF DOING SENDALL CLEAR IT
;	SETZRO TTSAL,(T2)	;ZERO SENDALL BIT
;	SOS SALCNT		;DECREMENT COUNT OF LINES DOING SENDALL
;	SETZRO TSALC,(T2)	;ZERO SENDALL COUNT (TVTs)
;	SETZRO TSALP,(T2)	;ZERO SENDALL POINTER
	CALL CLRSAL		; Interrupt-proof decrement
TMSTR2:	AOBJN T3,TMSTR1		;HAVE WE DONE ALL OF THE LINES
	RET			;YES RETURN
  >
> ; end IFNKA
;ASNTVT - ASSIGN A TCP VIRTUAL TERMINAL

;ACCEPTS:
;	T1/ TCB (WITH AN%NTP flag for new protocol)

;	CALL ASNNVT

;RETURNS +1: FAILURE
;	 +2: SUCESS
;		T1/ LINE NUMBER
;		T2/ ADDRESS OF DYNAMIC DATA AND DATA BASE LOCKED

	SWAPCD

ASNTVT::STKVAR <FLGTCB,TVLIN>
	MOVEM T1,FLGTCB
	HRRZ T1,TVTPTR		;GET FIRST TVT LINE NUMBER
	SETZ T3,		;START WITH FIRST TVT
	NOSKED
ASNTV1:	MOVE T2,T1		;GET FIRST TVT OFFSET
	ADD T2,T3		;ADD CURRENT TVT
	MOVEM T2,TVLIN		;SAVE LINE NUMBER
	CALL STADYN		;IS IT INITIALIZED
	 JUMPE T2,ASNTV4	;NO. NO DYNAMIC DATA
	SKIPG TTNETW(T2)	;FREE?
	 JRST ASNTV3		;YES.
ASNTV2:	CAIGE T3,NTTTVT-1	;LOOKED AT ALL TVT'S?
	 AOJA T3,ASNTV1		;NO
	OKSKED			;YES,
	RETBAD			;RETURN BAD

ASNTV3:	LOAD T2,TCJOB,(T2)	;GET JOB FOR WHICH THIS IS A CNTRL TTY.
	CAIN T2,-1		;IS THERE ONE
	  JRST ASNTV4		; No, use this one
	HLRZ T2,JOBPT(T2)	; Yes, is it really there?
	CAMN T2,TVLIN		; Skip if TCJOB has obsolete data
	  JRST ASNTV2		;YES. TTY ALREADY ATTACHED?
ASNTV4:	IFNKA <

; if job-0 ought to use TTYASC
; if other job, ought to use TTYASO
; For now, they are essentially the same

	MOVE T2,TVLIN		;GET LINE NUMBER BACK
	CALL TTYASC		;ASSIGN TVT
	 JRST ASNTV6		;COULD NOT ASSIGN IT
	>
	MOVE T2,TVLIN		;GET LINE NUMBER
	CALL LCKTTY		;AND LOCK DATA BASE
	 JRST ASNTV5		;CANNOT LOCK DATA BASE. SHOULD'NT HAPPEN
	SETONE TCJOB,(T2)	;INDICATE NO CONTROLLING JOB FOR TERM.
IFNKA <	SETONE TTPRM,(T2)>	;MAKE DATA PERMANENT UNTIL NVT CLOSED
	MOVE T1,FLGTCB		; Get arg back
	TXNN T1,AN%NTP		;NEW TELENET PROTOCOL REQUEST?
	 TLZA T3,-1		;NO, MAKE ZEROES
IFNKA <	  MOVX T3,NVNNV>	;YES, MAKE NEW NVB BIT
IFNDEF ISI,<IFKA <MOVX T3,NVNNV>>	;YES, MAKE NEW NVB BIT
IFDEF  ISI,<IFKA <MOVSI T3,NEWNVB>>	;YES, MAKE NEW NVB BIT
	HLLZM T3,TTNETW(T2)	;CLEAR TTNETW EXCEPT FOR NVNNV
	SETZM NVTOPF(T2)	;CLEAR OPTION STATUS
	HRRZ T1,FLGTCB		; Get the TCB
;	HRRZ T1,JCNTCB(T1)
	STOR T1,PTVT,(T2)	;REMEMBER UNIT
	SETONE TT%DUM,TTFLGS(T2) ;SET DUPLEX MODE
	MOVEI T1,.TTIDL		;SET TO BE AN "IDEAL" TERMINAL
	STOR T1,TTTYP,(T2)
IFDEF ISI,<
IFKA <	CALL TTCOBI		; Clear input, output buffers
	CALL TTCIBF>	; End of IFKA
> ; End of IFDEF ISI
	MOVE T1,TVLIN		;RETURN LINE NUMBER
	OKSKED
	RETSKP


ASNTV5:	CALL ULKTTY		;UNLOCK DATA BASE
ASNTV6:	HRRZ T1,TVTPTR		;GET FIRST TVT
	MOVE T3,TVLIN		;SET UP TO TRY NEXT LINE
	SUB T3,T1		;GET TVT NUMBER IN 3
	JRST ASNTV2		;AND TRY NEXT TVT

IFNKA <	ENDSV.
>
;TVTCSO - START OUTPUT TO A LINE CALLED FROM STRTOU

;	FNJRST OF TTVT13

;RETURNS +2: ALWAYS

	RESCD

TVTCSO::
	AOS TVTNOF		;REQUEST TTY SCAN
	AOS TCPFLG		; Say it is TCP that needs to run
	AOS INTFLG		; Get the Internet fork to run it
	RETSKP
;TVTDOB - TVT dismiss until output buffer empty

;FNCALL off of TTVT31
;
;Avoid doing a TELNET timing mark option negotiation if the connection
;is closing since the other end will not respond.

	SWAPCD

TVTDOB:	LOAD TCB,PTVT,(T2)	; Get TCB if exists
	 JUMPE TCB,R		; Return if none
	SETSEC TCB,INTSEC	; TCBs are in INTSEC
	LOAD T1,TSSYN,(TCB)	; Get send state
	CAIE T1,SYNCED		; Can we send?
	 RET			; No
	LOAD T1,TRSYN,(TCB)	; Get receive side state
	CAIE T1,SYNCED		; Can other end reply?
	 RET			; No
	JRST NVTDOB		; Yes and yes.  Do normal TELNET stuff
;TVTCOB - TVT CLEAR OUTPUT BUFFER CALLED FROM TTCBF2

;ACCEPTS:
;	T2/ ADDRESS OF DYNAMIC DATA

;	FNJRST OFF TTVT02

;RETURNS +1: ALWAYS


	RESCD

TVTCOB:
	SKIPE INSKED		;IN SCHEDULER
	 RET			;YES RETURN IMMEDIATELY
;;;IFNKA <	OKSKED>
	PUSH P,TCB
	SKIPG TCB,TTNETW(T2)	;STILL CONNECTED TO NETWORK?
	 JRST TVTCO3		;NO.  RETURN
	SETSEC TCB,INTSEC	; TCBs in Internet section
	JN TERR,(TCB),TVTCO3	; Don't DM if connection error

	NOINT			;PROTECT POSSIBLE ILOCKS
	CALL CKNNVT		;NEW STYLE NVT?
	 JRST TVTCO1		;OLD STYLE
	 JFCL			;3031 Supdup?
	MOVEI T1,DMCH		;DATA MARK CHARACTER
	CALL NVTSSP		;SEND NEW DM
	JRST TVTCO2

TVTCO1:	MOVX T1,1		;RESERVE ONE CHARACTER
	CALL NVTRSV		;GO REESERVE IT
	 JRST TVTCO2		;NONE AVAILABLE CANNOT WAIT
	MOVX T1,200
	CALL TCOBN		;SEND CHARACTER
	OKSKD1
TVTCO2:
	OKINT
TVTCO3:	POP P,TCB
;;;	IFNKA <	CALL TTXON>	;REACTIVATE OUTPUT IF NECESSARY
	RET
;CHECK OVERDUE NEGOTIATIONS

	RESCD

TVTNCK::STKVAR <TVTCTR>
	MOVE T2,TVTPTR		;POINTER TO TVTS
TVTNCL:	MOVEM T2,TVTCTR		;SAVE TVT COUNTER
	HRRZ T2,T2		;GET JUST RIGHT HALF
	CALL LCKTTY		;GET ADDRESS OF DYAMIC DATA AND LOCK
	 JRST TVTNCE		;NOT ACTIVE
	SKIPGE TTNETW(T2)	;ATTACHED?
	 JRST TVTNCE		;NO, SKIP IT
	MOVX T3,NVTMO		;TIME OUT
	HLLZ T1,NVTOPF(T2)	;GET OUTSTANDING OPTIONS
	 JUMPE T1,[ANDCAM T3,TTNETW(T2) ;NONE, CANCEL TIME-OUT IF ANY
		JRST TVTNCE]
	XORB T3,TTNETW(T2)	;YES, COUNT COUNTER
	TXNN T3,NVTMO		;COUNT FROM 1 TO 0?
	 HRRZS NVTOPF(T2)	;YES, CANCEL OUTSTANDING OPTION
TVTNCE:	CALL ULKTTY		;UNLOCK DATA BASE
	MOVE T2,TVTCTR		;GET AOBJ COUNTER
	AOBJN T2,TVTNCL		;ANY MORE TVT'S
	MOVE T1,TODCLK		;NO.  GET TIME OF DAY
	ADDI T1,NEGTM0		;ADD TIME OUT QUANITY
	MOVEM T1,TVTNTM		;SAVE TIME FOR NEXT CHECK
	RET

IFNKA <	ENDSV.
>
; SNDTVT		; Send virtual terminal data

;TCB/	Locked connection block
;PKT/	Pointer to Internet portion of packet being filled
;TPKT/	Pointer to TCP portion of packet
;T1/	Max number of characters to send
;T2/	Line block address
;
;	CALL SNDTVT
;Ret+1:	Always.  Terminal data moved into packet. T1 has number of chrs.

SNDTVT::INTLAC <XFRCNT,LINBLK,PKTPTR,CNT>
	DMOVEM T1,XFRCNT	; T1,2 to XFRCNT and LINBLK
IFN .TTYLG,<
	SKIPN TTDEV2(T2)	; Log file already?
	 CALL OPNLOG		; open log file if possible
	  JFCL
>
	LOAD PKTPTR,PTDO,(TPKT)	; Get TCP data offset
	HRLI PKTPTR,(<POINT 8,.-.(TPKT)>) ; Pointer to data area
	MOVEI CNT,0		; Init number moved to packet
IFNDEF ISI,<       MOVEI T3,(1B<RCTOPT+WILOPT>)> ; RCTE-on bit
IFDEF  ISI,<IFNKA <MOVEI T3,(1B<RCTOPT+WILOPT>)>> ; RCTE-on bit
IFDEF  ISI,<IFKA  <MOVE T3,[RCTWIL##]>>
	TDNE T3,NVTOPF(T2)	; Have we said we will do RCTE?
	CALL CKNNVT		; And is this a "new" TELNET terminal?
	 JRST SNDTV1		; No.
	 JFCL			;3031 Supdup?
	JE PBRCT,(T2),SNDTV1	; Check the break count
	CALL NVTRRR		; Try to send
SNDTV1:	SKIPG TTNETW(T2)	; Still connected?
	 JRST SNDTV2		; No
	JE TERR,(TCB),SNDTV3	; Error on connection (retrans timeout)?

SNDTV2:	CALL CLRSAL		; Flush sendall - DEC calls TTCOB5
				; instead of TTCBF2 - Why?
	CALL TTCOBN		; Flush output buffer
	JRST SNDTV9		; And return
SNDTV3:	SETONE TTOTP,(T2)	; Indicate output active

; Move characters from the terminal output buffer(s) into the packet.
; XFRCNT has space left in packet and CNT will be left with number
; moved.

SNDTV4:	SOJL XFRCNT,SNDTV5	; Jump if packet filled
	MOVE T2,LINBLK		; Restore address of data area
	NOSKD1
IFNKA <	CALL TTSND		; Get a chr from output buf to T3
	JRST SNDTV6>		; Failed to get any	
IFKA <	JSP T4,TTSND>		; Get a chr from output buf to T3
	OKSKD1
IFKA	<
	JE TTOTP,(LINBLK),SNDTV6 ; Jump if we did not get it
	IDPB T3,PKTPTR		; Add to packet
>
IFNKA	<
	IDPB T1,PKTPTR		; Add to packet
>
IFN .TTYLG,<
	CALL LOGCHR		; Log it
>
	AOJA CNT,SNDTV4		; Count it up and try for another

;;; Here if we didn't get a charcter
SNDTV6:
IFNKA	<OKSKD1>		; Go OKSKED again
	JRST SNDTV9		; And join below

SNDTV5:	SETZRO TTOTP,(LINBLK)	; Clear output active bit

SNDTV9:	MOVE T1,CNT		; Return number in packet

SNDTVX:	RESTORE
	RET
; PRCTVT		Process TCP Virtual Terminal data

;T1/	Byte pointer into packet where to begin (index by TPKT)
;T2/	Pointer to dynamic line data block
;T3/	Maximum number of characters to do
;PKT/	Pointer to Internet portion of packet
;TPKT/	Pointer to TCP portion of packet
;TCB/	Locked connection block
;
;	CALL PRCTVT
;Ret+1:	Always.  Given number of characters have been moved.

PRCTVT::INTLAC <LINBLK,XFRCNT,PKTPTR>
	MOVEM T1,PKTPTR
	DMOVEM T2,LINBLK

PRCTV1:	SOJL XFRCNT,PRCTVX	; Jump if all done
	ILDB T1,PKTPTR		; Get a character
	MOVE T2,LINBLK		; Line block address
	LOAD T3,NVSTP,(T2)	; Current Telnet command state
	SETZRO NVSTP,(T2)	; Reset for normal dispatch next time
	PUSH P,LINBLK		; Some of these are crashed by TTYSRV
	PUSH P,XFRCNT		; or TELNET
	PUSH P,PKTPTR
	CALL @NVTSTD(T3)	; Dispatch to Telnet routine
	POP P,PKTPTR
	POP P,XFRCNT
	POP P,LINBLK
	JRST PRCTV1		; Do another
PRCTVX:	RESTORE
	RET
;CHKTVT - SEE IF THIS LINE NUMBER IS A TVT

;ACCEPTS:
;	T2/ INTERNAL LINE NUMBER

;	CALL CHKTVT

;RETURNS +1: IF NOT TVT
;	 +2: IF TVT

	RESCD

CHKTVT::
IFNKA <	ACVAR <W1>		;GET AN AC TO WORK WITH
	LOAD W1,TTSTY,(T2)	;GET LINE TYPE FOR THIS LINE
	CAIE W1,TT.TVT		;IS IT A TVT?
	RETBAD			;NO. FAILURE
	RETSKP			;RETURN SUCCESS
	ENDAV.			;END ACVAR
>

IFKA <	CAIL T2,TVTLO
	CAILE T2,TVTHI
	 RETBAD
	RETSKP
>



	SWAPCD
; TVTCHK	See if this line is a TCP Virtual terminal

;T2/	Internal line number
;
;	CALL TVTCHK
;Ret+1: Line not initialized.	T2  0	Inactive	Not locked, okint
;				T2 -1	Becoming active	Not locked, okint
;				T2 adr	Non-standard blk Locked, noint
;   +2:	Line initialized.	T2 adr	Std dynamic data Locked, noint

TVTCHK::
IFNKA <	CAIL T2,NLINES		; Legal terminal line number?
	 JRST TVTCH8		; TCP Never calls with non-TVT
	LOAD T1,TTSTY,(T2)	; Line type for this line
	CAIE T1,TT.TVT		; Is it a TVT?
	 JRST TVTCH8		; No.
>
IFKA <	CAIL T2,TVTLO
	CAILE T2,TVTHI
	 JRST TVTCH8
>
	CALL LCKTTY		; Get addr of dynamic data and lock
	 RET			; Line not initialized
	JRST TVTCHX		; Return with line blk addr in T2
TVTCH8:	TCPBUG(HLT,<TVTCHK called with non-TVT>,TVTNTV)
TVTCHX:	RETSKP
; TVTISP	Get number of holes in input buffer

;T2/	Pointer to line block
;
;	CALL TVTISP
;Ret+1:	Always.  Space available in T1

TVTISP::LOAD T1,TIMAX,(T2)	; Max capacity of line
	SUB T1,TTICT(T2)	; Less what is already there
	RET			; Gives amount left



; TVTOSP	Get number of bytes in output buffer

;T2/	Line block pointer
;
;	CALL TVTOSP
;Ret+1:	Always.  Number in T1.

TVTOSP::LOAD T1,TSALC,(T2)	; Sendall count plus
	SKIPE T1		; If sendall, bump count so
	  ADDI T1,1		; extra TTSND clears sndall info
	ADD T1,TTOCT(T2)	; regular count
IFNKA <	JE <TTSFG,TTRXF,TTSHT>,(T2),TVTOSX
	MOVEI T1,0		; Hung on ^S, say no avail for output
>
TVTOSX:	RET
; TVTDTS	Close a full duplex TCP virtual terminal connection
;		upon carrier-off
;
;T2/	Line number
;
;	CALL TVTDTS	(FNJRST off off TTVT19)
;Ret+1:	Always
	
	RESCD

TVTDTS:	CALL TVTDTT		; Detach the TVT
	 RET
	RET			; Success
; TVTDET	Detach a job from a TCP virtual terminal connection
; For TOPS20 TVTDET returns to caller's caller, TVTDTT returns to caller.
IFNKA <
;	Called from HLTJB when a job logs off

;T2/	Line number
;
;	CALL TVTDET	(FNCALL off of TTVT11, TTVT19)
;Ret+1:	Failure.  T1/	1B0 + Addr of routine if dismiss needed
;		  or,   Error code if failed
;Ret+2:	Success


TVTDET:	POP	P,0(P)		; Flush return address
;;; Here to not flush return 
TVTDTT:	SE1CAL			; Enter section 1
	SAVEPQ			; Save local ACs
	STKVAR <TVTDLN,TVTDAD>	; Space for line number and block addr
	MOVEM T2,TVTDLN		; Save the line number
	CALL TVTCHK		; See if this is a TVT
	 RETSKP			; Not assigned.  Return.
	MOVEM T2,TVTDAD		; Save addr of dynamic data area
	CALL CLRPRM		; Clear permanent bit, allowing deassign

	SKIPG TTNETW(T2)	; Is there a connection?
	 JRST TVTDE1		; No
	PUSH P,TCB
	LOAD TCB,PTVT,(T2)	; Get the TCB
	SETSEC TCB,INTSEC	; Make extended address

	JE TSUOP,(TCB),TVTDE0	; Already closed?
	XMOVEI T1,TCBLCK(TCB)	; Lock to lock
	XMOVEI T2,CLOSE1	; Function to call
	CALL LCKCAL		; Do a cross-job close
TVTDE0:
	SETZRO TVTL,(TCB)	; Prevent OPSCAN from finding this TCB
	POP P,TCB
	MOVE T2,TVTDAD		; Restore pointer to data block
TVTDE1:
	SETZM TTNETW(T2)	; Flush the connection
	LOAD T3,TCJOB,(T2)	; Get owning job
	CAIN T3,-1		; Is there one?
	 JRST TVTDT2		; No. Just go deallocate data block.
	MOVE T2,TVTDLN		; Get TTY line number
	MOVEI T1,.TTDES(T2)	; Make into device designator
	CALL CHKDES		; Get index to device tables
	 JRST [	MOVE T2,TVTDAD	; Get dynamic data address back
		CALL ULKTTY
		RETBAD]		; Invalid device designator?????
	SETZRO DV%OPN,DEVCHR(T2) ; Permit RELD at LGOUT to win
	MOVE T2,TVTDAD		; Dynamic data block address
	MOVE T1,TVTDLN		; Terminal line number
	CAMN T1,CTRLTT		; Controlling terminal for this job?
	 JRST TVTDT2		; Yes.  Go deassign database
	LOAD T3,TCJOB,(T2)	; Get owning job
	HLRZ T3,JOBPT(T3)	; Get controlling terminal of job
	CAME T1,T3		; Is this a controlling terminaL
	 JRST TVTDT2		; No.  Go detach it

; A job exists on this line and the net connection has been broken.
; Generate a carrier off PSI for the top fork.  This will cause the
; terminal data block to be deassigned.

	MOVE T2,TVTDLN		; Get line number
	NOSKD1
	CALL TVTCOF		; Start the carrier off action
	OKSKD1
	MOVE T2,TVTDAD		; Get address
	CALL ULKTTY		; Unlock the data block
	RETSKP			; And give a good return

; Deassign the terminal's data block

TVTDT2:	JE TTSAL,(T2),TVTDT3	; Doing a Send-All?
;	SETZRO TTSAL,(T2)	; No longer.
;	SOS SALCNT		; Now one less line doing it
;	SETZRO TSALC,(T2)	; Clear send-all count
;	SETZM TTSAL2(T2)	; Clear send-all pointer
	CALL CLRSAL		; Interrupt-proof decrement
TVTDT3:

	CALL ULKTTY		; Unshare the data block
	MOVE T2,TVTDLN		; TVT Line number
	MOVEI T1,.TTDES(T2)	; Form device designator
	CALL CHKDES		; Get index to device tables
	 RETBAD			; Invalid device designator????
	MOVEM T2,TVTDAD		; Save index to device tables
	MOVE T2,TVTDLN		; Get terminal line number
	CALL TTYDE0		; Deallocate the line
	 RETBAD			; Return error or test routine

	MOVE T2,TVTDAD		; Device table index
	HRROS DEVUNT(T2)	; Set owning job to -1
	SETZRO DV%ASN!DV%OPN,DEVCHR(T2) ; Not assigned or openned
	MOVE T2,TVTDLN		; Get line number
	CAME T2,CTRLTT		; Controlling terminal
	 RETSKP			; No.
	SETOM CTRLTT		; Yes. Indicate no terminal
	MOVE T2,JOBNO		; Get job number
	HRROS JOBPT(T2)		; This nob no longer has a terminal
	RETSKP

	ENDSV.
> ; end IFNKA
IFKA <

TVTDET::
TVTDTT:	PUSH P,T2
	SKIPL TTFORK(T2)	; Line attached?
	 CALL TVTCOF		; Yes, initiate carrier off psi
	MOVE T2,0(P)
	SKIPG TTNETW(T2)	; Reasonable units?
	 JRST TVTDT1		; No
	PUSH P,TCB
	LOAD TCB,PTVT,(T2)
	SETSEC TCB,INTSEC
	JE TSUOP,(TCB),TVTDE0
	XMOVEI T1,TCBLCK(TCB)
	XMOVEI T2,CLOSE1
	CALL LCKCAL
TVTDE0:	SETZRO TVTL,(TCB)
	POP P,TCB
TVTDT1:	POP P,T2
	SETZM NVTOPF(T2)
	SETOM TTNETW(T2)
	SETZM TTPSI(T2)
	CALL TTCOBI
	CALL TTCIBF
	RET
> ; end IFKA
IF1 <PRINTX %TVTIGA ABSENT
>
TVTIGA:	RET
IFKA <

  IF1 <PRINTX %TVTCAP ABSENT
  >

TVTCAP::RET


  IF1 <PRINTX %TVTCIB ABSENT
  >

TVTCIB::RET
>; END IFKA
; TVTOPR	Main routine to operate TVTs

;(no args)
;
;	CALL TVTOPR
;Ret+1:	Always.

TVTOPR::SKIPLE TVTNOF		; Output scan needed?
	  CALL OPSCAN		; Yes.  Signal PZ where possible

	MOVE T1,TODCLK		; Now
	CAML T1,TVTNTM		; Time for check on overdue
	  CALL TVTNCK		; Telnet negotiations

	MOVE T1,LSNTIM		; Get time for listening
	SKIPE TVTLSN		; if no socket
	 CAMG T1,TODCLK		; time for another stab?
	  CALL LISTEN		; Try a listen
	RET



; LISTEN	Set up a TCB listening on the TELNET port

;(No args)
;
;	CALL LISTEN
;Ret+1:	Always.  TVTLSN set ge 0 if error,  le 0 if OK.

LISTEN:	MOVE T1,FACTSW		;BROADCAST REQ
	TXNN T1,SF%NVT		; NVT logins allowed?
	 JRST LSN1		; No, Don't open
	MOVE T1,[TCP%PS+TCP%VT+TVTCDB]
	MOVEI T2,LSNTMO		; Timeout
	SETZ T3,		; Default re-transmission algorithm
	%OPEN%			; Do the listen
	 CAIA			; Don't save if failed
	  MOVEM T1,TVTLSN	; Save

;;; Join here if remote logins not allowed
LSN1:	MOVE T1,TODCLK		; Get clock
	ADDI T1,^D60000		; in one minute
	MOVEM T1,LSNTIM		; try again regardless
	RET			; Return 

TVTCDB:	BLOCK .TCPCS		; Connection block
.X==.
	RELOC TVTCDB+.TCPLP
	LSNPRT
	RELOC .X
	PURGE .X
; TVTOPN	Open a TCP Virtual Terminal; Called in Job-0 context

;TCB/	Pointer to TCB
;
;	CALL TVTOPN
;Ret+1:	Always, T1 zero if OK or error code (ELT+^D4) otherwise

TVTOPN::HRRZ T1,TCB		; Needs TCB
	TXO T1,AN%NTP		; Say it will speak new Telnet
	CALL ASNTVT		; Assign a virtual terminal
	  JRST TVTOP7		; Failed (not available, etc)
	STOR T1,TVTL,(TCB)	; Save in connection block
	PUSH P,T2		; Save line block address
	MOVE T2,T1		; Put line number in right place
	MOVEI T1,"C"-100	; Get a control-C to awaken the job
	NOSKD1
	CALL TVTCHI		; Type it for the guy
	  JFCL			; Ignore error return
	OKSKD1
	SETZM TVTLSN		; Get another listen done
	SETZM TVTNTM		; Get done quickly
	POP P,T2		; Restore line block address
	CALL ULKTTY		; Block now stable
	SETZ T1,		; No error
	JRST TVTOPX

TVTOP7:	MOVX T1,ELT+^D4		; Out of resources error
TVTOPX:	RET
; TVTCLS	Close a TCP Virtual Terminal

;T1/	Code for reason
;TCB/	Pointer to connection block
;
;	CALL TVTCLS
;Ret+1:	Always.

	RESCD
TVTCLS::INTLAC <CCODE>
	MOVEM T1,CCODE

	CAIE CCODE,XFP+^D12	; "Closing" or
	 CAIN CCODE,EFP+^D7	; "Connection error or rejected"
	  CAIA			; (other end restarted)
	   JRST TVTCL1		; No.  Something else

; Here when other end restarted and we received a RESET.
; PRCRST called [USRERR with EFP+^D7] ABTCON with EFP+^D7.
; Beware: it may be THE listening connection.

; Here when remote end is closing. We are in the process of sending
; and ACK for his FIN, but may not be done sending everything from
; this end yet -- for instance, "Detached job N ..." msg.
; So, get the job to clean itself up and call TVTDTS via TTHNGU
; (from FLOGO1 as called from JOBCOF by top fork of the job), or
; via TTYDEA as called from TTYDAS from LDTACH or HLTJB.

	LOAD T2,TVTL,(TCB)	; Get the line number
	JUMPE T2,TVTCL2		; TVT may not be assigned if during
	NOSKD1			;  OPEN (if so, need another listen)
	CALL TVTCOF		; Start the carrier off sequence
	OKSKD1
	JRST TVTCLX		; and leave

TVTCL1:	CAIN CCODE,XLP+^D3	; "Closed"
	 JRST TVTCL4		; Yes, just go detach it

	CAIN CCODE,ELT+^D4	; "No free terminals"
	  JRST TVTCL2		; Go fake CLOSE & release JCN

	CAIE CCODE,ELP+^D14	; "Connection reset" due to
				;  Retransmission timeout?
	 JRST TVTCLX		; No, Something else.  Ignore it.
; Here when a connection OPENed correctly but there were no free TVTs.
; PRCACK (or PRCSYN) called USREVT(OK) which called TVTOPN which
; called ASNTVT which failed.  TVTOPN tried to send a message and then
; a RST to the other end before calling ABTCON(ELT+^D4) which called
; USREVT(ELT+^D4) which called TVTCLS(ELT+^D4).  The state is NOT.NOT
; but we have to fake a CLOSE and release the JCN.

; Here when we have suffered a retransmission timeout on an open
; connection.  REXMIT called [USRERR with ELP+^D9, "RX timeout", and]
; ABTCON with ELP+^D14, "Connection reset", which made the connection
; dead (state is NOTSYN in both directions) and called USREVT with
; ELP+^D14 who called us.   All that remains is to get the job
; detached.   Note that the job may or may not be logged in.

TVTCL2:	SETZRO TSUOP,(TCB)	; Don't send a FIN

; If this is a valid Job0 JCN we are dealing with the LISTENing port.
; The "said open" bit tells whether the timeout happened while the
; connection was opening (must do another listen) or after it had
; opened (next listen is already in progress).

	JN TSOPN,(TCB),TVTCL4	; Jump if next listen already done
	LOAD T1,TJCN,(TCB)	; or if not a valid Job0
	CAIN T1,-1		; JCN
	  JRST TVTCL4
	SETZM TVTLSN		; Get another listen done
	SETZM TVTNTM		; Now.
TVTCL4:

	LOAD T2,TVTL,(TCB)	; Get line number
	SKIPE T2		; TVT not assigned if during open
	  CALL TVTDTS		; Detach owning job

	JN TOWNR,(TCB),TVTCL5	; Jump if TVT not owned by Job-0 (never)
	LOAD T1,TJCN,(TCB)	; Get our (Job-0) handle on the TCB
	CALL RETJCN		; Release it
	SETZRO TJCN,(TCB)	; (RETJCN can't do this if TJCN was -1)
TVTCL5:
TVTCLX:	RESTORE
	RET
	SWAPCD
; OPSCAN	Get packets sent on each connection with output waiting

;(no args)
;
;	CALL OPSCAN
;Ret+1:	Always.

; Following note is no longer valid since some TVTs may be owned
; by other jobs
; Note: TVT TCBs are owned by job-0 which includes the Internet fork
; which runs this code.  No user fork has (write) access to any of them.
; The TCB might, however, be locked by a user STAT JSYS.

OPSCAN:	INTLAC <TVTP,LINADR>
	PUSH P,TCB
	SETZM TVTNOF		; Clear the run request flag
	MOVE TVTP,TVTPTR	; AOBJN for all TVTs

	JFCL ;NOSKED		; Keep TCBs
OPSCA1:	HRRZ T2,TVTP		; Next line number
	CALL LCKTTY		; Lock and get dynamic area to T2, NOINT
	 JUMPLE T2,OPSCA8	; Non standard block
	MOVE LINADR,T2		; Save the terminal block ptr

	LOAD TCB,PTVT,(T2)	; Have a TCB?
	JUMPE TCB,OPSCA7	; Jump if not there (??)
	SETSEC TCB,INTSEC	; Make extended address
; Following should never jump
	JE TTVT,(TCB),OPSCA7	; Jump if not a TVT (??)
	LOAD T3,TVTL,(TCB)	; Get the line number
	JUMPE T3,OPSCA7		; USREVT released the TVT line (??)

	CALL TVSBE1		; Any output waiting?
	 SKIPA T4,T1		; Yes.  Get PZ to call SNDTVT
	  JRST OPSCA7		; No.

	MOVX T1,^D200		; The function to queue for PZ if a lot
	CAIGE T4,^D8		; Less that 8 is echoing so
	  MOVX T1,-1		; Run the packetizer "now"
	CALL DLAYPZ		; Schedule the packetizer

OPSCA7:	MOVE T2,LINADR		; Restore address of terminal block
OPSCA8:	CALL ULKTTY		; Decrease reference count, OKINT
OPSCA9:	AOBJN TVTP,OPSCA1	; Loop over all TVTs
	JFCL ;OKSKED
IFNKA <	SKIPE T2,TVMSTM		; Any TTMSG's out?
	CAMLE T2,TODCLK		; Yes, time to flush yet?
	 JRST OPSCAX		; No, return.
	NOSKED			; Prevent anyone from changing data
	CALL TVMNTR		; Flush all TTMSG's to TVTs
	OKSKED
	SETZM TVMSTM		; Clear timer
>
OPSCAX:	POP P,TCB
	RESTORE
	RET

;3051 begin addition
;TVRFIL - ROUTINE TO SIGNAL TVT BUFFER REFILL WHEN EMPTY
;CALLED FROM GTTCI
TVRFIL:	SKIPG TTNETW(T2)	;STILL CONNECTED TO NETWORK?
	 RET			;NO, NOTHING TO DO
	SAVET			;SAVE DYNAMIC DATA
	PUSH P,TCB		;SAVE TTYSRV CONTEXT
	NOSKED			;OWN THE SYSTEM
	SKIPL RA+PRCLCK		;IS REASSEMBLER RUNNING ALREADY?
	IFSKP.
	  LOAD TCB,PTVT,(T2)	;GET TCB IF EXISTS
	  IFN. TCB		;HAVE ONE?
            SETSEC TCB,INTSEC	;TCB'S ARE IN INTSEC
	    DO.
	      IFQE. TRCB,(TCB)	;RECV% BUFFER EXISTS?
	        LOAD T1,QNEXT,<+TCBRPQ(TCB)> ;NO, GET NEXT ITEM ON RA QUEUE
	        CAIN T1,TCBRPQ(TCB) ;IS RA QUEUE EMPTY?
	         EXIT.		;YES, NO NEED TO RUN REASSEMBLER
	      ENDIF.
	      $SIGNL(RA,20)	;RUN REASSEMBLER AFTER SHORT DELAY
            ENDDO.
	  ENDIF.
	ENDIF.
	OKSKED			;RETURN THE SYSTEM
	POP P,TCB		;RESTORE TTYSRV CONTEXT
	RET
;3051 end addition

IFKA <	TNXEND
	END
> ; end of IFKA

>	; End of IFN .TVFLG at start of file