rev 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +45 -9
- data/doc/rdoc/classes/Rev.html +368 -0
- data/doc/rdoc/classes/Rev.src/M000001.html +28 -0
- data/doc/rdoc/classes/Rev.src/M000002.html +35 -0
- data/doc/rdoc/classes/Rev.src/M000003.html +24 -0
- data/doc/rdoc/classes/Rev.src/M000004.html +28 -0
- data/doc/rdoc/classes/Rev.src/M000005.html +27 -0
- data/doc/rdoc/classes/Rev.src/M000006.html +33 -0
- data/doc/rdoc/classes/Rev.src/M000007.html +43 -0
- data/doc/rdoc/classes/Rev.src/M000008.html +16 -0
- data/doc/rdoc/classes/Rev/Buffer.html +354 -0
- data/doc/rdoc/classes/Rev/Buffer.src/M000019.html +17 -0
- data/doc/rdoc/classes/Rev/Buffer.src/M000020.html +29 -0
- data/doc/rdoc/classes/Rev/Buffer.src/M000021.html +27 -0
- data/doc/rdoc/classes/Rev/Buffer.src/M000022.html +27 -0
- data/doc/rdoc/classes/Rev/Buffer.src/M000023.html +31 -0
- data/doc/rdoc/classes/Rev/Buffer.src/M000024.html +31 -0
- data/doc/rdoc/classes/Rev/Buffer.src/M000025.html +30 -0
- data/doc/rdoc/classes/Rev/Buffer.src/M000026.html +50 -0
- data/doc/rdoc/classes/Rev/Buffer.src/M000027.html +22 -0
- data/doc/rdoc/classes/Rev/Buffer.src/M000028.html +24 -0
- data/doc/rdoc/classes/Rev/Buffer.src/M000029.html +24 -0
- data/doc/rdoc/classes/Rev/BufferedIO.html +397 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000095.html +23 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000096.html +16 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000097.html +16 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000098.html +16 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000099.html +18 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000100.html +18 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000101.html +23 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000102.html +18 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000103.html +20 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000104.html +24 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000105.html +23 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000106.html +22 -0
- data/doc/rdoc/classes/Rev/BufferedIO.src/M000107.html +29 -0
- data/doc/rdoc/classes/Rev/BufferedIO/Writer.html +154 -0
- data/doc/rdoc/classes/Rev/BufferedIO/Writer.src/M000108.html +19 -0
- data/doc/rdoc/classes/Rev/BufferedIO/Writer.src/M000109.html +18 -0
- data/doc/rdoc/classes/Rev/DNSResolver.html +401 -0
- data/doc/rdoc/classes/Rev/DNSResolver.src/M000124.html +25 -0
- data/doc/rdoc/classes/Rev/DNSResolver.src/M000125.html +29 -0
- data/doc/rdoc/classes/Rev/DNSResolver.src/M000126.html +20 -0
- data/doc/rdoc/classes/Rev/DNSResolver.src/M000127.html +19 -0
- data/doc/rdoc/classes/Rev/DNSResolver.src/M000128.html +16 -0
- data/doc/rdoc/classes/Rev/DNSResolver.src/M000129.html +16 -0
- data/doc/rdoc/classes/Rev/DNSResolver.src/M000131.html +19 -0
- data/doc/rdoc/classes/Rev/DNSResolver.src/M000132.html +21 -0
- data/doc/rdoc/classes/Rev/DNSResolver.src/M000133.html +27 -0
- data/doc/rdoc/classes/Rev/DNSResolver.src/M000134.html +28 -0
- data/doc/rdoc/classes/Rev/DNSResolver.src/M000135.html +55 -0
- data/doc/rdoc/classes/Rev/DNSResolver/Timeout.html +154 -0
- data/doc/rdoc/classes/Rev/DNSResolver/Timeout.src/M000136.html +20 -0
- data/doc/rdoc/classes/Rev/DNSResolver/Timeout.src/M000137.html +22 -0
- data/doc/rdoc/classes/Rev/HttpChunkHeader.html +156 -0
- data/doc/rdoc/classes/Rev/HttpChunkHeader.src/M000031.html +19 -0
- data/doc/rdoc/classes/Rev/HttpClient.html +460 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000042.html +18 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000043.html +27 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000044.html +24 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000045.html +19 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000046.html +17 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000047.html +19 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000048.html +18 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000049.html +18 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000050.html +19 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000051.html +19 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000052.html +19 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000053.html +41 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000054.html +18 -0
- data/doc/rdoc/classes/Rev/HttpClient.src/M000055.html +34 -0
- data/doc/rdoc/classes/Rev/HttpEncoding.html +310 -0
- data/doc/rdoc/classes/Rev/HttpEncoding.src/M000009.html +20 -0
- data/doc/rdoc/classes/Rev/HttpEncoding.src/M000010.html +20 -0
- data/doc/rdoc/classes/Rev/HttpEncoding.src/M000011.html +18 -0
- data/doc/rdoc/classes/Rev/HttpEncoding.src/M000012.html +18 -0
- data/doc/rdoc/classes/Rev/HttpEncoding.src/M000013.html +18 -0
- data/doc/rdoc/classes/Rev/HttpEncoding.src/M000014.html +19 -0
- data/doc/rdoc/classes/Rev/HttpEncoding.src/M000015.html +18 -0
- data/doc/rdoc/classes/Rev/HttpEncoding.src/M000016.html +18 -0
- data/doc/rdoc/classes/Rev/HttpEncoding.src/M000017.html +22 -0
- data/doc/rdoc/classes/Rev/HttpEncoding.src/M000018.html +18 -0
- data/doc/rdoc/classes/Rev/HttpResponseHeader.html +219 -0
- data/doc/rdoc/classes/Rev/HttpResponseHeader.src/M000032.html +18 -0
- data/doc/rdoc/classes/Rev/HttpResponseHeader.src/M000033.html +18 -0
- data/doc/rdoc/classes/Rev/HttpResponseHeader.src/M000034.html +18 -0
- data/doc/rdoc/classes/Rev/IOWatcher.html +285 -0
- data/doc/rdoc/classes/Rev/IOWatcher.src/M000079.html +17 -0
- data/doc/rdoc/classes/Rev/IOWatcher.src/M000080.html +27 -0
- data/doc/rdoc/classes/Rev/IOWatcher.src/M000081.html +26 -0
- data/doc/rdoc/classes/Rev/IOWatcher.src/M000082.html +27 -0
- data/doc/rdoc/classes/Rev/IOWatcher.src/M000083.html +27 -0
- data/doc/rdoc/classes/Rev/IOWatcher.src/M000084.html +24 -0
- data/doc/rdoc/classes/Rev/IOWatcher.src/M000085.html +25 -0
- data/doc/rdoc/classes/Rev/Listener.html +207 -0
- data/doc/rdoc/classes/Rev/Listener.src/M000065.html +19 -0
- data/doc/rdoc/classes/Rev/Listener.src/M000066.html +19 -0
- data/doc/rdoc/classes/Rev/Listener.src/M000067.html +16 -0
- data/doc/rdoc/classes/Rev/Listener.src/M000068.html +18 -0
- data/doc/rdoc/classes/Rev/Loop.html +395 -0
- data/doc/rdoc/classes/Rev/Loop.src/M000070.html +25 -0
- data/doc/rdoc/classes/Rev/Loop.src/M000071.html +45 -0
- data/doc/rdoc/classes/Rev/Loop.src/M000072.html +18 -0
- data/doc/rdoc/classes/Rev/Loop.src/M000073.html +23 -0
- data/doc/rdoc/classes/Rev/Loop.src/M000074.html +19 -0
- data/doc/rdoc/classes/Rev/Loop.src/M000075.html +17 -0
- data/doc/rdoc/classes/Rev/Loop.src/M000076.html +27 -0
- data/doc/rdoc/classes/Rev/Loop.src/M000077.html +32 -0
- data/doc/rdoc/classes/Rev/Loop.src/M000078.html +32 -0
- data/doc/rdoc/classes/Rev/Server.html +164 -0
- data/doc/rdoc/classes/Rev/Server.src/M000121.html +32 -0
- data/doc/rdoc/classes/Rev/Server.src/M000122.html +20 -0
- data/doc/rdoc/classes/Rev/Socket.html +213 -0
- data/doc/rdoc/classes/Rev/Socket.src/M000035.html +21 -0
- data/doc/rdoc/classes/Rev/Socket.src/M000036.html +25 -0
- data/doc/rdoc/classes/Rev/Socket.src/M000037.html +16 -0
- data/doc/rdoc/classes/Rev/Socket.src/M000038.html +16 -0
- data/doc/rdoc/classes/Rev/Socket/Connector.html +154 -0
- data/doc/rdoc/classes/Rev/Socket/Connector.src/M000040.html +19 -0
- data/doc/rdoc/classes/Rev/Socket/Connector.src/M000041.html +28 -0
- data/doc/rdoc/classes/Rev/TCPListener.html +161 -0
- data/doc/rdoc/classes/Rev/TCPListener.src/M000069.html +23 -0
- data/doc/rdoc/classes/Rev/TCPServer.html +147 -0
- data/doc/rdoc/classes/Rev/TCPServer.src/M000123.html +20 -0
- data/doc/rdoc/classes/Rev/TCPSocket.html +233 -0
- data/doc/rdoc/classes/Rev/TCPSocket.src/M000056.html +20 -0
- data/doc/rdoc/classes/Rev/TCPSocket.src/M000057.html +34 -0
- data/doc/rdoc/classes/Rev/TCPSocket.src/M000058.html +24 -0
- data/doc/rdoc/classes/Rev/TCPSocket.src/M000059.html +18 -0
- data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectResolver.html +171 -0
- data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectResolver.src/M000060.html +19 -0
- data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectResolver.src/M000061.html +27 -0
- data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectResolver.src/M000062.html +23 -0
- data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectSocket.html +154 -0
- data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectSocket.src/M000063.html +25 -0
- data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectSocket.src/M000064.html +23 -0
- data/doc/rdoc/classes/Rev/TimerWatcher.html +288 -0
- data/doc/rdoc/classes/Rev/TimerWatcher.src/M000086.html +17 -0
- data/doc/rdoc/classes/Rev/TimerWatcher.src/M000087.html +27 -0
- data/doc/rdoc/classes/Rev/TimerWatcher.src/M000088.html +26 -0
- data/doc/rdoc/classes/Rev/TimerWatcher.src/M000089.html +27 -0
- data/doc/rdoc/classes/Rev/TimerWatcher.src/M000090.html +27 -0
- data/doc/rdoc/classes/Rev/TimerWatcher.src/M000091.html +42 -0
- data/doc/rdoc/classes/Rev/TimerWatcher.src/M000092.html +24 -0
- data/doc/rdoc/classes/Rev/UNIXListener.html +147 -0
- data/doc/rdoc/classes/Rev/UNIXListener.src/M000120.html +18 -0
- data/doc/rdoc/classes/Rev/UNIXServer.html +147 -0
- data/doc/rdoc/classes/Rev/UNIXServer.src/M000030.html +18 -0
- data/doc/rdoc/classes/Rev/UNIXSocket.html +175 -0
- data/doc/rdoc/classes/Rev/UNIXSocket.src/M000093.html +18 -0
- data/doc/rdoc/classes/Rev/UNIXSocket.src/M000094.html +21 -0
- data/doc/rdoc/classes/Rev/Watcher.html +349 -0
- data/doc/rdoc/classes/Rev/Watcher.src/M000110.html +20 -0
- data/doc/rdoc/classes/Rev/Watcher.src/M000111.html +20 -0
- data/doc/rdoc/classes/Rev/Watcher.src/M000112.html +17 -0
- data/doc/rdoc/classes/Rev/Watcher.src/M000113.html +48 -0
- data/doc/rdoc/classes/Rev/Watcher.src/M000114.html +62 -0
- data/doc/rdoc/classes/Rev/Watcher.src/M000115.html +34 -0
- data/doc/rdoc/classes/Rev/Watcher.src/M000116.html +34 -0
- data/doc/rdoc/classes/Rev/Watcher.src/M000117.html +27 -0
- data/doc/rdoc/classes/Rev/Watcher.src/M000118.html +24 -0
- data/doc/rdoc/classes/Rev/Watcher.src/M000119.html +27 -0
- data/doc/rdoc/created.rid +1 -0
- data/doc/rdoc/files/LICENSE.html +165 -0
- data/doc/rdoc/files/README.html +297 -0
- data/doc/rdoc/files/ext/rev/rev_buffer_c.html +101 -0
- data/doc/rdoc/files/ext/rev/rev_ext_c.html +101 -0
- data/doc/rdoc/files/ext/rev/rev_io_watcher_c.html +101 -0
- data/doc/rdoc/files/ext/rev/rev_loop_c.html +101 -0
- data/doc/rdoc/files/ext/rev/rev_timer_watcher_c.html +101 -0
- data/doc/rdoc/files/ext/rev/rev_watcher_c.html +101 -0
- data/doc/rdoc/files/lib/rev/buffered_io_rb.html +101 -0
- data/doc/rdoc/files/lib/rev/dns_resolver_rb.html +101 -0
- data/doc/rdoc/files/lib/rev/http_client_rb.html +101 -0
- data/doc/rdoc/files/lib/rev/io_watcher_rb.html +101 -0
- data/doc/rdoc/files/lib/rev/listener_rb.html +108 -0
- data/doc/rdoc/files/lib/rev/loop_rb.html +101 -0
- data/doc/rdoc/files/lib/rev/server_rb.html +101 -0
- data/doc/rdoc/files/lib/rev/socket_rb.html +109 -0
- data/doc/rdoc/files/lib/rev/timer_watcher_rb.html +101 -0
- data/doc/rdoc/files/lib/rev/watcher_rb.html +101 -0
- data/doc/rdoc/files/lib/rev_rb.html +101 -0
- data/doc/rdoc/fr_class_index.html +52 -0
- data/doc/rdoc/fr_file_index.html +45 -0
- data/doc/rdoc/fr_method_index.html +163 -0
- data/doc/rdoc/index.html +24 -0
- data/doc/rdoc/rdoc-style.css +208 -0
- data/ext/rev/extconf.rb +1 -1
- data/ext/rev/rev.h +0 -1
- data/ext/rev/rev_buffer.c +606 -0
- data/ext/rev/rev_ext.c +1 -0
- data/ext/rev/rev_io_watcher.c +53 -19
- data/ext/rev/rev_loop.c +12 -35
- data/ext/rev/rev_timer_watcher.c +45 -3
- data/ext/rev/rev_watcher.c +13 -1
- data/lib/http11_client.bundle +0 -0
- data/lib/rev.rb +1 -1
- data/lib/rev/buffered_io.rb +25 -22
- data/lib/rev/dns_resolver.rb +31 -14
- data/lib/rev/http_client.rb +88 -91
- data/lib/rev/listener.rb +22 -5
- data/lib/rev/loop.rb +13 -0
- data/lib/rev/server.rb +10 -3
- data/lib/rev/socket.rb +30 -9
- data/lib/rev/watcher.rb +4 -2
- data/lib/rev_ext.bundle +0 -0
- metadata +230 -2
data/lib/rev/http_client.rb
CHANGED
@@ -146,7 +146,7 @@ module Rev
|
|
146
146
|
@parser_nbytes = 0
|
147
147
|
|
148
148
|
@state = :response_header
|
149
|
-
@data =
|
149
|
+
@data = Rev::Buffer.new
|
150
150
|
|
151
151
|
@response_header = HttpResponseHeader.new
|
152
152
|
@chunk_header = HttpChunkHeader.new
|
@@ -224,9 +224,8 @@ module Rev
|
|
224
224
|
end
|
225
225
|
|
226
226
|
def on_read(data)
|
227
|
-
|
228
|
-
|
229
|
-
end
|
227
|
+
@data << data
|
228
|
+
dispatch
|
230
229
|
end
|
231
230
|
|
232
231
|
#
|
@@ -273,147 +272,145 @@ module Rev
|
|
273
272
|
# Response processing
|
274
273
|
#
|
275
274
|
|
276
|
-
def
|
277
|
-
case state
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
275
|
+
def dispatch
|
276
|
+
while case @state
|
277
|
+
when :response_header
|
278
|
+
parse_response_header
|
279
|
+
when :chunk_header
|
280
|
+
parse_chunk_header
|
281
|
+
when :chunk_body
|
282
|
+
process_chunk_body
|
283
|
+
when :chunk_footer
|
284
|
+
process_chunk_footer
|
285
|
+
when :response_footer
|
286
|
+
process_response_footer
|
287
|
+
when :body
|
288
|
+
process_body
|
289
|
+
when :finished, :invalid
|
290
|
+
break
|
291
|
+
else raise RuntimeError, "invalid state: #{@state}"
|
292
|
+
end
|
291
293
|
end
|
292
294
|
end
|
293
295
|
|
294
|
-
def parse_header(header
|
295
|
-
|
296
|
-
|
297
|
-
|
296
|
+
def parse_header(header)
|
297
|
+
return false if @data.empty?
|
298
|
+
|
299
|
+
@parser_nbytes = @parser.execute(header, @data.to_str, @parser_nbytes)
|
300
|
+
return false unless @parser.finished?
|
298
301
|
|
299
|
-
|
300
|
-
@data
|
302
|
+
# Clear parsed data from the buffer
|
303
|
+
@data.read(@parser_nbytes)
|
301
304
|
@parser.reset
|
302
305
|
@parser_nbytes = 0
|
303
|
-
|
304
|
-
|
306
|
+
|
307
|
+
true
|
305
308
|
end
|
306
309
|
|
307
|
-
def parse_response_header
|
308
|
-
|
309
|
-
return :response_header, '' if data.nil?
|
310
|
+
def parse_response_header
|
311
|
+
return false unless parse_header(@response_header)
|
310
312
|
|
311
313
|
unless @response_header.http_status and @response_header.http_reason
|
312
314
|
on_error "no HTTP response"
|
313
|
-
|
315
|
+
@state = :invalid
|
316
|
+
return false
|
314
317
|
end
|
315
318
|
|
316
319
|
on_response_header(@response_header)
|
317
320
|
|
318
321
|
if @response_header.chunked_encoding?
|
319
|
-
|
322
|
+
@state = :chunk_header
|
320
323
|
else
|
324
|
+
@state = :body
|
321
325
|
@bytes_remaining = @response_header.content_length
|
322
|
-
return :body, data
|
323
326
|
end
|
327
|
+
|
328
|
+
true
|
324
329
|
end
|
325
330
|
|
326
|
-
def parse_chunk_header
|
327
|
-
|
328
|
-
return :chunk_header, '' if data.nil?
|
331
|
+
def parse_chunk_header
|
332
|
+
return false unless parse_header(@chunk_header)
|
329
333
|
|
330
334
|
@bytes_remaining = @chunk_header.chunk_size
|
331
335
|
@chunk_header = HttpChunkHeader.new
|
332
336
|
|
333
|
-
|
334
|
-
|
335
|
-
else
|
336
|
-
@bytes_remaining = 2
|
337
|
-
return :response_footer, data
|
338
|
-
end
|
337
|
+
@state = @bytes_remaining > 0 ? :chunk_body : :response_footer
|
338
|
+
true
|
339
339
|
end
|
340
340
|
|
341
|
-
def process_chunk_body
|
342
|
-
if data.size < @bytes_remaining
|
343
|
-
@bytes_remaining -= data.size
|
344
|
-
on_body_data data
|
345
|
-
return
|
341
|
+
def process_chunk_body
|
342
|
+
if @data.size < @bytes_remaining
|
343
|
+
@bytes_remaining -= @data.size
|
344
|
+
on_body_data @data.read
|
345
|
+
return false
|
346
346
|
end
|
347
347
|
|
348
|
-
on_body_data data.
|
349
|
-
@bytes_remaining =
|
350
|
-
|
348
|
+
on_body_data @data.read(@bytes_remaining)
|
349
|
+
@bytes_remaining = 0
|
350
|
+
|
351
|
+
@state = :chunk_footer
|
352
|
+
true
|
351
353
|
end
|
352
354
|
|
353
|
-
def
|
354
|
-
|
355
|
-
@bytes_remaining = 2 - @data.size
|
356
|
-
return unless @bytes_remaining == 0
|
355
|
+
def process_chunk_footer
|
356
|
+
return false if @data.size < 2
|
357
357
|
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
return matches_crlf, data
|
362
|
-
end
|
363
|
-
|
364
|
-
def process_chunk_footer(data)
|
365
|
-
result, data = process_crlf(data)
|
366
|
-
return :chunk_footer, '' if result.nil?
|
367
|
-
|
368
|
-
if result
|
369
|
-
return :chunk_header, data
|
358
|
+
if @data.read(2) == CRLF
|
359
|
+
@state = :chunk_header
|
370
360
|
else
|
371
361
|
on_error "non-CRLF chunk footer"
|
372
|
-
|
362
|
+
@state = :invalid
|
373
363
|
end
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
if
|
380
|
-
|
364
|
+
|
365
|
+
true
|
366
|
+
end
|
367
|
+
|
368
|
+
def process_response_footer
|
369
|
+
return false if @data.size < 2
|
370
|
+
|
371
|
+
if @data.read(2) == CRLF
|
372
|
+
if @data.empty?
|
373
|
+
on_request_complete
|
374
|
+
@state = :finished
|
375
|
+
else
|
381
376
|
on_error "garbage at end of chunked response"
|
382
|
-
|
377
|
+
@state = :invalid
|
383
378
|
end
|
384
|
-
|
385
|
-
on_request_complete
|
386
|
-
return :finished
|
387
379
|
else
|
388
380
|
on_error "non-CRLF response footer"
|
389
|
-
|
381
|
+
@state = :invalid
|
390
382
|
end
|
383
|
+
|
384
|
+
false
|
391
385
|
end
|
392
386
|
|
393
|
-
def process_body
|
387
|
+
def process_body
|
394
388
|
# FIXME the proper thing to do here is probably to keep reading until
|
395
389
|
# the socket closes, then assume that's the end of the body, provided
|
396
390
|
# the server has specified Connection: close
|
397
391
|
if @bytes_remaining.nil?
|
398
392
|
on_error "no content length specified"
|
399
|
-
|
393
|
+
@state = :invalid
|
400
394
|
end
|
401
395
|
|
402
|
-
if data.size < @bytes_remaining
|
403
|
-
@bytes_remaining -= data.size
|
404
|
-
on_body_data data
|
405
|
-
return
|
396
|
+
if @data.size < @bytes_remaining
|
397
|
+
@bytes_remaining -= @data.size
|
398
|
+
on_body_data @data.read
|
399
|
+
return false
|
406
400
|
end
|
407
401
|
|
408
|
-
on_body_data data.
|
402
|
+
on_body_data @data.read(@bytes_remaining)
|
403
|
+
@bytes_remaining = 0
|
409
404
|
|
410
|
-
|
405
|
+
if @data.empty?
|
406
|
+
on_request_complete
|
407
|
+
@state = :finished
|
408
|
+
else
|
411
409
|
on_error "garbage at end of body"
|
412
|
-
|
410
|
+
@state = :invalid
|
413
411
|
end
|
414
412
|
|
415
|
-
|
416
|
-
return :finished
|
413
|
+
false
|
417
414
|
end
|
418
415
|
end
|
419
|
-
end
|
416
|
+
end
|
data/lib/rev/listener.rb
CHANGED
@@ -8,11 +8,20 @@ require 'socket'
|
|
8
8
|
require File.dirname(__FILE__) + '/../rev'
|
9
9
|
|
10
10
|
module Rev
|
11
|
+
# Listeners wait for incoming connections. When a listener receives a
|
12
|
+
# connection it fires the on_connection event with the newly accepted
|
13
|
+
# socket as a parameter.
|
11
14
|
class Listener < IOWatcher
|
12
15
|
def initialize(listen_socket)
|
13
16
|
@listen_socket = listen_socket
|
14
17
|
super(@listen_socket)
|
15
18
|
end
|
19
|
+
|
20
|
+
# Close the listener
|
21
|
+
def close
|
22
|
+
detach if attached?
|
23
|
+
@listen_socket.close
|
24
|
+
end
|
16
25
|
|
17
26
|
# Called whenever the server receives a new connection
|
18
27
|
def on_connection(socket); end
|
@@ -29,12 +38,20 @@ module Rev
|
|
29
38
|
end
|
30
39
|
|
31
40
|
class TCPListener < Listener
|
32
|
-
|
41
|
+
DEFAULT_BACKLOG = 1024
|
42
|
+
|
43
|
+
# Create a new Rev::TCPListener on the specified address and port.
|
44
|
+
# Accepts the following options:
|
33
45
|
#
|
34
|
-
#
|
35
|
-
|
36
|
-
|
37
|
-
|
46
|
+
# :backlog - Max size of the pending connection queue (default 1024)
|
47
|
+
# :reverse_lookup - Retain BasicSocket's reverse DNS functionality (default false)
|
48
|
+
#
|
49
|
+
def initialize(addr, port, options = {})
|
50
|
+
BasicSocket.do_not_reverse_lookup = true unless options[:reverse_lookup]
|
51
|
+
options[:backlog] ||= DEFAULT_BACKLOG
|
52
|
+
|
53
|
+
listen_socket = ::TCPServer.new(addr, port)
|
54
|
+
listen_socket.instance_eval { listen(options[:backlog]) }
|
38
55
|
super(listen_socket)
|
39
56
|
end
|
40
57
|
end
|
data/lib/rev/loop.rb
CHANGED
@@ -8,7 +8,20 @@ require File.dirname(__FILE__) + '/../rev'
|
|
8
8
|
|
9
9
|
module Rev
|
10
10
|
class Loop
|
11
|
+
@@default_loop = {}
|
11
12
|
attr_reader :watchers
|
13
|
+
|
14
|
+
# Retrieve the default event loop for the current thread
|
15
|
+
def self.default
|
16
|
+
# Well awesome, variables stashed in Thread.current[]
|
17
|
+
# are only accessible in the context of the Fiber where
|
18
|
+
# they were stored. Soo... we need to make our own
|
19
|
+
# thread-local store if we want Fiber compatibility
|
20
|
+
#
|
21
|
+
# I think this should be sufficient... but it may need
|
22
|
+
# a mutex or something, got me.
|
23
|
+
@@default_loop[Thread.current] ||= Loop.new
|
24
|
+
end
|
12
25
|
|
13
26
|
# Create a new Rev::Loop
|
14
27
|
#
|
data/lib/rev/server.rb
CHANGED
@@ -8,10 +8,13 @@ require File.dirname(__FILE__) + '/../rev'
|
|
8
8
|
|
9
9
|
module Rev
|
10
10
|
class Server < Listener
|
11
|
+
# Servers listen for incoming connections and create new connection objects
|
12
|
+
# whenever incoming connections are received. The default class for new
|
13
|
+
# connections is a Socket, but any subclass of IOWatcher is acceptable.
|
11
14
|
def initialize(listen_socket, klass = Socket, *args, &block)
|
12
15
|
# Ensure the provided class responds to attach
|
13
|
-
unless
|
14
|
-
raise ArgumentError, "provided class must
|
16
|
+
unless klass.allocate.is_a? IOWatcher
|
17
|
+
raise ArgumentError, "provided class must descend from IOWatcher"
|
15
18
|
end
|
16
19
|
|
17
20
|
# Verify the arity of the provided arguments
|
@@ -37,6 +40,8 @@ module Rev
|
|
37
40
|
end
|
38
41
|
end
|
39
42
|
|
43
|
+
# TCP server class. Listens on the specified host and port and creates
|
44
|
+
# new connection objects of the given class.
|
40
45
|
class TCPServer < Server
|
41
46
|
def initialize(host, port, klass = TCPSocket, *args, &block)
|
42
47
|
listen_socket = ::TCPServer.new(host, port)
|
@@ -45,9 +50,11 @@ module Rev
|
|
45
50
|
end
|
46
51
|
end
|
47
52
|
|
53
|
+
# UNIX server class. Listens on the specified UNIX domain socket and
|
54
|
+
# creates new connection objects of the given class.
|
48
55
|
class UNIXServer < Server
|
49
56
|
def initialize(path, klass = UNIXSocket, *args, &block)
|
50
57
|
super(::UNIXServer.new(*args), klass, *args, &block)
|
51
58
|
end
|
52
59
|
end
|
53
|
-
end
|
60
|
+
end
|
data/lib/rev/socket.rb
CHANGED
@@ -9,7 +9,7 @@ require 'resolv'
|
|
9
9
|
require File.dirname(__FILE__) + '/../rev'
|
10
10
|
|
11
11
|
module Rev
|
12
|
-
class Socket < BufferedIO
|
12
|
+
class Socket < BufferedIO
|
13
13
|
def self.connect(socket, *args)
|
14
14
|
new(socket, *args).instance_eval {
|
15
15
|
@connector = Connector.new(self, socket)
|
@@ -38,6 +38,10 @@ module Rev
|
|
38
38
|
def on_connect_failed; end
|
39
39
|
event_callback :on_connect_failed
|
40
40
|
|
41
|
+
# Called if a hostname failed to resolve when connecting
|
42
|
+
# Defaults to being aliased to on_connect_failed
|
43
|
+
alias_method :on_resolve_failed, :on_connect_failed
|
44
|
+
|
41
45
|
#########
|
42
46
|
protected
|
43
47
|
#########
|
@@ -76,6 +80,17 @@ module Rev
|
|
76
80
|
attr_reader :remote_host, :remote_addr, :remote_port, :address_family
|
77
81
|
watcher_delegate :@resolver
|
78
82
|
|
83
|
+
# Similar to .new, but used in cases where the resulting object is in a
|
84
|
+
# "half-open" state. This is primarily used for when asynchronous
|
85
|
+
# DNS resolution is taking place. We don't actually have a handle to
|
86
|
+
# the socket we want to use to create the watcher yet, since we don't
|
87
|
+
# know the IP address to connect to.
|
88
|
+
def self.precreate(*args, &block)
|
89
|
+
obj = allocate
|
90
|
+
obj.__send__(:preinitialize, *args, &block)
|
91
|
+
obj
|
92
|
+
end
|
93
|
+
|
79
94
|
# Perform a non-blocking connect to the given host and port
|
80
95
|
def self.connect(addr, port, *args)
|
81
96
|
family = nil
|
@@ -94,13 +109,17 @@ module Rev
|
|
94
109
|
return connect(host, port, *args)
|
95
110
|
end
|
96
111
|
|
97
|
-
|
98
|
-
@remote_host, @remote_addr, @remote_port = addr, addr, port
|
99
|
-
@resolver = TCPConnectResolver.new(self, addr, port, *args)
|
100
|
-
self
|
101
|
-
}
|
112
|
+
precreate(addr, port, *args)
|
102
113
|
end
|
103
114
|
|
115
|
+
# Called by precreate during asyncronous DNS resolution
|
116
|
+
def preinitialize(addr, port, *args)
|
117
|
+
@remote_host, @remote_addr, @remote_port = addr, addr, port
|
118
|
+
@resolver = TCPConnectResolver.new(self, addr, port, *args)
|
119
|
+
end
|
120
|
+
|
121
|
+
private :preinitialize
|
122
|
+
|
104
123
|
def initialize(socket)
|
105
124
|
unless socket.is_a?(::TCPSocket) or socket.is_a?(TCPConnectSocket)
|
106
125
|
raise TypeError, "socket must be a TCPSocket"
|
@@ -111,6 +130,10 @@ module Rev
|
|
111
130
|
@address_family, @remote_port, @remote_host, @remote_addr = socket.peeraddr
|
112
131
|
end
|
113
132
|
|
133
|
+
def peeraddr
|
134
|
+
[@address_family, @remote_port, @remote_host, @remote_addr]
|
135
|
+
end
|
136
|
+
|
114
137
|
#########
|
115
138
|
protected
|
116
139
|
#########
|
@@ -157,15 +180,13 @@ module Rev
|
|
157
180
|
end
|
158
181
|
|
159
182
|
def on_failure
|
160
|
-
@sock.
|
183
|
+
@sock.__send__(:on_resolve_failed)
|
161
184
|
@sock.instance_eval {
|
162
185
|
@resolver = nil
|
163
186
|
@failed = true
|
164
187
|
}
|
165
188
|
return
|
166
189
|
end
|
167
|
-
|
168
|
-
alias_method :on_timeout, :on_failure
|
169
190
|
end
|
170
191
|
end
|
171
192
|
|
data/lib/rev/watcher.rb
CHANGED