class TFTP::Transfer
An in-progress file transfer operation Holds all the state which a TFTP
server/client needs to track for a single transfer Subclasses contain logic specific to client downloads, server downloads, client uploads, server uploads
Constants
- BASE_RETRANSMIT_TIMEOUT
- MAX_RETRANSMIT_TIMEOUT
Attributes
block_no[RW]
buffer[RW]
peer_addr[R]
peer_port[R]
timeout[RW]
timer[RW]
Public Class Methods
new(connection, peer_addr, peer_port, listener)
click to toggle source
# File lib/em-tftp.rb, line 111 def initialize(connection, peer_addr, peer_port, listener) # 'connection' is the UDP socket used for this transfer (actually an EventMachine::Connection object) # each transfer uses a newly opened UDP socket, which is closed after the transfer is finished # this is because the UDP port number doubles as a TFTP transfer ID # so using the same port number for 2 successive requests to the same peer may cause problems @connection = connection @peer_addr, @peer_port, @listener = peer_addr, peer_port, listener @buffer = @block_no = @timer = nil @timeout = 1.5 end
Public Instance Methods
abort!(code=0, error_msg=Protocol::ERROR_MESSAGES[code])
click to toggle source
Abort the file transfer. An optional error message and code can be included. This should be called if the transfer cannot be completed due to a full hard disk, wrong permissions, etc
TFTP
error codes include:
0 Not defined, see error message (if any). 1 File not found. 2 Access violation. 3 Disk full or allocation exceeded. 4 Illegal TFTP
operation. 5 Unknown transfer ID. 6 File already exists. 7 No such user.
# File lib/em-tftp.rb, line 138 def abort!(code=0, error_msg=Protocol::ERROR_MESSAGES[code]) stop_timer! send_error(code, error_msg || "Unknown error") @connection.close_connection_after_writing @listener.failed(error_msg || "Unknown error") end
error!(error_msg)
click to toggle source
# File lib/em-tftp.rb, line 145 def error!(error_msg) stop_timer! @connection.close_connection @listener.failed(error_msg) end
Private Instance Methods
finished!()
click to toggle source
# File lib/em-tftp.rb, line 171 def finished! stop_timer! @connection.close_connection @listener.completed end
rrq(packet, port)
click to toggle source
# File lib/em-tftp.rb, line 183 def rrq(packet, port) # a transfer has already started and is not yet finished # a RRQ/WRQ shouldn't arrive at this time abort!(4, "Received unexpected TFTP RRQ packet") end
send_packet(addr=@peer_addr, port=@peer_port, packet_data)
click to toggle source
# File lib/em-tftp.rb, line 177 def send_packet(addr=@peer_addr, port=@peer_port, packet_data) $stderr.puts "Sending: #{packet_data} (#{packet_data[0..3].bytes.to_a.join(',')}) to #{addr}:#{port}" if $DEBUG @connection.send_datagram(packet_data, addr, port) set_timer!(packet_data) unless packet_data.start_with? "\0\5" # no timeout and retransmit for error packets end
set_timer!(data)
click to toggle source
# File lib/em-tftp.rb, line 160 def set_timer!(data) @timer = EM::Timer.new(@timeout) do @timeout *= 2 if @timeout <= MAX_RETRANSMIT_TIMEOUT send_packet(data) else abort!(0, "Connection timed out") end end end
stop_timer!()
click to toggle source
# File lib/em-tftp.rb, line 153 def stop_timer! if @timer @timer.cancel @timer = nil end @timeout = BASE_RETRANSMIT_TIMEOUT end
wrq(packet, port)
click to toggle source
# File lib/em-tftp.rb, line 188 def wrq(packet, port) abort!(4, "Received unexpected TFTP WRQ packet") end