mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-12-24 01:29:17 +00:00
git-svn-id: http://svn.code.sf.net/p/netboot65/code@111 93682198-c243-4bdb-bd91-e943c89aac3b
This commit is contained in:
parent
d0fb0d16ed
commit
ce3609f2bb
@ -5,7 +5,7 @@ MEMORY {
|
||||
IP65ZP: start = $A3, size = $0E, type = rw, define = yes;
|
||||
HEADER: start = $8000, size = $18, file = %O;
|
||||
ROM: start = $8018, size = $1F00, define = yes, file = %O;
|
||||
RAM: start = $C080, size = $0f80, define = yes;
|
||||
RAM: start = $C010, size = $0fE0, define = yes;
|
||||
|
||||
|
||||
}
|
||||
|
@ -24,14 +24,17 @@ get_key:
|
||||
;inputs: none
|
||||
;outputs: sec if RUN/STOP pressed, clear otherwise
|
||||
check_for_abort_key:
|
||||
lda $cb ;current key pressed
|
||||
cmp #$3F
|
||||
bne :+
|
||||
jsr $ffe4 ;get the keypress out of the buffer
|
||||
sec
|
||||
:
|
||||
clc
|
||||
rts
|
||||
lda $cb ;current key pressed
|
||||
cmp #$3F
|
||||
bne @not_abort
|
||||
@flush_loop:
|
||||
jsr $ffe4
|
||||
bne @flush_loop
|
||||
sec
|
||||
rts
|
||||
@not_abort:
|
||||
clc
|
||||
rts
|
||||
|
||||
;cribbed from http://codebase64.org/doku.php?id=base:robust_string_input
|
||||
;======================================================================
|
||||
|
@ -1,7 +1,7 @@
|
||||
.bss
|
||||
|
||||
;global scratch buffer that DHCP/DNS and others can use while building outbound packets.
|
||||
;global scratch buffer that DHCP/DNS/TFTP and others can use while building outbound packets.
|
||||
;you need to be careful if using this that you don't call a function that also uses it.
|
||||
;if this is reversed for higher level protocols, the likelyhood of collision is low.
|
||||
.export output_buffer
|
||||
output_buffer: .res 256
|
||||
output_buffer: .res 520
|
@ -1,5 +1,5 @@
|
||||
;minimal tftp implementation (client only)
|
||||
;supports file download (not upload) and custom directory listing (using non-standard tftp opcode of 0x65)
|
||||
;supports file download and upload and custom directory listing (using non-standard tftp opcode of 0x65)
|
||||
|
||||
|
||||
TFTP_MAX_RESENDS=10
|
||||
@ -15,12 +15,13 @@
|
||||
.export tftp_load_address
|
||||
.export tftp_ip
|
||||
.export tftp_download
|
||||
.export tftp_upload
|
||||
.export tftp_directory_listing
|
||||
.export tftp_data_block_length
|
||||
.export tftp_set_callback_vector
|
||||
.export tftp_data_block_length
|
||||
.export tftp_clear_callbacks
|
||||
.import output_buffer
|
||||
|
||||
.import ip65_process
|
||||
.import ip65_error
|
||||
|
||||
@ -29,7 +30,7 @@
|
||||
.import output_buffer
|
||||
.import udp_callback
|
||||
.import udp_send
|
||||
|
||||
.import check_for_abort_key
|
||||
.import udp_inp
|
||||
.import ip_inp
|
||||
.importzp ip_src
|
||||
@ -58,7 +59,6 @@ tftp_filename: .res 2 ;name of file to d/l or filemask to get directory listing
|
||||
;packet offsets
|
||||
tftp_inp = udp_inp + udp_data
|
||||
tftp_outp = output_buffer
|
||||
;= output_buffer
|
||||
|
||||
;everything after filename in a request at a relative address, not fixed, so don't bother defining offset constants
|
||||
|
||||
@ -69,22 +69,22 @@ tftp_load_address: .res 2 ;address file will be (or was) downloaded to
|
||||
tftp_ip: .res 4 ;ip address of tftp server - set to 255.255.255.255 (broadcast) to send request to all tftp servers on local lan
|
||||
|
||||
tftp_data_block_length: .res 2
|
||||
tftp_send_len: .res 2
|
||||
tftp_current_memloc: .res 2
|
||||
|
||||
; tftp state machine
|
||||
tftp_initializing = 1 ; initial state
|
||||
tftp_rrq_sent=2 ; sent the read request, waiting for some data
|
||||
tftp_receiving_file=3 ; we have received the first packet of file data
|
||||
tftp_complete=4 ; we have received the final packet of file data
|
||||
tftp_initial_request_sent=2 ; sent the RRQ or WRQ, waiting for some data
|
||||
tftp_transmission_in_progress=3 ; we have sent/received the first packet of file data
|
||||
tftp_complete=4 ; we have sent/received the final packet of file data
|
||||
tftp_error=5 ; we got an error
|
||||
|
||||
tftp_state: .res 1 ; current activity
|
||||
tftp_timer: .res 1
|
||||
tftp_resend_counter: .res 1
|
||||
tftp_break_inner_loop: .res 1
|
||||
tftp_expected_block_number: .res 1
|
||||
tftp_block_number_to_ack: .res 1
|
||||
tftp_actual_server_port: .res 2 ;this is read from the reply - it is not (usually) the port # we send the RRQ to
|
||||
tftp_current_block_number: .res 2
|
||||
tftp_actual_server_port: .res 2 ;this is read from the reply - it is not (usually) the port # we send the RRQ or WRQ to
|
||||
tftp_actual_server_ip: .res 4 ;this is read from the reply - it may not be the IP we sent to (e.g. if we send to broadcast)
|
||||
|
||||
tftp_just_set_new_load_address: .res 1
|
||||
@ -93,15 +93,34 @@ tftp_opcode: .res 2 ; will be set to 4 if we are doing a RRQ, or 7 if we are doi
|
||||
|
||||
.code
|
||||
|
||||
;uploads a file to a tftp server
|
||||
; inputs:
|
||||
; tftp_ip: ip address of host to download from (set to 255.255.255.255 for broadcast)
|
||||
; tftp_filename: pointer to null terminated name of file to download
|
||||
; of file should be loaded into (e.g. if downloading a C64 'prg' file)
|
||||
; a callback vector should have been set with tftp_set_callback_vector
|
||||
; outputs: carry flag is set if there was an error
|
||||
; if a callback vector has been set with tftp_set_callback_vector
|
||||
; then the specified routine will be called once for each 512 byte packet
|
||||
; sent from the tftp server (each time AX will point at data block just arrived,
|
||||
; and tftp_data_block_length will contain number of bytes in that data block)
|
||||
; otherwise, the buffer at tftp_load_address will be filled
|
||||
; with file downloaded.
|
||||
; tftp_load_address: will be set to the actual address loaded into (NB - this field is
|
||||
; ignored if a callback vector has been set with tftp_set_callback_vector)
|
||||
tftp_upload:
|
||||
ldax #$0200 ;opcode 02 = WRQ
|
||||
jmp set_tftp_opcode
|
||||
|
||||
; query a tftp server for a directory listing (uses a non-standard tftp opcode,
|
||||
; currently only supported by tftp server built in to 'netboot65' server)
|
||||
; inputs:
|
||||
; tftp_ip: ip address of host to download from (set to 255.255.255.255 for broadcast)
|
||||
; tftp_filename: pointer to null terminated filemask (e.g. "*.prg",0)
|
||||
; tftp_load_address: memory location that dir will be stored in (NB - this field is
|
||||
; ignored if a callback vector has been set with tftp_set_download_callback)
|
||||
; ignored if a callback vector has been set with tftp_set_callback_vector)
|
||||
; outputs: carry flag is set if there was an error, clear otherwise
|
||||
; if a callback vector has been set with tftp_set_download_callback
|
||||
; if a callback vector has been set with tftp_set_callback_vector
|
||||
; then the specified routine will be called once for each 512 byte packet
|
||||
; sent from the tftp server (each time AX will point at data block just arrived,
|
||||
; and tftp_data_block_length will contain number of bytes in that data block)
|
||||
@ -124,27 +143,28 @@ tftp_directory_listing:
|
||||
; treat first 2 bytes received from tftp server as memory address that rest
|
||||
; of file should be loaded into (e.g. if downloading a C64 'prg' file)
|
||||
; outputs: carry flag is set if there was an error
|
||||
; if a callback vector has been set with tftp_set_download_callback
|
||||
; if a callback vector has been set with tftp_set_callback_vector
|
||||
; then the specified routine will be called once for each 512 byte packet
|
||||
; sent from the tftp server (each time AX will point at data block just arrived,
|
||||
; and tftp_data_block_length will contain number of bytes in that data block)
|
||||
; otherwise, the buffer at tftp_load_address will be filled
|
||||
; with file downloaded.
|
||||
; tftp_load_address: will be set to the actual address loaded into (NB - this field is
|
||||
; ignored if a callback vector has been set with tftp_set_download_callback)
|
||||
; ignored if a callback vector has been set with tftp_set_callback_vector)
|
||||
tftp_download:
|
||||
ldax #$0100 ;opcode 01 = RRQ
|
||||
set_tftp_opcode:
|
||||
stax tftp_opcode
|
||||
lda #tftp_initializing
|
||||
sta tftp_state
|
||||
sta tftp_expected_block_number ;(tftp_initializing=1)
|
||||
ldx #00
|
||||
stax tftp_current_block_number ;(tftp_initializing=1)
|
||||
ldax tftp_load_address
|
||||
stax tftp_current_memloc
|
||||
ldax #tftp_in
|
||||
stax udp_callback
|
||||
lda #$69
|
||||
inc tftp_client_port_low_byte ;each call to resolve uses a different client address
|
||||
inc tftp_client_port_low_byte ;each transfer uses a different client port
|
||||
ldx tftp_client_port_low_byte ;so we don't get confused by late replies to a previous call
|
||||
jsr udp_add_listener
|
||||
|
||||
@ -187,20 +207,25 @@ set_tftp_opcode:
|
||||
jsr send_ack ;send the ack for the last block
|
||||
lda #$69
|
||||
ldx tftp_client_port_low_byte
|
||||
jsr udp_remove_listener
|
||||
jsr udp_remove_listener
|
||||
rts
|
||||
|
||||
@not_complete:
|
||||
cmp #tftp_receiving_file
|
||||
bne @not_receiving
|
||||
jsr send_ack
|
||||
cmp #tftp_transmission_in_progress
|
||||
bne @not_transmitting
|
||||
jsr send_tftp_packet
|
||||
jmp @inner_delay_loop
|
||||
@not_receiving:
|
||||
@not_transmitting:
|
||||
jsr send_request_packet
|
||||
|
||||
@inner_delay_loop:
|
||||
|
||||
jsr ip65_process
|
||||
@inner_delay_loop:
|
||||
jsr ip65_process
|
||||
jsr check_for_abort_key
|
||||
bcc @no_abort
|
||||
lda #NB65_ERROR_ABORTED_BY_USER
|
||||
sta ip65_error
|
||||
jmp @exit_with_error
|
||||
@no_abort:
|
||||
lda tftp_break_inner_loop
|
||||
bne @outer_delay_loop
|
||||
jsr timer_read
|
||||
@ -259,7 +284,7 @@ send_request_packet:
|
||||
ldax #tftp_outp
|
||||
jsr udp_send
|
||||
bcs @error_in_send
|
||||
lda #tftp_rrq_sent
|
||||
lda #tftp_initial_request_sent
|
||||
sta tftp_state
|
||||
rts
|
||||
@error_in_send:
|
||||
@ -271,8 +296,13 @@ send_request_packet:
|
||||
send_ack:
|
||||
ldax #$0400 ;opcode 04 = ACK
|
||||
stax tftp_outp
|
||||
ldx tftp_block_number_to_ack
|
||||
ldx tftp_current_block_number
|
||||
lda tftp_current_block_number+1
|
||||
dex
|
||||
stax tftp_outp+2
|
||||
ldax #04
|
||||
stax tftp_send_len
|
||||
send_tftp_packet: ;TFTP block should be created in tftp_outp, we just add the UDP&IP stuff and send
|
||||
lda #$69
|
||||
ldx tftp_client_port_low_byte
|
||||
stax udp_send_src_port
|
||||
@ -288,10 +318,11 @@ send_ack:
|
||||
ldx tftp_actual_server_port
|
||||
lda tftp_actual_server_port+1
|
||||
stax udp_send_dest_port
|
||||
ldax #04
|
||||
ldax tftp_send_len
|
||||
stax udp_send_len
|
||||
|
||||
ldax #tftp_outp
|
||||
; .byte $92
|
||||
jsr udp_send
|
||||
rts
|
||||
|
||||
@ -334,15 +365,13 @@ tftp_in:
|
||||
@dont_set_load_address:
|
||||
lda tftp_inp+3 ;get the (low byte) of the data block
|
||||
|
||||
; bmi @recv_error ;if we get to block $80, we've d/led more than 64k!
|
||||
cmp tftp_expected_block_number
|
||||
cmp tftp_current_block_number
|
||||
beq :+
|
||||
jmp @not_expected_block_number
|
||||
:
|
||||
;this is the block we wanted
|
||||
sta tftp_block_number_to_ack
|
||||
inc tftp_expected_block_number
|
||||
lda #tftp_receiving_file
|
||||
;this is the block we wanted
|
||||
inc tftp_current_block_number
|
||||
lda #tftp_transmission_in_progress
|
||||
sta tftp_state
|
||||
lda #TFTP_MAX_RESENDS
|
||||
sta tftp_resend_counter
|
||||
@ -384,7 +413,8 @@ tftp_in:
|
||||
@got_pointer_to_tftp_data:
|
||||
|
||||
jsr tftp_callback_vector
|
||||
|
||||
jsr send_ack
|
||||
|
||||
lda udp_inp+4 ;check the length of the UDP packet
|
||||
cmp #02
|
||||
bne @last_block
|
||||
@ -392,7 +422,47 @@ tftp_in:
|
||||
lda udp_inp+5
|
||||
cmp #$0c
|
||||
bne @last_block
|
||||
|
||||
@not_data_block:
|
||||
|
||||
cmp #3
|
||||
beq :+
|
||||
jmp @not_ack
|
||||
:
|
||||
;it's an ACK, so we must be sending a file
|
||||
ldx tftp_inp+3 ;get the (low byte) of the data block
|
||||
inx
|
||||
cpx tftp_current_block_number
|
||||
beq :+
|
||||
jmp @not_expected_block_number
|
||||
:
|
||||
;the last block we sent was acked so now we need to send the next one
|
||||
;
|
||||
ldax #output_buffer+4
|
||||
jsr tftp_callback_vector ;this (caller supplied) routine should fill the buffer with up to 512 bytes
|
||||
stax tftp_data_block_length
|
||||
clc
|
||||
adc #4
|
||||
bcc :+
|
||||
inx
|
||||
:
|
||||
stax tftp_send_len
|
||||
ldax #$0300 ;opcode 03 = DATA
|
||||
stax tftp_outp
|
||||
ldx tftp_current_block_number
|
||||
lda tftp_current_block_number+1
|
||||
stax tftp_outp+2
|
||||
jsr send_tftp_packet
|
||||
inc tftp_current_block_number
|
||||
bcc :+
|
||||
inc tftp_current_block_number+1
|
||||
:
|
||||
|
||||
lda tftp_data_block_length+1 ;get length of data we just sent (high byte)
|
||||
cmp #2
|
||||
beq @last_block
|
||||
|
||||
@not_ack:
|
||||
@not_expected_block_number:
|
||||
rts
|
||||
|
||||
|
@ -44,7 +44,7 @@ nb65_std_cart.bin: nb65_std_cart.o $(IP65LIB) $(C64NB65LIB) $(INCFILES) ../cfg/r
|
||||
ruby fix_cart.rb $@ 8192
|
||||
|
||||
nb65_rrnet.bin: nb65_rrnet.o $(IP65LIB) $(C64NB65LIB) $(INCFILES) ../cfg/rrbin.cfg
|
||||
$(LD) -m nb65_rrnet.map -vm -C ../cfg/rrbin.cfg -o $@ $< $(IP65LIB) $(C64NB65LIB)
|
||||
$(LD) -m nb65_rrnet.map -Ln nb65_rr.lab -vm -C ../cfg/rrbin.cfg -o $@ $< $(IP65LIB) $(C64NB65LIB)
|
||||
ruby fix_cart.rb $@ 8193
|
||||
|
||||
utherboot.pg2: utherboot.o $(IP65LIB) $(APPLE2PROGLIB) $(INCFILES) ../cfg/a2language_card.cfg
|
||||
|
@ -72,8 +72,9 @@
|
||||
.import __DATA_RUN__
|
||||
.import __DATA_SIZE__
|
||||
.import cfg_tftp_server
|
||||
tftp_dir_buffer = $6000
|
||||
|
||||
tftp_dir_buffer = $6020
|
||||
nb65_param_buffer = $6000
|
||||
|
||||
.data
|
||||
exit_cart:
|
||||
.if (BANKSWITCH_SUPPORT=$02)
|
||||
@ -90,7 +91,6 @@ call_downloaded_prg:
|
||||
|
||||
.bss
|
||||
|
||||
nb65_param_buffer: .res $20
|
||||
|
||||
|
||||
.segment "CARTRIDGE_HEADER"
|
||||
@ -161,6 +161,8 @@ ldax #init_msg
|
||||
nb65call #NB65_INITIALIZE
|
||||
|
||||
main_menu:
|
||||
lda #21 ;make sure we are in upper case
|
||||
sta $d018
|
||||
jsr cls
|
||||
ldax #netboot65_msg
|
||||
jsr print
|
||||
@ -285,13 +287,14 @@ main_menu:
|
||||
|
||||
jsr select_option_from_menu
|
||||
bcc @tftp_filename_set
|
||||
lda #21 ;switch back to upper case
|
||||
sta $d018
|
||||
jmp main_menu
|
||||
@tftp_filename_set:
|
||||
jsr download
|
||||
bcc @file_downloaded_ok
|
||||
jmp bad_boot
|
||||
@tftp_boot_failed:
|
||||
jsr wait_for_keypress
|
||||
jmp main_menu
|
||||
|
||||
|
||||
@dir_failed:
|
||||
ldax #tftp_dir_listing_fail_msg
|
||||
@ -306,7 +309,7 @@ main_menu:
|
||||
ldax #no_files_on_server
|
||||
jsr print
|
||||
|
||||
jmp bad_boot
|
||||
jmp @tftp_boot_failed
|
||||
|
||||
@file_downloaded_ok:
|
||||
|
||||
|
@ -15,6 +15,16 @@ INCFILES=\
|
||||
../inc/common.i\
|
||||
../inc/commonprint.i\
|
||||
../inc/net.i\
|
||||
|
||||
all: \
|
||||
ip65test.dsk \
|
||||
testdns.prg \
|
||||
testdns.pg2 \
|
||||
testtftp.prg \
|
||||
testtftp.pg2\
|
||||
test_cart_api.prg\
|
||||
testdottedquad.pg2\
|
||||
testdottedquad.prg\
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
@ -28,21 +38,14 @@ INCFILES=\
|
||||
%.pg2: %.o $(IP65LIB) $(APPLE2NETLIB) $(INCFILES) ../cfg/a2bin.cfg
|
||||
$(LD) -C ../cfg/a2bin.cfg -o $*.pg2 $(AFLAGS) $< $(IP65LIB) $(APPLE2PROGLIB)
|
||||
|
||||
ip65test.dsk: testdns.pg2 testdottedquad.pg2
|
||||
ip65test.dsk: testdns.pg2 testdottedquad.pg2 testtftp.pg2
|
||||
ripxplore.rb --init BeautifulBoot ip65test.dsk -a testdns.pg2 -t AppleBinary
|
||||
ripxplore.rb ip65test.dsk -a testtftp.pg2 -t AppleBinary
|
||||
ripxplore.rb ip65test.dsk -a testdottedquad.pg2 -t AppleBinary
|
||||
|
||||
all: \
|
||||
ip65test.dsk \
|
||||
testdns.prg \
|
||||
test_cart_api.prg \
|
||||
testdns.pg2 \
|
||||
testdottedquad.pg2 \
|
||||
testdottedquad.prg \
|
||||
|
||||
ripxplore.rb ip65test.dsk -a testdns.pg2 -t AppleBinary
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f testdns.prg testdns.map testdns.pg2 testdottedquad.prg testdottedquad.pg2
|
||||
rm -f *.o *.pg2 *.prg
|
||||
rm -f ip65test.dsk
|
||||
|
||||
distclean: clean
|
||||
|
100
client/test/testtftp.s
Normal file
100
client/test/testtftp.s
Normal file
@ -0,0 +1,100 @@
|
||||
.include "../inc/common.i"
|
||||
.include "../inc/commonprint.i"
|
||||
.include "../inc/net.i"
|
||||
|
||||
.import exit_to_basic
|
||||
|
||||
.import cfg_get_configuration_ptr
|
||||
.import copymem
|
||||
.importzp copy_src
|
||||
.importzp copy_dest
|
||||
|
||||
|
||||
.import __CODE_LOAD__
|
||||
.import __CODE_SIZE__
|
||||
.import __RODATA_SIZE__
|
||||
.import __DATA_SIZE__
|
||||
.import tftp_upload
|
||||
.import tftp_set_callback_vector
|
||||
.import tftp_ip
|
||||
.importzp tftp_filename
|
||||
|
||||
.segment "STARTUP" ;this is what gets put at the start of the file on the C64
|
||||
|
||||
.word basicstub ; load address
|
||||
|
||||
basicstub:
|
||||
.word @nextline
|
||||
.word 2003
|
||||
.byte $9e
|
||||
.byte <(((init / 1000) .mod 10) + $30)
|
||||
.byte <(((init / 100 ) .mod 10) + $30)
|
||||
.byte <(((init / 10 ) .mod 10) + $30)
|
||||
.byte <(((init ) .mod 10) + $30)
|
||||
.byte 0
|
||||
@nextline:
|
||||
.word 0
|
||||
|
||||
.segment "EXEHDR" ;this is what gets put an the start of the file on the Apple 2
|
||||
.addr __CODE_LOAD__-$11 ; Start address
|
||||
.word __CODE_SIZE__+__RODATA_SIZE__+__DATA_SIZE__+4 ; Size
|
||||
jmp init
|
||||
|
||||
.code
|
||||
|
||||
init:
|
||||
jsr print_cr
|
||||
init_ip_via_dhcp
|
||||
jsr print_ip_config
|
||||
|
||||
ldax #upload_callback
|
||||
jsr tftp_set_callback_vector
|
||||
lda #0
|
||||
sta block_number
|
||||
ldax #test_file
|
||||
stax tftp_filename
|
||||
lda #$ff
|
||||
ldx #$3
|
||||
:
|
||||
sta tftp_ip,x
|
||||
dex
|
||||
bpl :-
|
||||
|
||||
ldax #sending
|
||||
jsr print
|
||||
jsr tftp_upload
|
||||
rts
|
||||
|
||||
upload_callback:
|
||||
stax copy_dest
|
||||
ldax #buffer1
|
||||
stax copy_src
|
||||
inc block_number
|
||||
lda block_number
|
||||
ldx #00
|
||||
@next_byte:
|
||||
sta buffer1,x
|
||||
sta buffer2,x
|
||||
inx
|
||||
bne @next_byte
|
||||
cmp #7
|
||||
beq @last_block
|
||||
ldax #512
|
||||
jmp :+
|
||||
@last_block:
|
||||
ldax #0
|
||||
:
|
||||
stax block_length
|
||||
jsr copymem
|
||||
ldax block_length
|
||||
rts
|
||||
.rodata
|
||||
|
||||
test_file: .byte "TESTFILE.BIN",0
|
||||
sending: .byte "SENDING...",0
|
||||
|
||||
.bss
|
||||
block_number: .res 1
|
||||
block_length: .res 2
|
||||
buffer1: .res 256
|
||||
buffer2: .res 256
|
1
dist/make_dist.rb
vendored
1
dist/make_dist.rb
vendored
@ -16,6 +16,7 @@ end
|
||||
[
|
||||
["client/nb65/utherboot.dsk","nb65/"],
|
||||
["client/nb65/nb65_rrnet.bin","nb65/"],
|
||||
["client/nb65/nb65_c64_ram.prg","nb65/"],
|
||||
["client/nb65/nb65_std_cart.bin","nb65/"],
|
||||
["server/lib/tftp_server.rb","lib"],
|
||||
["server/bin/tftp_only_server.rb","bin/tftp_server.rb"],
|
||||
|
@ -9,6 +9,8 @@
|
||||
require 'socket'
|
||||
class Netboot65TFTPServer
|
||||
|
||||
|
||||
|
||||
TFTP_OPCODES={
|
||||
1=>'RRQ', #read request
|
||||
2=>'WRQ', #write request
|
||||
@ -34,7 +36,7 @@ class Netboot65TFTPServer
|
||||
@bootfile_dir=bootfile_dir
|
||||
@port=port
|
||||
@server_thread=nil
|
||||
|
||||
@current_connection={}
|
||||
end
|
||||
|
||||
def send_error(client_ip,client_port,error_code,error_msg)
|
||||
@ -86,12 +88,17 @@ class Netboot65TFTPServer
|
||||
|
||||
client_sock=UDPSocket.open
|
||||
client_sock.connect(client_ip,client_port)
|
||||
|
||||
client_id="#{client_ip}:#{client_port}"
|
||||
if @current_connection[client_id]==true then
|
||||
log_msg("already sending to #{client_id}" )
|
||||
end
|
||||
@current_connection[client_id]=true
|
||||
log_msg("receiving #{filename} from #{client_ip}:#{client_port}")
|
||||
got_last_block=false
|
||||
sent_last_ack=false
|
||||
finished=false
|
||||
block_number=0
|
||||
until sent_last_ack do
|
||||
finished
|
||||
until finished do
|
||||
packet=[4,block_number].pack("nn")
|
||||
got_block=false
|
||||
TFTP_MAX_RESENDS.times do |attempt_number|
|
||||
@ -99,7 +106,7 @@ class Netboot65TFTPServer
|
||||
client_sock.send(packet,0,client_ip,client_port)
|
||||
if got_last_block then
|
||||
puts "last block received"
|
||||
sent_last_ack=true
|
||||
finished=true
|
||||
break
|
||||
else
|
||||
if (IO.select([client_sock], nil, nil, 1)) then
|
||||
@ -123,15 +130,17 @@ class Netboot65TFTPServer
|
||||
end
|
||||
end
|
||||
break if got_block
|
||||
if !got_block then
|
||||
log_msg "TFTP: timed out waiting for DATA for block #{block_number+1} from #{client_ip}"
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if !got_block && !finished then
|
||||
log_msg "TFTP: timed out waiting for DATA for block #{block_number+1} from #{client_ip}"
|
||||
finished=true
|
||||
break
|
||||
end
|
||||
block_number+=1
|
||||
end
|
||||
file_handle.close
|
||||
@current_connection[client_id]=false
|
||||
end
|
||||
|
||||
def start()
|
||||
|
Loading…
Reference in New Issue
Block a user