diff --git a/client/basic/Makefile b/client/basic/Makefile index 136c8c2..6a1ac6a 100644 --- a/client/basic/Makefile +++ b/client/basic/Makefile @@ -19,6 +19,9 @@ C64PROGLIB=../drivers/c64prog.lib all: kipperbas.d64 bails.prg +bails.o: bails.s $(INCFILES) httpd.inc + $(AS) $(AFLAGS) $< + %.o: %.s $(INCFILES) $(AS) $(AFLAGS) $< diff --git a/client/basic/bails.s b/client/basic/bails.s index 73b72a6..293d9da 100644 --- a/client/basic/bails.s +++ b/client/basic/bails.s @@ -81,6 +81,7 @@ crunched_line = $0200 ;Input buffer .import http_variables_buffer + .zeropage temp: .res 2 temp2: .res 2 @@ -566,6 +567,16 @@ make_null_terminated_and_print: ldax #string_buffer jmp print +print_integer: +sta $63 +stx $62 +jmp $bdd1 ;BASIC routine + +print_decimal: + jsr reset_string + jsr emit_decimal + jmp make_null_terminated_and_print + print_mac: jsr reset_string jsr emit_mac @@ -888,7 +899,8 @@ grok_keyword: stax http_variables_buffer jsr extract_string ldax #transfer_buffer - jsr http_parse_request +got_http_request: + jsr http_parse_request lda #$02 jsr http_get_value stax copy_src @@ -964,10 +976,19 @@ grok_keyword: httpd_keyword: jsr get_integer - stax httpd_port + stax httpd_port_number jsr skip_comma_get_integer stax default_line_number - rts + 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 + jmp httpd_start .rodata vectors: @@ -983,6 +1004,9 @@ vectors: hexdigits: .byte "0123456789ABCDEF" +listening: +.byte"LISTENING ON ",0 + pinging: .byte"PINGING ",0 interface_type: @@ -1104,5 +1128,25 @@ transfer_buffer: .res 256 handler_address: .res 2 hash: .res 1 string_ptr: .res 1 -httpd_port: .res 2 -default_line_number: .res 2 \ No newline at end of file +default_line_number: .res 2 + + +.include "httpd.inc" +;-- LICENSE FOR bails.s -- +; The contents of this file are subject to the Mozilla Public License +; Version 1.1 (the "License"); you may not use this file except in +; compliance with the License. You may obtain a copy of the License at +; http://www.mozilla.org/MPL/ +; +; Software distributed under the License is distributed on an "AS IS" +; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +; License for the specific language governing rights and limitations +; under the License. +; +; The Original Code is netboot65. +; +; The Initial Developer of the Original Code is Jonno Downes, +; jonno@jamtronix.com. +; Portions created by the Initial Developer are Copyright (C) 2009,2010 +; Jonno Downes. All Rights Reserved. +; -- LICENSE END -- diff --git a/client/basic/httpd.inc b/client/basic/httpd.inc new file mode 100644 index 0000000..ee8e55a --- /dev/null +++ b/client/basic/httpd.inc @@ -0,0 +1,379 @@ +;a simple HTTP server (ip65 httpd customised for use with BASIC on bails) +;.include "../inc/common.i" +; +;.ifndef KPR_API_VERSION_NUMBER +; .define EQU = +; .include "../inc/kipper_constants.i" +;.endif + + +HTTPD_TIMEOUT_SECONDS=5 ;what's the maximum time we let 1 connection be open for? + +DEBUG=1 + + +.import http_parse_request +.import http_get_value +.import tcp_listen +.import tcp_callback +.import ip65_process +.import check_for_abort_key +.import ip65_error +.import parse_hex_digits +.import copymem +.importzp copy_src +.importzp copy_dest +.import tcp_inbound_data_ptr +.import tcp_inbound_data_length +.import tcp_send_data_len +.import tcp_send +.import tcp_close +.import io_read_catalogue +.import native_to_ascii +.import io_read_file_with_callback +.import io_filename +.import io_callback +.import tcp_connect_remote_port +.import tcp_remote_ip + +temp_ptr =copy_src + +.bss +found_eol: .byte 0 +connection_closed: .byte 0 +output_buffer_length: .res 2 +sent_header: .res 1 +connection_timeout_seconds: .byte 0 +tcp_buffer_ptr: .res 2 +buffer_size: .res 1 +temp_x: .res 1 + + +.segment "TCP_VARS" + +__httpd_io_buffer: .res 1024 ;temp buffer for storing inbound requests. + +.segment "HTTP_VARS" + +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 + +.code + +;start a HTTP server +;this routine will stay in an endless loop that is broken only if user press the ABORT key (runstop on a c64) +;inputs: +; none +;outputs: +; none +httpd_start: + lda #0 + sta $dc08 ;make sure TOD clock is started + +@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 + rts +@connect_ok: +.ifdef DEBUG + inc $d020 +.endif + 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 + clc + lda $dc09 ;time of day clock: seconds (in BCD) + sed + adc #HTTPD_TIMEOUT_SECONDS + cmp #$60 + bcc @timeout_set + sec + sbc #$60 +@timeout_set: + cld + sta connection_timeout_seconds + +@main_polling_loop: + jsr ip65_process + jsr check_for_abort_key + bcc @no_abort + lda #KPR_ERROR_ABORTED_BY_USER + sta ip65_error + rts +@no_abort: + lda found_eol + bne @got_eol + + lda $dc09 ;time of day clock: seconds + + cmp connection_timeout_seconds + beq @connection_timed_out + lda connection_closed + beq @main_polling_loop +@connection_timed_out: +.ifdef DEBUG + dec $d020 +.endif + jmp @listen + +@got_eol: + 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 temp_ptr + lda tcp_buffer_ptr+1 + adc tcp_inbound_data_length+1 + sta tcp_buffer_ptr+1 + sta temp_ptr+1 + +;put a null byte at the end (assumes we have set temp_ptr already) + lda #0 + tay + sta (temp_ptr),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 + + send_header: +;inputs: Y = header type +;$00 = no header (assume header sent already) +;$01 = 200 OK, 'text/text' +;$02 = 200 OK, 'text/html' +;$03 = 200 OK, 'application/octet-stream' +;$04 = 404 Not Found +;$05..$FF = 500 System Error + + cpy #00 + bne :+ + rts +: + cpy #1 + bne @not_text + jsr emit_ok_status_line_and_content_type + ldax #text_text + jsr emit_string + jmp @done + +@not_text: + cpy #2 + + bne @not_html + jsr emit_ok_status_line_and_content_type + ldax #text_html + jsr emit_string + jmp @done + +@not_html: + cpy #3 + bne @not_binary + jsr emit_ok_status_line_and_content_type + ldax #application_octet_stream + jsr emit_string + jmp @done + +@not_binary: + cpy #4 + bne @not_404 + ldax #http_version + jsr emit_string + ldax #status_not_found + jsr emit_string + + jsr @done + ldax #status_not_found + jmp emit_string + +@not_404: + ldax #http_version + jsr emit_string + ldax #status_system_error + jsr emit_string + jsr @done + ldax #status_system_error + jmp emit_string +@done: + ldax #end_of_header + jmp emit_string + + +emit_ok_status_line_and_content_type: + ldax #http_version + jsr emit_string + ldax #status_ok + jsr emit_string + ldax #content_type + jmp emit_string + +emit_string: + stax temp_ptr + ldy #0 +@next_byte: + lda (temp_ptr),y + beq @done + jsr xmit_a + iny + bne @next_byte +@done: + rts + + +.rodata + +CR=$0D +LF=$0A + +http_version: + .byte "HTTP/1.0 ",0 + +status_ok: + .byte "200 OK",CR,LF,0 + +status_not_found: + .byte "404 Not Found",CR,LF,0 + +status_system_error: + .byte "500 System Error",CR,LF,0 +content_type: + .byte "Content-Type: ",0 + +text_text: + .byte "text/text",CR,LF,0 + +text_html: + .byte "text/html",CR,LF,0 + +application_octet_stream: + .byte "application/octet-stream",CR,LF,0 + +end_of_header: + .byte "Connection: Close",CR,LF + .byte "Server: BoB_httpd/0.c64",CR,LF + .byte CR,LF,0 + +connection_from: .byte "CONNECTION FROM ",0 + + +;-- LICENSE FOR httpd.inc -- +; The contents of this file are subject to the Mozilla Public License +; Version 1.1 (the "License"); you may not use this file except in +; compliance with the License. You may obtain a copy of the License at +; http://www.mozilla.org/MPL/ +; +; Software distributed under the License is distributed on an "AS IS" +; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +; License for the specific language governing rights and limitations +; under the License. +; +; The Original Code is netboot65. +; +; The Initial Developer of the Original Code is Jonno Downes, +; jonno@jamtronix.com. +; Portions created by the Initial Developer are Copyright (C) 2009,2010 +; Jonno Downes. All Rights Reserved. +; -- LICENSE END -- diff --git a/client/basic/kipperbas.d64 b/client/basic/kipperbas.d64 index 3e926a0..96af7d1 100644 Binary files a/client/basic/kipperbas.d64 and b/client/basic/kipperbas.d64 differ diff --git a/client/cfg/kipperbas.cfg b/client/cfg/kipperbas.cfg index 187376d..1f81400 100644 --- a/client/cfg/kipperbas.cfg +++ b/client/cfg/kipperbas.cfg @@ -18,6 +18,7 @@ MEMORY { SELF_MODIFIED_CODE: load = MAINRAM, type = rw; RODATA: load = MAINRAM, type = ro; DATA: load = MAINRAM, type = rw, define = yes; + HTTP_VARS: load = MAINRAM, type = rw, define = yes; BSS: load = MAINRAM, type = bss; IP65ZP: load = IP65ZP, type = zp; @@ -25,4 +26,5 @@ MEMORY { ZEROPAGE: load = IP65ZP, type = zp; TCP_VARS: load = HIRAM, type = bss; + } diff --git a/client/ip65/tcp.s b/client/ip65/tcp.s index f00b92d..18d1261 100644 --- a/client/ip65/tcp.s +++ b/client/ip65/tcp.s @@ -27,6 +27,8 @@ MAX_TCP_PACKETS_SENT=8 ;timeout after sending 8 messages will be about 7 sec .export tcp_close .export tcp_listen .export tcp_send_keep_alive +.export tcp_connect_remote_port +.export tcp_remote_ip .export tcp_inbound_data_ptr .export tcp_inbound_data_length