class Communicator

Attributes

ConnectionIdentifier[R]
heartbeat[RW]
responses[RW]
utils[RW]

Public Class Methods

new(client, host='127.0.0.1', port=9481, version = 2.0) click to toggle source

clients name must be unique This performs NodeHello operations upon initialization. Communicator handles packet sending and recieving and sorting

# File lib/ruby-fcp/communicator.rb, line 12
def initialize(client, host='127.0.0.1', port=9481, version = 2.0)
  @version = version
  @ConnectionIdentifier = ""
  @host = host
  @port = port
  @client = client
  @responses = { peers: [],dda: [], default: [], error: [], datalengths: {} }
  @tex = Mutex.new
  @state = false
  @queue = Queue.new
  @heartbeat = 300
  @utils = Utils.new
  connect
end

Public Instance Methods

close() click to toggle source

Send disconnect message and close the socket

# File lib/ruby-fcp/communicator.rb, line 132
def close
  @tex.synchronize{@sock.write "Disconnect EndMessage\n"}
  @sock.close
end
connect() click to toggle source
# File lib/ruby-fcp/communicator.rb, line 27
def connect
  @sock = TCPSocket.new @host ,@port
  @sock.write @utils.packet_mangler({"Name" => @client,"ExpectedVersion" => @version},"ClientHello")
  response = grab_response
  unless response[:state] == -1
    @sock_thrd = Thread.new {sock_thrd}
    @ConnectionIdentifier = response["ConnectionIdentifier"]
    @state = true
    keep_alive
  end
end
grab_response() click to toggle source
# File lib/ruby-fcp/communicator.rb, line 107
def grab_response
  response = { state: 1 }
  line = @sock.readline
  response[:state] = -1 if line =~ /ClosedConnectionDuplicateClientName|ProtocolError/
  response[:head] = line.chomp
  until line =~ /EndMessage|^Data$/
    response[line.split('=')[0]] = line.split('=')[1].chomp if line.split('=').size == 2
    line = @sock.readline
  end
  @responses[:datalengths][response["Identifier"]] = response["DataLength"].to_i if response.has_key? "DataLength"
  response[:data] = @sock.read @responses[:datalengths][response["Identifier"]] if response[:head] =~ /AllData/
  response
end
keep_alive() click to toggle source
# File lib/ruby-fcp/communicator.rb, line 121
def keep_alive
  Thread.start do
    loop do
     send_packet "Void\nEndMessage\n"
     sleep @heartbeat
     break if @state == false
    end
  end
end
send_packet(message) click to toggle source
# File lib/ruby-fcp/communicator.rb, line 103
def send_packet(message)
  @queue.push message
end
sock_thrd() click to toggle source
# File lib/ruby-fcp/communicator.rb, line 39
def sock_thrd
  @threads = []
  loop do
    @threads.each do |thrd|
      begin 
        @threads.delete thrd if thrd.join(0.5)
      rescue RequestFinished => req
        @responses[:error].push req 
      rescue Exception => excpt
        puts "#{excpt}"
        @threads.delete thrd 
      end
      if thrd.status == false
        @threads.delete thrd 
      elsif thrd.status == nil
        @threads.delete thrd 
      end
    end
    
    @sock.close Thread.exit if @state == false
    
    begin
      while packet = @queue.pop(true)
        @tex.synchronize{@sock.write packet}
        #sort_out(packet)
      end
    rescue ThreadError => err
    end
    
    begin 
      if select([@sock], nil,nil,2)
        packet = @tex.synchronize{grab_response}
        sort_out(packet)
      end
    rescue
      @sock.close Thread.exit
      state = false
      connect
    end
  end
end
sort_out(packet) click to toggle source
# File lib/ruby-fcp/communicator.rb, line 81
def sort_out(packet)
  if packet[:head].include? "NodeHello"
    @ConnectionIdentifier = packet["ConnectionIdentifier"]
  elsif packet[:head].include? "CloseConnectionDuplicateClientName"
    @state = false
  elsif packet.has_key? "Identifier"
    if @responses.has_key? packet["Identifier"]
      @responses[packet["Identifier"]].push packet
    else
      @responses[packet["Identifier"]] = [packet]
    end
  elsif packet[:head].include? "DDA"
    @responses[:dda].push packet 
  elsif packet[:state] == -1
    @responses[:error].push packet
  elsif packet[:head].include? "Peer"
    @responses[:peers].push packet
  else packet
    @responses[:default].push packet
  end
end