Class: Frostbitten::Connection

Inherits:
Object
  • Object
show all
Defined in:
lib/frostbitten/connection.rb

Constant Summary collapse

DEFAULTS =
{
	# connect/read/write timeout for socket operations
	:socket_timeout => 0.5,
	
	:keepalive => true
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri, options = {}) ⇒ Connection

Initialize class with URI ‘fbrcon://password@ip:port’ Also accept options { :keepalive = true/false, :socket_timeout => 1 }



26
27
28
29
30
31
32
33
34
35
36
# File 'lib/frostbitten/connection.rb', line 26

def initialize(uri, options={})
	server_parsed = URI.parse(uri)
	self.hostname = server_parsed.host
	self.password = server_parsed.user
	self.port = server_parsed.port ||= 47200

	@sock = nil 
	@sequence = options[:sequence] ||= 0

	@options = DEFAULTS.merge(options)
end

Instance Attribute Details

#hostnameObject

Returns the value of attribute hostname.



19
20
21
# File 'lib/frostbitten/connection.rb', line 19

def hostname
  @hostname
end

#passwordObject

Returns the value of attribute password.



19
20
21
# File 'lib/frostbitten/connection.rb', line 19

def password
  @password
end

#portObject

Returns the value of attribute port.



19
20
21
# File 'lib/frostbitten/connection.rb', line 19

def port
  @port
end

#sequenceObject (readonly)

Returns the value of attribute sequence.



20
21
22
# File 'lib/frostbitten/connection.rb', line 20

def sequence
  @sequence
end

#sockObject (readonly)

Returns the value of attribute sock.



20
21
22
# File 'lib/frostbitten/connection.rb', line 20

def sock
  @sock
end

#timeoutObject (readonly)

Returns the value of attribute timeout.



20
21
22
# File 'lib/frostbitten/connection.rb', line 20

def timeout
  @timeout
end

Instance Method Details

#alive?Boolean

Returns if the socket is alive of closed

Returns:

  • (Boolean)


39
40
41
42
# File 'lib/frostbitten/connection.rb', line 39

def alive?
	return true if @sock
	return false
end

#closeObject

Close socket



62
63
64
65
66
# File 'lib/frostbitten/connection.rb', line 62

def close
	return unless alive?
	@sock.close
	@sock = nil
end

#connectObject

Connects socket



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/frostbitten/connection.rb', line 45

def connect
	return if alive?
	@sock = TCPSocket.open(self.hostname, self.port);
	if @options[:socket_timeout]
      		secs = Integer(@options[:socket_timeout])
      		usecs = Integer((@options[:socket_timeout] - secs) * 1_000_000)
      		optval = [secs, usecs].pack("l_2")
      		@sock.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, optval
      		@sock.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval
    		end

    		if @options[:keepalive]
    			@sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
    		end
end

#send(message) ⇒ Object

Accepts a Frostbitten::Mesage and sends it over socket updates message.header.sequence with a incremented version of server sequence counter. can raise NameError, ArgumentError or StandardError based on return data from server.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/frostbitten/connection.rb', line 74

def send(message) 
	connect unless self.alive?
	unless message.header.is_response?
		@sequence += 1
	end

	message.header.sequence = self.sequence
	message.write @sock

	m = Message.new()
	m.read @sock

	unless m.words.first == "OK"
		m.words.first.tap do |word|
		 	if word == "UnknownCommand"
		 		raise NameError, "UnknownCommand raised by server"
		 	elsif word == "InvalidArguments"
		 		raise ArgumentError, "InvalidArguments raised by server"
		 	else
		 		raise StandardError, "Server returned #{word}"
		 	end
		 end
	end
	return m
end