source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/net/protocol.rb@ 18425

Last change on this file since 18425 was 18425, checked in by davidb, 15 years ago

Video extension to Greenstone

File size: 7.6 KB
Line 
1#
2# = net/protocol.rb
3#
4#--
5# Copyright (c) 1999-2005 Yukihiro Matsumoto
6# Copyright (c) 1999-2005 Minero Aoki
7#
8# written and maintained by Minero Aoki <[email protected]>
9#
10# This program is free software. You can re-distribute and/or
11# modify this program under the same terms as Ruby itself,
12# Ruby Distribute License or GNU General Public License.
13#
14# $Id: protocol.rb 11708 2007-02-12 23:01:19Z shyouhei $
15#++
16#
17# WARNING: This file is going to remove.
18# Do not rely on the implementation written in this file.
19#
20
21require 'socket'
22require 'timeout'
23
24module Net # :nodoc:
25
26 class Protocol #:nodoc: internal use only
27 private
28 def Protocol.protocol_param(name, val)
29 module_eval(<<-End, __FILE__, __LINE__ + 1)
30 def #{name}
31 #{val}
32 end
33 End
34 end
35 end
36
37
38 class ProtocolError < StandardError; end
39 class ProtoSyntaxError < ProtocolError; end
40 class ProtoFatalError < ProtocolError; end
41 class ProtoUnknownError < ProtocolError; end
42 class ProtoServerError < ProtocolError; end
43 class ProtoAuthError < ProtocolError; end
44 class ProtoCommandError < ProtocolError; end
45 class ProtoRetriableError < ProtocolError; end
46 ProtocRetryError = ProtoRetriableError
47
48
49 class BufferedIO #:nodoc: internal use only
50 def initialize(io)
51 @io = io
52 @read_timeout = 60
53 @debug_output = nil
54 @rbuf = ''
55 end
56
57 attr_reader :io
58 attr_accessor :read_timeout
59 attr_accessor :debug_output
60
61 def inspect
62 "#<#{self.class} io=#{@io}>"
63 end
64
65 def closed?
66 @io.closed?
67 end
68
69 def close
70 @io.close
71 end
72
73 #
74 # Read
75 #
76
77 public
78
79 def read(len, dest = '', ignore_eof = false)
80 LOG "reading #{len} bytes..."
81 read_bytes = 0
82 begin
83 while read_bytes + @rbuf.size < len
84 dest << (s = rbuf_consume(@rbuf.size))
85 read_bytes += s.size
86 rbuf_fill
87 end
88 dest << (s = rbuf_consume(len - read_bytes))
89 read_bytes += s.size
90 rescue EOFError
91 raise unless ignore_eof
92 end
93 LOG "read #{read_bytes} bytes"
94 dest
95 end
96
97 def read_all(dest = '')
98 LOG 'reading all...'
99 read_bytes = 0
100 begin
101 while true
102 dest << (s = rbuf_consume(@rbuf.size))
103 read_bytes += s.size
104 rbuf_fill
105 end
106 rescue EOFError
107 ;
108 end
109 LOG "read #{read_bytes} bytes"
110 dest
111 end
112
113 def readuntil(terminator, ignore_eof = false)
114 begin
115 until idx = @rbuf.index(terminator)
116 rbuf_fill
117 end
118 return rbuf_consume(idx + terminator.size)
119 rescue EOFError
120 raise unless ignore_eof
121 return rbuf_consume(@rbuf.size)
122 end
123 end
124
125 def readline
126 readuntil("\n").chop
127 end
128
129 private
130
131 def rbuf_fill
132 timeout(@read_timeout) {
133 @rbuf << @io.sysread(1024)
134 }
135 end
136
137 def rbuf_consume(len)
138 s = @rbuf.slice!(0, len)
139 @debug_output << %Q[-> #{s.dump}\n] if @debug_output
140 s
141 end
142
143 #
144 # Write
145 #
146
147 public
148
149 def write(str)
150 writing {
151 write0 str
152 }
153 end
154
155 def writeline(str)
156 writing {
157 write0 str + "\r\n"
158 }
159 end
160
161 private
162
163 def writing
164 @written_bytes = 0
165 @debug_output << '<- ' if @debug_output
166 yield
167 @debug_output << "\n" if @debug_output
168 bytes = @written_bytes
169 @written_bytes = nil
170 bytes
171 end
172
173 def write0(str)
174 @debug_output << str.dump if @debug_output
175 len = @io.write(str)
176 @written_bytes += len
177 len
178 end
179
180 #
181 # Logging
182 #
183
184 private
185
186 def LOG_off
187 @save_debug_out = @debug_output
188 @debug_output = nil
189 end
190
191 def LOG_on
192 @debug_output = @save_debug_out
193 end
194
195 def LOG(msg)
196 return unless @debug_output
197 @debug_output << msg + "\n"
198 end
199 end
200
201
202 class InternetMessageIO < BufferedIO #:nodoc: internal use only
203 def InternetMessageIO.old_open(addr, port,
204 open_timeout = nil, read_timeout = nil, debug_output = nil)
205 debug_output << "opening connection to #{addr}...\n" if debug_output
206 s = timeout(open_timeout) { TCPsocket.new(addr, port) }
207 io = new(s)
208 io.read_timeout = read_timeout
209 io.debug_output = debug_output
210 io
211 end
212
213 def initialize(io)
214 super
215 @wbuf = nil
216 end
217
218 #
219 # Read
220 #
221
222 def each_message_chunk
223 LOG 'reading message...'
224 LOG_off()
225 read_bytes = 0
226 while (line = readuntil("\r\n")) != ".\r\n"
227 read_bytes += line.size
228 yield line.sub(/\A\./, '')
229 end
230 LOG_on()
231 LOG "read message (#{read_bytes} bytes)"
232 end
233
234 # *library private* (cannot handle 'break')
235 def each_list_item
236 while (str = readuntil("\r\n")) != ".\r\n"
237 yield str.chop
238 end
239 end
240
241 def write_message_0(src)
242 prev = @written_bytes
243 each_crlf_line(src) do |line|
244 write0 line.sub(/\A\./, '..')
245 end
246 @written_bytes - prev
247 end
248
249 #
250 # Write
251 #
252
253 def write_message(src)
254 LOG "writing message from #{src.class}"
255 LOG_off()
256 len = writing {
257 using_each_crlf_line {
258 write_message_0 src
259 }
260 }
261 LOG_on()
262 LOG "wrote #{len} bytes"
263 len
264 end
265
266 def write_message_by_block(&block)
267 LOG 'writing message from block'
268 LOG_off()
269 len = writing {
270 using_each_crlf_line {
271 begin
272 block.call(WriteAdapter.new(self, :write_message_0))
273 rescue LocalJumpError
274 # allow `break' from writer block
275 end
276 }
277 }
278 LOG_on()
279 LOG "wrote #{len} bytes"
280 len
281 end
282
283 private
284
285 def using_each_crlf_line
286 @wbuf = ''
287 yield
288 if not @wbuf.empty? # unterminated last line
289 write0 @wbuf.chomp + "\r\n"
290 elsif @written_bytes == 0 # empty src
291 write0 "\r\n"
292 end
293 write0 ".\r\n"
294 @wbuf = nil
295 end
296
297 def each_crlf_line(src)
298 buffer_filling(@wbuf, src) do
299 while line = @wbuf.slice!(/\A.*(?:\n|\r\n|\r(?!\z))/n)
300 yield line.chomp("\n") + "\r\n"
301 end
302 end
303 end
304
305 def buffer_filling(buf, src)
306 case src
307 when String # for speeding up.
308 0.step(src.size - 1, 1024) do |i|
309 buf << src[i, 1024]
310 yield
311 end
312 when File # for speeding up.
313 while s = src.read(1024)
314 buf << s
315 yield
316 end
317 else # generic reader
318 src.each do |s|
319 buf << s
320 yield if buf.size > 1024
321 end
322 yield unless buf.empty?
323 end
324 end
325 end
326
327
328 #
329 # The writer adapter class
330 #
331 class WriteAdapter
332 def initialize(socket, method)
333 @socket = socket
334 @method_id = method
335 end
336
337 def inspect
338 "#<#{self.class} socket=#{@socket.inspect}>"
339 end
340
341 def write(str)
342 @socket.__send__(@method_id, str)
343 end
344
345 alias print write
346
347 def <<(str)
348 write str
349 self
350 end
351
352 def puts(str = '')
353 write str.chomp("\n") + "\n"
354 end
355
356 def printf(*args)
357 write sprintf(*args)
358 end
359 end
360
361
362 class ReadAdapter #:nodoc: internal use only
363 def initialize(block)
364 @block = block
365 end
366
367 def inspect
368 "#<#{self.class}>"
369 end
370
371 def <<(str)
372 call_block(str, &@block) if @block
373 end
374
375 private
376
377 # This method is needed because @block must be called by yield,
378 # not Proc#call. You can see difference when using `break' in
379 # the block.
380 def call_block(str)
381 yield str
382 end
383 end
384
385
386 module NetPrivate #:nodoc: obsolete
387 Socket = ::Net::InternetMessageIO
388 end
389
390end # module Net
Note: See TracBrowser for help on using the repository browser.