require 'drb/drb'
require 'net/http'
require 'urb'

module DRb
  class StrSoc 
    def initialize(str='')
      @buf = str
    end
    attr_reader :buf

    def shutdown(n); end

    def read(n)
      begin
	return @buf[0,n]
      ensure
	@buf[0,n] = ''
      end
    end

    def write(s)
      @buf.concat s
    end
  end

  class DRbConn
    @@proxy_map = {}
    def self.proxy_map
      @@proxy_map
    end

    alias send_message_org send_message

    def send_message(ref, msg_id, *arg, &block)
      return send_message_org(ref, msg_id, *arg, &block) unless proxy

      sio = StrSoc.new
      send_request(sio, ref, msg_id, *arg, &block)
      sio = post(proxy, sio.buf)
      recv_reply(sio)
    end

    private
    def proxy
      @@proxy_map[@host]
    end

    def post(url, data)
      it = URb.parse(url)
      path = [(it.path=='' ? '/' : it.path), it.query].compact.join('?')
      http = Net::HTTP.new(it.host, it.port)
      header = {
	'DRb-Server'=>"druby://#{@host}:#{@port}",
	'DRb-Here'=>DRb.uri
      }
      sio = StrSoc.new
      http.post(path, data, header) do |str|
	sio.write(str)
	raise TypeError, 'too large packet' if load_limit < sio.buf.size
      end
      sio
    end
  end
end
