msgpack-rpc 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,48 @@
1
+ #
2
+ # MessagePack-RPC for Ruby
3
+ #
4
+ # Copyright (C) 2010 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ module MessagePack
19
+ module RPC
20
+
21
+
22
+ module MessageReceiver
23
+ def on_message(msg, *ctx)
24
+ case msg[0]
25
+ when REQUEST
26
+ on_request(msg[1], msg[2], msg[3], *ctx)
27
+ when RESPONSE
28
+ on_response(msg[1], msg[2], msg[3], *ctx)
29
+ when NOTIFY
30
+ on_notify(msg[1], msg[2], *ctx)
31
+ else
32
+ raise RPCError.new("unknown message type #{msg[0]}")
33
+ end
34
+ end
35
+
36
+ #def on_request(msgid, method, param)
37
+ #end
38
+
39
+ #def on_notify(method, param)
40
+ #end
41
+
42
+ #def on_response(msgid, error, result)
43
+ #end
44
+ end
45
+
46
+
47
+ end
48
+ end
@@ -0,0 +1,242 @@
1
+ #
2
+ # MessagePack-RPC for Ruby TCP transport
3
+ #
4
+ # Copyright (C) 2010 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ module MessagePack
19
+ module RPC
20
+
21
+
22
+ class TCPTransport
23
+ def initialize
24
+ @reconnect_limit = 5 # FIXME default reconnect_limit
25
+ end
26
+
27
+ attr_accessor :reconnect_limit
28
+
29
+ # Transport interface
30
+ def build_transport(session, address)
31
+ TCPClientTransport.new(session, address, @reconnect_limit)
32
+ end
33
+
34
+ class BasicSocket < Rev::TCPSocket
35
+ def initialize(io)
36
+ super(io)
37
+ @pac = MessagePack::Unpacker.new
38
+ end
39
+
40
+ # from Rev::TCPSocket
41
+ def on_read(data)
42
+ @pac.feed(data)
43
+ @pac.each {|obj|
44
+ on_message(obj)
45
+ }
46
+ end
47
+
48
+ include MessageReceiver
49
+ end
50
+ end
51
+
52
+
53
+ class TCPClientTransport
54
+ def initialize(session, address, reconnect_limit)
55
+ @session = session
56
+ @address = address
57
+
58
+ @pending = ""
59
+ @sockpool = []
60
+ @connecting = 0
61
+ @reconnect_limit = reconnect_limit
62
+ end
63
+
64
+ # ClientTransport interface
65
+ def send_data(data)
66
+ if @sockpool.empty?
67
+ if @connecting == 0
68
+ try_connect
69
+ @connecting = 1
70
+ end
71
+ @pending << data
72
+ else
73
+ # FIXME pesudo connection load balance
74
+ # sock = @sockpool.choice
75
+ sock = @sockpool.first
76
+ sock.send_data(data)
77
+ end
78
+ end
79
+
80
+ # ClientTransport interface
81
+ def close
82
+ @sockpool.reject! {|sock|
83
+ sock.detach if sock.attached?
84
+ sock.close
85
+ true
86
+ }
87
+ @sockpool = []
88
+ @connecting = 0
89
+ @pending = ""
90
+ self
91
+ end
92
+
93
+ # from TCPClientTransport::ClientSocket::on_connect
94
+ def on_connect(sock)
95
+ @sockpool.push(sock)
96
+ sock.send_pending(@pending)
97
+ @pending = ""
98
+ @connecting = 0
99
+ end
100
+
101
+ # from TCPClientTransport::ClientSocket::on_connect_failed
102
+ def on_connect_failed(sock)
103
+ if @connecting < @reconnect_limit
104
+ try_connect
105
+ @connecting += 1
106
+ else
107
+ @connecting = 0
108
+ @pending = ""
109
+ @deflate.reset if @deflate
110
+ @session.on_connect_failed
111
+ end
112
+ end
113
+
114
+ # from TCPClientTransport::ClientSocket::on_close
115
+ def on_close(sock)
116
+ @sockpool.delete(sock)
117
+ end
118
+
119
+ private
120
+ def try_connect
121
+ host, port = *@address
122
+ sock = ClientSocket.connect(host, port, self, @session) # async connect
123
+ @session.loop.attach(sock)
124
+ end
125
+
126
+ class ClientSocket < TCPTransport::BasicSocket
127
+ def initialize(io, transport, session)
128
+ super(io)
129
+ @t = transport
130
+ @s = session
131
+ end
132
+
133
+ # MessageSendable interface
134
+ def send_data(data)
135
+ write data
136
+ end
137
+
138
+ # from TCPClientTransport::on_connect
139
+ def send_pending(data)
140
+ write data
141
+ end
142
+
143
+ # MessageReceiver interface
144
+ def on_request(msgid, method, param)
145
+ raise RPCError.new("request message on client session")
146
+ end
147
+
148
+ # MessageReceiver interface
149
+ def on_notify(method, param)
150
+ raise RPCError.new("notify message on client session")
151
+ end
152
+
153
+ # MessageReceiver interface
154
+ def on_response(msgid, error, result)
155
+ @s.on_response(self, msgid, error, result)
156
+ end
157
+
158
+ # from Rev::TCPSocket
159
+ def on_connect
160
+ return unless @t
161
+ @t.on_connect(self)
162
+ end
163
+
164
+ # from Rev::TCPSocket
165
+ def on_connect_failed
166
+ return unless @t
167
+ @t.on_connect_failed(self)
168
+ rescue
169
+ nil
170
+ end
171
+
172
+ # from Rev::TCPSocket
173
+ def on_close
174
+ return unless @t
175
+ @t.on_close(self)
176
+ @t = nil
177
+ @s = nil
178
+ rescue
179
+ nil
180
+ end
181
+ end
182
+ end
183
+
184
+
185
+ class TCPServerTransport
186
+ def initialize(address)
187
+ @address = address
188
+ @lsock = nil
189
+ end
190
+
191
+ # ServerTransport interface
192
+ def listen(server)
193
+ @server = server
194
+ host, port = *@address.unpack
195
+ @lsock = Rev::TCPServer.new(host, port, ServerSocket, @server)
196
+ begin
197
+ @server.loop.attach(@lsock)
198
+ rescue
199
+ @lsock.close
200
+ raise
201
+ end
202
+ end
203
+
204
+ # ServerTransport interface
205
+ def close
206
+ return unless @lsock
207
+ @lsock.detach if @lsock.attached?
208
+ @lsock.close
209
+ end
210
+
211
+ private
212
+ class ServerSocket < TCPTransport::BasicSocket
213
+ def initialize(io, server)
214
+ super(io)
215
+ @server = server
216
+ end
217
+
218
+ # MessageSendable interface
219
+ def send_data(data)
220
+ write data
221
+ end
222
+
223
+ # MessageReceiver interface
224
+ def on_request(msgid, method, param)
225
+ @server.on_request(self, msgid, method, param)
226
+ end
227
+
228
+ # MessageReceiver interface
229
+ def on_notify(method, param)
230
+ @server.on_notify(method, param)
231
+ end
232
+
233
+ # MessageReceiver interface
234
+ def on_response(msgid, error, result)
235
+ raise RPCError.new("response message on server session")
236
+ end
237
+ end
238
+ end
239
+
240
+
241
+ end
242
+ end
@@ -0,0 +1,192 @@
1
+ #
2
+ # MessagePack-RPC for Ruby UDP transport
3
+ #
4
+ # Copyright (C) 2010 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ module MessagePack
19
+ module RPC
20
+
21
+
22
+ class UDPTransport
23
+ def initialize
24
+ end
25
+
26
+ # Transport interface
27
+ def build_transport(session, address)
28
+ UDPClientTransport.new(session, address)
29
+ end
30
+
31
+ class BasicSocket < Rev::IOWatcher
32
+ def initialize(io)
33
+ super(io)
34
+ @io = io
35
+ end
36
+
37
+ attr_reader :io
38
+
39
+ def on_readable
40
+ begin
41
+ data, addr = @io.recvfrom(64*1024) # FIXME buffer size
42
+ rescue Errno::EAGAIN
43
+ return
44
+ end
45
+
46
+ # FIXME multiple objects in one message
47
+ obj = MessagePack.unpack(data)
48
+ on_message(obj, addr)
49
+ end
50
+
51
+ include MessageReceiver
52
+ end
53
+ end
54
+
55
+
56
+ class UDPClientTransport
57
+ def initialize(session, address)
58
+ io = UDPSocket.new
59
+ io.connect(*address)
60
+
61
+ begin
62
+ @sock = ClientSocket.new(io, session)
63
+ rescue
64
+ io.close
65
+ raise
66
+ end
67
+
68
+ begin
69
+ session.loop.attach(@sock)
70
+ rescue
71
+ @sock.close
72
+ raise
73
+ end
74
+ end
75
+
76
+ # ClientTransport interface
77
+ def send_data(data)
78
+ @sock.send_data(data)
79
+ end
80
+
81
+ # ClientTransport interface
82
+ def close
83
+ @sock.detach if @sock.attached?
84
+ @sock.close
85
+ end
86
+
87
+ private
88
+ class ClientSocket < UDPTransport::BasicSocket
89
+ def initialize(io, session)
90
+ super(io)
91
+ @s = session
92
+ end
93
+
94
+ # MessageSendable interface
95
+ def send_data(data)
96
+ @io.send(data, 0)
97
+ end
98
+
99
+ # MessageReceiver interface
100
+ def on_request(msgid, method, param, addr)
101
+ raise RPCError.new("request message on client session")
102
+ end
103
+
104
+ # MessageReceiver interface
105
+ def on_notify(method, param, addr)
106
+ raise RPCError.new("notify message on client session")
107
+ end
108
+
109
+ # MessageReceiver interface
110
+ def on_response(msgid, error, result, addr)
111
+ @s.on_response(self, msgid, error, result)
112
+ end
113
+ end
114
+ end
115
+
116
+
117
+ class UDPServerTransport
118
+ def initialize(address)
119
+ @address = address
120
+ @sock = nil
121
+ end
122
+
123
+ # ServerTransport interface
124
+ def listen(server)
125
+ @server = server
126
+ host, port = *@address.unpack
127
+ io = UDPSocket.new
128
+ io.bind(*@address)
129
+
130
+ begin
131
+ @sock = ServerSocket.new(io, @server)
132
+ rescue
133
+ io.close
134
+ raise
135
+ end
136
+
137
+ begin
138
+ @server.loop.attach(@sock)
139
+ rescue
140
+ @sock.close
141
+ raise
142
+ end
143
+ end
144
+
145
+ # ServerTransport interface
146
+ def close
147
+ return unless @lsock
148
+ @lsock.detach if @lsock.attached?
149
+ @lsock.close
150
+ end
151
+
152
+ private
153
+ class ServerSocket < UDPTransport::BasicSocket
154
+ def initialize(io, server)
155
+ super(io)
156
+ @server = server
157
+ end
158
+
159
+ # MessageReceiver interface
160
+ def on_request(msgid, method, param, addr)
161
+ sender = ResponseSender.new(@io, addr[3], addr[1])
162
+ @server.on_request(sender, msgid, method, param)
163
+ end
164
+
165
+ # MessageReceiver interface
166
+ def on_notify(method, param, addr)
167
+ @server.on_notify(method, param)
168
+ end
169
+
170
+ # MessageReceiver interface
171
+ def on_response(msgid, error, result, addr)
172
+ raise RPCError.new("response message on server session")
173
+ end
174
+ end
175
+
176
+ class ResponseSender
177
+ def initialize(io, host, port)
178
+ @io = io
179
+ @host = host
180
+ @port = port
181
+ end
182
+
183
+ # MessageSendable interface
184
+ def send_data(data)
185
+ @io.send(data, 0, @host, @port)
186
+ end
187
+ end
188
+ end
189
+
190
+
191
+ end
192
+ end