;----------------------------------------------------------------------------
;File name:	M_MASTER.S			Revision date:	2000.07.05
;Creator:	Ulf Ronald Andersson		Creation date:	1999.05.15
;(c)1999 by:	Ulf Ronald Andersson		All rights reserved
;----------------------------------------------------------------------------
	include	RA_APP.I	;General application support
	include	RA_SIM.I	;Simulation of form_alert for TOS programs
	include	RA_JAR.I	;Cookie jar handling
	include	RA_AV.I		;AV/VA protocol + MP protocol
;
	include	sting\PORT.I
	include	sting\LAYER.I
	include	sting\TRANSPRT.I
	include	sting\DOMAIN.I
;----------------------------------------------------------------------------
	output	.APP
;----------------------------------------------------------------------------
	struct	masq_port
	d_s	masq_port_main,sizeof_prt_des	;as defined in PORT.SH
	struc_p	masq_port_ptr			;-> port to be masked
	uint32	masq_port_ip			;ip number for masking it
	uint32	masq_port_ISP_ip		;masked ip number
	d_end	masq_port
;----------------------------------------------------------------------------
UNDETERMINED_IP		=	0
MASQ_MASTER_PORT	=	'MM'
MASQ_INFO_IP		=	$0A00FF49
MASQ_INFO_PORT		=	'MI'
MAX_VA_ARGLEN		=	128
;----------------------------------------------------------------------------
;;;huge_program	set 1		;uncomment if TEXT+DATA sections are > 32KB
;;;keep_windows	set 1		;uncomment to keep ACC vwk in main eventloop
;;;exec_timeout	set 1000	;uncomment to enable timer in main eventloop
exec_message	set 1		;uncomment for messages in main eventloop
;----------------------------------------------------------------------------
M_ALHDR	MACRO
	dc.b	'STinG  M_Master (2000.07.05) |'
	dc.b	'-----------------------------|'
	ENDM
;----------------------------------------------------------------------------
	SECTION	TEXT
	start_app		;expand startup code from RA_APP.I
;----------------------------------------------------------------------------
	IFEQ	huge_program
	SECTION	DATA
	ENDC
;----------------------------------------------------------------------------
acc_name:
	dc.b	'  Lookup Masked IP',NUL	;for ACC menu registration
	dc.b	NUL
	even
;
id_app_name_s:
	dc.b	'M_MASTER',NUL
	even
;
;----------------------------------------------------------------------------
	IFEQ	huge_program
	SECTION	BSS
	ENDC
;----------------------------------------------------------------------------
message:	ds.w	8		;evnt_mesag message pipe
intin:		ds.w	30		;30 words or more for AES/VDI
intout:		ds.w	45		;45 words or more for AES/VDI
ptsin:		ds.w	30		;30 words or more for VDI
ptsout:		ds.w	12		;12 words or more for VDI output coordinates
		ds.l	200		;subroutine stack >= 100 longs
mystack:	ds.l	1		;top of subroutine stack
;----------------------------------------------------------------------------
	SECTION	TEXT
;----------------------------------------------------------------------------
;	Constants, Variables, and Usage of the RA_APP.I library
;
;rz		'relative zero' for internal references
;basepage_p	-> program's base page
;tsr_size	.L size of BASEPAGE+TEXT+DATA+BSS  (only TOS/TTP may TSR)
;progtype	.L indicates program type:
;  ...			$0000.$FFFF == TOS/TTP/boot_PRG
;  ...			$0000.ap_id == APP/GTP/non_boot_PRG
;  ...			$FFFF.ap_id == ACC
;acc_flag	is the high word of 'progtype'
;tos_flag	is the low word of 'progtype'
;bootflag	.W $FFFF == PRG booted from AUTO (also sets 'tos_flag')
;menu_id	.W menu id for an ACC, otherwise null
;g_handle	.W workstation handle for ACC/APP/GTP/non_boot_PRG
;vwk_handle	.W virtual workstation handle
;contrl		12 words for AES/VDI control data
;
;wk_x_rez \
;wk_y_rez  \/ from
;wk_pix_w  /\ opnvwk
;wk_pix_h /
;
;MiNT_p		.L NULL or -> MiNT structure
;MagX_p		.L NULL or -> MagX structure
;nAES_p		.L NULL or -> nAES structure
;Gnva_p		.L NULL or -> Gnva structure
;
;line_a_base_p	.L -> line_a variable base
;kbshift_p	.L -> kbshift byte of OS
;currbp_p_p	.L -> OS var -> current basepage
;
;NB: if symbol 'huge_program' is defined, above data is in TEXT section (else in BSS)
;NB: defining 'huge_program' also makes function calls use 'jsr' (instead of bsr)
;
;Required user routines:
;
;init_app	called for ACC/APP/GTP/non_boot_PRG to init application,
;		but doesn't need appl_init, graf_handle, or v_opnvwk,
;		nor does an ACC need menu_register.
;		Suitable use is for initialization of object trees.
;NB:  for ACC	menu_register is called between init_app and exec_app
;
;exec_app	called to execute the main application regardless of type,
;		but doesn't need v_clsvwk, or appl_exit, or ACC appl_mesag.
;		This call will be repeated for a reactivated ACC.
;		Non_acc programs should have exit code in d0 at RTS.
;		(See details at 'Exit codes:' below)
;
;	At entry to either of these two routines:
;
;		d6.W	== bootflag	\
;		d7.L	== progtype	 > See descriptions above.
;		a6.L	== rz		/
;
;Optional user routines:
;
;exec_timer	Called for ACC that has a defined constant 'exec_timeout',
;		whenever evnt_multi produces such a timer event.
;		The constant is placed as long at 'main_timeout', and may
;		there be dynamically adjusted by the program.
;
;exec_mesag	Called for ACC that has a defined constant 'exec_message',
;		whenever evnt_multi/evnt_mesag produces messages that are
;		not AC_OPEN  (such as VA_START).
;
;		If the constant 'keep_windows' is also set, the workstation
;		will not be closed at each return (you must obey AC_CLOSE).
;		This places a word == $FF00 at 'keep_wind_f', and if the top
;		byte is cleared the workstation closure is enabled again.
;
;NB:	Top bit of the word 'revise_type_f' is used for 3 purposes:
;   1:	Let ACC start 'exec_app' directly without awaiting event.
;   2:	Let APP delay 'exec_app' until an event occurs.
;   3:	Let APP loop back for more events after 'exec_app'
;The flag must be set by 'init_app' in the first two cases, and in case 3
;should be set/cleared in 'exec_app' to decide whether to exit program.
;
;Exit codes:	At exit from exec_app, d0 has the following effects
;		when the program was not started as accessory.
;
; negative	=> Pterm(d0)			=> error code exit
; 0		=> Pterm(d0)			=> error free exit
; 0x0000ADD0	=> Ptermres(tsr_size,0)		=> error free resident exit
; 0x0000ADD1	=> Ptermres(d1,0)		=> error free resident exit
; 0x0000ADD2	=> Ptermres(d1,d2)		=> error code resident exit
;----------------------------------------------------------------------------
;Start of:	init_app
;----------------------------------------------------------------------------
init_app:
	st		fatal_f			;assume fatal errors can happen
	gemdos		Super,0.w
	move.l		d0,d4
	eval_cookie	#"STiK"
	move.l		d0,d3			;d3 = d0 -> DRV_LIST structure
	gemdos		Super|_ind,d4
	move.l		d3,sting_drivers	;sting_drivers -> DRV_LIST structure
	ble.s		.STiK_not_found
	move.l		d3,a3			;a3 -> DRV_LIST structure
	lea		DRV_LIST_magic(a3),a0
	lea		STiKmagic_s(pc),a1
	moveq		#10-1,d0
.strcmp_loop:					;loop to test STiKmagic of DRV_LIST
	cmpm.b		(a0)+,(a1)+
	dbne		d0,.strcmp_loop
	bne.s		.STiK_not_valid
;
	move.l		DRV_LIST_get_dftab(a3),a0	;a0 -> get_dftab function
	pea		TRANSPORT_DRIVER_s		;-(sp) = "TRANSPORT_TCPIP"
	jsr		(a0)				;call get_dftab
	addq		#4,sp
	move.l		d0,tpl				;store pointer in 'tpl'
	ble.s		.driver_not_valid
;
	move.l		DRV_LIST_get_dftab(a3),a0	;a0 -> get_dftab function
	pea		MODULE_DRIVER_s			;-(sp) = "MODULE_LAYER"
	jsr		(a0)				;call get_dftab
	addq		#4,sp
	move.l		d0,stx				;store pointer in 'stx'
	ble.s		.layer_not_valid
	clr		fatal_f
;
;Add client/server dependent init here
;
	clr.l		initerr_mess_p
	rts
;
.STiK_not_found:
	lea		STiK_not_found_al_s(pc),a0
	bra.s		.init_error
;
.STiK_not_valid:
	lea		STiK_not_valid_al_s(pc),a0
	bra.s		.init_error
;
.driver_not_valid:
	lea		driver_not_valid_al_s(pc),a0
	bra.s		.init_error
;
.layer_not_valid:
	lea		layer_not_valid_al_s(pc),a0
.init_error:
	move.l		a0,initerr_mess_p
	rts
;----------------------------------------------------------------------------
;End of:	init_app
;----------------------------------------------------------------------------
M_Master_CAB:
	dc.w	MASQ_MASTER_PORT	;lport
	dc.w	MASQ_INFO_PORT		;rport
	dc.l	MASQ_INFO_IP		;rhost
	dc.l	UNDETERMINED_IP		;lhost
;----------------------------------------------------------------------------
INFO_buff:
	dc.l	0,0,0,0
INFO_buff_end:
FORCED_IP_s:
	dc.b	'FORCED_IP',NUL
	even
;----------------------------------------------------------------------------
;Start of:	exec_app
;----------------------------------------------------------------------------
exec_app:
	move.l		initerr_mess_p,d3
	beq.s		no_init_err
	move.l		d3,a3
	sim_aes		form_alert,#1,(a3)
	tst		fatal_f
	bne		exit_exec_err
no_init_err:
exec_main:
	UDP_open	#M_Master_CAB,#UDP_EXTEND
	ext.l		d0
	move.l		d0,d7
	bmi		closed_INFO
	PRTCL_get_parameters	#MASQ_INFO_IP,INFO_buff(pc),(NULL).w,(NULL).w
	UDP_send	d7,INFO_buff(pc),#(INFO_buff_end-INFO_buff)
	TIMER_now
	move.l		d0,d6
.loop_1:
	CNbyte_count	d7
	cmp		#E_NODATA,d0
	beq.s		.next_1
	tst		d0
	bmi.s		close_INFO
	cmp		#8,d0
	bge.s		.have_data
.next_1:
	_appl_yield
	TIMER_elapsed	d6
	cmp.l		#1000,d0
	blo.s		.loop_1
	moveq		#E_CNTIMEOUT,d0
	bra.s		close_INFO
;
.have_data:
	CNget_block	d7,INFO_buff(pc),#8
	cmp		#8,d0
	bne.s		close_INFO
	biptodip	INFO_buff(pc),dotted_ip_buff(pc)
	setvstr		FORCED_IP_s(pc),dotted_ip_buff(pc)
	moveq		#E_NORMAL,d0
close_INFO:
	ext.l		d0
	exg		d0,d7
	UDP_close	d0
closed_INFO:
	tst.l		d7
	bmi.s		Master_failure
Master_success:
	lea		alert_tail_s(pc),a0
	lea		dotted_ip_buff(pc),a1
	str_conc	a0,a1
	sim_aes		form_alert,#1,Master_success_al_s(pc)
	bra.s		exit_exec_ok
;
Master_failure:
	sim_aes		form_alert,#1,Master_failure_al_s(pc)
exit_exec_ok:
exit_terminate:
	clr.l	d0
exit_exec_app:
	rts
;
exit_exec_err:
	moveq	#E_ERROR,d0
	rts
;----------------------------------------------------------------------------
;End of:	exec_app
;----------------------------------------------------------------------------
;Start of:	exec_timer
;----------------------------------------------------------------------------
	IFNE	exec_timeout	;cond:	ifne exec_timeout
exec_timer:
exit_exec_timer:
	clr.l		d0
	rts
	ENDC			;ends:	ifne exec_timeout
;----------------------------------------------------------------------------
;End of:	exec_timer
;----------------------------------------------------------------------------
;Start of:	exec_mesag
;----------------------------------------------------------------------------
	IFNE		exec_message
exec_mesag:
	cmp		#AC_CLOSE,message
	bne.s		.not_AC_CLOSE
	sf		keep_wind_f
	bra		exit_exec_mesag
;
.not_AC_CLOSE:
	cmp		#AP_TERM,message
	bne.s		.not_AP_TERM
	tst.l		d7
	bmi		exit_exec_mesag		;AP_TERM is not for ACCs
	clr.l		d0			;flag no error
	bra		exit_terminate
;
.not_AP_TERM:
	cmp		#VA_START,message
	bne		.not_VA_START
	st		VA_START_f
	move		message+2,AV_partner_id
	move.l		message+6,VA_START_cmd_p
	AV_send		PROTOKOLL,#w_VA_START+w_AV_STARTED_A,id_app_name_s
;
	move.l		VA_START_cmd_p(pc),a0	;a0 -> argument on Venus
	move.l		a0,a1			;a1 -> argument on Venus
	str_pass	a1
	sub.l		VA_START_cmd_p(pc),a1
	move.l		a1,d1			;d1 = length of argument
	move		#MAX_VA_ARGLEN,d0
	cmp.l		d0,d1			;argument too long ?
	blo.s		.length_ok
	move.l		d0,d1			;limit argument length
.length_ok:
	move.b		-1(a0,d1.w),d0		;save byte at termination point
	clr.b		-1(a0,d1.w)		;enforce limited termination
	move.l		a0,a1			;a1 -> argument on Venus
	lea		VA_arg_s(pc),a2		;a2 -> local argument area
	move.l		a2,VA_arg_p		;prep a pointer for future
	str_copy	a1,a2			;make a local copy of argument
	move.b		d0,-1(a0,d1.w)		;repair original copy
;
	AV_send.i	STARTED,VA_START_cmd_p
	bra		exec_app
;
.not_VA_START:
	cmp		#VA_PROTOSTATUS,message
	bne.s		.not_VA_PROTOSTATUS
	move		message+8,VA_protostatus
	move		message+6,VA_protostatus+2
	bra		exit_exec_mesag
;
.not_VA_PROTOSTATUS:
exec_mesag_extend:
;
;Add client/server dependent message event work here
;
exit_exec_mesag:
	rts
	ENDC		;exec_message
;----------------------------------------------------------------------------
;End of:	exec_mesag
;----------------------------------------------------------------------------
	make	SIM_links
	make	JAR_links
	make	DOMAIN_links
	make	AV_links
;----------------------------------------------------------------------------
text_limit:
	SECTION	DATA
;----------------------------------------------------------------------------
STiKmagic_s:
	dc.b	'STiKmagic',NUL
TRANSPORT_DRIVER_s:
	dc.b	'TRANSPORT_TCPIP',NUL
MODULE_DRIVER_s:
	dc.b	'MODULE_LAYER',NUL
;
Masquerade_s:
	dc.b	'Masquerade',NUL
;
STiK_not_found_al_s:
	dc.b	'[3]['
	M_ALHDR
	dc.b	'The STiK cookie is missing !]'
	dc.b	'[ Abort ]',NUL
;
STiK_not_valid_al_s:
	dc.b	'[3]['
	M_ALHDR
	dc.b	'The STiK cookie is corrupted!]'
	dc.b	'[ Abort ]',NUL
;
driver_not_valid_al_s:
	dc.b	'[3]['
	M_ALHDR
	dc.b	'TRANSPORT driver is missing !]'
	dc.b	'[ Abort ]',NUL
;
layer_not_valid_al_s:
	dc.b	'[3]['
	M_ALHDR
	dc.b	'MODULE driver is missing !]'
	dc.b	'[ Abort ]',NUL
	even
;
Master_failure_al_s:
	dc.b	'[3]['
	M_ALHDR
	dc.b	'This machine failed to set up|'
	dc.b	'itself as Masquerade Master. '
alert_tail_s:
	dc.b	']'
	dc.b	'[ Ok ]',NUL
;
Master_success_al_s:
	dc.b	'[1]['
	M_ALHDR
	dc.b	'This Machine is now Master of|'
	dc.b	'the Masquerade using ISP IP: |'
	dc.b	'       '
dotted_ip_buff:
	dc.b	       '000.000.000.000',NUL
	ds.b	32
;----------------------------------------------------------------------------
data_limit:
	SECTION	BSS
;----------------------------------------------------------------------------
sting_drivers:	ds.l	1	;DRV_LIST	*sting_drivers;
tpl:		ds.l	1	;TPL		*tpl;
stx:		ds.l	1	;STX		*stx;
initerr_mess_p:	ds.l	1
fatal_f:	ds.w	1
VA_START_f:	ds.w	1
VA_START_cmd_p:	ds.l	1
VA_protostatus:	ds.l	1
VA_arg_p:	ds.l	1
VA_arg_s:	ds.b	MAX_VA_ARGLEN
		even
;----------------------------------------------------------------------------
bss_limit:
	END
;----------------------------------------------------------------------------
;End of file:	M_MASTER.S
;----------------------------------------------------------------------------
