;-*- Mode: MIDAS -*-
TITLE TIMSRV	; Net time server

GMTDIF==5	; # hours difference between local zone and GMT.

F=0		;TCP flag.
A=1
B=2
C=3

P=17

NETO==1
NETI==2

.INSRT KSC;MACROS >
LOC 42
	JSR TSINT
LOC 100
PAT:	BLOCK 20
PDL:	BLOCK 20
DEBUG:	0

ICPSOC==45	; Official ICP socket for Time Server.

	;Interrupt handler - mostly for fatal conditions
TSINT:	0
	0
	JSR LOGOUT		; Any interrupt is cause for death.

	; Start of program
GO:	MOVEI P,PDL	    ;init pdl pointer

	.SUSET [.RJNAME,,A]
	CAME A,[SIXBIT /TCP/]
	 JRST NCPICP
TCPICP:	SYSCAL TCPOPN,[ MOVEI NETI ? MOVEI NETO
		MOVEI ICPSOC ? [-1] ? [-1]]
	 JSR LOGOUT	    ; Failed (should timeout!)
	MOVEI B,3*30.	    ; Try for 30 sec
TCPIP1:	MOVEI A,10.
	.SLEEP A,
	SYSCAL WHYINT,[MOVEI NETO ? MOVEM A ? MOVEM A]
	 .LOSE %LSSYS
	CAIE A,%NSOPN
	 CAIN A,%NSRFN
	  CAIA
	   SOJG B,TCPIP1
	CAIG B,
	 JSR LOGOUT	    ; Timed out...
	SETO F,
	JRST SERVE	    ; Or got connected...

	;set timer to log out if icp not finished within 60 sec.
NCPICP:	MOVE A,[600000,,[60.*60.]]	;flush old ticks, start
	.REALT A,			;new rate, 60 sec frame(ints).
	 JFCL
	.SUSET [.SMASK,,[%PIRLT+%PIIOC]]	;enable ioc and realt
	.SUSET [.SPICLR,,[-1]]		;enable ints

	;start icp
	.OPEN NETO,[40060+.UIO,,'NET ? ICPSOC]	;open 32-bit listen on ICP socket.
	 JSR LOGOUT
	MOVEI A,NETO
	NETHANG 900.,A,%NSLSN,[%NSRFC]	;hang until rfc received
	 JSR LOGOUT
	.NETAC NETO,		;accept it
	 JSR LOGOUT
	MOVEI A,NETO
	NETHANG 900.,A,%NSRFC,[%NSOPN]	;wait until open
	 JSR LOGOUT
	SETZ F,

SERVE:	.RLPDTM A,		; Get in A, # secs since beg of year.
	CAME A,[-1]
	 CAMN B,[-1]
	  JSR LOGOUT		; If either is -1, time not known.
	CAIGE B,		; If 4.9 on,
	 SUBI A,24.*3600.	; subtract 1 day - .RLPDTM misfeature!
	TLNE B,100000		; Bit 4.7 = Daylight Savings time?
	 SUBI A,3600.		; If on, subtract one hour to get Standard.
	MOVEI B,-1900.(B)	; Get year, relative to 1900.
	MOVEI C,-1(B)		; Adjust and
	LSH C,-2		; Get # leap years since 1900
				; not including this year.
	IMULI B,365.		; Find # days in years thus far
	ADDI B,(C)		; Plus # LY's, to get total days in years past.
	IMULI B,86400.		; Now get # seconds in all them days.
	ADD A,B			; and produce total seconds since 1/1/00 !
	ADD A,[GMTDIF*3600.]	; Adjust to GMT.
	SKIPN F			; If connected via NCP
	 JRST [	.IOT NETO,A	; Send out a word of the 32-bit time.
		JRST SRVDUN ]
	MOVE B,[401000,,A]	; If connected via TCP
	MOVEI C,4.		; Send four 8-bit bytes of the 32-bit time.
	SYSCAL SIOT,[MOVEI NETO ? B ? C]
	 JSR LOGOUT
SRVDUN:	.NETS NETO,		; Force the output.
	.CLOSE NETO,		; Disconnect.
	CAIA
LOGOUT:	0
	SKIPE DEBUG
	 .VALUE
	.LOGOUT			; All done

END GO
