1require 'drb/drb'
2require 'net/http'
3require 'uri'
4
5module DRb
6  module HTTP0
7    class StrStream
8      def initialize(str='')
9	@buf = str
10      end
11      attr_reader :buf
12
13      def read(n)
14	begin
15	  return @buf[0,n]
16	ensure
17	  @buf[0,n] = ''
18	end
19      end
20
21      def write(s)
22	@buf.concat s
23      end
24    end
25
26    def self.uri_option(uri, config)
27      return uri, nil
28    end
29
30    def self.open(uri, config)
31      unless /^http:/ =~ uri
32	raise(DRbBadScheme, uri) unless uri =~ /^http:/
33	raise(DRbBadURI, 'can\'t parse uri:' + uri)
34      end
35      ClientSide.new(uri, config)
36    end
37
38    class ClientSide
39      def initialize(uri, config)
40	@uri = uri
41	@res = nil
42	@config = config
43	@msg = DRbMessage.new(config)
44	@proxy = ENV['HTTP_PROXY']
45      end
46
47      def close; end
48      def alive?; false; end
49
50      def send_request(ref, msg_id, *arg, &b)
51	stream = StrStream.new
52	@msg.send_request(stream, ref, msg_id, *arg, &b)
53	@reply_stream = StrStream.new
54	post(@uri, stream.buf)
55      end
56
57      def recv_reply
58	@msg.recv_reply(@reply_stream)
59      end
60
61      def post(url, data)
62	it = URI.parse(url)
63	path = [(it.path=='' ? '/' : it.path), it.query].compact.join('?')
64	http = Net::HTTP.new(it.host, it.port)
65	sio = StrStream.new
66	http.post(path, data, {'Content-Type'=>'application/octetstream;'}) do |str|
67	  sio.write(str)
68	  if @config[:load_limit] < sio.buf.size
69	    raise TypeError, 'too large packet'
70	  end
71	end
72	@reply_stream = sio
73      end
74    end
75  end
76  DRbProtocol.add_protocol(HTTP0)
77end
78