eventmachine 0.12.10-x86-mswin32-60 → 1.0.0.beta.2-x86-mswin32-60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/Gemfile +1 -0
- data/README +80 -81
- data/Rakefile +7 -370
- data/docs/COPYING +60 -60
- data/docs/ChangeLog +211 -211
- data/docs/DEFERRABLES +246 -133
- data/docs/EPOLL +141 -141
- data/docs/GNU +281 -281
- data/docs/INSTALL +13 -13
- data/docs/KEYBOARD +42 -38
- data/docs/LEGAL +25 -25
- data/docs/LIGHTWEIGHT_CONCURRENCY +130 -70
- data/docs/PURE_RUBY +75 -75
- data/docs/RELEASE_NOTES +94 -94
- data/docs/SMTP +4 -2
- data/docs/SPAWNED_PROCESSES +148 -89
- data/docs/TODO +8 -8
- data/eventmachine.gemspec +19 -26
- data/examples/ex_channel.rb +42 -42
- data/examples/ex_queue.rb +2 -2
- data/examples/ex_tick_loop_array.rb +15 -0
- data/examples/ex_tick_loop_counter.rb +32 -0
- data/examples/helper.rb +1 -1
- data/ext/binder.cpp +0 -1
- data/ext/cmain.cpp +36 -25
- data/ext/ed.cpp +104 -113
- data/ext/ed.h +24 -30
- data/ext/em.cpp +349 -283
- data/ext/em.h +25 -29
- data/ext/eventmachine.h +5 -4
- data/ext/extconf.rb +58 -49
- data/ext/fastfilereader/extconf.rb +5 -3
- data/ext/fastfilereader/mapper.cpp +214 -214
- data/ext/fastfilereader/mapper.h +59 -59
- data/ext/fastfilereader/rubymain.cpp +127 -127
- data/ext/kb.cpp +1 -3
- data/ext/page.cpp +107 -107
- data/ext/page.h +51 -51
- data/ext/pipe.cpp +9 -11
- data/ext/project.h +12 -8
- data/ext/rubymain.cpp +138 -104
- data/java/.classpath +8 -8
- data/java/.project +17 -17
- data/java/src/com/rubyeventmachine/EmReactor.java +1 -0
- data/java/src/com/rubyeventmachine/EmReactorException.java +40 -40
- data/lib/em/buftok.rb +138 -138
- data/lib/em/callback.rb +25 -25
- data/lib/em/channel.rb +1 -1
- data/lib/em/connection.rb +6 -1
- data/lib/em/deferrable.rb +16 -2
- data/lib/em/file_watch.rb +53 -53
- data/lib/em/future.rb +61 -61
- data/lib/em/iterator.rb +270 -0
- data/lib/em/messages.rb +66 -66
- data/lib/em/process_watch.rb +43 -43
- data/lib/em/protocols.rb +1 -1
- data/lib/em/protocols/header_and_content.rb +138 -138
- data/lib/em/protocols/httpclient.rb +267 -262
- data/lib/em/protocols/line_protocol.rb +28 -0
- data/lib/em/protocols/memcache.rb +322 -322
- data/lib/em/protocols/postgres3.rb +247 -247
- data/lib/em/protocols/saslauth.rb +175 -175
- data/lib/em/protocols/smtpserver.rb +640 -547
- data/lib/em/protocols/stomp.rb +200 -200
- data/lib/em/protocols/tcptest.rb +52 -52
- data/lib/{pr_eventmachine.rb → em/pure_ruby.rb} +1013 -1022
- data/lib/em/queue.rb +1 -0
- data/lib/em/spawnable.rb +85 -85
- data/lib/em/streamer.rb +130 -130
- data/lib/em/tick_loop.rb +85 -0
- data/lib/em/timers.rb +2 -1
- data/lib/em/version.rb +1 -1
- data/lib/eventmachine.rb +40 -84
- data/lib/jeventmachine.rb +2 -1
- data/lib/rubyeventmachine.rb +2 -0
- data/setup.rb +1585 -1585
- data/tasks/doc.rake +30 -0
- data/tasks/package.rake +85 -0
- data/tasks/test.rake +6 -0
- data/tests/client.crt +31 -31
- data/tests/client.key +51 -51
- data/tests/test_attach.rb +13 -3
- data/tests/test_basic.rb +60 -95
- data/tests/test_channel.rb +3 -2
- data/tests/test_defer.rb +49 -47
- data/tests/test_deferrable.rb +35 -0
- data/tests/test_error_handler.rb +35 -35
- data/tests/test_errors.rb +82 -82
- data/tests/test_exc.rb +55 -55
- data/tests/test_file_watch.rb +49 -49
- data/tests/test_futures.rb +198 -198
- data/tests/test_handler_check.rb +36 -36
- data/tests/test_hc.rb +190 -218
- data/tests/test_httpclient.rb +227 -218
- data/tests/test_httpclient2.rb +3 -2
- data/tests/test_inactivity_timeout.rb +3 -3
- data/tests/test_kb.rb +60 -60
- data/tests/test_ltp.rb +13 -5
- data/tests/test_ltp2.rb +317 -317
- data/tests/test_next_tick.rb +1 -1
- data/tests/test_object_protocol.rb +36 -36
- data/tests/test_pending_connect_timeout.rb +2 -2
- data/tests/test_process_watch.rb +50 -48
- data/tests/test_proxy_connection.rb +52 -0
- data/tests/test_pure.rb +134 -125
- data/tests/test_queue.rb +44 -44
- data/tests/test_running.rb +42 -42
- data/tests/test_sasl.rb +72 -72
- data/tests/test_send_file.rb +251 -242
- data/tests/test_servers.rb +76 -76
- data/tests/test_smtpclient.rb +83 -83
- data/tests/test_smtpserver.rb +85 -85
- data/tests/test_spawn.rb +322 -322
- data/tests/test_ssl_methods.rb +49 -49
- data/tests/test_ssl_verify.rb +82 -82
- data/tests/test_tick_loop.rb +59 -0
- data/tests/test_timers.rb +13 -15
- data/tests/test_ud.rb +36 -36
- data/tests/testem.rb +31 -31
- metadata +66 -51
- data/ext/cplusplus.cpp +0 -202
- data/ext/emwin.cpp +0 -300
- data/ext/emwin.h +0 -94
- data/ext/epoll.cpp +0 -26
- data/ext/epoll.h +0 -25
- data/ext/eventmachine_cpp.h +0 -96
- data/ext/files.cpp +0 -94
- data/ext/files.h +0 -65
- data/ext/sigs.cpp +0 -89
- data/ext/sigs.h +0 -32
- data/java/src/com/rubyeventmachine/application/Application.java +0 -194
- data/java/src/com/rubyeventmachine/application/Connection.java +0 -74
- data/java/src/com/rubyeventmachine/application/ConnectionFactory.java +0 -37
- data/java/src/com/rubyeventmachine/application/DefaultConnectionFactory.java +0 -46
- data/java/src/com/rubyeventmachine/application/PeriodicTimer.java +0 -38
- data/java/src/com/rubyeventmachine/application/Timer.java +0 -54
- data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +0 -109
- data/java/src/com/rubyeventmachine/tests/ConnectTest.java +0 -148
- data/java/src/com/rubyeventmachine/tests/EMTest.java +0 -80
- data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +0 -53
- data/java/src/com/rubyeventmachine/tests/TestServers.java +0 -75
- data/java/src/com/rubyeventmachine/tests/TestTimers.java +0 -90
- data/lib/evma.rb +0 -32
- data/lib/evma/callback.rb +0 -32
- data/lib/evma/container.rb +0 -75
- data/lib/evma/factory.rb +0 -77
- data/lib/evma/protocol.rb +0 -87
- data/lib/evma/reactor.rb +0 -48
- data/web/whatis +0 -7
data/lib/em/messages.rb
CHANGED
@@ -1,66 +1,66 @@
|
|
1
|
-
#--
|
2
|
-
#
|
3
|
-
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
|
-
# Homepage:: http://rubyeventmachine.com
|
5
|
-
# Date:: 16 Jul 2006
|
6
|
-
#
|
7
|
-
# See EventMachine and EventMachine::Connection for documentation and
|
8
|
-
# usage examples.
|
9
|
-
#
|
10
|
-
#----------------------------------------------------------------------------
|
11
|
-
#
|
12
|
-
# Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
13
|
-
# Gmail: blackhedd
|
14
|
-
#
|
15
|
-
# This program is free software; you can redistribute it and/or modify
|
16
|
-
# it under the terms of either: 1) the GNU General Public License
|
17
|
-
# as published by the Free Software Foundation; either version 2 of the
|
18
|
-
# License, or (at your option) any later version; or 2) Ruby's License.
|
19
|
-
#
|
20
|
-
# See the file COPYING for complete licensing information.
|
21
|
-
#
|
22
|
-
#---------------------------------------------------------------------------
|
23
|
-
#
|
24
|
-
#
|
25
|
-
|
26
|
-
=begin
|
27
|
-
|
28
|
-
Message Routing in EventMachine.
|
29
|
-
|
30
|
-
The goal here is to enable "routing points," objects that can send and receive
|
31
|
-
"messages," which are delimited streams of bytes. The boundaries of a message
|
32
|
-
are preserved as it passes through the reactor system.
|
33
|
-
|
34
|
-
There will be several module methods defined in EventMachine to create route-point
|
35
|
-
objects (which will probably have a base class of EventMachine::MessageRouter
|
36
|
-
until someone suggests a better name).
|
37
|
-
|
38
|
-
As with I/O objects, routing objects will receive events by having the router
|
39
|
-
core call methods on them. And of course user code can and will define handlers
|
40
|
-
to deal with events of interest.
|
41
|
-
|
42
|
-
The message router base class only really needs a receive_message method. There will
|
43
|
-
be an EM module-method to send messages, in addition to the module methods to create
|
44
|
-
the various kinds of message receivers.
|
45
|
-
|
46
|
-
The simplest kind of message receiver object can receive messages by being named
|
47
|
-
explicitly in a parameter to EM#send_message. More sophisticated receivers can define
|
48
|
-
pub-sub selectors and message-queue names. And they can also define channels for
|
49
|
-
route-points in other processes or even on other machines.
|
50
|
-
|
51
|
-
A message is NOT a marshallable entity. Rather, it's a chunk of flat content more like
|
52
|
-
an Erlang message. Initially, all content submitted for transmission as a message will
|
53
|
-
have the to_s method called on it. Eventually, we'll be able to transmit certain structured
|
54
|
-
data types (XML and YAML documents, Structs within limits) and have them reconstructed
|
55
|
-
on the other end.
|
56
|
-
|
57
|
-
A fundamental goal of the message-routing capability is to interoperate seamlessly with
|
58
|
-
external systems, including non-Ruby systems like ActiveMQ. We will define various protocol
|
59
|
-
handlers for things like Stomp and possibly AMQP, but these will be wrapped up and hidden
|
60
|
-
from the users of the basic routing capability.
|
61
|
-
|
62
|
-
As with Erlang, a critical goal is for programs that are built to use message-passing to work
|
63
|
-
WITHOUT CHANGE when the code is re-based on a multi-process system.
|
64
|
-
|
65
|
-
=end
|
66
|
-
|
1
|
+
#--
|
2
|
+
#
|
3
|
+
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
|
+
# Homepage:: http://rubyeventmachine.com
|
5
|
+
# Date:: 16 Jul 2006
|
6
|
+
#
|
7
|
+
# See EventMachine and EventMachine::Connection for documentation and
|
8
|
+
# usage examples.
|
9
|
+
#
|
10
|
+
#----------------------------------------------------------------------------
|
11
|
+
#
|
12
|
+
# Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
13
|
+
# Gmail: blackhedd
|
14
|
+
#
|
15
|
+
# This program is free software; you can redistribute it and/or modify
|
16
|
+
# it under the terms of either: 1) the GNU General Public License
|
17
|
+
# as published by the Free Software Foundation; either version 2 of the
|
18
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
19
|
+
#
|
20
|
+
# See the file COPYING for complete licensing information.
|
21
|
+
#
|
22
|
+
#---------------------------------------------------------------------------
|
23
|
+
#
|
24
|
+
#
|
25
|
+
|
26
|
+
=begin
|
27
|
+
|
28
|
+
Message Routing in EventMachine.
|
29
|
+
|
30
|
+
The goal here is to enable "routing points," objects that can send and receive
|
31
|
+
"messages," which are delimited streams of bytes. The boundaries of a message
|
32
|
+
are preserved as it passes through the reactor system.
|
33
|
+
|
34
|
+
There will be several module methods defined in EventMachine to create route-point
|
35
|
+
objects (which will probably have a base class of EventMachine::MessageRouter
|
36
|
+
until someone suggests a better name).
|
37
|
+
|
38
|
+
As with I/O objects, routing objects will receive events by having the router
|
39
|
+
core call methods on them. And of course user code can and will define handlers
|
40
|
+
to deal with events of interest.
|
41
|
+
|
42
|
+
The message router base class only really needs a receive_message method. There will
|
43
|
+
be an EM module-method to send messages, in addition to the module methods to create
|
44
|
+
the various kinds of message receivers.
|
45
|
+
|
46
|
+
The simplest kind of message receiver object can receive messages by being named
|
47
|
+
explicitly in a parameter to EM#send_message. More sophisticated receivers can define
|
48
|
+
pub-sub selectors and message-queue names. And they can also define channels for
|
49
|
+
route-points in other processes or even on other machines.
|
50
|
+
|
51
|
+
A message is NOT a marshallable entity. Rather, it's a chunk of flat content more like
|
52
|
+
an Erlang message. Initially, all content submitted for transmission as a message will
|
53
|
+
have the to_s method called on it. Eventually, we'll be able to transmit certain structured
|
54
|
+
data types (XML and YAML documents, Structs within limits) and have them reconstructed
|
55
|
+
on the other end.
|
56
|
+
|
57
|
+
A fundamental goal of the message-routing capability is to interoperate seamlessly with
|
58
|
+
external systems, including non-Ruby systems like ActiveMQ. We will define various protocol
|
59
|
+
handlers for things like Stomp and possibly AMQP, but these will be wrapped up and hidden
|
60
|
+
from the users of the basic routing capability.
|
61
|
+
|
62
|
+
As with Erlang, a critical goal is for programs that are built to use message-passing to work
|
63
|
+
WITHOUT CHANGE when the code is re-based on a multi-process system.
|
64
|
+
|
65
|
+
=end
|
66
|
+
|
data/lib/em/process_watch.rb
CHANGED
@@ -1,44 +1,44 @@
|
|
1
|
-
module EventMachine
|
2
|
-
|
3
|
-
# This is subclassed from EventMachine::Connection for use with the process monitoring API. Read the
|
4
|
-
# documentation on the instance methods of this class, and for a full explanation see EventMachine.watch_process.
|
5
|
-
class ProcessWatch < Connection
|
6
|
-
# :stopdoc:
|
7
|
-
Cfork = 'fork'.freeze
|
8
|
-
Cexit = 'exit'.freeze
|
9
|
-
# :startdoc:
|
10
|
-
|
11
|
-
def receive_data(data) # :nodoc:
|
12
|
-
case data
|
13
|
-
when Cfork
|
14
|
-
process_forked
|
15
|
-
when Cexit
|
16
|
-
process_exited
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# Returns the pid that EventMachine::watch_process was originally called with.
|
21
|
-
def pid
|
22
|
-
@pid
|
23
|
-
end
|
24
|
-
|
25
|
-
# Should be redefined with the user's custom callback that will be fired when the prcess is forked.
|
26
|
-
#
|
27
|
-
# There is currently not an easy way to get the pid of the forked child.
|
28
|
-
def process_forked
|
29
|
-
end
|
30
|
-
|
31
|
-
# Should be redefined with the user's custom callback that will be fired when the process exits.
|
32
|
-
#
|
33
|
-
# stop_watching is called automatically after this callback
|
34
|
-
def process_exited
|
35
|
-
end
|
36
|
-
|
37
|
-
# Discontinue monitoring of the process.
|
38
|
-
# This will be called automatically when a process dies. User code may call it as well.
|
39
|
-
def stop_watching
|
40
|
-
EventMachine::unwatch_pid(@signature)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
1
|
+
module EventMachine
|
2
|
+
|
3
|
+
# This is subclassed from EventMachine::Connection for use with the process monitoring API. Read the
|
4
|
+
# documentation on the instance methods of this class, and for a full explanation see EventMachine.watch_process.
|
5
|
+
class ProcessWatch < Connection
|
6
|
+
# :stopdoc:
|
7
|
+
Cfork = 'fork'.freeze
|
8
|
+
Cexit = 'exit'.freeze
|
9
|
+
# :startdoc:
|
10
|
+
|
11
|
+
def receive_data(data) # :nodoc:
|
12
|
+
case data
|
13
|
+
when Cfork
|
14
|
+
process_forked
|
15
|
+
when Cexit
|
16
|
+
process_exited
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the pid that EventMachine::watch_process was originally called with.
|
21
|
+
def pid
|
22
|
+
@pid
|
23
|
+
end
|
24
|
+
|
25
|
+
# Should be redefined with the user's custom callback that will be fired when the prcess is forked.
|
26
|
+
#
|
27
|
+
# There is currently not an easy way to get the pid of the forked child.
|
28
|
+
def process_forked
|
29
|
+
end
|
30
|
+
|
31
|
+
# Should be redefined with the user's custom callback that will be fired when the process exits.
|
32
|
+
#
|
33
|
+
# stop_watching is called automatically after this callback
|
34
|
+
def process_exited
|
35
|
+
end
|
36
|
+
|
37
|
+
# Discontinue monitoring of the process.
|
38
|
+
# This will be called automatically when a process dies. User code may call it as well.
|
39
|
+
def stop_watching
|
40
|
+
EventMachine::unwatch_pid(@signature)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
44
|
end
|
data/lib/em/protocols.rb
CHANGED
@@ -1,138 +1,138 @@
|
|
1
|
-
#--
|
2
|
-
#
|
3
|
-
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
|
-
# Homepage:: http://rubyeventmachine.com
|
5
|
-
# Date:: 15 Nov 2006
|
6
|
-
#
|
7
|
-
# See EventMachine and EventMachine::Connection for documentation and
|
8
|
-
# usage examples.
|
9
|
-
#
|
10
|
-
#----------------------------------------------------------------------------
|
11
|
-
#
|
12
|
-
# Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
13
|
-
# Gmail: blackhedd
|
14
|
-
#
|
15
|
-
# This program is free software; you can redistribute it and/or modify
|
16
|
-
# it under the terms of either: 1) the GNU General Public License
|
17
|
-
# as published by the Free Software Foundation; either version 2 of the
|
18
|
-
# License, or (at your option) any later version; or 2) Ruby's License.
|
19
|
-
#
|
20
|
-
# See the file COPYING for complete licensing information.
|
21
|
-
#
|
22
|
-
#---------------------------------------------------------------------------
|
23
|
-
#
|
24
|
-
#
|
25
|
-
|
26
|
-
module EventMachine
|
27
|
-
module Protocols
|
28
|
-
|
29
|
-
# === Usage
|
30
|
-
#
|
31
|
-
# class RequestHandler < EM::P::HeaderAndContentProtocol
|
32
|
-
# def receive_request headers, content
|
33
|
-
# p [:request, headers, content]
|
34
|
-
# end
|
35
|
-
# end
|
36
|
-
#
|
37
|
-
# EM.run{
|
38
|
-
# EM.start_server 'localhost', 80, RequestHandler
|
39
|
-
# }
|
40
|
-
#
|
41
|
-
#--
|
42
|
-
# Originally, this subclassed LineAndTextProtocol, which in
|
43
|
-
# turn relies on BufferedTokenizer, which doesn't gracefully
|
44
|
-
# handle the transitions between lines and binary text.
|
45
|
-
# Changed 13Sep08 by FCianfrocca.
|
46
|
-
class HeaderAndContentProtocol < Connection
|
47
|
-
include LineText2
|
48
|
-
|
49
|
-
ContentLengthPattern = /Content-length:\s*(\d+)/i
|
50
|
-
|
51
|
-
def initialize *args
|
52
|
-
super
|
53
|
-
init_for_request
|
54
|
-
end
|
55
|
-
|
56
|
-
def receive_line line
|
57
|
-
case @hc_mode
|
58
|
-
when :discard_blanks
|
59
|
-
unless line == ""
|
60
|
-
@hc_mode = :headers
|
61
|
-
receive_line line
|
62
|
-
end
|
63
|
-
when :headers
|
64
|
-
if line == ""
|
65
|
-
raise "unrecognized state" unless @hc_headers.length > 0
|
66
|
-
if respond_to?(:receive_headers)
|
67
|
-
receive_headers @hc_headers
|
68
|
-
end
|
69
|
-
# @hc_content_length will be nil, not 0, if there was no content-length header.
|
70
|
-
if @hc_content_length.to_i > 0
|
71
|
-
set_binary_mode @hc_content_length
|
72
|
-
else
|
73
|
-
dispatch_request
|
74
|
-
end
|
75
|
-
else
|
76
|
-
@hc_headers << line
|
77
|
-
if ContentLengthPattern =~ line
|
78
|
-
# There are some attacks that rely on sending multiple content-length
|
79
|
-
# headers. This is a crude protection, but needs to become tunable.
|
80
|
-
raise "extraneous content-length header" if @hc_content_length
|
81
|
-
@hc_content_length = $1.to_i
|
82
|
-
end
|
83
|
-
if @hc_headers.length == 1 and respond_to?(:receive_first_header_line)
|
84
|
-
receive_first_header_line line
|
85
|
-
end
|
86
|
-
end
|
87
|
-
else
|
88
|
-
raise "internal error, unsupported mode"
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def receive_binary_data text
|
93
|
-
@hc_content = text
|
94
|
-
dispatch_request
|
95
|
-
end
|
96
|
-
|
97
|
-
def dispatch_request
|
98
|
-
if respond_to?(:receive_request)
|
99
|
-
receive_request @hc_headers, @hc_content
|
100
|
-
end
|
101
|
-
init_for_request
|
102
|
-
end
|
103
|
-
private :dispatch_request
|
104
|
-
|
105
|
-
def init_for_request
|
106
|
-
@hc_mode = :discard_blanks
|
107
|
-
@hc_headers = []
|
108
|
-
# originally was @hc_headers ||= []; @hc_headers.clear to get a performance
|
109
|
-
# boost, but it's counterproductive because a subclassed handler will have to
|
110
|
-
# call dup to use the header array we pass in receive_headers.
|
111
|
-
|
112
|
-
@hc_content_length = nil
|
113
|
-
@hc_content = ""
|
114
|
-
end
|
115
|
-
private :init_for_request
|
116
|
-
|
117
|
-
# Basically a convenience method. We might create a subclass that does this
|
118
|
-
# automatically. But it's such a performance killer.
|
119
|
-
def headers_2_hash hdrs
|
120
|
-
self.class.headers_2_hash hdrs
|
121
|
-
end
|
122
|
-
|
123
|
-
class << self
|
124
|
-
def headers_2_hash hdrs
|
125
|
-
hash = {}
|
126
|
-
hdrs.each {|h|
|
127
|
-
if /\A([^\s:]+)\s*:\s*/ =~ h
|
128
|
-
tail = $'.dup
|
129
|
-
hash[ $1.downcase.gsub(/-/,"_").intern ] = tail
|
130
|
-
end
|
131
|
-
}
|
132
|
-
hash
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
1
|
+
#--
|
2
|
+
#
|
3
|
+
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
|
+
# Homepage:: http://rubyeventmachine.com
|
5
|
+
# Date:: 15 Nov 2006
|
6
|
+
#
|
7
|
+
# See EventMachine and EventMachine::Connection for documentation and
|
8
|
+
# usage examples.
|
9
|
+
#
|
10
|
+
#----------------------------------------------------------------------------
|
11
|
+
#
|
12
|
+
# Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
13
|
+
# Gmail: blackhedd
|
14
|
+
#
|
15
|
+
# This program is free software; you can redistribute it and/or modify
|
16
|
+
# it under the terms of either: 1) the GNU General Public License
|
17
|
+
# as published by the Free Software Foundation; either version 2 of the
|
18
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
19
|
+
#
|
20
|
+
# See the file COPYING for complete licensing information.
|
21
|
+
#
|
22
|
+
#---------------------------------------------------------------------------
|
23
|
+
#
|
24
|
+
#
|
25
|
+
|
26
|
+
module EventMachine
|
27
|
+
module Protocols
|
28
|
+
|
29
|
+
# === Usage
|
30
|
+
#
|
31
|
+
# class RequestHandler < EM::P::HeaderAndContentProtocol
|
32
|
+
# def receive_request headers, content
|
33
|
+
# p [:request, headers, content]
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# EM.run{
|
38
|
+
# EM.start_server 'localhost', 80, RequestHandler
|
39
|
+
# }
|
40
|
+
#
|
41
|
+
#--
|
42
|
+
# Originally, this subclassed LineAndTextProtocol, which in
|
43
|
+
# turn relies on BufferedTokenizer, which doesn't gracefully
|
44
|
+
# handle the transitions between lines and binary text.
|
45
|
+
# Changed 13Sep08 by FCianfrocca.
|
46
|
+
class HeaderAndContentProtocol < Connection
|
47
|
+
include LineText2
|
48
|
+
|
49
|
+
ContentLengthPattern = /Content-length:\s*(\d+)/i
|
50
|
+
|
51
|
+
def initialize *args
|
52
|
+
super
|
53
|
+
init_for_request
|
54
|
+
end
|
55
|
+
|
56
|
+
def receive_line line
|
57
|
+
case @hc_mode
|
58
|
+
when :discard_blanks
|
59
|
+
unless line == ""
|
60
|
+
@hc_mode = :headers
|
61
|
+
receive_line line
|
62
|
+
end
|
63
|
+
when :headers
|
64
|
+
if line == ""
|
65
|
+
raise "unrecognized state" unless @hc_headers.length > 0
|
66
|
+
if respond_to?(:receive_headers)
|
67
|
+
receive_headers @hc_headers
|
68
|
+
end
|
69
|
+
# @hc_content_length will be nil, not 0, if there was no content-length header.
|
70
|
+
if @hc_content_length.to_i > 0
|
71
|
+
set_binary_mode @hc_content_length
|
72
|
+
else
|
73
|
+
dispatch_request
|
74
|
+
end
|
75
|
+
else
|
76
|
+
@hc_headers << line
|
77
|
+
if ContentLengthPattern =~ line
|
78
|
+
# There are some attacks that rely on sending multiple content-length
|
79
|
+
# headers. This is a crude protection, but needs to become tunable.
|
80
|
+
raise "extraneous content-length header" if @hc_content_length
|
81
|
+
@hc_content_length = $1.to_i
|
82
|
+
end
|
83
|
+
if @hc_headers.length == 1 and respond_to?(:receive_first_header_line)
|
84
|
+
receive_first_header_line line
|
85
|
+
end
|
86
|
+
end
|
87
|
+
else
|
88
|
+
raise "internal error, unsupported mode"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def receive_binary_data text
|
93
|
+
@hc_content = text
|
94
|
+
dispatch_request
|
95
|
+
end
|
96
|
+
|
97
|
+
def dispatch_request
|
98
|
+
if respond_to?(:receive_request)
|
99
|
+
receive_request @hc_headers, @hc_content
|
100
|
+
end
|
101
|
+
init_for_request
|
102
|
+
end
|
103
|
+
private :dispatch_request
|
104
|
+
|
105
|
+
def init_for_request
|
106
|
+
@hc_mode = :discard_blanks
|
107
|
+
@hc_headers = []
|
108
|
+
# originally was @hc_headers ||= []; @hc_headers.clear to get a performance
|
109
|
+
# boost, but it's counterproductive because a subclassed handler will have to
|
110
|
+
# call dup to use the header array we pass in receive_headers.
|
111
|
+
|
112
|
+
@hc_content_length = nil
|
113
|
+
@hc_content = ""
|
114
|
+
end
|
115
|
+
private :init_for_request
|
116
|
+
|
117
|
+
# Basically a convenience method. We might create a subclass that does this
|
118
|
+
# automatically. But it's such a performance killer.
|
119
|
+
def headers_2_hash hdrs
|
120
|
+
self.class.headers_2_hash hdrs
|
121
|
+
end
|
122
|
+
|
123
|
+
class << self
|
124
|
+
def headers_2_hash hdrs
|
125
|
+
hash = {}
|
126
|
+
hdrs.each {|h|
|
127
|
+
if /\A([^\s:]+)\s*:\s*/ =~ h
|
128
|
+
tail = $'.dup
|
129
|
+
hash[ $1.downcase.gsub(/-/,"_").intern ] = tail
|
130
|
+
end
|
131
|
+
}
|
132
|
+
hash
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|