mirror of
https://github.com/bobbimanners/emailler.git
synced 2025-01-17 02:30:10 +00:00
9c6f0f97c3
git-svn-id: http://svn.code.sf.net/p/netboot65/code@332 93682198-c243-4bdb-bd91-e943c89aac3b
615 lines
11 KiB
ArmAsm
615 lines
11 KiB
ArmAsm
.include "../inc/common.i"
|
|
.include "../inc/commonprint.i"
|
|
.include "../inc/a2const.i"
|
|
.include "../inc/net.i"
|
|
|
|
.import exit_to_basic
|
|
.import cfg_get_configuration_ptr
|
|
.import dns_ip
|
|
.import dns_resolve
|
|
.import dns_set_hostname
|
|
.import icmp_ping
|
|
.import icmp_echo_ip
|
|
|
|
|
|
.import copymem
|
|
.importzp copy_src
|
|
|
|
.importzp copy_dest
|
|
.importzp buffer_ptr
|
|
|
|
.import http_parse_request
|
|
.import http_get_value
|
|
.import http_variables_buffer
|
|
|
|
.import tcp_inbound_data_ptr
|
|
.import tcp_inbound_data_length
|
|
.import tcp_send_data_len
|
|
.import tcp_send
|
|
.import check_for_abort_key
|
|
.import tcp_connect_remote_port
|
|
.import tcp_remote_ip
|
|
.import tcp_listen
|
|
.import tcp_callback
|
|
.import tcp_close
|
|
|
|
.import __CODE_LOAD__
|
|
.import __CODE_SIZE__
|
|
.import __RODATA_SIZE__
|
|
.import __DATA_SIZE__
|
|
.import __IP65_DEFAULTS_SIZE__
|
|
.import __BSS_RUN__
|
|
.import __BSS_SIZE__
|
|
|
|
END_OF_BSS = __BSS_RUN__+__BSS_SIZE__
|
|
|
|
.segment "EXEHDR" ;this is what gets put an the start of the file on the Apple 2
|
|
.addr __CODE_LOAD__-$03 ; Start address
|
|
.word __CODE_SIZE__+__RODATA_SIZE__+__DATA_SIZE__+__IP65_DEFAULTS_SIZE__+4 ; file size
|
|
jmp init
|
|
.code
|
|
|
|
init:
|
|
jsr ip65_init
|
|
bcc @init_ok
|
|
ldax #@no_nic
|
|
jsr print
|
|
|
|
jmp exit_to_basic
|
|
@no_nic:
|
|
.byte "NO NIC - UNINSTALLING",0
|
|
@install_msg:
|
|
.byte " FOUND",13,"APPLESOFT.NET USING $801-$"
|
|
|
|
.byte 0
|
|
@init_ok:
|
|
;print the banner
|
|
ldax #eth_driver_name
|
|
jsr print_ascii_as_native
|
|
ldax #@install_msg
|
|
jsr print
|
|
print_hex_double #END_OF_BSS
|
|
jsr print_cr
|
|
|
|
;take over the ampersand vector
|
|
ldax AMPERSAND_VECTOR+1
|
|
stax old_amper_handler
|
|
ldax #amper_handler
|
|
stax AMPERSAND_VECTOR+1
|
|
|
|
lda #$FF
|
|
sta CURLIN+1 ;put into 'immediate' mode
|
|
ldax #END_OF_BSS+1
|
|
stax TXTTAB
|
|
lda #0
|
|
sta END_OF_BSS ;if the byte before the start of the BASIC is not zero, we
|
|
;get a weird 'SYNTAX ERROR IN LINE' because
|
|
;STXTPT (called by RUN) sets TXTPTR (address of next BASIC token) to be TXTTAB-1
|
|
;if this byte is zero, then NEWSTT tries to execute that byte
|
|
jsr SCRTCH ;reset BASIC now we have updated the start address
|
|
lday #chain_cmd
|
|
jsr STROUT
|
|
jmp exit_to_basic
|
|
|
|
print_error:
|
|
jsr print
|
|
ldax #error
|
|
jsr print
|
|
lda ip65_error
|
|
jsr print_hex
|
|
jsr print_cr
|
|
sec
|
|
rts
|
|
amper_handler:
|
|
;see if & is followed by one of our keywords
|
|
|
|
ldx #0
|
|
ldy #0
|
|
lda keyword_table
|
|
|
|
@check_one_handler:
|
|
cmp #$FF ;end of table?
|
|
beq exit_to_old_handler
|
|
cmp (TXTPTR),y ;char in line
|
|
beq @this_char_ok
|
|
@skip_to_next_handler_loop:
|
|
inx
|
|
lda keyword_table,x
|
|
bne @skip_to_next_handler_loop
|
|
inx ;skip first part of handler address
|
|
inx ;skip next part of handler address
|
|
ldy #$FF
|
|
@this_char_ok:
|
|
iny
|
|
inx
|
|
lda keyword_table,x ;get cmd char
|
|
bne @check_one_handler
|
|
;if we get here, we have matched a keyword, and X points to the zero terminating the keyword, Y is length of keyword
|
|
lda keyword_table+2,x ;get high byte of handler address
|
|
pha
|
|
lda keyword_table+1,x ;get low byte of handler address
|
|
pha
|
|
jmp ADDON ;fix-up TXTPTR - on return control will transfer to address we just pushed
|
|
|
|
exit_to_old_handler:
|
|
jmp $ffff
|
|
old_amper_handler=exit_to_old_handler+1
|
|
|
|
get_optional_byte:
|
|
jsr CHRGOT
|
|
beq @no_param ;leave X as it was
|
|
jmp COMBYTE
|
|
@no_param:
|
|
rts
|
|
|
|
extract_string:
|
|
jsr FRMEVL
|
|
jsr FRESTR ;if not string, will create type mismatch error
|
|
sta param_length
|
|
tay
|
|
lda #0
|
|
sta transfer_buffer,y
|
|
dey
|
|
@loop:
|
|
lda (INDEX),y
|
|
sta transfer_buffer,y
|
|
dey
|
|
bpl @loop
|
|
rts
|
|
|
|
get_ip_parameter:
|
|
stax buffer_ptr
|
|
jsr extract_string
|
|
ldax #transfer_buffer
|
|
|
|
jsr dns_set_hostname
|
|
|
|
bcs @error
|
|
jsr dns_resolve
|
|
bcc @ok
|
|
@error:
|
|
ldax #address_resolution
|
|
jmp print_error
|
|
|
|
@ok:
|
|
ldax #dns_ip
|
|
ldx #4
|
|
@copy_dns_ip:
|
|
lda dns_ip,y
|
|
sta (buffer_ptr),y
|
|
iny
|
|
dex
|
|
bne @copy_dns_ip
|
|
rts
|
|
|
|
ipcfg_handler:
|
|
jmp print_ip_config
|
|
|
|
ping_handler:
|
|
ldax #icmp_echo_ip
|
|
jsr get_ip_parameter
|
|
bcc @no_error
|
|
rts
|
|
@no_error:
|
|
;is there an optional parameter?
|
|
ldx #3
|
|
jsr get_optional_byte
|
|
stx ping_counter
|
|
|
|
ldax #pinging
|
|
jsr print
|
|
ldax #dns_ip
|
|
jsr print_dotted_quad
|
|
jsr print_cr
|
|
|
|
@ping_loop:
|
|
jsr icmp_ping
|
|
bcs @error
|
|
lda #'.'
|
|
@print_and_loop:
|
|
jsr print_a
|
|
lda $c000 ;key pressed
|
|
sta $c010 ;clear keyboard
|
|
cmp #$9B ;escape
|
|
beq @done
|
|
dec ping_counter
|
|
bne @ping_loop
|
|
@done:
|
|
jmp print_cr
|
|
@error:
|
|
lda #'!'
|
|
jmp @print_and_loop
|
|
|
|
|
|
dhcp_handler:
|
|
jsr dhcp_init
|
|
bcc @init_ok
|
|
jsr ip65_init ;if DHCP failed, then reinit the IP stack (which will reset IP address etc that DHCP messed with to default values)
|
|
|
|
@init_failed:
|
|
ldax #dhcp
|
|
jmp print_error
|
|
@init_ok:
|
|
rts
|
|
|
|
myip_handler:
|
|
ldax #cfg_ip
|
|
jmp get_ip_parameter
|
|
|
|
dns_handler:
|
|
ldax #cfg_dns
|
|
jmp get_ip_parameter
|
|
|
|
gateway_handler:
|
|
ldax #cfg_gateway
|
|
jmp get_ip_parameter
|
|
|
|
netmask_handler:
|
|
ldax #cfg_netmask
|
|
jmp get_ip_parameter
|
|
|
|
|
|
skip_comma_get_integer:
|
|
jsr CHKCOM
|
|
get_integer:
|
|
jsr CHRGOT
|
|
jsr LINGET
|
|
ldax LINNUM
|
|
rts
|
|
|
|
|
|
httpd_handler:
|
|
jsr flush_handler ;clean out the last connection
|
|
jsr get_integer
|
|
stax httpd_port_number
|
|
tsx
|
|
stx top_of_stack
|
|
|
|
ldax #listening
|
|
jsr print
|
|
ldax #cfg_ip
|
|
jsr print_dotted_quad
|
|
lda #':'
|
|
jsr print_a
|
|
ldax httpd_port_number
|
|
jsr print_integer
|
|
jsr print_cr
|
|
|
|
@listen:
|
|
jsr tcp_close
|
|
ldax httpd_io_buffer
|
|
stax tcp_buffer_ptr
|
|
|
|
ldax #http_callback
|
|
stax tcp_callback
|
|
ldax httpd_port_number
|
|
|
|
jsr tcp_listen
|
|
bcc @connect_ok
|
|
jmp END4
|
|
|
|
@connect_ok:
|
|
ldax #connection_from
|
|
jsr print
|
|
ldax #tcp_remote_ip
|
|
jsr print_dotted_quad
|
|
lda #':'
|
|
jsr print_a
|
|
ldax tcp_connect_remote_port
|
|
|
|
jsr print_integer
|
|
jsr print_cr
|
|
lda #0
|
|
sta connection_closed
|
|
sta found_eol
|
|
sta polling_counter
|
|
|
|
@main_polling_loop:
|
|
jsr ip65_process
|
|
jsr ISCNTC ;check for ^C, if so print error message, warm start BASIC
|
|
|
|
lda found_eol
|
|
bne @got_eol
|
|
lda #75
|
|
jsr $fca8 ;wait for about 15ms - this gives a total timeout of ~4seconds
|
|
inc polling_counter
|
|
bne @main_polling_loop
|
|
jmp @listen
|
|
|
|
@got_eol:
|
|
|
|
jsr reset_output_buffer
|
|
|
|
ldy #$FF
|
|
:
|
|
iny
|
|
lda status_ok,y
|
|
sta status_code_buffer,y
|
|
bne :-
|
|
|
|
ldy #$FF
|
|
:
|
|
iny
|
|
lda text_html,y
|
|
sta content_type_buffer,y
|
|
bne :-
|
|
|
|
sta sent_header
|
|
|
|
ldax httpd_io_buffer
|
|
jmp got_http_request
|
|
|
|
http_callback:
|
|
lda tcp_inbound_data_length+1
|
|
cmp #$ff
|
|
bne @not_eof
|
|
inc connection_closed
|
|
@done:
|
|
rts
|
|
@not_eof:
|
|
lda found_eol
|
|
bne @done
|
|
|
|
;copy this chunk to our input buffer
|
|
ldax tcp_buffer_ptr
|
|
stax copy_dest
|
|
ldax tcp_inbound_data_ptr
|
|
stax copy_src
|
|
ldax tcp_inbound_data_length
|
|
jsr copymem
|
|
|
|
;increment the pointer into the input buffer
|
|
clc
|
|
lda tcp_buffer_ptr
|
|
adc tcp_inbound_data_length
|
|
sta tcp_buffer_ptr
|
|
sta copy_src
|
|
lda tcp_buffer_ptr+1
|
|
adc tcp_inbound_data_length+1
|
|
sta tcp_buffer_ptr+1
|
|
sta copy_src+1
|
|
|
|
;put a null byte at the end (assumes we have set copy_src already)
|
|
lda #0
|
|
tay
|
|
sta (copy_src),y
|
|
|
|
;look for CR or LF in input
|
|
sta found_eol
|
|
ldax httpd_io_buffer
|
|
stax get_next_byte+1
|
|
|
|
@look_for_eol:
|
|
jsr get_next_byte
|
|
cmp #$0a
|
|
beq @found_eol
|
|
cmp #$0d
|
|
bne @not_eol
|
|
@found_eol:
|
|
inc found_eol
|
|
rts
|
|
@not_eol:
|
|
cmp #0
|
|
bne @look_for_eol
|
|
rts
|
|
|
|
|
|
|
|
reset_output_buffer:
|
|
ldax httpd_io_buffer
|
|
sta xmit_a_ptr+1
|
|
stx xmit_a_ptr+2
|
|
lda #0
|
|
sta output_buffer_length
|
|
sta output_buffer_length+1
|
|
rts
|
|
|
|
|
|
send_buffer:
|
|
ldax output_buffer_length
|
|
stax tcp_send_data_len
|
|
ldax httpd_io_buffer
|
|
jsr tcp_send
|
|
jmp reset_output_buffer
|
|
|
|
|
|
emit_string:
|
|
stax copy_src
|
|
ldy #0
|
|
@next_byte:
|
|
lda (copy_src),y
|
|
beq @done
|
|
jsr xmit_a
|
|
iny
|
|
bne @next_byte
|
|
@done:
|
|
rts
|
|
|
|
got_http_request:
|
|
jsr http_parse_request
|
|
ldax #path
|
|
jsr print
|
|
lda #$02
|
|
jsr http_get_value
|
|
stax copy_src
|
|
jsr print
|
|
jsr print_cr
|
|
|
|
;now restore stack to how it was when &HTTPD was called, and return to BASIC
|
|
ldx top_of_stack
|
|
txs
|
|
rts
|
|
|
|
|
|
bang_handler:
|
|
jsr extract_string
|
|
lda sent_header
|
|
bne :+
|
|
jsr send_header
|
|
:
|
|
ldy #0
|
|
sty string_ptr
|
|
@loop:
|
|
lda transfer_buffer,y
|
|
jsr xmit_a
|
|
inc string_ptr
|
|
ldy string_ptr
|
|
cpy param_length
|
|
bne @loop
|
|
rts
|
|
|
|
send_header:
|
|
inc sent_header
|
|
ldax #http_version
|
|
jsr emit_string
|
|
ldax #status_code_buffer
|
|
jsr emit_string
|
|
ldax #crlf
|
|
jsr emit_string
|
|
ldax #content_type
|
|
jsr emit_string
|
|
ldax #content_type_buffer
|
|
jsr emit_string
|
|
ldax #end_of_header
|
|
jmp emit_string
|
|
|
|
flush_handler:
|
|
lda output_buffer_length
|
|
bne :+
|
|
ldx output_buffer_length+1
|
|
bne :+
|
|
rts
|
|
:
|
|
jmp send_buffer
|
|
|
|
.rodata
|
|
keyword_table:
|
|
.byte "IPCFG",0
|
|
.word ipcfg_handler-1
|
|
.byte "DHCP",0
|
|
.word dhcp_handler-1
|
|
.byte "PING",0
|
|
.word ping_handler-1
|
|
.byte "MYIP",0
|
|
.word myip_handler-1
|
|
.byte "DNS",0
|
|
.word dns_handler-1
|
|
.byte "G",$c5,"EWAY",0 ;$C5 is token for 'AT'
|
|
.word gateway_handler-1
|
|
.byte "NETMASK",0
|
|
.word netmask_handler-1
|
|
.byte "HTTPD",0
|
|
.word httpd_handler-1
|
|
.byte "!",0
|
|
.word bang_handler-1
|
|
.byte "FLUSH",0
|
|
.word flush_handler-1
|
|
|
|
.byte $ff
|
|
|
|
keyword_table_size=*-keyword_table
|
|
.if keyword_table_size>255
|
|
.error "KEYWORD TABLE TOO BIG!"
|
|
.endif
|
|
|
|
CR=$0D
|
|
LF=$0A
|
|
|
|
dhcp:
|
|
.byte "DHCP",0
|
|
address_resolution:
|
|
.byte "ADDRESS RESOLUTION",0
|
|
error:
|
|
.byte " ERROR $",0
|
|
pinging:
|
|
.byte "PINGING ",0
|
|
|
|
path:
|
|
.byte "PATH: ",0
|
|
http_version:
|
|
.byte "HTTP/1.0 ",0
|
|
|
|
status_ok:
|
|
.byte "200 OK",0
|
|
status_error:
|
|
.byte "500 "
|
|
system_error:
|
|
.byte "SYSTEM ERROR",0
|
|
content_type:
|
|
.byte "Content-Type: ",0
|
|
text_html:
|
|
.byte "text/html",0
|
|
|
|
end_of_header:
|
|
.byte CR,LF
|
|
.byte "Connection: Close",CR,LF
|
|
.byte "Server: AppleSoft.NET/0.2",CR,LF
|
|
crlf:
|
|
.byte CR,LF,0
|
|
|
|
connection_from: .byte "CONNECTION FROM ",0
|
|
chain_cmd:
|
|
|
|
.byte 13,4,"RUN AUTOEXEC.BAS",13,0
|
|
|
|
listening:
|
|
.byte"LISTENING ON ",0
|
|
|
|
|
|
|
|
.data
|
|
|
|
|
|
httpd_io_buffer: .word __httpd_io_buffer
|
|
httpd_port_number: .word 80
|
|
|
|
|
|
get_next_byte:
|
|
lda $ffff
|
|
inc get_next_byte+1
|
|
bne @skip
|
|
inc get_next_byte+2
|
|
@skip:
|
|
rts
|
|
|
|
|
|
xmit_a:
|
|
|
|
xmit_a_ptr:
|
|
sta $ffff
|
|
inc xmit_a_ptr+1
|
|
bne :+
|
|
inc xmit_a_ptr+2
|
|
:
|
|
inc output_buffer_length
|
|
bne :+
|
|
inc output_buffer_length+1
|
|
lda output_buffer_length+1
|
|
cmp #2
|
|
bne :+
|
|
stx temp_x
|
|
jsr send_buffer
|
|
ldx temp_x
|
|
:
|
|
rts
|
|
|
|
.bss
|
|
|
|
transfer_buffer: .res 256
|
|
param_length: .res 1
|
|
ping_counter: .res 1
|
|
handler_address: .res 2
|
|
temp_x: .res 1
|
|
output_buffer_length: .res 2
|
|
sent_header: .res 1
|
|
content_type_buffer: .res 128
|
|
status_code_buffer: .res 128
|
|
found_eol: .byte 0
|
|
connection_closed: .byte 0
|
|
tcp_buffer_ptr: .res 2
|
|
top_of_stack: .res 1
|
|
polling_counter: .res 1
|
|
string_ptr: .res 1
|
|
__httpd_io_buffer: .res 1024 ;temp buffer for storing inbound requests.
|
|
|