msgpack-rpc 0.2.0 → 0.3.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.
- data/NOTICE +4 -0
- data/README +1 -1
- data/lib/msgpack/rpc.rb +904 -287
- metadata +14 -27
- data/Rakefile +0 -132
data/NOTICE
ADDED
data/README
CHANGED
data/lib/msgpack/rpc.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#
|
2
2
|
# MessagePack-RPC for Ruby
|
3
3
|
#
|
4
|
-
# Copyright (C)
|
4
|
+
# Copyright (C) 2010 FURUHASHI Sadayuki
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
7
|
# you may not use this file except in compliance with the License.
|
@@ -17,6 +17,7 @@
|
|
17
17
|
#
|
18
18
|
require 'msgpack'
|
19
19
|
require 'rev'
|
20
|
+
require 'zlib'
|
20
21
|
|
21
22
|
module MessagePack
|
22
23
|
module RPC
|
@@ -51,20 +52,15 @@ class ConnectError < TimeoutError
|
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
54
|
-
class Responder
|
55
|
-
def initialize(socket, msgid)
|
56
|
-
@socket = socket
|
57
|
-
@msgid = msgid
|
58
|
-
end
|
59
|
-
|
60
|
-
def result(retval, err = nil)
|
61
|
-
@socket.write RPCSocket.pack_response(@msgid, retval, err)
|
62
|
-
end
|
63
55
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
56
|
+
REQUEST = 0 # [0, msgid, method, param]
|
57
|
+
RESPONSE = 1 # [1, msgid, error, result]
|
58
|
+
NOTIFY = 2 # [2, method, param]
|
59
|
+
SESSION = 3 # [3, addr]
|
60
|
+
OPTION = 4 # [4, txopt, rxopt] #[, rxproto, rxaddr]
|
61
|
+
OPT_DEFLATE = 0b00000001
|
62
|
+
#PROTO_TCP = 0
|
63
|
+
#PROTO_UDP = 1
|
68
64
|
|
69
65
|
|
70
66
|
class Address
|
@@ -84,25 +80,29 @@ class Address
|
|
84
80
|
test = Socket.pack_sockaddr_in(0,'0.0.0.0')
|
85
81
|
if test[0] == "\0"[0] || test[1] == "\0"[0]
|
86
82
|
# Linux
|
87
|
-
|
83
|
+
def initialize(host, port)
|
84
|
+
raw = Socket.pack_sockaddr_in(port, host)
|
85
|
+
family = raw.unpack('S')[0]
|
86
|
+
if family == Socket::AF_INET
|
87
|
+
@serial = raw[2,6]
|
88
|
+
elsif family == Socket::AF_INET6
|
89
|
+
@serial = raw[2,2] + raw[8,16]
|
90
|
+
else
|
91
|
+
raise "Unknown address family: #{family}"
|
92
|
+
end
|
93
|
+
end
|
88
94
|
else
|
89
95
|
# BSD
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
def initialize(host, port)
|
94
|
-
raw = Socket.pack_sockaddr_in(port, host)
|
95
|
-
if IMPL_LINUX
|
96
|
-
family = raw.unpack('S')[0]
|
97
|
-
else
|
96
|
+
def initialize(host, port)
|
97
|
+
raw = Socket.pack_sockaddr_in(port, host)
|
98
98
|
family = raw.unpack('CC')[1]
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
99
|
+
if family == Socket::AF_INET
|
100
|
+
@serial = raw[2,6]
|
101
|
+
elsif family == Socket::AF_INET6
|
102
|
+
@serial = raw[2,2] + raw[8,16]
|
103
|
+
else
|
104
|
+
raise "Unknown address family: #{family}"
|
105
|
+
end
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
@@ -166,7 +166,6 @@ class Address
|
|
166
166
|
"#<#{self.class} #{to_s} @serial=#{@serial.inspect}>"
|
167
167
|
end
|
168
168
|
|
169
|
-
|
170
169
|
def eql?(o)
|
171
170
|
o.class == Address && dump.eql?(o.dump)
|
172
171
|
end
|
@@ -181,235 +180,262 @@ class Address
|
|
181
180
|
end
|
182
181
|
|
183
182
|
|
184
|
-
|
185
|
-
|
186
|
-
NOTIFY = 2
|
187
|
-
INIT = 3
|
188
|
-
|
189
|
-
|
190
|
-
class RPCSocket < Rev::TCPSocket
|
191
|
-
def initialize(sock, session)
|
192
|
-
@buffer = ''
|
193
|
-
@nread = 0
|
194
|
-
@mpac = MessagePack::Unpacker.new
|
195
|
-
@s = session
|
196
|
-
super(sock)
|
197
|
-
end
|
198
|
-
|
199
|
-
def bind_session(s)
|
183
|
+
class Future
|
184
|
+
def initialize(s, loop, block = nil)
|
200
185
|
@s = s
|
186
|
+
@timeout = s.timeout
|
187
|
+
@loop = loop
|
188
|
+
@block = block
|
189
|
+
@error = nil
|
190
|
+
@result = nil
|
201
191
|
end
|
192
|
+
attr_reader :loop
|
193
|
+
attr_accessor :result, :error
|
202
194
|
|
203
|
-
def
|
204
|
-
|
195
|
+
def attach_callback(proc = nil, &block)
|
196
|
+
@block = proc || block
|
205
197
|
end
|
206
198
|
|
207
|
-
def
|
208
|
-
@
|
209
|
-
|
210
|
-
|
211
|
-
@
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
@mpac.reset
|
217
|
-
@buffer.slice!(0, @nread)
|
218
|
-
@nread = 0
|
219
|
-
|
220
|
-
on_message(msg) # RPCSocket#on_message
|
221
|
-
|
222
|
-
next unless @buffer.empty?
|
223
|
-
end
|
199
|
+
def call(err, res)
|
200
|
+
@error = err
|
201
|
+
@result = res
|
202
|
+
if @block
|
203
|
+
@block.call(err, res)
|
204
|
+
end
|
205
|
+
@s = nil
|
206
|
+
end
|
224
207
|
|
225
|
-
|
208
|
+
def join
|
209
|
+
while @s
|
210
|
+
@loop.run_once
|
226
211
|
end
|
212
|
+
self
|
227
213
|
end
|
228
214
|
|
229
|
-
def
|
230
|
-
|
231
|
-
|
232
|
-
on_request(msg[1], msg[2], msg[3])
|
233
|
-
when RESPONSE
|
234
|
-
on_response(msg[1], msg[2], msg[3])
|
235
|
-
when NOTIFY
|
236
|
-
on_notify(msg[1], msg[2])
|
237
|
-
when INIT
|
238
|
-
on_init(msg[1])
|
215
|
+
def step_timeout
|
216
|
+
if @timeout < 1
|
217
|
+
true
|
239
218
|
else
|
240
|
-
|
219
|
+
@timeout -= 1
|
220
|
+
false
|
241
221
|
end
|
242
222
|
end
|
223
|
+
end
|
243
224
|
|
244
|
-
def on_connect
|
245
|
-
return unless @s
|
246
|
-
@s.on_connect(self)
|
247
|
-
end
|
248
225
|
|
249
|
-
|
250
|
-
|
251
|
-
@
|
226
|
+
class Responder
|
227
|
+
def initialize(tran, msgid)
|
228
|
+
@tran = tran # send_message method is required
|
229
|
+
@msgid = msgid
|
252
230
|
end
|
253
231
|
|
254
|
-
def
|
255
|
-
|
256
|
-
@s.on_close(self)
|
257
|
-
@s = nil
|
258
|
-
rescue
|
259
|
-
nil
|
232
|
+
def result(retval, err = nil)
|
233
|
+
@tran.send_message [RESPONSE, @msgid, err, retval]
|
260
234
|
end
|
261
235
|
|
262
|
-
def
|
263
|
-
|
264
|
-
@s.on_request(method, param, Responder.new(self,msgid))
|
236
|
+
def error(err, retval = nil)
|
237
|
+
result(retval, err)
|
265
238
|
end
|
239
|
+
end
|
266
240
|
|
267
|
-
|
268
|
-
|
269
|
-
|
241
|
+
|
242
|
+
class ExchangeOption
|
243
|
+
def initialize(flags = 0)
|
244
|
+
@flags = flags
|
270
245
|
end
|
271
246
|
|
272
|
-
def
|
273
|
-
|
274
|
-
@s.on_response(msgid, error, result)
|
247
|
+
def get
|
248
|
+
@flags
|
275
249
|
end
|
276
250
|
|
277
|
-
def
|
278
|
-
|
251
|
+
def deflate=(val)
|
252
|
+
val ? (@flags |= OPT_DEFLATE) : (@flags &= ~OPT_DEFLATE)
|
279
253
|
end
|
280
254
|
|
281
|
-
def
|
282
|
-
|
255
|
+
def deflate?
|
256
|
+
@flags & OPT_DEFLATE != 0
|
283
257
|
end
|
284
258
|
|
285
|
-
def
|
286
|
-
|
259
|
+
def reset
|
260
|
+
@flags = 0
|
261
|
+
self
|
287
262
|
end
|
288
263
|
|
289
|
-
def
|
290
|
-
|
264
|
+
def ==(o)
|
265
|
+
@flags == o.get
|
291
266
|
end
|
292
267
|
|
293
|
-
def
|
294
|
-
|
268
|
+
def to_msgpack(out = '')
|
269
|
+
@flags.to_msgpack(out)
|
295
270
|
end
|
296
271
|
|
297
|
-
def self.
|
298
|
-
|
272
|
+
def self.from_msgpack(obj)
|
273
|
+
@flags = obj
|
299
274
|
end
|
300
275
|
end
|
301
276
|
|
277
|
+
class StreamOption
|
278
|
+
def initialize(txopt = ExchangeOption.new, rxopt = ExchangeOption.new) #, rxproto = nil, rxaddr = nil)
|
279
|
+
@txopt = txopt
|
280
|
+
@rxopt = rxopt
|
281
|
+
#@rxproto = rxproto # nil or PROTO_TCP or PROTO_UDP
|
282
|
+
#@rxaddr = rxaddr # nil or address
|
283
|
+
end
|
284
|
+
attr_accessor :txopt, :rxopt #, :rxproto, :rxaddr
|
302
285
|
|
303
|
-
|
286
|
+
def default?
|
287
|
+
@txopt.get == 0 && @rxopt.get == 0 && @rxproto.nil?
|
288
|
+
end
|
304
289
|
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
290
|
+
def reset
|
291
|
+
@txopt.reset
|
292
|
+
@rxopt.reset
|
293
|
+
#@rxproto = nil
|
294
|
+
#@rxaddr = nil
|
295
|
+
self
|
296
|
+
end
|
312
297
|
|
313
|
-
|
314
|
-
|
315
|
-
|
298
|
+
def ==(o)
|
299
|
+
@txopt == o.txopt && @rxopt == o.rxopt # &&
|
300
|
+
#@rxproto == o.rxproto && @rxaddr == o.rxaddr
|
301
|
+
end
|
316
302
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
303
|
+
def to_msgpack(out = '')
|
304
|
+
array = [OPTION, @txopt, @rxopt]
|
305
|
+
#if @rxproto
|
306
|
+
# array << @rxproto
|
307
|
+
# if @rxaddr
|
308
|
+
# array << @rxaddr
|
309
|
+
# end
|
310
|
+
#end
|
311
|
+
array.to_msgpack(out)
|
312
|
+
end
|
313
|
+
|
314
|
+
def self.from_msgpack(obj)
|
315
|
+
txopt = ExchangeOption.new(obj[1] || 0)
|
316
|
+
rxopt = ExchangeOption.new(obj[2] || 0)
|
317
|
+
#if obj[3]
|
318
|
+
# rxproto = obj[3]
|
319
|
+
# if obj[4]
|
320
|
+
# rxaddr = Address.load(obj[4])
|
321
|
+
# end
|
322
|
+
#end
|
323
|
+
StreamOption.new(txopt, rxopt) #, rxproto, rxaddr)
|
324
|
+
end
|
325
|
+
end
|
323
326
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
+
class TransportOption < StreamOption
|
328
|
+
def initialize(*args)
|
329
|
+
super()
|
330
|
+
#@proto = PROTO_TCP
|
331
|
+
#@address = nil
|
332
|
+
args.each do |x|
|
333
|
+
case x
|
334
|
+
#when :tx_tcp, :tcp
|
335
|
+
# @proto = PROTO_TCP
|
336
|
+
#when :tx_udp, :udp
|
337
|
+
# @proto = PROTO_UDP
|
338
|
+
#when :rx_tcp
|
339
|
+
# @rxproto = PROTO_TCP
|
340
|
+
#when :rx_udp
|
341
|
+
# @rxproto = PROTO_UDP
|
342
|
+
when :deflate
|
343
|
+
@txopt.deflate = true
|
344
|
+
@rxopt.deflate = true
|
345
|
+
when :tx_deflate
|
346
|
+
@txopt.deflate = true
|
347
|
+
when :rx_deflate
|
348
|
+
@rxopt.deflate = true
|
349
|
+
#when PROTO_TCP
|
350
|
+
# @proto = PROTO_TCP
|
351
|
+
#when PROTO_UDP
|
352
|
+
# @proto = PROTO_UDP
|
353
|
+
#when Address
|
354
|
+
# @rxaddr = x
|
327
355
|
else
|
328
|
-
|
329
|
-
false
|
356
|
+
raise "unknown option #{x.inspect}"
|
330
357
|
end
|
331
358
|
end
|
332
359
|
end
|
360
|
+
#attr_accessor :proto, :address
|
333
361
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
end
|
340
|
-
attr_accessor :result, :error
|
362
|
+
def reset
|
363
|
+
#@proto = PROTO_TCP
|
364
|
+
@address = nil
|
365
|
+
super
|
366
|
+
end
|
341
367
|
|
342
|
-
|
343
|
-
|
344
|
-
@result = res
|
345
|
-
@s = nil
|
346
|
-
end
|
368
|
+
def ==(o)
|
369
|
+
super(o) # && @proto = o.proto && @address = o.address
|
347
370
|
end
|
348
371
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
@block = block
|
353
|
-
end
|
372
|
+
#def deflate(val = true) txopt.deflate = va; rxopt.deflate = va; self end
|
373
|
+
#def rx_deflate(val = true) @rxopt.deflate = val; self; end
|
374
|
+
#def tx_deflate(val = true) @txopt.deflate = val; self; end
|
354
375
|
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
end
|
376
|
+
#def tcp; @proto = PROTO_TCP; self; end
|
377
|
+
#def tx_tcp; @proto = PROTO_TCP; self; end
|
378
|
+
#def rx_tcp; @rxproto = PROTO_TCP; self; end
|
359
379
|
|
380
|
+
#def udp; @proto = PROTO_UDP; self; end
|
381
|
+
#def rx_udp; @proto = PROTO_UDP; self; end
|
382
|
+
#def rx_udp; @rxproto = PROTO_UDP; self; end
|
383
|
+
end
|
360
384
|
|
361
|
-
|
362
|
-
|
363
|
-
|
385
|
+
|
386
|
+
class Session
|
387
|
+
def initialize(to_addr, dtopt, dispatcher, self_addr, loop)
|
388
|
+
@address = to_addr # destination address
|
389
|
+
@self_address = self_addr # self session identifier
|
364
390
|
@dispatcher = dispatcher || NullDispatcher.new
|
391
|
+
@dtopt = dtopt # default transport option
|
392
|
+
@dtran = create_transport(@dtopt) # default transport
|
365
393
|
@loop = loop
|
394
|
+
@trans = []
|
395
|
+
@reqtable = {}
|
366
396
|
@timeout = 10 # FIXME default timeout time
|
367
|
-
@reconnect = 5 # FIXME default reconnect limit
|
368
397
|
reset
|
369
398
|
end
|
370
|
-
|
399
|
+
attr_reader :address, :self_address, :loop
|
400
|
+
attr_accessor :timeout
|
371
401
|
|
372
|
-
def
|
373
|
-
|
402
|
+
def send(method, *args)
|
403
|
+
send_over(nil, method, *args)
|
374
404
|
end
|
375
405
|
|
376
|
-
def
|
377
|
-
|
378
|
-
sock.write @pending
|
379
|
-
@pending = ""
|
380
|
-
@connecting = 0
|
406
|
+
def callback(method, *args, &block)
|
407
|
+
callback_over(nil, method, *args, &block)
|
381
408
|
end
|
382
409
|
|
383
|
-
def
|
384
|
-
|
385
|
-
try_connect
|
386
|
-
@connecting += 1
|
387
|
-
else
|
388
|
-
@connecting = 0
|
389
|
-
@reqtable.reject! {|msgid, req|
|
390
|
-
begin
|
391
|
-
req.call ConnectError.new, nil
|
392
|
-
rescue
|
393
|
-
end
|
394
|
-
true
|
395
|
-
}
|
396
|
-
end
|
410
|
+
def call(method, *args)
|
411
|
+
call_over(nil, method, *args)
|
397
412
|
end
|
398
413
|
|
414
|
+
def notify(method, *args)
|
415
|
+
notify_over(nil, method, *args)
|
416
|
+
end
|
399
417
|
|
400
|
-
def
|
401
|
-
|
402
|
-
@reqtable[msgid] = AsyncRequest.new(self, @loop)
|
418
|
+
def over(*args)
|
419
|
+
Over.new(self, TransportOption.new(*args))
|
403
420
|
end
|
404
421
|
|
405
|
-
def
|
406
|
-
|
407
|
-
@reqtable[msgid] = CallbackRequest.new(self, @loop, block)
|
422
|
+
def default_option
|
423
|
+
@dtopt.dup
|
408
424
|
end
|
409
425
|
|
410
|
-
def
|
426
|
+
def send_over(topt, method, *args)
|
427
|
+
msgid = send_request(topt, method, args)
|
428
|
+
@reqtable[msgid] = Future.new(self, @loop)
|
429
|
+
end
|
430
|
+
|
431
|
+
def callback_over(topt, method, *args, &block)
|
432
|
+
msgid = send_request(topt, method, args)
|
433
|
+
@reqtable[msgid] = Future.new(self, @loop, block)
|
434
|
+
end
|
435
|
+
|
436
|
+
def call_over(topt, method, *args)
|
411
437
|
# FIXME if @reqtable.empty? optimize
|
412
|
-
req =
|
438
|
+
req = send_over(topt, method, *args)
|
413
439
|
req.join
|
414
440
|
if req.error
|
415
441
|
raise req.error if req.error.is_a?(Error)
|
@@ -418,16 +444,17 @@ class Session
|
|
418
444
|
req.result
|
419
445
|
end
|
420
446
|
|
421
|
-
def
|
422
|
-
send_notify(method, args)
|
447
|
+
def notify_over(topt, method, *args)
|
448
|
+
send_notify(topt, method, args)
|
449
|
+
end
|
450
|
+
|
451
|
+
def send_message_over(topt, msg) # for Over#send_message
|
452
|
+
get_transport(topt).send_message(msg)
|
423
453
|
end
|
424
454
|
|
425
455
|
def close
|
426
|
-
@
|
427
|
-
|
428
|
-
sock.close
|
429
|
-
true
|
430
|
-
}
|
456
|
+
@dtran.close
|
457
|
+
@trans.each {|tran| tran.close }
|
431
458
|
reset
|
432
459
|
self
|
433
460
|
end
|
@@ -448,18 +475,116 @@ class Session
|
|
448
475
|
!@reqtable.empty?
|
449
476
|
end
|
450
477
|
|
478
|
+
def on_message(sock, msg) # Session interface
|
479
|
+
case msg[0]
|
480
|
+
when REQUEST
|
481
|
+
on_request(sock, msg[1], msg[2], msg[3])
|
482
|
+
when RESPONSE
|
483
|
+
on_response(sock, msg[1], msg[2], msg[3])
|
484
|
+
when NOTIFY
|
485
|
+
on_notify(sock, msg[1], msg[2])
|
486
|
+
when SESSION
|
487
|
+
# ignore because session is already bound
|
488
|
+
else
|
489
|
+
raise RPCError.new("unknown message type #{msg[0]}")
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
def on_connect_failed
|
494
|
+
@reqtable.reject! {|msgid, req|
|
495
|
+
begin
|
496
|
+
req.call ConnectError.new, nil
|
497
|
+
rescue
|
498
|
+
end
|
499
|
+
true
|
500
|
+
}
|
501
|
+
# FIXME reset?
|
502
|
+
end
|
503
|
+
|
504
|
+
private
|
505
|
+
def create_transport(topt)
|
506
|
+
TCPTransport.new(self, topt)
|
507
|
+
end
|
508
|
+
|
509
|
+
def get_transport(topt)
|
510
|
+
if topt.nil? || @dtran.match?(topt)
|
511
|
+
return @dtran
|
512
|
+
end
|
513
|
+
if tran = @trans.find {|f| f.match?(topt) }
|
514
|
+
return tran
|
515
|
+
end
|
516
|
+
tran = create_transport(topt)
|
517
|
+
@trans.push(tran)
|
518
|
+
tran
|
519
|
+
end
|
520
|
+
|
521
|
+
class Over
|
522
|
+
def initialize(session, topt)
|
523
|
+
@session = session
|
524
|
+
@topt = topt
|
525
|
+
end
|
526
|
+
|
527
|
+
def send(method, *args)
|
528
|
+
@session.send_over(@topt, method, *args)
|
529
|
+
end
|
530
|
+
|
531
|
+
def callback(method, *args, &block)
|
532
|
+
@session.callback_over(@topt, method, *args, &block)
|
533
|
+
end
|
534
|
+
|
535
|
+
def call(method, *args)
|
536
|
+
@session.call_over(@topt, method, *args)
|
537
|
+
end
|
538
|
+
|
539
|
+
def notify(method, *args)
|
540
|
+
@session.notify_over(@topt, method, *args)
|
541
|
+
end
|
542
|
+
|
543
|
+
def send_message(msg) # Transport interface for Responder
|
544
|
+
@session.send_message_over(@topt, msg)
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
def send_notify(topt, method, param)
|
549
|
+
unless @address
|
550
|
+
raise RPCError.new("unexpected send request on server session")
|
551
|
+
end
|
552
|
+
method = method.to_s unless method.is_a?(Integer)
|
553
|
+
tran = get_transport(topt)
|
554
|
+
tran.send_message([NOTIFY, method, param])
|
555
|
+
end
|
556
|
+
|
557
|
+
def send_request(topt, method, param)
|
558
|
+
unless @address
|
559
|
+
raise RPCError.new("unexpected send request on server session")
|
560
|
+
end
|
561
|
+
method = method.to_s unless method.is_a?(Integer)
|
562
|
+
tran = get_transport(topt)
|
563
|
+
msgid = @seqid
|
564
|
+
@seqid += 1; if @seqid >= 1<<31 then @seqid = 0 end
|
565
|
+
@reqtable[msgid] = Future.new(self, @loop)
|
566
|
+
tran.send_message([REQUEST, msgid, method, param])
|
567
|
+
msgid
|
568
|
+
end
|
451
569
|
|
452
|
-
def on_response(msgid, error, result)
|
570
|
+
def on_response(sock, msgid, error, result)
|
453
571
|
if req = @reqtable.delete(msgid)
|
454
572
|
req.call(error, result)
|
455
573
|
end
|
456
574
|
end
|
457
575
|
|
458
|
-
def on_request(method, param
|
576
|
+
def on_request(sock, msgid, method, param)
|
577
|
+
#if sock.option.rxproto
|
578
|
+
# #if @address
|
579
|
+
# tran = Over.new(self, sock.option)
|
580
|
+
#else
|
581
|
+
tran = sock
|
582
|
+
#end
|
583
|
+
res = Responder.new(tran, msgid)
|
459
584
|
@dispatcher.dispatch_request(self, method, param, res)
|
460
585
|
end
|
461
586
|
|
462
|
-
def on_notify(method, param)
|
587
|
+
def on_notify(sock, method, param)
|
463
588
|
@dispatcher.dispatch_notify(self, method, param)
|
464
589
|
end
|
465
590
|
|
@@ -467,57 +592,513 @@ class Session
|
|
467
592
|
@sockpool.delete(sock)
|
468
593
|
end
|
469
594
|
|
470
|
-
|
471
|
-
private
|
472
595
|
def reset
|
473
|
-
@sockpool = []
|
474
596
|
@reqtable = {}
|
475
597
|
@seqid = 0
|
476
|
-
@pending = ""
|
477
|
-
@connecting = 0
|
478
598
|
end
|
599
|
+
end
|
479
600
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
@
|
484
|
-
|
485
|
-
msgid
|
601
|
+
|
602
|
+
class BasicTransport
|
603
|
+
def initialize(session, topt)
|
604
|
+
@session = session
|
605
|
+
@option = topt
|
486
606
|
end
|
487
607
|
|
488
|
-
def
|
489
|
-
|
490
|
-
send_data RPCSocket.pack_notify(method, param)
|
491
|
-
nil
|
608
|
+
def match?(topt)
|
609
|
+
@option == topt
|
492
610
|
end
|
493
611
|
|
494
|
-
def
|
495
|
-
|
496
|
-
|
612
|
+
#def close; end
|
613
|
+
|
614
|
+
protected
|
615
|
+
def get_address
|
616
|
+
#@option.address || @session.address
|
617
|
+
@session.address
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
621
|
+
class TCPTransport < BasicTransport
|
622
|
+
def initialize(session, topt)
|
623
|
+
super(session, topt)
|
624
|
+
|
625
|
+
@pending = ""
|
626
|
+
@sockpool = []
|
627
|
+
@connecting = 0
|
628
|
+
@reconnect = 5 # FIXME default reconnect limit
|
629
|
+
|
630
|
+
@initmsg = ""
|
631
|
+
if session.self_address
|
632
|
+
@initmsg << [SESSION, session.self_address].to_msgpack
|
633
|
+
end
|
634
|
+
unless topt.default?
|
635
|
+
@initmsg << topt.to_msgpack
|
636
|
+
end
|
637
|
+
@initmsg = nil if @initmsg.empty?
|
638
|
+
|
639
|
+
if topt.txopt.deflate?
|
640
|
+
@deflate = Zlib::Deflate.new
|
641
|
+
else
|
642
|
+
@deflate = nil
|
497
643
|
end
|
644
|
+
end
|
645
|
+
|
646
|
+
def send_message(msg) # Transport interface
|
498
647
|
if @sockpool.empty?
|
499
648
|
if @connecting == 0
|
500
649
|
try_connect
|
501
650
|
@connecting = 1
|
502
651
|
end
|
503
|
-
@
|
652
|
+
if @deflate
|
653
|
+
@pending << @deflate.deflate(msg.to_msgpack, Zlib::SYNC_FLUSH)
|
654
|
+
else
|
655
|
+
@pending << msg.to_msgpack
|
656
|
+
end
|
504
657
|
else
|
505
658
|
# FIXME pesudo connection load balance
|
506
659
|
sock = @sockpool.first
|
507
|
-
sock.
|
660
|
+
sock.send_message(msg)
|
508
661
|
end
|
509
662
|
end
|
510
663
|
|
664
|
+
def close # Transport interface
|
665
|
+
@sockpool.reject! {|sock|
|
666
|
+
sock.detach if sock.attached?
|
667
|
+
sock.close
|
668
|
+
true
|
669
|
+
}
|
670
|
+
@sockpool = []
|
671
|
+
@connecting = 0
|
672
|
+
@pending = ""
|
673
|
+
@deflate.reset if @deflate
|
674
|
+
self
|
675
|
+
end
|
676
|
+
|
677
|
+
def on_connect(sock)
|
678
|
+
@sockpool.push(sock)
|
679
|
+
sock.send_pending(@pending, @deflate)
|
680
|
+
@pending = ""
|
681
|
+
@deflate = Zlib::Deflate.new if @deflate
|
682
|
+
@connecting = 0
|
683
|
+
end
|
684
|
+
|
685
|
+
def on_connect_failed(sock)
|
686
|
+
if @connecting < @reconnect
|
687
|
+
try_connect
|
688
|
+
@connecting += 1
|
689
|
+
else
|
690
|
+
@connecting = 0
|
691
|
+
@pending = ""
|
692
|
+
@session.on_connect_failed
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
696
|
+
def on_close(sock)
|
697
|
+
@sockpool.delete(sock)
|
698
|
+
end
|
699
|
+
|
700
|
+
private
|
511
701
|
def try_connect
|
512
|
-
|
513
|
-
|
702
|
+
addr = get_address
|
703
|
+
if addr.nil?
|
704
|
+
return # FIXME raise?
|
705
|
+
end
|
706
|
+
host, port = *addr
|
707
|
+
sock = ActiveSocket.connect(host, port, self, @option, @session) # async connect
|
514
708
|
if @initmsg
|
515
709
|
sock.write @initmsg
|
516
710
|
end
|
517
|
-
@loop.attach(sock)
|
711
|
+
@session.loop.attach(sock)
|
712
|
+
end
|
713
|
+
end
|
714
|
+
|
715
|
+
class TCPTransport::Socket < Rev::TCPSocket
|
716
|
+
def initialize(sock, session)
|
717
|
+
@buffer = ''
|
718
|
+
@nread = 0
|
719
|
+
@mpac = MessagePack::Unpacker.new
|
720
|
+
@deflate = nil
|
721
|
+
@inflate = nil
|
722
|
+
@s = session
|
723
|
+
super(sock)
|
724
|
+
end
|
725
|
+
|
726
|
+
def session
|
727
|
+
@s
|
728
|
+
end
|
729
|
+
|
730
|
+
def on_read(data)
|
731
|
+
if @inflate
|
732
|
+
data = @inflate.inflate(data)
|
733
|
+
return if data.empty?
|
734
|
+
end
|
735
|
+
@buffer << data
|
736
|
+
|
737
|
+
while true
|
738
|
+
@nread = @mpac.execute(@buffer, @nread)
|
739
|
+
if @mpac.finished?
|
740
|
+
msg = @mpac.data
|
741
|
+
@mpac.reset
|
742
|
+
@buffer.slice!(0, @nread)
|
743
|
+
@nread = 0
|
744
|
+
on_message(msg)
|
745
|
+
next unless @buffer.empty?
|
746
|
+
end
|
747
|
+
break
|
748
|
+
end
|
749
|
+
end
|
750
|
+
|
751
|
+
def on_message(msg)
|
752
|
+
return unless @s
|
753
|
+
@s.on_message(self, msg)
|
754
|
+
end
|
755
|
+
|
756
|
+
def on_close
|
757
|
+
@deflate.close if @deflate
|
758
|
+
@inflate.close if @inflate
|
759
|
+
end
|
760
|
+
|
761
|
+
def send_message(msg) # Transport interface
|
762
|
+
if @deflate
|
763
|
+
data = @deflate.deflate(msg.to_msgpack, Zlib::SYNC_FLUSH)
|
764
|
+
else
|
765
|
+
data = msg.to_msgpack
|
766
|
+
end
|
767
|
+
write data
|
768
|
+
end
|
769
|
+
end
|
770
|
+
|
771
|
+
class TCPTransport::ActiveSocket < TCPTransport::Socket
|
772
|
+
def initialize(sock, tran, topt, session)
|
773
|
+
super(sock, session)
|
774
|
+
@tran = tran
|
775
|
+
set_option(topt)
|
776
|
+
end
|
777
|
+
|
778
|
+
def on_connect
|
779
|
+
return unless @tran
|
780
|
+
@tran.on_connect(self)
|
781
|
+
end
|
782
|
+
|
783
|
+
def on_connect_failed
|
784
|
+
return unless @tran
|
785
|
+
@tran.on_connect_failed(self)
|
786
|
+
end
|
787
|
+
|
788
|
+
def on_close
|
789
|
+
return unless @tran
|
790
|
+
@tran.on_close(self)
|
791
|
+
@tran = nil
|
792
|
+
@s = nil
|
793
|
+
rescue
|
794
|
+
nil
|
795
|
+
ensure
|
796
|
+
super
|
797
|
+
end
|
798
|
+
|
799
|
+
def send_pending(data, z)
|
800
|
+
write data
|
801
|
+
@deflate = z
|
802
|
+
end
|
803
|
+
|
804
|
+
private
|
805
|
+
def set_option(sopt) # stream option
|
806
|
+
if sopt.txopt.deflate?
|
807
|
+
@deflate = Zlib::Deflate.new
|
808
|
+
end
|
809
|
+
if sopt.rxopt.deflate?
|
810
|
+
@inflate = Zlib::Inflate.new
|
811
|
+
#@buffer = @inflate.inflate(@buffer) unless @buffer.empty?
|
812
|
+
end
|
518
813
|
end
|
519
814
|
end
|
520
815
|
|
816
|
+
class TCPTransport::PassiveSocket < TCPTransport::Socket
|
817
|
+
def initialize(sock, create_session)
|
818
|
+
super(sock, create_session.call)
|
819
|
+
@option = TransportOption.new # active option (reversed)
|
820
|
+
end
|
821
|
+
|
822
|
+
attr_reader :option # for Session#on_request
|
823
|
+
|
824
|
+
def rebind(session)
|
825
|
+
@s = session
|
826
|
+
end
|
827
|
+
|
828
|
+
def on_message(msg)
|
829
|
+
if msg[0] == OPTION
|
830
|
+
sopt = StreamOption.from_msgpack(msg)
|
831
|
+
set_option(sopt)
|
832
|
+
return
|
833
|
+
end
|
834
|
+
super(msg)
|
835
|
+
end
|
836
|
+
|
837
|
+
private
|
838
|
+
def set_option(sopt)
|
839
|
+
if sopt.txopt.deflate?
|
840
|
+
@inflate = Zlib::Inflate.new
|
841
|
+
@buffer = @inflate.inflate(@buffer) unless @buffer.empty?
|
842
|
+
end
|
843
|
+
if sopt.rxopt.deflate?
|
844
|
+
@deflate = Zlib::Deflate.new
|
845
|
+
end
|
846
|
+
# rx-tx reverse
|
847
|
+
@option = TransportOption.new
|
848
|
+
@option.txopt = sopt.rxopt
|
849
|
+
@option.rxopt = sopt.txopt
|
850
|
+
#@option.proto = sopt.rxproto || PROTO_TCP
|
851
|
+
#@option.address = sopt.rxaddr
|
852
|
+
end
|
853
|
+
end
|
854
|
+
|
855
|
+
class TCPTransport::Listener
|
856
|
+
def initialize(host, port, &create_session)
|
857
|
+
@lsock = Rev::TCPServer.new(host, port, TCPTransport::PassiveSocket, create_session)
|
858
|
+
end
|
859
|
+
|
860
|
+
def activate(loop)
|
861
|
+
loop.attach(@lsock)
|
862
|
+
end
|
863
|
+
|
864
|
+
def close
|
865
|
+
@lsock.detach if @lsock.attached?
|
866
|
+
@lsock.close
|
867
|
+
end
|
868
|
+
end
|
869
|
+
|
870
|
+
|
871
|
+
=begin
|
872
|
+
class UDPTransport < BasicTransport
|
873
|
+
def initialize(session, topt)
|
874
|
+
super(session, topt)
|
875
|
+
|
876
|
+
initmsg = ""
|
877
|
+
if session.self_address
|
878
|
+
initmsg << [SESSION, session.self_address].to_msgpack
|
879
|
+
end
|
880
|
+
unless topt.default?
|
881
|
+
initmsg << topt.to_msgpack
|
882
|
+
end
|
883
|
+
initmsg = nil if initmsg.empty?
|
884
|
+
|
885
|
+
sock = UDPSocket.new
|
886
|
+
@addr = get_address
|
887
|
+
@asock = ActiveSocket.new(sock, initmsg, topt, session)
|
888
|
+
end
|
889
|
+
|
890
|
+
def send_message(msg) # Transport interface
|
891
|
+
@asock.send_message_to(msg, @addr)
|
892
|
+
end
|
893
|
+
|
894
|
+
def close
|
895
|
+
@sock.close
|
896
|
+
@deflate.close if @deflate
|
897
|
+
end
|
898
|
+
end
|
899
|
+
|
900
|
+
class UDPTransport::Socket < Rev::IO
|
901
|
+
def initialize(sock, create_session)
|
902
|
+
@sock = sock
|
903
|
+
@mpac = MessagePack::Unpacker.new
|
904
|
+
@create_session = create_session
|
905
|
+
super(sock)
|
906
|
+
end
|
907
|
+
|
908
|
+
def on_readable
|
909
|
+
begin
|
910
|
+
buffer, from = @sock.recvfrom(65536)
|
911
|
+
rescue Errno::EAGAIN
|
912
|
+
return
|
913
|
+
rescue Errno::EINTR
|
914
|
+
return
|
915
|
+
end
|
916
|
+
# addr = Address.from_sockaddr(from) FIXME
|
917
|
+
on_recv(buffer, addr)
|
918
|
+
end
|
919
|
+
|
920
|
+
def on_message(rc, msg)
|
921
|
+
return unless @s
|
922
|
+
@s.on_message(rc, msg)
|
923
|
+
end
|
924
|
+
|
925
|
+
def send_message_with(initmsg, msg, deflate, addr)
|
926
|
+
if deflate
|
927
|
+
d2 = deflate.deflate(msg.to_msgpack, Zlib::SYNC_FLUSH)
|
928
|
+
else
|
929
|
+
d2 = msg.to_msgpack
|
930
|
+
end
|
931
|
+
if initmsg
|
932
|
+
data = d2
|
933
|
+
else
|
934
|
+
data = initmsg.dup
|
935
|
+
data << d2
|
936
|
+
end
|
937
|
+
@sock.sendto(data, 0, addr.sockaddr)
|
938
|
+
end
|
939
|
+
end
|
940
|
+
|
941
|
+
class UDPTransport::ActiveSocket < UDPTransport::Socket
|
942
|
+
def initialize(sock, initmsg, topt, session)
|
943
|
+
@sock = sock
|
944
|
+
super(sock)
|
945
|
+
if topt.txopt.deflate?
|
946
|
+
@deflate = Zlib::Deflate.new
|
947
|
+
else
|
948
|
+
@deflate = nil
|
949
|
+
end
|
950
|
+
@initmsg = initmsg
|
951
|
+
@s = session
|
952
|
+
end
|
953
|
+
|
954
|
+
def on_recv(data, addr)
|
955
|
+
rc = ReturnContext.new(self, addr)
|
956
|
+
if @inflate
|
957
|
+
data = @inflate.inflate(data)
|
958
|
+
@inflate.finish
|
959
|
+
return if data.empty?
|
960
|
+
end
|
961
|
+
nread = 0
|
962
|
+
while true
|
963
|
+
nread = @mpac.execute(data, nread)
|
964
|
+
if @mpac.finished?
|
965
|
+
msg = @mpac.data
|
966
|
+
@mpac.reset
|
967
|
+
data.slice!(0, nread)
|
968
|
+
nread = 0
|
969
|
+
on_message(rc, msg)
|
970
|
+
next unless data.empty?
|
971
|
+
else
|
972
|
+
@mpac.reset
|
973
|
+
end
|
974
|
+
break
|
975
|
+
end
|
976
|
+
end
|
977
|
+
|
978
|
+
def send_message_to(msg, addr)
|
979
|
+
send_message_with(@initmsg, msg, @deflate, addr)
|
980
|
+
end
|
981
|
+
|
982
|
+
private
|
983
|
+
class ReturnContext
|
984
|
+
def initialize(asock, addr)
|
985
|
+
@asock = asock
|
986
|
+
@addr = addr
|
987
|
+
end
|
988
|
+
|
989
|
+
def send_message(msg) # Transport interface
|
990
|
+
@asock.send_message_to(msg, @addr)
|
991
|
+
end
|
992
|
+
end
|
993
|
+
end
|
994
|
+
|
995
|
+
class UDPTransport::PassiveSocket < UDPTransport::Socket
|
996
|
+
def initialize(sock, create_session)
|
997
|
+
super(sock)
|
998
|
+
@create_session = create_session
|
999
|
+
@inflate = LazyInflate.new
|
1000
|
+
@deflate = LazyInflate.new
|
1001
|
+
end
|
1002
|
+
|
1003
|
+
def on_recv(data, addr)
|
1004
|
+
rc = PassiveReturnContext.new(self, addr)
|
1005
|
+
nread = 0
|
1006
|
+
while true
|
1007
|
+
nread = @mpac.execute(data, nread)
|
1008
|
+
if @mpac.finished?
|
1009
|
+
msg = @mpac.data
|
1010
|
+
@mpac.reset
|
1011
|
+
data.slice!(0, nread)
|
1012
|
+
nread = 0
|
1013
|
+
data = on_message(data, rc, msg)
|
1014
|
+
next unless data.empty?
|
1015
|
+
else
|
1016
|
+
@mpac.reset
|
1017
|
+
end
|
1018
|
+
break
|
1019
|
+
end
|
1020
|
+
end
|
1021
|
+
|
1022
|
+
def on_message(data, rc, msg)
|
1023
|
+
if msg[0] == OPTION
|
1024
|
+
sopt = StreamOption.from_msgpack(msg)
|
1025
|
+
return set_option(data, rc, sopt)
|
1026
|
+
end
|
1027
|
+
super(rc, msg)
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
attr_reader :deflate # for ReturnContext#send_message
|
1031
|
+
|
1032
|
+
private
|
1033
|
+
class ReturnContext
|
1034
|
+
def initialize(psock, addr)
|
1035
|
+
@psock = psock
|
1036
|
+
@addr = addr
|
1037
|
+
@option = TransportOption.new
|
1038
|
+
end
|
1039
|
+
attr_accessor :option
|
1040
|
+
|
1041
|
+
def send_message(msg) # Transport interface
|
1042
|
+
if @option.txopt.deflate?
|
1043
|
+
deflate = @psock.deflate.get
|
1044
|
+
else
|
1045
|
+
deflate = nil
|
1046
|
+
end
|
1047
|
+
@psock.send_message_with(nil, msg, deflate, @addr)
|
1048
|
+
end
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
class LazyDeflate
|
1052
|
+
def initialize
|
1053
|
+
@deflate = nil
|
1054
|
+
end
|
1055
|
+
def get
|
1056
|
+
@deflate ||= Zlib::Deflate.new
|
1057
|
+
end
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
class LazyInflate
|
1061
|
+
def initialize
|
1062
|
+
@inflate = nil
|
1063
|
+
end
|
1064
|
+
def get
|
1065
|
+
@inflate ||= Zlib::Inflate.new
|
1066
|
+
end
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
def set_option(data, rc, sopt)
|
1070
|
+
if sopt.txopt.deflate?
|
1071
|
+
inflate = @inflate.get
|
1072
|
+
data = inflate.inflate(data)
|
1073
|
+
@inflate.finish
|
1074
|
+
end
|
1075
|
+
# rx-tx reverse
|
1076
|
+
rc.option.reset
|
1077
|
+
rc.option.txopt = sopt.rxopt
|
1078
|
+
rc.option.proto = sopt.rxproto || PROTO_UDP
|
1079
|
+
rc.option.address = sopt.rxaddr
|
1080
|
+
data
|
1081
|
+
end
|
1082
|
+
end
|
1083
|
+
|
1084
|
+
class UDPTransport::Listener
|
1085
|
+
def initialize(host, port, &create_session)
|
1086
|
+
@sock = UDPSocket.new
|
1087
|
+
@sock.bind(host, port)
|
1088
|
+
@psock = PassiveSocket.new(@sock, &create_session)
|
1089
|
+
end
|
1090
|
+
|
1091
|
+
def activate(loop)
|
1092
|
+
loop.attach(@psock)
|
1093
|
+
end
|
1094
|
+
|
1095
|
+
def close
|
1096
|
+
@psock.detach if @psock.attached?
|
1097
|
+
@psock.close
|
1098
|
+
end
|
1099
|
+
end
|
1100
|
+
=end
|
1101
|
+
|
521
1102
|
|
522
1103
|
class AsyncResult
|
523
1104
|
def initialize
|
@@ -662,13 +1243,13 @@ end
|
|
662
1243
|
|
663
1244
|
|
664
1245
|
class Client < Session
|
665
|
-
def initialize(host, port, loop = Loop.new)
|
1246
|
+
def initialize(host, port, loop = Loop.new, dtopt = TransportOption.new)
|
666
1247
|
@loop = loop
|
667
1248
|
@host = host
|
668
1249
|
@port = port
|
669
1250
|
|
670
|
-
|
671
|
-
super(
|
1251
|
+
addr = Address.new(host, port)
|
1252
|
+
super(addr, dtopt, NullDispatcher.new, nil, loop)
|
672
1253
|
|
673
1254
|
@timer = Timer.new(1, true) {
|
674
1255
|
step_timeout
|
@@ -677,8 +1258,8 @@ class Client < Session
|
|
677
1258
|
end
|
678
1259
|
attr_reader :host, :port
|
679
1260
|
|
680
|
-
def self.open(host, port, loop = Loop.new, &block)
|
681
|
-
cli = new(host, port, loop)
|
1261
|
+
def self.open(host, port, loop = Loop.new, dtopt = TransportOption.new, &block)
|
1262
|
+
cli = new(host, port, loop, dtopt)
|
682
1263
|
begin
|
683
1264
|
block.call(cli)
|
684
1265
|
ensure
|
@@ -696,20 +1277,25 @@ end
|
|
696
1277
|
|
697
1278
|
|
698
1279
|
class SessionPool
|
699
|
-
def initialize(loop = Loop.new)
|
1280
|
+
def initialize(loop = Loop.new, dtopt = TransportOption.new)
|
700
1281
|
@loop = loop
|
701
1282
|
@spool = {}
|
702
1283
|
@stimer = Timer.new(1, true, &method(:step_timeout))
|
1284
|
+
@dtopt = dtopt
|
703
1285
|
loop.attach(@stimer)
|
704
1286
|
end
|
705
1287
|
|
706
1288
|
def get_session(host, port)
|
707
|
-
|
708
|
-
|
1289
|
+
addr = Address.new(host, port)
|
1290
|
+
get_session_addr(addr)
|
1291
|
+
end
|
1292
|
+
|
1293
|
+
def get_session_addr(addr)
|
1294
|
+
@spool[addr] ||= create_session(addr)
|
709
1295
|
end
|
710
1296
|
|
711
1297
|
def close
|
712
|
-
@spool.reject! {|
|
1298
|
+
@spool.reject! {|addr, s|
|
713
1299
|
s.close
|
714
1300
|
true
|
715
1301
|
}
|
@@ -720,13 +1306,13 @@ class SessionPool
|
|
720
1306
|
include LoopUtil
|
721
1307
|
|
722
1308
|
protected
|
723
|
-
def create_session(
|
724
|
-
Session.new(
|
1309
|
+
def create_session(addr)
|
1310
|
+
Session.new(addr, @dtopt, nil, nil, @loop)
|
725
1311
|
end
|
726
1312
|
|
727
1313
|
private
|
728
1314
|
def step_timeout
|
729
|
-
@spool.each_pair {|
|
1315
|
+
@spool.each_pair {|addr, s|
|
730
1316
|
s.step_timeout
|
731
1317
|
}
|
732
1318
|
end
|
@@ -734,66 +1320,86 @@ end
|
|
734
1320
|
|
735
1321
|
|
736
1322
|
class Server < SessionPool
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
end
|
1323
|
+
def initialize(loop = Loop.new)
|
1324
|
+
super(loop, TransportOption.new)
|
1325
|
+
@dispatcher = nil
|
1326
|
+
@listeners = []
|
742
1327
|
end
|
743
1328
|
|
744
|
-
def
|
745
|
-
|
746
|
-
|
1329
|
+
def serve(obj, accept = obj.public_methods)
|
1330
|
+
@dispatcher = ObjectDispatcher.new(obj, accept)
|
1331
|
+
end
|
1332
|
+
|
1333
|
+
def listen(host, port, obj = nil, accept = obj.public_methods)
|
1334
|
+
unless obj.nil?
|
1335
|
+
serve(obj, accept)
|
1336
|
+
end
|
1337
|
+
listen_real(host, port)
|
1338
|
+
self
|
747
1339
|
end
|
748
1340
|
|
749
|
-
def
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
1341
|
+
def listen_real(host, port) #, proto = PROTO_TCP)
|
1342
|
+
creator = Proc.new { create_session(nil) }
|
1343
|
+
#case proto
|
1344
|
+
#when PROTO_TCP, :tcp
|
1345
|
+
# listener = TCPTransport::Listener.new(host, port, &creator)
|
1346
|
+
#when PROTO_UDP, :udp
|
1347
|
+
# listener = UDPTransport::Listener.new(host, port, &creator)
|
1348
|
+
#else
|
1349
|
+
# raise "unknown option: #{proto.inspect}"
|
1350
|
+
#end
|
1351
|
+
listener = TCPTransport::Listener.new(host, port, &creator)
|
1352
|
+
@listeners.push(listener)
|
1353
|
+
listener.activate(@loop)
|
1354
|
+
self
|
754
1355
|
end
|
755
1356
|
|
756
1357
|
def close
|
757
|
-
@
|
758
|
-
|
759
|
-
lsock.close
|
1358
|
+
@listeners.reject! {|listener|
|
1359
|
+
listener.close
|
760
1360
|
true
|
761
1361
|
}
|
762
1362
|
super
|
763
1363
|
end
|
1364
|
+
|
1365
|
+
protected
|
1366
|
+
def create_session(addr)
|
1367
|
+
Session.new(addr, @dtopt, @dispatcher, nil, @loop)
|
1368
|
+
end
|
764
1369
|
end
|
765
1370
|
|
766
1371
|
|
767
1372
|
class Cluster < SessionPool
|
768
|
-
|
769
|
-
|
770
|
-
@binder = binder
|
771
|
-
super(sock, nil)
|
772
|
-
end
|
773
|
-
|
774
|
-
def on_message(msg)
|
775
|
-
if bound?
|
776
|
-
super
|
777
|
-
else
|
778
|
-
@binder.call(self, msg)
|
779
|
-
end
|
780
|
-
end
|
781
|
-
end
|
782
|
-
|
783
|
-
def initialize(host, port, loop = Loop.new)
|
784
|
-
super(loop)
|
1373
|
+
def initialize(host, port, loop = Loop.new, dtopt = TransportOption.new)
|
1374
|
+
super(loop, dtopt)
|
785
1375
|
@host = host
|
786
1376
|
@port = port
|
787
1377
|
@dispatcher = nil
|
788
|
-
self_addr = Address.new(host, port)
|
789
|
-
@
|
1378
|
+
@self_addr = Address.new(host, port)
|
1379
|
+
@listeners = []
|
1380
|
+
listen(host, port) # FIXME obsolete?
|
790
1381
|
end
|
791
1382
|
attr_reader :host, :port
|
792
1383
|
|
793
1384
|
def serve(obj, accept = obj.public_methods)
|
794
1385
|
@dispatcher = ObjectDispatcher.new(obj, accept)
|
795
|
-
|
796
|
-
|
1386
|
+
self
|
1387
|
+
end
|
1388
|
+
|
1389
|
+
def listen(host, port) #, proto = PROTO_TCP)
|
1390
|
+
lz = LazyBinder.new(self)
|
1391
|
+
creator = Proc.new { lz }
|
1392
|
+
#case proto
|
1393
|
+
#when PROTO_TCP, :tcp
|
1394
|
+
# listener = TCPTransport::Listener.new(host, port, &creator)
|
1395
|
+
#when PROTO_UDP, :udp
|
1396
|
+
# listener = UDPTransport::Listener.new(host, port, &creator)
|
1397
|
+
#else
|
1398
|
+
# raise "unknown option: #{proto.inspect}"
|
1399
|
+
#end
|
1400
|
+
listener = TCPTransport::Listener.new(host, port, &creator)
|
1401
|
+
@listeners.push(listener)
|
1402
|
+
listener.activate(@loop)
|
797
1403
|
self
|
798
1404
|
end
|
799
1405
|
|
@@ -808,28 +1414,39 @@ class Cluster < SessionPool
|
|
808
1414
|
include LoopUtil
|
809
1415
|
|
810
1416
|
protected
|
811
|
-
def create_session(
|
812
|
-
Session.new(
|
1417
|
+
def create_session(addr)
|
1418
|
+
Session.new(addr, @dtopt, @dispatcher, @self_addr, @loop)
|
1419
|
+
end
|
1420
|
+
|
1421
|
+
public
|
1422
|
+
def create_server_session
|
1423
|
+
# FIXME
|
1424
|
+
Session.new(nil, @dtopt, @dispatcher, @self_addr, @loop)
|
813
1425
|
end
|
814
1426
|
|
815
1427
|
private
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
1428
|
+
class LazyBinder < Session
|
1429
|
+
def initialize(cluster)
|
1430
|
+
@cluster = cluster
|
1431
|
+
end
|
1432
|
+
|
1433
|
+
def on_message(sock, msg) # Session interface
|
1434
|
+
if msg[0] == SESSION
|
1435
|
+
# cluster
|
1436
|
+
addr = Address.load(msg[1])
|
1437
|
+
session = @cluster.get_session_addr(addr)
|
1438
|
+
sock.rebind(session)
|
1439
|
+
else
|
1440
|
+
# subsys
|
1441
|
+
session = @cluster.create_server_session
|
1442
|
+
sock.rebind(session)
|
1443
|
+
sock.on_message(msg)
|
1444
|
+
end
|
828
1445
|
end
|
829
1446
|
end
|
830
1447
|
end
|
831
1448
|
|
832
1449
|
|
833
|
-
end
|
834
|
-
end
|
1450
|
+
end
|
1451
|
+
end
|
835
1452
|
|