require 'logger' require 'rubygems' require 'eventmachine' require 'bert' module ProxyLocal VERSION = '0.1.0' module Serializer def self.dump(object) BERT.encode(object) end def self.load(data) BERT.decode(data) end end class Client < EventMachine::Connection include EventMachine::Protocols::ObjectProtocol def self.run(options = {}) @@logger = Logger.new(STDOUT) @@logger.level = options[:verbose] ? Logger::INFO : Logger::WARN @@logger.info("Run with options #{options.inspect}") trap "SIGCLD", "IGNORE" trap "INT" do puts EventMachine.run exit end EventMachine.run do EventMachine.connect(options[:server_host], options[:server_port], self) do |c| c.instance_eval do @options = options if @options[:tls] @@logger.info("Request TLS") send_object(:start_tls) else send_options end end end end end def serializer Serializer end def send_options send_object(BERT::Tuple[:options, @options]) end def ssl_handshake_completed send_options end def first_line(data) data.split(/\r?\n/, 2).first end def receive_object(message) message = [message] unless message.is_a?(Array) case message[0] when :start_tls @@logger.info("Start TLS") start_tls when :message puts message[1] when :halt EventMachine.stop_event_loop when :request _, uuid, request = message @@logger.info(first_line(request)) EventMachine.connect('127.0.0.1', @options[:local_port], ClientProxy) do |connection| connection.callback do |data| @@logger.info("#{first_line(data)} - #{first_line(request)}") send_object(BERT::Tuple[:response, uuid, data]) end connection.send_data(request) end end end def unbind EventMachine.stop_event_loop puts "A connection has been terminated" end end class ClientProxy < EventMachine::Connection def post_init @data = '' end def receive_data(data) @data << data end def unbind @callback.call(@data) if @callback end def callback(&block) @callback = block end end end