Last active
December 24, 2015 03:59
-
-
Save penguin2716/6740958 to your computer and use it in GitHub Desktop.
メソッド呼ばれた時とかにsignaling_emitしてsingnaling_connectで登録されたメソッドを叩けると便利じゃね
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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