class GxG::Networking::XmppAgentFileTransfer
File Transfer
Public Class Methods
new(manager, direction, details, parent)
click to toggle source
Review : totally rewrite this
# File lib/gxg/net_clients.rb, line 2538 def initialize(manager, direction, details, parent) @reference = ::GxG::uuid_generate.to_sym @session_id = nil @pending = true @inprogress = false @percent_completed = 0 @status_thread_safety = ::Mutex.new @manager = manager @direction = direction @info = {:reference => @reference} @bytestream = nil @file_details = nil @cancel = false the_value = ::GxG::SYSTEM.maximum_buffer_size.get_at_path("/:ipv4/:tcp/:write/:valid") if the_value.is_a?(::Range) @valid_write_buffer_sizes = the_value else @valid_write_buffer_sizes = (4096..65536) end @buffer_size = 4096 @client = parent if @direction == :download @invitation = details[:iq] @sender = details[:iq].from @info[:sender] = @sender.to_s @info[:recipient] = @client.jid.to_s @file_details = {:filename => details[:file_info].fname, :path => (details[:download_directory] + "/" + details[:file_info].fname), :size => details[:file_info].size, :md5 => details[:file_info].hash, :description => details[:file_info].description} @download_directory = details[:download_directory] @info[:details] = @file_details @recipient = nil # # end if @direction == :upload @info[:sender] = @client.jid.to_s @info[:recipient] = details[:jid].to_s @recipient = ::Jabber::JID.new(details[:jid]) @file_details = {:filename => ::File.basename(details[:path]), :path => details[:path], :size => ::File.size(details[:path]), :md5 => ::Digest::MD5.file(details[:path]), :description => details[:description]} @info[:details] = @file_details @invitation = nil @download_directory = nil end self end
Public Instance Methods
accept()
click to toggle source
# File lib/gxg/net_clients.rb, line 2651 def accept() if @client if @status_thread_safety.synchronize { @pending == true && @direction == :download } Thread.new { begin bytes_received = 0 total_size = @file_details[:size] @bytestream = @manager.accept(@invitation) if @bytestream @bytestream.accept() @status_thread_safety.synchronize { @pending = false @inprogress = true @session_id = @bytestream.session_id.to_s } # cancel_callback = Proc.new do |the_iq| if the_iq.type == :error the_error = ::Jabber::ServerError.new(the_iq.error) if @invitation.id.to_s == the_iq.id.to_s the_transfer = @client.find_file_transfer(@reference) if the_transfer the_transfer.cancel end end log_error({:error => the_error, :parameters => {:iq => the_iq}}) end end @client.set_xfr_callback(@session_id,&cancel_callback) # the_file = ::File.open(@file_details[:path], "w+b",0664) the_file.pos = 0 buffer = @bytestream.read() while buffer && @status_thread_safety.synchronize { @cancel == false } do the_file.write(buffer.to_s) bytes_received += buffer.to_s.size @status_thread_safety.synchronize { @percent_completed = ((bytes_received.to_f / total_size.to_f) * 100.0).to_i } @client.notify({:event => :file_transfer_progress, :transfer => @reference, :progress => @status_thread_safety.synchronize { @percent_completed }}) buffer = @bytestream.read() end the_file.close @bytestream.close @status_thread_safety.synchronize { @inprogress = false @pending = false } the_path = @file_details[:path] if @status_thread_safety.synchronize { @cancel == true } ::File.delete(the_path) @client.notify({:event => :file_transfer_cancelled, :transfer => @reference}) else if @file_details[:md5] unless @file_details[:md5] == ::Digest::MD5.file(the_path) raise Exception, "MD5 Checksum Failure - file corruption on file: #{the_path}" end @client.notify({:event => :file_transfer_complete, :transfer => @reference}) end end else @status_thread_safety.synchronize { @inprogress = false @pending = false } the_file = nil raise Exception, "Failed to negotiate a transfer method." end rescue Exception => the_error @status_thread_safety.synchronize { @inprogress = false @pending = false } if the_file the_file.close end if @bytestream @bytestream.close end log_error({:error => the_error, :parameters => {}}) @client.notify({:event => :file_transfer_error, :transfer => @reference}) end if @session_id @client.clear_xfr_callback(@session_id) end @client.refresh_file_transfers } end true else false end end
buffer_size()
click to toggle source
# File lib/gxg/net_clients.rb, line 2603 def buffer_size() @status_thread_safety.synchronize { @buffer_size } end
buffer_size=(the_size=4096)
click to toggle source
# File lib/gxg/net_clients.rb, line 2607 def buffer_size=(the_size=4096) begin unless the_size.is_a?(::Integer) raise ArgumentError, "You MUST provide an Integer to set buffer size." end if @status_thread_safety.synchronize { @direction == :upload } unless @valid_write_buffer_sizes.include?(the_size) raise ArgumentError, "You MUST provide an Integer between #{@valid_read_buffer_sizes.first} and #{@valid_read_buffer_sizes.last}." @status_thread_safety.synchronize { @buffer_size = the_size } end else log_warn("Buffer size is only set on upload file transfers.") end the_size rescue Exception => the_error log_error({:error => the_error, :parameters => {}}) nil end end
cancel()
click to toggle source
# File lib/gxg/net_clients.rb, line 2631 def cancel() if @client begin if @status_thread_safety.synchronize { @pending == true } @status_thread_safety.synchronize { @pending = false } end if @status_thread_safety.synchronize { @inprogress == true } @status_thread_safety.synchronize { @inprogress = false } end @status_thread_safety.synchronize { @cancel = true } @client.refresh_file_transfers true rescue Exception => the_error log_error({:error => the_error, :parameters => {}}) end else false end end
cancelled?()
click to toggle source
# File lib/gxg/net_clients.rb, line 2627 def cancelled?() @status_thread_safety.synchronize { @cancel } end
decline()
click to toggle source
# File lib/gxg/net_clients.rb, line 2743 def decline() if @client if @status_thread_safety.synchronize { @pending == true && @direction == :download } begin @manager.decline(@invitation) @status_thread_safety.synchronize { @pending = false } rescue Exception => the_error log_error({:error => the_error, :parameters => {}}) end end true else false end end
download_directory()
click to toggle source
# File lib/gxg/net_clients.rb, line 2771 def download_directory() @status_thread_safety.synchronize { @download_directory.clone } end
download_directory=(the_path=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 2775 def download_directory=(the_path=nil) begin unless the_path.is_a?(::String) raise ArgumentError, "You MUST supply a String as valid directory path." end the_path = ::File.expand_path(the_path) unless the_path.valid_path?() raise ArgumentError, "You MUST supply a valid directory path." end unless ::File.exist?(the_path) raise ArgumentError, "You MUST supply a valid directory path - Directory does not exist." end @status_thread_safety.synchronize { unless @inprogress == true if @direction == :download @download_directory = ::File.expand_path(the_path) @file_details[:path] = (@download_directory + "/" + @file_details[:filename]) end end } rescue Exception => the_error log_error({:error => the_error, :parameters => {}}) end end
file_details()
click to toggle source
# File lib/gxg/net_clients.rb, line 2767 def file_details() @status_thread_safety.synchronize { @file_details.clone } end
in_progress?()
click to toggle source
# File lib/gxg/net_clients.rb, line 2759 def in_progress?() @status_thread_safety.synchronize { @inprogress } end
info()
click to toggle source
# File lib/gxg/net_clients.rb, line 2587 def info() @info.clone end
inspect()
click to toggle source
# File lib/gxg/net_clients.rb, line 2583 def inspect() "<Transfer: #{@direction.inspect} - #{@reference}, with Session ID: #{@session_id} for File #{@file_details[:filename]}>" end
pending?()
click to toggle source
# File lib/gxg/net_clients.rb, line 2599 def pending?() @status_thread_safety.synchronize { @pending } end
percent_completed()
click to toggle source
# File lib/gxg/net_clients.rb, line 2763 def percent_completed() @status_thread_safety.synchronize { @percent_completed.clone } end
reference()
click to toggle source
# File lib/gxg/net_clients.rb, line 2591 def reference() @reference.clone end
session_id()
click to toggle source
# File lib/gxg/net_clients.rb, line 2595 def session_id() @session_id.clone end
upload_file(proxy=nil)
click to toggle source
# File lib/gxg/net_clients.rb, line 2800 def upload_file(proxy=nil) if @client if @direction == :upload unless @status_thread_safety.synchronize { @inprogress == true } Thread.new { begin bytes_sent = 0 buffer_size = @status_thread_safety.synchronize { @buffer_size } the_file_source = ::Jabber::FileTransfer::FileSource.new(@file_details[:path]) the_file_source.length = buffer_size total_size = the_file_source.size @bytestream = nil response = @manager.offer(@recipient,the_file_source,@file_details[:description],nil,@reference.to_s) if response.is_a?(::Hash) @bytestream = response[:bytestream] the_iq_id = response[:iq_id] if @bytestream if @bytestream.is_a?(::Jabber::Bytestreams::SOCKS5BytestreamsInitiator) if proxy.is_any?(::String, ::Jabber::JID) @bytestream.add_streamhost(proxy) end end if @bytestream.is_a?(::Jabber::Bytestreams::IBBInitiator) @bytestream.block_size = buffer_size end # @status_thread_safety.synchronize { @pending = false @inprogress = true } open_response = @bytestream.open() if open_response puts "Got: (open_response) - #{open_response.inspect}" if open_response.type == :result # @session_id = @bytestream.session_id.to_s # cancel_callback = Proc.new do |the_iq| if the_iq.type == :error the_error = ::Jabber::ServerError.new(the_iq.error) if the_iq_id.to_s == the_iq.id.to_s the_transfer = @client.find_file_transfer(@reference) if the_transfer the_transfer.cancel end end log_error({:error => the_error, :parameters => {:iq => the_iq}}) end end @client.set_xfr_callback(@session_id,&cancel_callback) # ::GxG.apportioned_ranges(total_size,buffer_size).each do |the_range| if @status_thread_safety.synchronize { @cancel == true } the_file_source.close break end the_file_source.seek(the_range.first) bytes_sent += @bytestream.write(the_file_source.read(the_range.size)).to_i @status_thread_safety.synchronize { @percent_completed = ((bytes_sent.to_f / total_size.to_f) * 100.0).to_i } # end @bytestream.flush @bytestream.close @status_thread_safety.synchronize { @inprogress = false } else # Error? @status_thread_safety.synchronize { @pending = false @inprogress = false } end else raise Exception, "Failed to open the stream." end end else @status_thread_safety.synchronize { @pending = false @inprogress = false } end rescue Exception => the_error the_file_source.close @bytestream.close @status_thread_safety.synchronize { @inprogress = false } log_error({:error => the_error, :parameters => {:proxy => proxy}}) end @client.clear_xfr_callback(@reference.to_s) if @session_id @client.clear_xfr_callback(@session_id) end @client.refresh_file_transfers } end end end end