smartfox 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/lib/smartfox/client.rb +63 -6
- data/lib/smartfox/packet.rb +37 -5
- data/lib/smartfox/room.rb +3 -0
- data/lib/smartfox/socket/connection.rb +13 -6
- data/smartfox.gemspec +6 -3
- data/spec/packet_spec.rb +26 -0
- data/spec/smartfox_spec.rb +42 -0
- metadata +7 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.1
|
data/lib/smartfox/client.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'builder'
|
2
2
|
require 'libxml'
|
3
|
+
require 'json'
|
3
4
|
|
4
5
|
class SmartFox::Client
|
5
6
|
class ConnectionFailureError < SmartFox::SmartFoxError; end
|
@@ -7,19 +8,27 @@ class SmartFox::Client
|
|
7
8
|
class TransportTimeoutError < SmartFox::SmartFoxError; end
|
8
9
|
|
9
10
|
attr_reader :connected, :room_list, :buddy_list, :server, :port
|
11
|
+
attr_reader :current_room
|
10
12
|
alias_method :connected?, :connected
|
11
13
|
|
12
14
|
CLIENT_VERSION = "1.5.8"
|
13
15
|
CONNECTION_TIMEOUT = 5
|
14
16
|
TRANSPORTS = [ SmartFox::Socket::Connection, SmartFox::BlueBox::Connection ]
|
15
|
-
EVENTS = [ :connected, :logged_in ]
|
17
|
+
EVENTS = [ :connected, :logged_in, :rooms_updated ]
|
16
18
|
|
17
19
|
HEADER_SYSTEM = 'sys'
|
20
|
+
HEADER_EXTENDED = 'xt'
|
21
|
+
|
18
22
|
ACTION_VERSION_CHECK = 'verChk'
|
19
23
|
ACTION_API_OK = 'apiOK'
|
20
24
|
ACTION_API_OBSOLETE = 'apiKO'
|
21
25
|
ACTION_LOGIN = 'login'
|
22
26
|
ACTION_LOGIN_OK = 'logOK'
|
27
|
+
ACTION_AUTO_JOIN = 'autoJoin'
|
28
|
+
ACTION_UPDATE_ROOMS = 'getRmList'
|
29
|
+
ACTION_ROOM_LIST = 'rmList'
|
30
|
+
|
31
|
+
EXTENDED_RESPONSE = 'xtRes'
|
23
32
|
|
24
33
|
def initialize(options = {})
|
25
34
|
@room_list = {}
|
@@ -30,6 +39,7 @@ class SmartFox::Client
|
|
30
39
|
@server = options[:server] || 'localhost'
|
31
40
|
@port = options[:port]
|
32
41
|
@events = {}
|
42
|
+
@rooms = []
|
33
43
|
end
|
34
44
|
|
35
45
|
def connect()
|
@@ -59,13 +69,30 @@ class SmartFox::Client
|
|
59
69
|
end
|
60
70
|
end
|
61
71
|
|
72
|
+
def extended_command(action, data = nil, room = -1, options = {})
|
73
|
+
options[:format] ||= :xml
|
74
|
+
|
75
|
+
case options[:format]
|
76
|
+
when :xml
|
77
|
+
send_packet(HEADER_EXTENDED, action, room) { |x| x.cdata!(data || '') }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
62
81
|
def add_handler(event, &proc)
|
63
82
|
@events[event.to_sym] = [] unless @events[event.to_sym]
|
64
83
|
@events[event.to_sym] << proc
|
65
84
|
end
|
66
85
|
|
86
|
+
def refresh_rooms
|
87
|
+
send_packet(HEADER_SYSTEM, ACTION_UPDATE_ROOMS)
|
88
|
+
end
|
89
|
+
|
67
90
|
def connect_succeeded
|
68
|
-
send_packet(HEADER_SYSTEM, ACTION_VERSION_CHECK) { |x| x.ver(:v => CLIENT_VERSION.delete('.')) }
|
91
|
+
send_packet(HEADER_SYSTEM, ACTION_VERSION_CHECK, 0) { |x| x.ver(:v => CLIENT_VERSION.delete('.')) }
|
92
|
+
end
|
93
|
+
|
94
|
+
def auto_join
|
95
|
+
send_packet(HEADER_SYSTEM, ACTION_AUTO_JOIN)
|
69
96
|
end
|
70
97
|
|
71
98
|
def packet_recieved(data)
|
@@ -80,7 +107,7 @@ class SmartFox::Client
|
|
80
107
|
complete_login(packet)
|
81
108
|
end
|
82
109
|
when HEADER_EXTENSION
|
83
|
-
|
110
|
+
raise_event :extended_response, self, packet.data
|
84
111
|
end
|
85
112
|
rescue => e
|
86
113
|
SmartFox::Logger.error "In SmartFox::Client#packet_received"
|
@@ -98,19 +125,40 @@ class SmartFox::Client
|
|
98
125
|
Thread.pass
|
99
126
|
end
|
100
127
|
|
128
|
+
def send_extended(extension, action, options)
|
129
|
+
options[:format] ||= :xml
|
130
|
+
options[:room] ||= (current_room ? current_room.id : 0)
|
131
|
+
options[:parameters] ||= {}
|
132
|
+
|
133
|
+
case options[:format]
|
134
|
+
when :xml
|
135
|
+
|
136
|
+
when :json
|
137
|
+
send_extended_json_packet(extension, action, options[:room], options[:parameters])
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
101
141
|
private
|
102
|
-
def send_packet(header, action, room_id =
|
142
|
+
def send_packet(header, action, room_id = -1)
|
103
143
|
xml = Builder::XmlMarkup.new()
|
104
144
|
xml.msg(:t => header) do |msg|
|
105
145
|
msg.body(:r => room_id, :action => action) do |body|
|
106
|
-
|
146
|
+
if block_given?
|
147
|
+
yield body
|
148
|
+
end
|
107
149
|
end
|
108
150
|
end
|
109
151
|
packet = xml.target!
|
110
|
-
SmartFox::Logger.
|
152
|
+
SmartFox::Logger.debug "SmartFox::Client#send_packet -> #{packet}"
|
111
153
|
@transport.send_data(packet + "\0")
|
112
154
|
end
|
113
155
|
|
156
|
+
def send_extended_json_packet(name, action, room, object)
|
157
|
+
packet = { :t => 'xt', :b => { :x => name, :c => action, :r => room, :p => object } }
|
158
|
+
SmartFox::Logger.debug "SmartFox::Client#send_extended_json_packet -> #{packet.to_json}"
|
159
|
+
@transport.send_data(packet.to_json + "\0")
|
160
|
+
end
|
161
|
+
|
114
162
|
def raise_event(event_name, *params)
|
115
163
|
event = @events[event_name.to_sym]
|
116
164
|
return unless event
|
@@ -138,6 +186,15 @@ class SmartFox::Client
|
|
138
186
|
@id = packet.data['id']
|
139
187
|
SmartFox::Logger.info "SmartFox::Client logged in as #{@username}"
|
140
188
|
raise_event(:logged_in, self)
|
189
|
+
when ACTION_ROOM_LIST
|
190
|
+
@rooms.clear
|
191
|
+
packet.data.children.each do |room|
|
192
|
+
@rooms << SmartFox::Room.parse(room)
|
193
|
+
end
|
194
|
+
|
195
|
+
raise_event(:rooms_updated, self, @rooms)
|
141
196
|
end
|
142
197
|
end
|
198
|
+
|
199
|
+
|
143
200
|
end
|
data/lib/smartfox/packet.rb
CHANGED
@@ -6,8 +6,8 @@ class SmartFox::Packet
|
|
6
6
|
def initialize(header, action, room = 0, extra = nil)
|
7
7
|
@header = header
|
8
8
|
@action = action
|
9
|
-
@room = room
|
10
|
-
@data = extra
|
9
|
+
@room = room.to_i
|
10
|
+
@data = (@header == SmartFox::Client::HEADER_EXTENDED ? SmartFox::Packet.parse_extended(extra) : extra)
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.parse(data)
|
@@ -22,7 +22,7 @@ class SmartFox::Packet
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.parse_xml(data)
|
25
|
-
SmartFox::Logger.debug "SmartFox::Packet
|
25
|
+
SmartFox::Logger.debug "SmartFox::Packet.parse_xml('#{data}')"
|
26
26
|
document = LibXML::XML::Parser.string(data).parse
|
27
27
|
header = document.root['t']
|
28
28
|
action = document.root.child['action']
|
@@ -32,10 +32,42 @@ class SmartFox::Packet
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def self.parse_json(data)
|
35
|
-
SmartFox::Logger.debug "SmartFox::Packet
|
35
|
+
SmartFox::Logger.debug "SmartFox::Packet.parse_json('#{data}')"
|
36
36
|
end
|
37
37
|
|
38
38
|
def self.parse_string(data)
|
39
|
-
SmartFox::Logger.debug "SmartFox::Packet
|
39
|
+
SmartFox::Logger.debug "SmartFox::Packet.parse_string('#{data}')"
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.parse_extended(data)
|
43
|
+
SmartFox::Logger.debug "SmartFox::Packet.parse_extended('#{data}')"
|
44
|
+
document = LibXML::XML::Parser.string(data.content).parse
|
45
|
+
parse_extended_object document.root
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.parse_extended_scaler(node)
|
49
|
+
case node['t']
|
50
|
+
when 'n'
|
51
|
+
node.content.to_i
|
52
|
+
when 's'
|
53
|
+
node.content
|
54
|
+
when 'b'
|
55
|
+
node.content == "1"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.parse_extended_object(node)
|
60
|
+
result = {}
|
61
|
+
|
62
|
+
node.children.each do |child|
|
63
|
+
case child.name
|
64
|
+
when 'var'
|
65
|
+
result[child["n"].to_sym] = parse_extended_scaler(child)
|
66
|
+
when 'obj'
|
67
|
+
result[child["o"].to_sym] = parse_extended_object(child)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
result
|
40
72
|
end
|
41
73
|
end
|
@@ -50,14 +50,21 @@ class SmartFox::Socket::Connection
|
|
50
50
|
until @disconnecting
|
51
51
|
SmartFox::Logger.debug "SmartFox::Socket::Connection#event_loop tick #{ticks}"
|
52
52
|
|
53
|
-
|
53
|
+
buffer = String.new
|
54
|
+
begin
|
55
|
+
@socket.read_nonblock(4096, buffer)
|
56
|
+
|
57
|
+
@buffer += buffer if buffer
|
54
58
|
|
55
|
-
|
56
|
-
|
57
|
-
|
59
|
+
while index = @buffer.index("\0")
|
60
|
+
@packets << @buffer.slice!(0..index)
|
61
|
+
end
|
58
62
|
|
59
|
-
|
60
|
-
|
63
|
+
@packets.each { |packet| @client.packet_recieved(packet) }
|
64
|
+
@packets.clear
|
65
|
+
rescue => e
|
66
|
+
Thread.pass
|
67
|
+
end
|
61
68
|
|
62
69
|
ticks += 1
|
63
70
|
end
|
data/smartfox.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{smartfox}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Richard Penwell"]
|
12
|
-
s.date = %q{2010-06-
|
12
|
+
s.date = %q{2010-06-08}
|
13
13
|
s.description = %q{Provides a client library for the SmartFox realtime communication server, including BlueBox extensions.}
|
14
14
|
s.email = %q{self@richardpenwell.me}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -28,6 +28,7 @@ Gem::Specification.new do |s|
|
|
28
28
|
"lib/smartfox/blue_box/connection.rb",
|
29
29
|
"lib/smartfox/client.rb",
|
30
30
|
"lib/smartfox/packet.rb",
|
31
|
+
"lib/smartfox/room.rb",
|
31
32
|
"lib/smartfox/socket.rb",
|
32
33
|
"lib/smartfox/socket/connection.rb",
|
33
34
|
"nbproject/configs/Spec.properties",
|
@@ -39,6 +40,7 @@ Gem::Specification.new do |s|
|
|
39
40
|
"nbproject/project.properties",
|
40
41
|
"nbproject/project.xml",
|
41
42
|
"smartfox.gemspec",
|
43
|
+
"spec/packet_spec.rb",
|
42
44
|
"spec/smartfox_spec.rb",
|
43
45
|
"spec/spec.opts",
|
44
46
|
"spec/spec_helper.rb",
|
@@ -50,7 +52,8 @@ Gem::Specification.new do |s|
|
|
50
52
|
s.rubygems_version = %q{1.3.7}
|
51
53
|
s.summary = %q{Client library for SmartFoxServer}
|
52
54
|
s.test_files = [
|
53
|
-
"spec/
|
55
|
+
"spec/packet_spec.rb",
|
56
|
+
"spec/smartfox_spec.rb",
|
54
57
|
"spec/spec_helper.rb",
|
55
58
|
"spec/waiter.rb"
|
56
59
|
]
|
data/spec/packet_spec.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe SmartFox::Packet do
|
4
|
+
it "should parse system packets" do
|
5
|
+
SYSTEM_PACKET = "<msg t='sys'><body action='apiOK' r='0'></body></msg>\0"
|
6
|
+
|
7
|
+
packet = SmartFox::Packet.parse(SYSTEM_PACKET)
|
8
|
+
|
9
|
+
packet.header.should == SmartFox::Client::HEADER_SYSTEM
|
10
|
+
packet.action.should == SmartFox::Client::ACTION_API_OK
|
11
|
+
packet.room.should == 0
|
12
|
+
packet.data.should be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should parse extended packets" do
|
16
|
+
EXTENDED_PACKET = "<msg t='xt'><body action='xtRes' r='-1'><![CDATA[<dataObj><var n='uid' t='n'>481942</var><var n='_cmd' t='s'>logOK</var><obj o='ent' t='a'><var n='chat_priv' t='s'>1</var><var n='init_block' t='s'>1</var><var n='chat_join_rooms' t='s'>10</var><var n='chat_occupancy' t='s'>200</var><var n='init_chat' t='s'>1</var><var n='chat_admin' t='s'>0</var></obj></dataObj>]]></body></msg>\0"
|
17
|
+
|
18
|
+
packet = SmartFox::Packet.parse(EXTENDED_PACKET)
|
19
|
+
|
20
|
+
packet.header.should == SmartFox::Client::HEADER_EXTENDED
|
21
|
+
packet.action.should == SmartFox::Client::EXTENDED_RESPONSE
|
22
|
+
packet.room.should == -1
|
23
|
+
packet.data.should == { :uid => 481942, :_cmd => 'logOK', :ent => { :chat_priv => "1", :init_block => "1", :chat_join_rooms => "10", :chat_occupancy => "200", :init_chat => "1", :chat_admin => "0" } }
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
data/spec/smartfox_spec.rb
CHANGED
@@ -1,6 +1,27 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
1
3
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
4
|
|
3
5
|
describe SmartFox::Client do
|
6
|
+
def transport
|
7
|
+
@connection.instance_variable_get(:@transport)
|
8
|
+
end
|
9
|
+
|
10
|
+
def expect_send_data
|
11
|
+
transport.should_receive(:send_data) do |data|
|
12
|
+
yield data
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def login_to_connection
|
17
|
+
login_waiter = Waiter.new
|
18
|
+
@connection.add_handler(:connected) { |connection| connection.login 'simpleChat', 'penwellr' }
|
19
|
+
@connection.add_handler(:logged_in) { login_waiter.fire }
|
20
|
+
@connection.connect
|
21
|
+
|
22
|
+
login_waiter.wait(10)
|
23
|
+
end
|
24
|
+
|
4
25
|
before(:each) do
|
5
26
|
@connection = SmartFox::Client.new()
|
6
27
|
end
|
@@ -40,6 +61,27 @@ describe SmartFox::Client do
|
|
40
61
|
|
41
62
|
login_waiter.wait(10)
|
42
63
|
end
|
64
|
+
|
65
|
+
it "should properly serialize extended json packets" do
|
66
|
+
@connection.connect
|
67
|
+
expect_send_data do |data|
|
68
|
+
object = JSON.parse(data.chop)
|
69
|
+
object.should == { "t" => 'xt', "b" => { "x" => 'ManChatXT', "c" => 'grlbk', "r" => 6, "p" => {} } }
|
70
|
+
end
|
71
|
+
|
72
|
+
@connection.send_extended('ManChatXT', 'grlbk', :room => 6, :format => :json)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should retrieve the room list asyncronously" do
|
76
|
+
login_to_connection
|
77
|
+
updated_waiter = Waiter.new
|
78
|
+
room_list = nil
|
79
|
+
@connection.add_handler(:rooms_updated) { |client, rooms| room_list = rooms; updated_waiter.fire }
|
80
|
+
@connection.refresh_rooms
|
81
|
+
updated_waiter.wait
|
82
|
+
|
83
|
+
room_list.should_not be_blank
|
84
|
+
end
|
43
85
|
|
44
86
|
it "should fall back on BlueBox if needed"
|
45
87
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smartfox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 1
|
10
|
+
version: 0.2.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Richard Penwell
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-06-
|
18
|
+
date: 2010-06-08 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -83,6 +83,7 @@ files:
|
|
83
83
|
- lib/smartfox/blue_box/connection.rb
|
84
84
|
- lib/smartfox/client.rb
|
85
85
|
- lib/smartfox/packet.rb
|
86
|
+
- lib/smartfox/room.rb
|
86
87
|
- lib/smartfox/socket.rb
|
87
88
|
- lib/smartfox/socket/connection.rb
|
88
89
|
- nbproject/configs/Spec.properties
|
@@ -94,6 +95,7 @@ files:
|
|
94
95
|
- nbproject/project.properties
|
95
96
|
- nbproject/project.xml
|
96
97
|
- smartfox.gemspec
|
98
|
+
- spec/packet_spec.rb
|
97
99
|
- spec/smartfox_spec.rb
|
98
100
|
- spec/spec.opts
|
99
101
|
- spec/spec_helper.rb
|
@@ -133,6 +135,7 @@ signing_key:
|
|
133
135
|
specification_version: 3
|
134
136
|
summary: Client library for SmartFoxServer
|
135
137
|
test_files:
|
138
|
+
- spec/packet_spec.rb
|
136
139
|
- spec/smartfox_spec.rb
|
137
140
|
- spec/spec_helper.rb
|
138
141
|
- spec/waiter.rb
|