;----------------------------------------------------------------------------
;File name:	CONNTEST.S			Revision date:	1998.01.21
;Creator:	Ulf Ronald Andersson		Creation date:	1998.01.21
;(c)1997 by:	Ulf Ronald Andersson		All rights reserved
;----------------------------------------------------------------------------
;Required header declarations:
;
	.include	"uran\STRUCT.SH"	;PASM adapted structures
	.include	"uran\URAn_SYS.SH"	;Main system definitions
	.include	"uran\URAn_LA.SH"	;Line A variables etc
	.include	"uran\URAn_DOS.SH"	;GEMDOS, BIOS, XBIOS
	.include	"uran\URAn_GEM.SH"	;VDI & AES
	.include	"uran\URAn_SIM.SH"	;some AES funcs for TOS/TTP
	.include	"uran\URAn_APP.SH"	;General application support
	.include	"uran\URAn_JAR.SH"	;Cookie jar handling
	.include	"uran\URAn_AV.SH"	;AV/VA protocol + MP protocol
;
	.include	"sting\LAYER.SH"	;only used by servers
	.include	"sting\TRANSPRT.SH"	;used by servers/clients
	.include	"sting\DOMAIN.SH"	;handles domain name/ip conv.
;
;----------------------------------------------------------------------------
;
DEFAULT_IP	equ	$7F000001
DEFAULT_PORT	equ	13
;
TOS_NORMAL	equ	0
BUF_SIZE	equ	500
MAX_VA_ARGLEN	equ	512
;
;----------------------------------------------------------------------------
;
;;;huge_program		= 1	;uncomment if TEXT+DATA sections are > 32KB
;;;keep_windows		= 1	;uncomment to keep ACC vwk in main eventloop
;;;;;;exec_timeout		= 1000	;uncomment to enable timer in main eventloop
exec_message		= 1	;uncomment for messages in main eventloop
;
;----------------------------------------------------------------------------
;
	.text
;
	start_app
;
;----------------------------------------------------------------------------
;
	.ifeq	huge_program
	.data
	.endif
;
acc_name:
	dc.b	'  ConnTest Client',NUL	;for ACC menu registration
	dc.b	NUL
	even
;
id_app_name_s:
	dc.b	'CONNTEST',NUL
	even
;
;----------------------------------------------------------------------------
;
	.ifeq	huge_program
	.bss
	.endif
;
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
;
;----------------------------------------------------------------------------
;
	.text
;
;----------------------------------------------------------------------------
;Start of:	init_app
;----------------------------------------------------------------------------
;
init_app:
	st		handle
;
	include		"uran\URAn_ARG.S"		;load ARGV handler
;
; Here URAn_ARG.S defines two variables
;
;arg_cnt	== number of strings on command line
;arg_ptr	-> NUL_separated argument strings + final NUL
;
;NB:	Both of the above include a dummy program name (first string==NUL).
;-------
	clr.l		VA_arg_p
	cmp		#2,arg_cnt
	blo.s		.done_arg
	move.l		arg_ptr,a0
	str_pass	a0
	move.l		a0,VA_arg_p
.done_arg:
;
	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 'tpl'
	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
;----------------------------------------------------------------------------
;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:
	tst.w		d7			;GEM/TOS program ?
	bmi.s		exec_TOS		;go run TOS/TTP routines
exec_GEM:
	tst.l		d7			;APP/ACC program ?
	bmi		exec_multi_GEM		;go run ACC routines
	cmp		#1,global+2		;Singletasking APP ?
	beq.s		exec_single_GEM		;go run singletasking GEM code
exec_multi_APP:
	btst		#7,revise_type_f	;been here before ?
	bne		exec_multi_GEM		;then behave like an ACC this time
	tst.l		d3			;init_error ?
	bne		exit_exec_err		;go exit program on init errors (bad STiK etc)
	bset		#7,revise_type_f	;tell main loop to behave like ACC
	cmp		#1,arg_cnt		;any arguments for this APP
	bgt		exec_multi_GEM		;then start directly
	bra		exit_exec_ok		;exit to main event loop
;
;-------------------------------------
;
exec_TOS:
exec_single_GEM:
exec_multi_GEM:
	bsr		close_channel
	bsr		find_conn_server
	bmi		exit_exec_ok
	bsr		ask_protocol
	bmi		exit_exec_ok
	bsr		resolve_conn_server
	bmi		resolve_error
	bsr		test_connection
	bmi		some_conn_error
	sim_aes		form_alert,#1,connect_success_al_s(pc)
	bra		exit_exec_ok
;
resolve_error:
	sim_aes		form_alert,#1,resolve_error_al_s(pc)
	bra		exit_exec_ok
;
some_conn_error:
	bsr		conv_error_word
	sim_aes		form_alert,#1,connect_error_al_s(pc)
	bra		exit_exec_ok
;
;-------------------------------------
;
;
exec_APP_error:		;jump here to display alert (a3) and then exit
	sim_aes		form_alert,#1,(a3)	;NB: has simulation for TOS/TTP
exit_exec_err:		;jump here to exit with error code -1
	moveq		#-1,d0
exit_terminate:		;jump here to exit with error code in d0
	move.l		d0,d3
	bclr		#7,revise_type_f
;
;Add client/server dependent termination code here
;
	move.l		d3,d0
	bra.s		exit_exec_app
;
;-------------------------------------
;
exit_exec_ok:
	clr.l	d0
exit_exec_app:
	rts
;
;----------------------------------------------------------------------------
;End of:	exec_app
;----------------------------------------------------------------------------
;Start of:	exec_timer
;----------------------------------------------------------------------------
;
	.ifne	exec_timeout	;cond:	ifne exec_timeout
exec_timer:
	clr.l		d0
	rts
	.endif			;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
	.endif		exec_message
;
;----------------------------------------------------------------------------
;End of:	exec_mesag
;----------------------------------------------------------------------------
;Start of:	subroutines
;----------------------------------------------------------------------------
;
ask_protocol:
	sim_aes		form_alert,#1,ask_protocol_al_s(pc)
	cmp		#2,d0		;UDP button ?
	slo		TCP_f
	bhi.s		.cancel
	clr.l		d0		;flag zero for TCP/UDP buttons
	rts
;
.cancel:
	moveq		#-1,d0		;flac -1 for Cancel button
	rts
;
;----------------------------------------------------------------------------
;
find_conn_server:
	clr.l		conn_server_ip
	move.l		VA_arg_p(pc),d0
	bsr		test_conn_server
	bne.s		.exit
	move.l		#default_ip_s,conn_server_s_p
	move.l		#DEFAULT_IP,conn_server_ip
.exit:
	rts
;
;----------------------------------------------------------------------------
;
test_conn_server:
	is_unblank.i	d0
	move.l		a0,conn_server_s_p
	beq.s		.exit
	is_dip		(a0)
	move.l		a0,d0
	beq.s		.exit
	diptobip	(a0)
	move.l		d0,conn_server_ip
.exit:
	move.l		conn_server_s_p(pc),d0
	rts
;
;----------------------------------------------------------------------------
;
resolve_conn_server:
	clr.l		d0
	tst.l		conn_server_ip
	bne.s		.exit
	resolve.i	conn_server_s_p(pc),#0,#conn_server_ip,#1
.exit:
	ext.l		d0
	rts		
;
;----------------------------------------------------------------------------
;
get_5ms_time:
	move.l		(_hz_200).w,time_value
	rts
;
;----------------------------------------------------------------------------
;
test_connection:
	tst		TCP_f
	beq.s		open_UDP
open_TCP:
	TCP_open	conn_server_ip,#DEFAULT_PORT,#TOS_NORMAL,#BUF_SIZE
	move		d0,handle
	bra		done_send
;
open_UDP:
	UDP_open	conn_server_ip,#DEFAULT_PORT
	move		d0,handle
	blt		done_send
	UDP_send	handle,buffer(pc),#0
done_send:
	tst		d0
	blt		close_channel
	xbios		Supexec,get_5ms_time
	move.l		time_value(pc),time_start
wait_loop:
	CNbyte_count	handle		;d0 = byte_count/error_code
	cmp		#E_NODATA,d0
	beq.s		continue	;loop on if E_NODATA
	tst		d0
	blt.s		close_channel	;go flag error on other negatives
	bgt.s		success		;go flag success if count > 0
;test on for E_NORMAL
continue:
	_appl_yield			;avoid blocking MagiC etc.
	xbios		Supexec,get_5ms_time
	move.l		time_value,d0
	sub.l		time_start,d0
	cmp.l		#1000,d0
	blo		wait_loop	;loop back unless timed out
;Falling in here means slow success, fast success jumps here
success:
	clr		d0		;flag success
close_channel:
	move		d0,d3
	tst		handle
	blt.s		return_d3
	tst		TCP_f
	beq.s		close_udp
close_tcp:
	TCP_close	handle,#1
	bra.s		return_d3
;
close_udp:
	UDP_close	handle
	st		handle
return_d3:
	move		d3,d0
return_d0:
	move		test_CIB_status,d1
	ext		d0
	rts
;
;----------------------------------------------------------------------------
conv_error_word:
	lea	error_word_s(pc),a0
	ext.l	d0
conv_ul2h:
	swap	d0
	bsr	conv_us2h
	swap	d0
conv_us2h:
	rol	#8,d0
	bsr	conv_uc2h
	rol	#8,d0
conv_uc2h:
	rol.b	#4,d0
	bsr	conv_nybble2h
	rol.b	#4,d0
conv_nybble2h:
	move	d0,-(sp)
	and	#$0f,d0
	add	#'0',d0
	cmp	#'9',d0
	bls.s	.have_digit
	add	#'A'-('0'+10),d0
.have_digit:
	move.b	d0,(a0)+
	move	(sp)+,d0
	rts
;----------------------------------------------------------------------------
;End of:	subroutines
;----------------------------------------------------------------------------
;
	make	SIM_links
	make	JAR_links
	make	DOMAIN_links
	make	AV_links
;
;----------------------------------------------------------------------------
;
text_limit:	.data
;
;----------------------------------------------------------------------------
;
STiKmagic_s:
	dc.b	'STiKmagic',NUL
TRANSPORT_DRIVER_s:
	dc.b	'TRANSPORT_TCPIP',NUL
MODULE_DRIVER_s:
	dc.b	'MODULE_LAYER',NUL
;
STiK_not_found_al_s:
	dc.b	'[3]['
	dc.b	'STinG  ConnTest test client: |'
	dc.b	'-----------------------------|'
	dc.b	'The STiK cookie is missing !]'
	dc.b	'[ Abort ]',NUL
;
STiK_not_valid_al_s:
	dc.b	'[3]['
	dc.b	'STinG  ConnTest test client: |'
	dc.b	'-----------------------------|'
	dc.b	'The STiK cookie is corrupted!]'
	dc.b	'[ Abort ]',NUL
;
driver_not_valid_al_s:
	dc.b	'[3]['
	dc.b	'STinG  ConnTest test client: |'
	dc.b	'-----------------------------|'
	dc.b	'TRANSPORT driver is missing !]'
	dc.b	'[ Abort ]',NUL
;
layer_not_valid_al_s:
	dc.b	'[3]['
	dc.b	'STinG  ConnTest test client: |'
	dc.b	'-----------------------------|'
	dc.b	'MODULE driver is missing !]'
	dc.b	'[ Abort ]',NUL
	even
;
;
default_ip_s:
	dc.b	'127.0.0.1',NUL
;
resolve_error_al_s:
	dc.b	'[3]['
	dc.b	'STinG  ConnTest test client: |'
	dc.b	'-----------------------------|'
	dc.b	'The IP address for connection|'
	dc.b	'test could not be resolved ! ]'
	dc.b	'[ Abort ]',NUL
;
connect_success_al_s:
	dc.b	'[3]['
	dc.b	'STinG  ConnTest test client: |'
	dc.b	'-----------------------------|'
	dc.b	'Connection Succeeded...!     ]'
	dc.b	'[ Abort ]',NUL
;
connect_error_al_s:
	dc.b	'[3]['
	dc.b	'STinG  ConnTest test client: |'
	dc.b	'-----------------------------|'
	dc.b	'Connection failed...!        |'
	dc.b	'Error code = $'
error_word_s:
	dc.b	'00000000'
	dc.b	' ]'
	dc.b	'[ Abort ]',NUL
;
ask_protocol_al_s:
	dc.b	'[2]['
	dc.b	'STinG  ConnTest test client: |'
	dc.b	'-----------------------------|'
	dc.b	'Which protocol do you want to|'
	dc.b	'use on this server request ?]'
	dc.b	'[ TCP | UDP | Cancel ]',NUL
;
;----------------------------------------------------------------------------
;
data_limit:	.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
;
conn_server_s_p:	ds.l	1
conn_server_ip:		ds.l	1
TCP_f:			ds.w	1
handle:			ds.w	1
time_value:		ds.l	1
time_start:		ds.l	1
test_CIB_status:	ds.w	1
buffer:			ds.b	BUF_SIZE
;
;----------------------------------------------------------------------------
bss_limit:	.end
;----------------------------------------------------------------------------
;End of file:	CONNTEST.S
;----------------------------------------------------------------------------
