	.title	K11REC	recieve processing
	.ident	/T2.23/
	.include	/IN:K11MAC.MAC/
	.include	/IN:K11DEF.MAC/
	.psect
	.enabl	gbl

;	13-Oct-84  14:06:43  Brian Nelson
;
;	Creation: Moved from K11PAK
;
;
;	Copyright (C) 1983 1984   Change Software, Inc.
;	
;	
;	This software is furnished under a license and may
;	be  used  and  copied  only in accordance with the
;	terms of such license and with  the  inclusion  of
;	the  above copyright notice.  This software or any
;	other copies thereof may not be provided or other-
;	wise made available to any other person.  No title
;	to and ownership of the software is hereby  trans-
;	ferred.
;	
;	The information in this  software  is  subject  to
;	change  without notice and should not be construed
;	as a commitment by the author.
;
;
	.sbttl	recsw	state table controller for receiving files

recsw::	clr	paknum			; packet_number := 0
rec.sw::movb	@r5	,state		; assume RECEIVE-INIT for starters
	clr	cccnt			; control_c_count := 0
	mov	$image	,image		; insure correct default for mode
	movb	#defchk	,chktyp		; reset checksum type to default
	mov	#1	,chksiz		; the size of the checksum
	clr	numtry			; number_trys   := 0
	clr	oldtry			; 
	add	pcnt.r+2,reccnt+2	; /43/ Save rec packet count
	adc	reccnt+0		; /43/ 32 bits today
	add	pcnt.r+0,reccnt+0	; /43/ 32 bits in the total
	call	clrsta			; clear the stats out now
	clr	outopn			; say nothing is open now
	tst	remote			; local or remote
	bne	5$			; remote
	call	ttrini			; perhaps special init for local tt:
5$:	call	rechdr
	call	incsta			; /43/ Timer stats init

10$:	call	recdeb			; perhaps debugging should be done
	tst	remote			; /43/ Control C and a server?
	bne	20$			; /43/ Yep, ignore random noise.
	tst	cccnt			; /36/ control C abort ?
	beq	20$			; /36/ no
	movb	#STA.CCABO,state	; /36/ yes, enter ABORT state
20$:	scan	state	,#200$		; case state of
	asl	r0			; dispatch to correct routine
	jsr	pc	,@210$(r0)
	bcc	10$


100$:	movb	#defchk	,chktyp		; reset type of checksum to 1
	mov	#1	,chksiz		; the size of the checksum
	save	<r0>			; insure files are closed
	tst	remote			; remote or local
	bne	105$			; remote
	call	ttrfin			; local, perhaps clean up console
105$:	tst	outopn			; file open from a failure ?
	bpl	110$			; no
	calls	close	,<#lun.ou>	; insure that it's closed
110$:	clr	outopn
	call	incsta			; /43/ Timer stats init
	unsave	<r0>			; pop exit status code please
	return

200$:	.byte	STA.RIN	,STA.FIL,STA.DAT,STA.COM,STA.ABO,STA.CCABO,0
	.even
210$:	.word	recs.$
	.word	recs.r	,recs.f	,recs.d	,recs.c	,recs.a, ccabort



recs.$:	clc				; Unknown state
	return				; back to caller

recs.r:	call	rinit			; receive-init
	movb	r1	,state		; set state and exit
	clc				; saying there is more to come
	return				; bye

recs.f:	call	rfile			; receive-file
	movb	r1	,state
	clc
	return

recs.d:	call	rdata			; receive-data
	movb	r1	,state
	clc
	return

recs.c:	clr	r0			; complete
	sec
	return

ccabort:strlen	#ccmsg0			; /43/ Send msg text over
	spack	#MSG$ERROR,paknum,r0,#ccmsg0 ; /36/ break out the sender please
recs.a:	mov	sp	,r0		; abort
	sec
	return

ccmsg0:	.asciz	/Control C abort on file receive/
	.even

	global	<cccnt	,chktyp	,outopn	,remote	,state	,ttrfin	,ttrini>


	.sbttl	debugging and logging for receive



recdeb:	save	<r1,r2>
	sub	#50	,sp
	mov	sp	,r1		; allocate a small buffer
	mov	#200$	,r2		; point to a header
10$:	movb	(r2)+	,(r1)+		; copy a header please
	bne	10$			; until we find a null
	dec	r1			; all done
	movb	state	,(r1)+		; copy the current state over
	movb	#40	,(r1)+		;
	sub	sp	,r1		; get the record length
	mov	sp	,r0		; and point back to the record
	bit	#log$st	,trace		; debugging for RECSW
	beq	30$			; if trace is on then dump the
	calls	putrec	,<r0,r1,#lun.lo>; dump it
30$:	tst	debug			; terminal debugging on ?
	beq	40$			; no
	print	r0	,r1
	.newli				; and a crlf

40$:	tst	remote			; running locally ?
	bne	100$			; no
	tst	xmode			; simply printing text to ti: ?
	bne	100$			; yes, skip the packet stats then
	call	reclog
	
100$:	add	#50	,sp
	unsave	<r2,r1>
	return

200$:	.asciz	/Recsw - state is /
	.even

	global	<reccnt	,pcnt.r	,pcnt.s	,state	,trace	,xmode>


	.sbttl	rinit	receive initialization


;	R I N I T
;
;	input:	nothing

	.enabl	lsb


rinit:	save	<r2,r3,r4>		; get registers we use saved
	inc	numtry			; check for retry count
	cmp	numtry	,maxtry		; been here too often ?
	blos	10$			; no
	 call	m$retry			; log/send the reason for the abort
	 movb	#STA.ABO,r1		; yes, return ABORT state
	 br	100$


10$:	rpack	r2,r3,#packet		; get the next packet please
	scan	r1,#200$		; look for the packet type
	asl	r0			; and dispatch to it
	jsr	pc	,@210$(r0)	; simple
100$:	unsave	<r4,r3,r2>
	return

200$:	.byte	MSG$SND	,MSG$ERROR,TIMOUT,BADCHK,0
	.even
210$:	.word	rini.$
	.word	rini.S	,rini.E	,rini$$	,rini$$

	.dsabl	lsb


rini.$:					; unknown packet type
rini$$:	spack	#MSG$NAK,paknum		; error, send a NAK
	movb	state	,r1		; and exit
	return

rini.e:	calls	prerrp	,<#packet>
	movb	#STA.ABO,r1
	return

rini.s:	calls	rpar	,<#packet,r2>	; SEND-INIT
	calls	spar	,<#packet>	; get other sides init and fill with
	spack	#MSG$ACK,paknum,sparsz,#packet; ours
	mov	numtry	,oldtry
	clr	numtry
	incm64	paknum			; paknum := (paknum+1) mod 64
	call	inirepeat		; initialize repeat processing
	movb	#STA.FIL,r1		; state  := FILE-RECEIVE
	return



	.sbttl	rfile	receive file header



rfile:	save	<r2,r3,r4>		; get registers we use saved
	call	clratr			; insure attribute stuff is cleared
	movb	conpar+p.chkt,chktyp	; time to use new checksum ?
	movb	chktyp	,chksiz		; compute the checksum size also
	sub	#'0	,chksiz		; simple
	mov	$image	,image		; insure correct default for mode
	inc	numtry			; check for retry count
	cmp	numtry	,maxtry		; been here too often ?
	blos	5$			; no
	 call	m$retry			; log why we aborted please
	 movb	#STA.ABO,r1		; yes, return ABORT state
	 br	100$
5$:	tst	xgottn			; already get the x packet ?
	beq	10$			; no
	movb	#STA.TYP,r1		; yes, fake that we already got it
	br	20$


10$:	rpack	r2,r3,#packet		; get the next packet please
20$:	scan	r1,#200$		; look for the packet type
	asl	r0			; and dispatch to it
	jsr	pc	,@210$(r0)	; simple
100$:	unsave	<r4,r3,r2>
	return


200$:	.byte	MSG$SND	,MSG$EOF,MSG$FILE,MSG$BREAK,MSG$ERROR,MSG$TEXT
	.byte	timout	,badchk	,0
	.even

210$:	.word	rfil.$
	.word	rfil.s	,rfil.z	,rfil.f	,rfil.b	,rfil.e	,rfil.x
	.word	rfil$$	,rfil$$




	.sbttl	more rfile



rfil.$:					; unknow packet type
rfil$$:	spack	#MSG$NAK,paknum		; timeout or checksum error, send
	movb	state	,r1		; NAK and continue in current state
	return


rfil.b:	cmp	r3	,paknum		; Break XMIT (EOT)
	beq	10$			; insure BREAK is for current packet
	 call	m$synch			; for abort, say we are out of synch
	 movb	#STA.ABO,r1		; no, return 'ABORT"
	 return				; exit


10$:	spack	#MSG$ACK,paknum		; ACK the BREAK
	movb	#STA.COM,r1		; and return state as 'COMPLETE'
	return


rfil.e:	calls	prerrp	,<#packet>	; error packet, print it out
	movb	#STA.ABO,r1		; return 'ABORT'
	return


rfil.s:	inc	oldtry			; SEND-INIT, must have lost ours
	cmp	oldtry	,maxtry		; tried this too many times ?
	blos	10$			; no
	 call	m$retry			; log the reason for the abort
	 movb	#STA.ABO,r1		; yes, return 'ABORT'
	 return

10$:	mov	paknum	,r1		; see if thispacket=(paknum+63) mod 64
	add	#77	,r1		; ie, check if this data packet was the
	clr	r0			; one sent the last time. if so, we
	div	#100	,r0		; must reack that packet and remain
	clr	r0			; in the current state.
	cmp	r3	,r1		; 
	bne	20$			; no
	 calls	spar	,<#packet>	; resend our SEND-INIT stuff
	 spack	#MSG$ACK,r3,sparsz,#packet ; reack this then

	 clr	numtry			; clear out retry counter
	 movb	state	,r1		; and return current state
	 return

20$:	 call	m$synch			; log the reason for this event please
	 movb	#STA.ABO,r1		; otherwise return ABORT since we must
	 return				; be way out of synch then.

rfil.z:	inc	oldtry			; END-OF-FILE ?
	cmp	oldtry	,maxtry		; tried this too many times ?
	blos	10$			; no
	 call	m$retry			; log the reason for this event
	 movb	#STA.ABO,r1		; yes, return 'ABORT'
	 return

10$:	mov	paknum	,r1		; see if thispacket=(paknum+63) mod 64
	add	#77	,r1		; ie, check if this data packet was the
	clr	r0			; one sent the last time. if so, we
	div	#100	,r0		; must reack that packet and remain
	clr	r0			; in the current state.
	cmp	r3	,r1		; 
	bne	20$			; not the last one after all
	 spack	#MSG$ACK,r3		; reack this then
	 clr	numtry			; clear out retry counter
	 movb	state	,r1		; and return current state
	 return

20$:	 call	m$retry			; log the reason for this please
	 movb	#STA.ABO,r1		; otherwise return ABORT since we must
	 return				; be way out of synch then.




	.sbttl	more rfile subroutines


;	Move the actual file create to RDATA so we can create
;	the output file after all attribute packets have come.
;	Thus, when we get the first DATA packet is when we go
;	and create the file.
;
;	18-Apr-84  10:24:45  Brian Nelson



rfil.f:	cmp	r3	,paknum		; FILE name
	beq	10$			; insure correct packet numer
	 call	m$synch			; log the reason for this ABORT
	 movb	#STA.ABO,r1		; no, return 'ABORT'
	 return				; bye

10$:	calls	fixfil	,<#packet,#srcnam>; check for invalid chars
	tst	r0			; was the filname ok ?
	beq	15$			; yes
	calls	printm	,<#3,#packet,#200$,#srcnam>
15$:	calls	fparse	,<#srcnam,#filnam>; parse and fill in defaults
	tst	r0			; /42/ Successful $PARSE?
	bne	100$			; /42/ No
	tst	outopn			; output already open as if from
	bpl	20$			; a NAK or something
	calls	close	,<#lun.ou>	; yes, close it please
20$:	clr	outopn			; it's closed
	spack	#MSG$ACK,paknum		; please ack the fileheader packet
	mov	numtry	,oldtry		; update number of retrys
	clr	numtry			; and init the current retry count
	incm64	paknum			; paknum := (paknum+1) mod 64
	movb	#STA.DAT,r1		; return 'DATA'
	return

100$:	calls	syserr	,<r0,#errtxt>	; /42/ no, get the system error text
	calls	error	,<#3,#230$,#errtxt,r4> /42/
	movb	#STA.ABO,r1		; /42/ return 'ABORT'
	return


200$:	.asciz	/ was renamed to /
230$:	.asciz	/RMS $PARSE failed /	; /42/
	.even


rfil.x:	cmp	r3	,paknum		; X header name
	beq	10$			; insure correct packet numer
	 movb	#STA.ABO,r1		; no, return 'ABORT'
	 return				; bye
10$:	spack	#MSG$ACK,paknum		; ACK the filename
	clr	outlun			; not a real file to output to
	clr	outopn			; nothing is open for output
	mov	sp	,xmode		; flag this also please
	mov	numtry	,oldtry		; update number of retrys
	clr	numtry			; and init the current retry count
	incm64	paknum			; paknum := (paknum+1) mod 64
	movb	#STA.DAT,r1		; return 'DATA'
	return


	global	<filnam	,errtxt	,numtry	,oldtry	,packet	,paknum>
	global	<outlun>



	.sbttl	rdata	receive data from pc


;	R D A T A
;
;	input:	nothing
;	output:	global	paknum	packet number
;			oldtry	retry count
;			packet	packet just received
;			numtry
;		r1	returned state




rdata:	save	<r2,r3,r4>
	clr	datauk			; /43/ Unknown/out synch NAK count
	clr	r0			; error := 0
	inc	numtry			; abort of retry count is too large
	cmp	numtry	,maxtry		; been here too many times ?
	blos	10$			; no
	call	m$retry			; log/send error message about it
	movb	#STA.ABO,r1		; yes, return state(abort)
	br	100$			; bye

10$:	rpack	r2,r3,#packet		; get the next imcoming packet
	scan	r1	,#200$		; look for the packet type and dispatch
	asl	r0			; to the correct routine. ie, a crude
	jsr	pc	,@210$(r0)	; case statement
100$:	unsave	<r4,r3,r2>
	return


200$:	.byte	MSG$ATR	,MSG$DATA,MSG$ERROR,MSG$FILE,MSG$EOF,MSG$TEXT
	.byte	timout	,badchk	,0
	.even
210$:	.word	rdat.$
	.word	rdat.a	,rdat.d	,rdat.e	,rdat.f	,rdat.z	,rdat.x
	.word	rdat$$	,rdat$$

	global	<numtry	,oldtry	,packet	,paknum	,state	>

	.sbttl	rdata packet handlers




rdat.d:	tst	xmode			; do we need to create the file
	bne	1$			; no
	tst	outopn			; did we already open the file up?
	bne	1$			; yes, please don't try again then.
	tst	filprot			; no supercede on file creates ?
	beq	2$			; no
	clr	-(sp)			; yes, check for the file already
	mov	sp	,r0		; there please
	calls	lookup	,<#3,#filnam,r0,#srcnam>
	tst	(sp)+			; pop context for lookup
	tst	r0			; did we find the file today?
	bne	2$			; no
	calls	printm	,<#2,#250$,#filnam>
	spack	#MSG$ACK,paknum,#1,#220$; yes, send ack with X in data
	incm64	paknum			; increment packet number mod 64
	clr	numtry			; /48/
	mov	#1	,outopn		; never really opened it up
	movb	#STA.DAT,r1		; switch to data state
	return				; bye

1$:	br	10$

2$:	mov	#filnam	,r4		; /36/ setup address of file
	tstb	asname			; /36/ use alternate name for file?
	beq	3$			; /36/ nothing there
	calls	fparse	,<#asname,r4>	; /37/ insure defaults are inserted
	tst	r0			; /37/ is parse successful
	bne	4$			; /37/ no, exit
3$:	calls	create	,<r4,#lun.ou,image>; /36/ now create it
	clrb	asname			; /36/ one shot for alternate name
	mov	#lun.ou	,outlun		; set a real LUN for output
	tst	r0			; did the file create work ?
	beq	5$			; yes
4$:	calls	syserr	,<r0,#errtxt>	; no, get the system error text
	tst	remote			; /51/ Are we LOCAL or Remote
	bne	444$			; /51/ We must be the server
	strlen	#errtxt			; /51/ We are local, get the
	spack	#MSG$ERR,paknum,r0,#errtxt ; /51/ Other side to STOP.
444$:	calls	error	,<#3,#230$,#errtxt,r4> /36/
	movb	#STA.ABO,r1		; return 'ABORT'
	return


5$:	calls	fillog	,<#0,r4>	; /36/ log to disk perhaps ?
	calls	printm	,<#2,#240$,r4>	; /36/ log to terminal perhaps?
	mov	#-1	,outopn		; flag output as being open

10$:	cmp	r3	,paknum		; case "D"
	beq	40$			; Correct packet number ?
	inc	oldtry			; no, see if retry limit expired
	cmp	oldtry	,maxtry		; if so, return ABORT
	blos	20$			; no
	 call	m$retry			; log/send notice of what happened
	 movb	#STA.ABO,r1		; yes, return 'ABORT'
	 return				; bye

20$:	mov	paknum	,r1		; see if thispacket=(paknum+63) mod 64
	add	#77	,r1		; ie, check if this data packet was the
	clr	r0			; one sent the last time. if so, we
	div	#100	,r0		; must reack that packet and remain
	clr	r0			; in the current state.
	cmp	r3	,r1		; insure r0 is not affected
	bne	30$			; not the last packet
	 spack	#MSG$ACK,r3		; reack this then
	 clr	numtry			; clear out retry counter
	 movb	state	,r1		; and return current state
	 return

30$:	 call	m$synch			; log/send the reason for the abort
	 movb	#STA.ABO,r1		; otherwise return ABORT since we must
	 return				; be way out of synch then.


40$:	add	r2	,charin+2	; /43/ Stats
	adc	charin+0		; /43/ In 32 bits please
	calls	bufemp	,<#packet,r2>	; correct packet, get the data out
	tst	r0			; did BUFEMP return any errors?
	beq	41$			; no
	calls	syserr	,<r0,#errtxt>	; it failed, send error packet
	calls	error	,<#2,#200$,#errtxt>
	br	100$			; take the abort exit please

41$:	tst	remote			; are we a local kermit today ?
	bne	70$			; no, just ack normally
	tst	cccnt			; we are local. check for control
	bne	60$			; c abort for this file please
	call	chkabo			; check for abort via ^X and ^Z
	cmpb	r0	,#ABT$ERROR&37	; control E aborts NOW
	beq	60$			; yes, abort please
	cmpb	r0	,#ABT$ALL&37	; did the user type a control Z?
	beq	50$			; yes
	cmpb	r0	,#ABT$CUR&37	; no, what about a control X then?
	bne	70$			; no

45$:	spack	#MSG$ACK,paknum,#1,#220$; ^X typed, send an X in the data
	br	80$
50$:	spack	#MSG$ACK,paknum,#1,#210$; yes, send an ACK with "Z" data
	br	80$			;
60$:	spack	#MSG$ERROR,paknum	; break the sender out please
	clr	cccnt			; /36/ clear control C flag
	br	100$			; bye

70$:	spack	#MSG$ACK,paknum		; ack it
80$:	mov	numtry	,oldtry		; oldtry_count:= numtry
	clr	numtry			; numtry := 0
	incm64	paknum			; increment packet number mod 64
	movb	#STA.DAT,r1		; switch to data state
	return				; bye

100$:	mov	#STA.ABO,r1		; abort for some reason
	return


	global	<chkabo	,errtxt	,numtry	,oldtry	,packet	,paknum	,state	>
	global	<filpro>


200$:	.asciz	/Local KERMIT error: /
210$:	.byte	ABT$ALL	,0
220$:	.byte	ABT$CUR	,0
230$:	.asciz	/Create failed - /
240$:	.asciz	/Created file - /
250$:	.asciz	/File exists, not superceded - /
	.even




	.sbttl	rdata subroutines, continued

					; 'F', got a FILE HEADER
rdat.x:					; 'X', also handle EXTENED REPLY
rdat.f:	inc	oldtry			; no, see if retry limit expired
	cmp	oldtry	,maxtry		; if so, return ABORT
	blos	10$			; no
	 call	m$retry			; log/send the reason for the abort
	 movb	#STA.ABO,r1		; yes, return 'ABORT'
	 return				; bye

10$:	mov	paknum	,r1		; see if thispacket=(paknum+63) mod 64
	add	#77	,r1		; ie, check if this data packet was the
	clr	r0			; one sent the last time. if so, we
	div	#100	,r0		; must reack that packet and remain
	clr	r0			; in the current state.
	cmp	r3	,r1		; 
	bne	20$			; not the last packet
	 spack	#MSG$ACK,r3		; reack this then
	 clr	numtry			; clear out retry counter
	 movb	state	,r1		; and return current state
	 return

20$:	call	m$synch			; log/send the reason for the abort
	movb	#STA.ABO,r1		; else return ABORT
	return


rdat.e:	calls	prerrp	,<#packet>	; flag error, print it
	movb	#STA.ABO,r1		; return ABORT
	return

rdat.z:	cmp	paknum	,r3		; END OF FILE. If not correct packet
	beq	10$			; the return 'ABORT'
	 call	m$synch			; log/send the reason for the abort
	 movb	#STA.ABO,r1		; switch to abort state
	 return				; and exit

10$:	mov	#lun.ou	,r2		; assume that we close a disk file
	tst	outopn			; real output or to the terminal
	bmi	20$			; it's a for real disk file today
	bgt	30$			; open was aborted via fileprotection
	clr	r2			; no, it's the console terminal
20$:	calls	close	,<r2>		; do the close now
	call	clratr			; attributes no longer valid
30$:	clr	outopn			; flag it
	spack	#MSG$ACK,r3		; acknowledge the eof packet
	mov	numtry	,oldtry		; /48/
	clr	numtry			; /48/
	incm64	paknum			; paknum := (paknum+1) mod 64
	movb	#STA.FIL,r1		; back to receive file state
	clr	xgottn			; don't have an X packet anymore
	return

rdat.$:	inc	datauk			; /43/ Unknown packet type
	cmp	datauk	,#2		; /43/ Been here too often ?
	blo	rdat$$			; /43/ No, simply NAK it
	strlen	#200$			; /43/ Yes, send error packet
	spack	#MSG$ERROR,paknum,r0,#200$ ; /43/ ...
	movb	#STA.ABO,r1		; /43/ Exit please
	return

200$:	.asciz	/Expecting ACK, packet type not valid in current RDATA state/
	.even

rdat$$:	spack	#MSG$NAK,paknum		; timed out or checksum error
	movb	state	,r1		; NAK it and return current state
	return

	global	<outopn	,paknum	,state	,xgottn	,clratr>
	global	<datauk>



	.sbttl	receive data attribute packets



rdat.a:	cmp	r3	,paknum		; case "A"
	beq	40$			; Correct packet number ?
	inc	oldtry			; no, see if retry limit expired
	cmp	oldtry	,maxtry		; if so, return ABORT
	blos	20$			; no
	 call	m$retry			; log/send the reason for the abort
	 movb	#STA.ABO,r1		; yes, return 'ABORT'
	 return				; bye

20$:	mov	paknum	,r1		; see if thispacket=(paknum+63) mod 64
	add	#77	,r1		; ie, check if this data packet was the
	clr	r0			; one sent the last time. if so, we
	div	#100	,r0		; must reack that packet and remain
	clr	r0			; in the current state.
	cmp	r3	,r1		; insure r0 is not affected
	bne	30$			; not the last packet
	 spack	#MSG$ACK,r3		; reack this then
	 clr	numtry			; clear out retry counter
	 movb	state	,r1		; and return current state
	 return

30$:	 movb	#STA.ABO,r1		; otherwise return ABORT since we must
	 return				; be way out of synch then.

40$:	calls	r$attr	,<#packet>	; simple
	tst	r0			; was this successful ?
	bne	50$			; no
	spack	#MSG$ACK,paknum
	mov	numtry	,oldtry		; oldtry_count:= numtry
	clr	numtry			; numtry := 0
	incm64	paknum			; increment packet number mod 64
	movb	state	,r1		; retain current state
	br	100$			; all done

50$:	movb	#STA.ABO,r1		; new state
	br	100$			; bye

100$:	return				; exti


200$:	.asciz	/Attribute packet error - /
	.even


	.end
