Skip to content

Instantly share code, notes, and snippets.

@penguin2716
Last active December 24, 2015 03:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save penguin2716/6740958 to your computer and use it in GitHub Desktop.
Save penguin2716/6740958 to your computer and use it in GitHub Desktop.
メソッド呼ばれた時とかにsignaling_emitしてsingnaling_connectで登録されたメソッドを叩けると便利じゃね
#!/usr/bin/env ruby
#-*- coding: utf-8 -*-
require 'securerandom'
require 'socket'
require 'zlib'
module Signaling
def debug(message)
puts "debug: #{message}" if @debug_mode == true
end
def initialize
# @signal_table => { signal_name, [[proc, uuid], [proc, uuid], ...] }
@signaling_table ||= {}
@signaling_table_remote ||= {}
@debug_mode = true if ARGV[0] == '--debug'
end
def signaling_emit(signal, *args)
if @signaling_table[signal]
@signaling_table[signal].each { |proc, uuid|
proc.call(args)
}
end
end
def signaling_register(signal, &proc)
uuid = SecureRandom.uuid
if @signaling_table[signal] != nil
@signaling_table[signal] << [proc, uuid]
else
@signaling_table[signal] = [[proc, uuid]]
end
signaling_emit('registered', uuid)
uuid
end
def signaling_remove(remove_uuid)
@signaling_table.each do |signal, procs|
procs.delete_if {|proc, uuid| uuid == remove_uuid}
end
signaling_emit('removed', remove_uuid)
end
module Remote
def signaling_remote_client_init(host, port)
@mode = :client
@client = TCPSocket.new(host, port)
debug "client: connection established to #{@client.addr}"
@client
end
def signaling_remote_client_close
@client.close
end
def _send_tagged_message(socket, tag, data)
socket.puts "<#{tag}>"
socket.puts Zlib::Deflate.deflate(Marshal.dump(data))
socket.puts "</#{tag}>"
end
def _receive_tagged_message(socket, tag)
loop do break if socket.gets == "<#{tag}>\n" end
data = ""
while socket.gets
break if $_ == "</#{tag}>\n"
data += $_
end
Marshal.restore(Zlib::Inflate.inflate(data))
end
def send_request(socket, data)
_send_tagged_message(socket, 'request', data)
end
def send_response(socket, data)
_send_tagged_message(socket, 'response', data)
end
def receive_request(socket)
_receive_tagged_message(socket, 'request')
end
def receive_response(socket)
_receive_tagged_message(socket, 'response')
end
def signaling_remote_server_init(host, port)
@mode = :server
@server = TCPServer.new(host, port)
loop do
Thread.start(@server.accept) do |client|
debug "server: connection established from #{client.addr}"
while (args = receive_request(client))
if args[0] == :emit
debug "server: received request :emit"
send_response(client, _signaling_remote_emit(args[1], args[2]))
elsif args[0] == :register
debug "server: received request :register"
send_response(client, _signaling_remote_register(args[1], args[2]))
elsif args[0] == :remove
debug "server: received request :remove"
send_response(client, _signaling_remote_remove(args[1]))
end
end
client.close
debug "server: connection closed"
end
end
end
def signaling_remote_emit(signal, args)
send_request(@client, [:emit, signal, args])
receive_response(@client).each do |proc_str|
begin
(eval proc_str).call
rescue
nil
end
end
end
def signaling_remote_register(signal, proc_str)
send_request(@client, [:register, signal, proc_str])
receive_response(@client)
end
def signaling_remote_remove(remove_uuid)
send_request(@client, [:remove, remove_uuid])
receive_response(@client)
end
def _signaling_remote_emit(signal, args)
results = []
if @signaling_table_remote[signal]
@signaling_table_remote[signal].each { |proc, uuid|
result = proc.call(args)
results << result
}
end
results
end
def _signaling_remote_register(signal, proc_str)
uuid = SecureRandom.uuid
proc = eval proc_str
if @signaling_table_remote[signal] != nil
@signaling_table_remote[signal] << [proc, uuid]
else
@signaling_table_remote[signal] = [[proc, uuid]]
end
uuid
end
def _signaling_remote_remove(remove_uuid)
@signaling_table_remote.each do |signal, procs|
procs.delete_if {|proc, uuid| uuid == remove_uuid}
end
remove_uuid
end
end
end
class Foo
include Signaling
include Signaling::Remote
def bar
signaling_emit('fizz', [10, 20])
signaling_remote_emit('fizz', [10, 20])
end
def buzz
puts signaling_remote_emit('buzz', [10, 20])
end
end
Thread.new do
remote = Foo.new
code = %{
lambda{ |args|
lhs = args[0]
rhs = args[1]
print ">>> server: "
puts "lhs * rhs = \#{lhs * rhs}"
"foooooo"
}
}
remote._signaling_remote_register('buzz', code)
uuid = remote._signaling_remote_register('foo', code)
remote._signaling_remote_emit('foo', [40, 30])
remote._signaling_remote_remove(uuid)
remote.signaling_remote_server_init('localhost', 12345)
end
sleep 1
local = Foo.new
local.signaling_remote_client_init('localhost', 12345)
code = %{
lambda{ |args|
lhs = args[0]
rhs = args[1]
print ">>> server: "
puts "lhs + rhs = \#{lhs + rhs}"
%{
lambda{
print ">>> client: "
puts "\#{lhs} * \#{rhs} = \#{lhs * rhs}"
}
}
}
}
uuid = local.signaling_remote_register('fizz', code)
local.bar
local.buzz
local.signaling_remote_remove(uuid)
local.signaling_remote_client_close
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment