maniaplanet-rpc 0.1.0 → 0.2.0

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.
@@ -1,137 +1,165 @@
1
1
  require 'xmlrpc/client'
2
2
  require 'thread'
3
3
 
4
- class ManiaConnection
5
-
6
- include XMLRPC::ParserWriterChooseMixin
7
-
8
- def initialize(ip, port, callback)
9
- @callback = callback
10
- @request_handle = 0x80000000
11
- @ip = ip
12
- @port = port
13
- @send_queue = Queue.new
14
- @socket = TCPSocket.new ip, port
15
- @protocol = 0
16
- authenticate
17
- end
4
+ module ManiaRPC
5
+ class ManiaConnection
6
+
7
+ include XMLRPC::ParserWriterChooseMixin
8
+
9
+ def initialize(ip, port, callback)
10
+ @callback = callback
11
+ @request_handle = 0x80000000
12
+ @ip = ip
13
+ @port = port
14
+ @send_queue = Queue.new
15
+ begin
16
+ @socket = TCPSocket.new ip, port
17
+ rescue
18
+ puts "Failed to establish a connection, is the ManiaPlanet server really running?"
19
+ exit
20
+ end
21
+ @protocol = 0
22
+ handshake
23
+ end
18
24
 
19
- def authenticate
20
- header = @socket.recv(4).unpack "Vsize"
25
+ def handshake
26
+ header = @socket.recv(4).unpack "Vsize"
21
27
 
22
- if header[0] > 64
23
- raise Exception, "Wrong low-level protocol header!"
24
- end
28
+ if header[0] > 64
29
+ raise Exception, "Wrong low-level protocol header!"
30
+ end
25
31
 
26
- handshake = @socket.recv header[0]
32
+ handshake = @socket.recv header[0]
27
33
 
28
- if handshake == "GBXRemote 1"
29
- @protocol = 1
30
- elsif handshake == "GBXRemote 2"
31
- @protocol = 2
32
- else
33
- raise Exception, "Unknown protocol version!"
34
+ if handshake == "GBXRemote 1"
35
+ @protocol = 1
36
+ elsif handshake == "GBXRemote 2"
37
+ @protocol = 2
38
+ else
39
+ raise Exception, "Unknown protocol version!"
40
+ end
34
41
  end
35
- end
36
42
 
37
- def start
38
- loop do
39
- sleep(1.0/24.0)
40
- tick
43
+ def start
44
+ loop do
45
+ sleep(1.0/24.0)
46
+ tick
47
+ end
41
48
  end
42
- end
43
49
 
44
- def call(method, *args)
45
- @request_handle = @request_handle + 1
46
- @send_queue.push [@request_handle, create().methodCall(method, *args)]
47
- @request_handle - 0x80000000
48
- end
50
+ def call(method, *args)
51
+ @request_handle = @request_handle + 1
52
+ @send_queue.push [@request_handle, create().methodCall(method, *args)]
53
+ @request_handle - 0x80000000
54
+ end
49
55
 
50
- def tick
51
- write
52
- read
53
- end
56
+ def tick
57
+ write
58
+ read
59
+ end
54
60
 
55
- def read
56
- if IO.select([@socket], nil, nil, 0) != nil
57
- if @protocol == 1
58
- content = @socket.recv 4
59
- if content.bytesize == 0
60
- raise Exception, "Cannot read size!"
61
+ def read
62
+ if IO.select([@socket], nil, nil, 0) != nil
63
+ if @protocol == 1
64
+ content = @socket.recv 4
65
+ if content.bytesize == 0
66
+ raise Exception, "Cannot read size!"
67
+ end
68
+ result = content.unpack "Vsize"
69
+ size = result[0]
70
+ receive_handle = @request_handle
71
+ else
72
+ content = @socket.recv 8
73
+ if content.bytesize == 0
74
+ raise Exception, "Cannot read size/handle!"
75
+ end
76
+ result = content.unpack "Vsize/Vhandle"
77
+ size = result[0]
78
+ receive_handle = result[1]
61
79
  end
62
- result = content.unpack "Vsize"
63
- size = result[0]
64
- receive_handle = @request_handle
65
- else
66
- content = @socket.recv 8
67
- if content.bytesize == 0
68
- raise Exception, "Cannot read size/handle!"
69
- end
70
- result = content.unpack "Vsize/Vhandle"
71
- size = result[0]
72
- receive_handle = result[1]
73
- end
74
80
 
75
- if receive_handle == 0 || size == 0
76
- raise Exception, "Connection interrupted!"
77
- end
81
+ if receive_handle == 0 || size == 0
82
+ raise Exception, "Connection interrupted!"
83
+ end
78
84
 
79
- if size > 4096 * 1024
80
- raise Exception, "Response too large!"
81
- end
85
+ if size > 4096 * 1024
86
+ raise Exception, "Response too large!"
87
+ end
82
88
 
83
- response = ""
84
- response_length = 0
89
+ response = ""
90
+ response_length = 0
85
91
 
86
- while response_length < size
87
- response << @socket.recv(size - response_length)
88
- response_length = response.bytesize
89
- end
92
+ while response_length < size
93
+ response << @socket.recv(size - response_length)
94
+ response_length = response.bytesize
95
+ end
90
96
 
91
- if @callback.response_map[receive_handle] == nil
92
- @callback.parse_callback parser().parseMethodResponse(response)
93
- else
94
- @callback.response_map[receive_handle].call parser().parseMethodResponse(response)
97
+ begin # Response
98
+ response = parser().parseMethodResponse(response)
99
+ @callback.response_map[receive_handle].call response
100
+ rescue Exception # Callback
101
+ response = parser().parseMethodCall(response)
102
+ @callback.parse_callback response
103
+ end
95
104
  end
96
105
  end
97
- end
98
106
 
99
- def write
100
- while @send_queue.length > 0
101
- request = @send_queue.pop
102
- if @protocol == 1
103
- bytes = [request[1].bytesize, request[1]].pack("Va*")
104
- else
105
- bytes = [request[1].bytesize, request[0], request[1]].pack("VVa*")
107
+ def write
108
+ while @send_queue.length > 0
109
+ request = @send_queue.pop
110
+ if @protocol == 1
111
+ bytes = [request[1].bytesize, request[1]].pack("Va*")
112
+ else
113
+ bytes = [request[1].bytesize, request[0], request[1]].pack("VVa*")
114
+ end
115
+ @socket.write bytes
106
116
  end
107
- @socket.write bytes
108
117
  end
118
+
109
119
  end
110
120
 
111
- end
121
+ ##
122
+ # This class provides the interface for a ManiaPlanet Server by sending/receiving requests as well as callbacks.
123
+ class ManiaClient
112
124
 
113
- class ManiaClient
125
+ attr_reader :connection
126
+ attr_accessor :response_map
114
127
 
115
- attr_reader :connection
116
- attr_accessor :response_map
128
+ def initialize(ip, port)
129
+ @response_map = {}
130
+ @callback_map = {}
131
+ @connection = ManiaConnection.new ip, port, self
132
+ Thread.new do
133
+ @connection.start
134
+ end
135
+ end
117
136
 
118
- def initialize(ip, port)
119
- @response_map = {}
120
- @connection = ManiaConnection.new ip, port, self
121
- Thread.new do
122
- @connection.start
137
+ def parse_callback(message)
138
+ @callback_map[message.first].call message
139
+ @callback_map[:all].call message
123
140
  end
124
- end
125
141
 
126
- def parse_callback(message)
127
- # TODO: Fix
128
- end
142
+ ##
143
+ # Call this with a block to handle a callback with the given name.
144
+ def on(what, &block)
145
+ @callback_map[what] = block
146
+ end
129
147
 
130
- def call(method, *args, &block)
131
- if block_given?
132
- @response_map[@connection.call(method, *args)] = block
133
- else
134
- @response_map[@connection.call(method, *args)] = proc {}
148
+ ##
149
+ # Call this with a block to receive all callbacks. Can be used in conjunction with the on method.
150
+ def all(&block)
151
+ @callback_map[:all] = block
152
+ end
153
+
154
+ ##
155
+ # Calls an RPC method with the given name and arguments, optionally handling the result within the passed block.
156
+ # Note: The response is asynchronous.
157
+ def call(method, *args, &block)
158
+ if block_given?
159
+ @response_map[@connection.call(method, *args)] = block
160
+ else
161
+ @response_map[@connection.call(method, *args)] = proc {}
162
+ end
135
163
  end
136
164
  end
137
165
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maniaplanet-rpc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,10 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-08 00:00:00.000000000 Z
12
+ date: 2013-04-12 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: maniaplanet-rpc is a library for interfacing with maniaplanet servers
15
- using their custom variant of xml-rpc
15
+ using its custom variant of xml-rpc
16
16
  email: johan.f.ljungberg@gmail.com
17
17
  executables: []
18
18
  extensions: []