wj_eventmachine 1.3.0.dev.1
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +179 -0
- data/GNU +281 -0
- data/LICENSE +60 -0
- data/README.md +110 -0
- data/docs/DocumentationGuidesIndex.md +27 -0
- data/docs/GettingStarted.md +520 -0
- data/docs/old/ChangeLog +211 -0
- data/docs/old/DEFERRABLES +246 -0
- data/docs/old/EPOLL +141 -0
- data/docs/old/INSTALL +13 -0
- data/docs/old/KEYBOARD +42 -0
- data/docs/old/LEGAL +25 -0
- data/docs/old/LIGHTWEIGHT_CONCURRENCY +130 -0
- data/docs/old/PURE_RUBY +75 -0
- data/docs/old/RELEASE_NOTES +94 -0
- data/docs/old/SMTP +4 -0
- data/docs/old/SPAWNED_PROCESSES +148 -0
- data/docs/old/TODO +8 -0
- data/examples/guides/getting_started/01_eventmachine_echo_server.rb +18 -0
- data/examples/guides/getting_started/02_eventmachine_echo_server_that_recognizes_exit_command.rb +22 -0
- data/examples/guides/getting_started/03_simple_chat_server.rb +149 -0
- data/examples/guides/getting_started/04_simple_chat_server_step_one.rb +27 -0
- data/examples/guides/getting_started/05_simple_chat_server_step_two.rb +43 -0
- data/examples/guides/getting_started/06_simple_chat_server_step_three.rb +98 -0
- data/examples/guides/getting_started/07_simple_chat_server_step_four.rb +121 -0
- data/examples/guides/getting_started/08_simple_chat_server_step_five.rb +141 -0
- data/examples/old/ex_channel.rb +43 -0
- data/examples/old/ex_queue.rb +2 -0
- data/examples/old/ex_tick_loop_array.rb +15 -0
- data/examples/old/ex_tick_loop_counter.rb +32 -0
- data/examples/old/helper.rb +2 -0
- data/ext/binder.cpp +124 -0
- data/ext/binder.h +52 -0
- data/ext/cmain.cpp +1046 -0
- data/ext/ed.cpp +2238 -0
- data/ext/ed.h +460 -0
- data/ext/em.cpp +2378 -0
- data/ext/em.h +266 -0
- data/ext/eventmachine.h +152 -0
- data/ext/extconf.rb +285 -0
- data/ext/fastfilereader/extconf.rb +120 -0
- data/ext/fastfilereader/mapper.cpp +214 -0
- data/ext/fastfilereader/mapper.h +59 -0
- data/ext/fastfilereader/rubymain.cpp +126 -0
- data/ext/kb.cpp +79 -0
- data/ext/page.cpp +107 -0
- data/ext/page.h +51 -0
- data/ext/pipe.cpp +354 -0
- data/ext/project.h +174 -0
- data/ext/rubymain.cpp +1610 -0
- data/ext/ssl.cpp +627 -0
- data/ext/ssl.h +103 -0
- data/ext/wait_for_single_fd.h +36 -0
- data/java/.classpath +8 -0
- data/java/.project +17 -0
- data/java/src/com/rubyeventmachine/EmReactor.java +625 -0
- data/java/src/com/rubyeventmachine/EmReactorException.java +40 -0
- data/java/src/com/rubyeventmachine/EmReactorInterface.java +70 -0
- data/java/src/com/rubyeventmachine/EventableChannel.java +72 -0
- data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +201 -0
- data/java/src/com/rubyeventmachine/EventableSocketChannel.java +415 -0
- data/java/src/com/rubyeventmachine/NullEmReactor.java +157 -0
- data/java/src/com/rubyeventmachine/NullEventableChannel.java +81 -0
- data/lib/em/buftok.rb +59 -0
- data/lib/em/callback.rb +58 -0
- data/lib/em/channel.rb +69 -0
- data/lib/em/completion.rb +307 -0
- data/lib/em/connection.rb +776 -0
- data/lib/em/deferrable.rb +210 -0
- data/lib/em/deferrable/pool.rb +2 -0
- data/lib/em/file_watch.rb +73 -0
- data/lib/em/future.rb +61 -0
- data/lib/em/io_streamer.rb +68 -0
- data/lib/em/iterator.rb +252 -0
- data/lib/em/messages.rb +66 -0
- data/lib/em/pool.rb +151 -0
- data/lib/em/process_watch.rb +45 -0
- data/lib/em/processes.rb +123 -0
- data/lib/em/protocols.rb +37 -0
- data/lib/em/protocols/header_and_content.rb +138 -0
- data/lib/em/protocols/httpclient.rb +303 -0
- data/lib/em/protocols/httpclient2.rb +602 -0
- data/lib/em/protocols/line_and_text.rb +125 -0
- data/lib/em/protocols/line_protocol.rb +33 -0
- data/lib/em/protocols/linetext2.rb +179 -0
- data/lib/em/protocols/memcache.rb +331 -0
- data/lib/em/protocols/object_protocol.rb +46 -0
- data/lib/em/protocols/postgres3.rb +246 -0
- data/lib/em/protocols/saslauth.rb +175 -0
- data/lib/em/protocols/smtpclient.rb +394 -0
- data/lib/em/protocols/smtpserver.rb +666 -0
- data/lib/em/protocols/socks4.rb +66 -0
- data/lib/em/protocols/stomp.rb +205 -0
- data/lib/em/protocols/tcptest.rb +54 -0
- data/lib/em/pure_ruby.rb +1299 -0
- data/lib/em/queue.rb +80 -0
- data/lib/em/resolver.rb +232 -0
- data/lib/em/spawnable.rb +84 -0
- data/lib/em/streamer.rb +118 -0
- data/lib/em/threaded_resource.rb +90 -0
- data/lib/em/tick_loop.rb +85 -0
- data/lib/em/timers.rb +61 -0
- data/lib/em/version.rb +3 -0
- data/lib/eventmachine.rb +1602 -0
- data/lib/jeventmachine.rb +318 -0
- data/rakelib/package.rake +120 -0
- data/rakelib/test.rake +6 -0
- data/rakelib/test_pure.rake +11 -0
- data/tests/client.crt +31 -0
- data/tests/client.key +51 -0
- data/tests/dhparam.pem +13 -0
- data/tests/em_ssl_handlers.rb +153 -0
- data/tests/em_test_helper.rb +198 -0
- data/tests/jruby/test_jeventmachine.rb +38 -0
- data/tests/test_attach.rb +199 -0
- data/tests/test_basic.rb +321 -0
- data/tests/test_channel.rb +75 -0
- data/tests/test_completion.rb +178 -0
- data/tests/test_connection_count.rb +83 -0
- data/tests/test_connection_write.rb +35 -0
- data/tests/test_defer.rb +35 -0
- data/tests/test_deferrable.rb +35 -0
- data/tests/test_epoll.rb +141 -0
- data/tests/test_error_handler.rb +38 -0
- data/tests/test_exc.rb +37 -0
- data/tests/test_file_watch.rb +86 -0
- data/tests/test_fork.rb +75 -0
- data/tests/test_futures.rb +170 -0
- data/tests/test_handler_check.rb +35 -0
- data/tests/test_hc.rb +155 -0
- data/tests/test_httpclient.rb +238 -0
- data/tests/test_httpclient2.rb +132 -0
- data/tests/test_idle_connection.rb +31 -0
- data/tests/test_inactivity_timeout.rb +102 -0
- data/tests/test_io_streamer.rb +47 -0
- data/tests/test_ipv4.rb +96 -0
- data/tests/test_ipv6.rb +107 -0
- data/tests/test_iterator.rb +122 -0
- data/tests/test_kb.rb +28 -0
- data/tests/test_keepalive.rb +113 -0
- data/tests/test_line_protocol.rb +33 -0
- data/tests/test_ltp.rb +155 -0
- data/tests/test_ltp2.rb +332 -0
- data/tests/test_many_fds.rb +21 -0
- data/tests/test_next_tick.rb +104 -0
- data/tests/test_object_protocol.rb +36 -0
- data/tests/test_pause.rb +109 -0
- data/tests/test_pending_connect_timeout.rb +52 -0
- data/tests/test_pool.rb +196 -0
- data/tests/test_process_watch.rb +50 -0
- data/tests/test_processes.rb +128 -0
- data/tests/test_proxy_connection.rb +180 -0
- data/tests/test_pure.rb +156 -0
- data/tests/test_queue.rb +64 -0
- data/tests/test_resolver.rb +129 -0
- data/tests/test_running.rb +14 -0
- data/tests/test_sasl.rb +46 -0
- data/tests/test_send_file.rb +217 -0
- data/tests/test_servers.rb +32 -0
- data/tests/test_shutdown_hooks.rb +23 -0
- data/tests/test_smtpclient.rb +75 -0
- data/tests/test_smtpserver.rb +90 -0
- data/tests/test_sock_opt.rb +53 -0
- data/tests/test_spawn.rb +290 -0
- data/tests/test_ssl_args.rb +41 -0
- data/tests/test_ssl_dhparam.rb +57 -0
- data/tests/test_ssl_ecdh_curve.rb +57 -0
- data/tests/test_ssl_extensions.rb +24 -0
- data/tests/test_ssl_methods.rb +31 -0
- data/tests/test_ssl_protocols.rb +190 -0
- data/tests/test_ssl_verify.rb +52 -0
- data/tests/test_stomp.rb +38 -0
- data/tests/test_system.rb +46 -0
- data/tests/test_threaded_resource.rb +68 -0
- data/tests/test_tick_loop.rb +58 -0
- data/tests/test_timers.rb +150 -0
- data/tests/test_ud.rb +8 -0
- data/tests/test_unbind_reason.rb +40 -0
- metadata +384 -0
data/lib/em/messages.rb
ADDED
@@ -0,0 +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
|
+
|
data/lib/em/pool.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
module EventMachine
|
2
|
+
# A simple async resource pool based on a resource and work queue. Resources
|
3
|
+
# are enqueued and work waits for resources to become available.
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# require 'em-http-request'
|
7
|
+
#
|
8
|
+
# EM.run do
|
9
|
+
# pool = EM::Pool.new
|
10
|
+
# spawn = lambda { pool.add EM::HttpRequest.new('http://example.org') }
|
11
|
+
# 10.times { spawn[] }
|
12
|
+
# done, scheduled = 0, 0
|
13
|
+
#
|
14
|
+
# check = lambda do
|
15
|
+
# done += 1
|
16
|
+
# if done >= scheduled
|
17
|
+
# EM.stop
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# pool.on_error { |conn| spawn[] }
|
22
|
+
#
|
23
|
+
# 100.times do |i|
|
24
|
+
# scheduled += 1
|
25
|
+
# pool.perform do |conn|
|
26
|
+
# req = conn.get :path => '/', :keepalive => true
|
27
|
+
#
|
28
|
+
# req.callback do
|
29
|
+
# p [:success, conn.object_id, i, req.response.size]
|
30
|
+
# check[]
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# req.errback { check[] }
|
34
|
+
#
|
35
|
+
# req
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# Resources are expected to be controlled by an object responding to a
|
41
|
+
# deferrable/completion style API with callback and errback blocks.
|
42
|
+
#
|
43
|
+
class Pool
|
44
|
+
|
45
|
+
def initialize
|
46
|
+
@resources = EM::Queue.new
|
47
|
+
@removed = []
|
48
|
+
@contents = []
|
49
|
+
@on_error = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def add resource
|
53
|
+
@contents << resource
|
54
|
+
requeue resource
|
55
|
+
end
|
56
|
+
|
57
|
+
def remove resource
|
58
|
+
@contents.delete resource
|
59
|
+
@removed << resource
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns a list for introspection purposes only. You should *NEVER* call
|
63
|
+
# modification or work oriented methods on objects in this list. A good
|
64
|
+
# example use case is periodic statistics collection against a set of
|
65
|
+
# connection resources.
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# pool.contents.inject(0) { |sum, connection| connection.num_bytes }
|
69
|
+
def contents
|
70
|
+
@contents.dup
|
71
|
+
end
|
72
|
+
|
73
|
+
# Define a default catch-all for when the deferrables returned by work
|
74
|
+
# blocks enter a failed state. By default all that happens is that the
|
75
|
+
# resource is returned to the pool. If on_error is defined, this block is
|
76
|
+
# responsible for re-adding the resource to the pool if it is still usable.
|
77
|
+
# In other words, it is generally assumed that on_error blocks explicitly
|
78
|
+
# handle the rest of the lifetime of the resource.
|
79
|
+
def on_error *a, &b
|
80
|
+
@on_error = EM::Callback(*a, &b)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Perform a given #call-able object or block. The callable object will be
|
84
|
+
# called with a resource from the pool as soon as one is available, and is
|
85
|
+
# expected to return a deferrable.
|
86
|
+
#
|
87
|
+
# The deferrable will have callback and errback added such that when the
|
88
|
+
# deferrable enters a finished state, the object is returned to the pool.
|
89
|
+
#
|
90
|
+
# If on_error is defined, then objects are not automatically returned to the
|
91
|
+
# pool.
|
92
|
+
def perform(*a, &b)
|
93
|
+
work = EM::Callback(*a, &b)
|
94
|
+
|
95
|
+
@resources.pop do |resource|
|
96
|
+
if removed? resource
|
97
|
+
@removed.delete resource
|
98
|
+
reschedule work
|
99
|
+
else
|
100
|
+
process work, resource
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
alias reschedule perform
|
105
|
+
|
106
|
+
# A peek at the number of enqueued jobs waiting for resources
|
107
|
+
def num_waiting
|
108
|
+
@resources.num_waiting
|
109
|
+
end
|
110
|
+
|
111
|
+
# Removed will show resources in a partial pruned state. Resources in the
|
112
|
+
# removed list may not appear in the contents list if they are currently in
|
113
|
+
# use.
|
114
|
+
def removed? resource
|
115
|
+
@removed.include? resource
|
116
|
+
end
|
117
|
+
|
118
|
+
protected
|
119
|
+
def requeue resource
|
120
|
+
@resources.push resource
|
121
|
+
end
|
122
|
+
|
123
|
+
def failure resource
|
124
|
+
if @on_error
|
125
|
+
@contents.delete resource
|
126
|
+
@on_error.call resource
|
127
|
+
# Prevent users from calling a leak.
|
128
|
+
@removed.delete resource
|
129
|
+
else
|
130
|
+
requeue resource
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def completion deferrable, resource
|
135
|
+
deferrable.callback { requeue resource }
|
136
|
+
deferrable.errback { failure resource }
|
137
|
+
end
|
138
|
+
|
139
|
+
def process work, resource
|
140
|
+
deferrable = work.call resource
|
141
|
+
if deferrable.kind_of?(EM::Deferrable)
|
142
|
+
completion deferrable, resource
|
143
|
+
else
|
144
|
+
raise ArgumentError, "deferrable expected from work"
|
145
|
+
end
|
146
|
+
rescue
|
147
|
+
failure resource
|
148
|
+
raise
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,45 @@
|
|
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
|
+
# @private
|
7
|
+
Cfork = 'fork'.freeze
|
8
|
+
# @private
|
9
|
+
Cexit = 'exit'.freeze
|
10
|
+
|
11
|
+
# @private
|
12
|
+
def receive_data(data)
|
13
|
+
case data
|
14
|
+
when Cfork
|
15
|
+
process_forked
|
16
|
+
when Cexit
|
17
|
+
process_exited
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the pid that EventMachine::watch_process was originally called with.
|
22
|
+
def pid
|
23
|
+
@pid
|
24
|
+
end
|
25
|
+
|
26
|
+
# Should be redefined with the user's custom callback that will be fired when the prcess is forked.
|
27
|
+
#
|
28
|
+
# There is currently not an easy way to get the pid of the forked child.
|
29
|
+
def process_forked
|
30
|
+
end
|
31
|
+
|
32
|
+
# Should be redefined with the user's custom callback that will be fired when the process exits.
|
33
|
+
#
|
34
|
+
# stop_watching is called automatically after this callback
|
35
|
+
def process_exited
|
36
|
+
end
|
37
|
+
|
38
|
+
# Discontinue monitoring of the process.
|
39
|
+
# This will be called automatically when a process dies. User code may call it as well.
|
40
|
+
def stop_watching
|
41
|
+
EventMachine::unwatch_pid(@signature)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/lib/em/processes.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
#--
|
2
|
+
#
|
3
|
+
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
|
+
# Homepage:: http://rubyeventmachine.com
|
5
|
+
# Date:: 13 Dec 07
|
6
|
+
#
|
7
|
+
# See EventMachine and EventMachine::Connection for documentation and
|
8
|
+
# usage examples.
|
9
|
+
#
|
10
|
+
#----------------------------------------------------------------------------
|
11
|
+
#
|
12
|
+
# Copyright (C) 2006-08 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
|
+
|
27
|
+
module EventMachine
|
28
|
+
|
29
|
+
# EM::DeferrableChildProcess is a sugaring of a common use-case
|
30
|
+
# involving EM::popen.
|
31
|
+
# Call the #open method on EM::DeferrableChildProcess, passing
|
32
|
+
# a command-string. #open immediately returns an EM::Deferrable
|
33
|
+
# object. It also schedules the forking of a child process, which
|
34
|
+
# will execute the command passed to #open.
|
35
|
+
# When the forked child terminates, the Deferrable will be signalled
|
36
|
+
# and execute its callbacks, passing the data that the child process
|
37
|
+
# wrote to stdout.
|
38
|
+
#
|
39
|
+
class DeferrableChildProcess < EventMachine::Connection
|
40
|
+
include EventMachine::Deferrable
|
41
|
+
|
42
|
+
# @private
|
43
|
+
def initialize
|
44
|
+
super
|
45
|
+
@data = []
|
46
|
+
end
|
47
|
+
|
48
|
+
# Sugars a common use-case involving forked child processes.
|
49
|
+
# #open takes a String argument containing an shell command
|
50
|
+
# string (including arguments if desired). #open immediately
|
51
|
+
# returns an EventMachine::Deferrable object, without blocking.
|
52
|
+
#
|
53
|
+
# It also invokes EventMachine#popen to run the passed-in
|
54
|
+
# command in a forked child process.
|
55
|
+
#
|
56
|
+
# When the forked child terminates, the Deferrable that
|
57
|
+
# #open calls its callbacks, passing the data returned
|
58
|
+
# from the child process.
|
59
|
+
#
|
60
|
+
def self.open cmd
|
61
|
+
EventMachine.popen( cmd, DeferrableChildProcess )
|
62
|
+
end
|
63
|
+
|
64
|
+
# @private
|
65
|
+
def receive_data data
|
66
|
+
@data << data
|
67
|
+
end
|
68
|
+
|
69
|
+
# @private
|
70
|
+
def unbind
|
71
|
+
succeed( @data.join )
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# @private
|
76
|
+
class SystemCmd < EventMachine::Connection
|
77
|
+
def initialize cb
|
78
|
+
@cb = cb
|
79
|
+
@output = []
|
80
|
+
end
|
81
|
+
def receive_data data
|
82
|
+
@output << data
|
83
|
+
end
|
84
|
+
def unbind
|
85
|
+
@cb.call @output.join(''), get_status if @cb
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# EM::system is a simple wrapper for EM::popen. It is similar to Kernel::system, but requires a
|
90
|
+
# single string argument for the command and performs no shell expansion.
|
91
|
+
#
|
92
|
+
# The block or proc passed to EM::system is called with two arguments: the output generated by the command,
|
93
|
+
# and a Process::Status that contains information about the command's execution.
|
94
|
+
#
|
95
|
+
# EM.run{
|
96
|
+
# EM.system('ls'){ |output,status| puts output if status.exitstatus == 0 }
|
97
|
+
# }
|
98
|
+
#
|
99
|
+
# You can also supply an additional proc to send some data to the process:
|
100
|
+
#
|
101
|
+
# EM.run{
|
102
|
+
# EM.system('sh', proc{ |process|
|
103
|
+
# process.send_data("echo hello\n")
|
104
|
+
# process.send_data("exit\n")
|
105
|
+
# }, proc{ |out,status|
|
106
|
+
# puts(out)
|
107
|
+
# })
|
108
|
+
# }
|
109
|
+
#
|
110
|
+
# Like EventMachine.popen, EventMachine.system currently does not work on windows.
|
111
|
+
# It returns the pid of the spawned process.
|
112
|
+
def EventMachine::system cmd, *args, &cb
|
113
|
+
cb ||= args.pop if args.last.is_a? Proc
|
114
|
+
init = args.pop if args.last.is_a? Proc
|
115
|
+
|
116
|
+
# merge remaining arguments into the command
|
117
|
+
cmd = [cmd, *args] if args.any?
|
118
|
+
|
119
|
+
EM.get_subprocess_pid(EM.popen(cmd, SystemCmd, cb) do |c|
|
120
|
+
init[c] if init
|
121
|
+
end.signature)
|
122
|
+
end
|
123
|
+
end
|
data/lib/em/protocols.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module EventMachine
|
2
|
+
# This module contains various protocol implementations, including:
|
3
|
+
# - HttpClient and HttpClient2
|
4
|
+
# - Stomp
|
5
|
+
# - Memcache
|
6
|
+
# - SmtpClient and SmtpServer
|
7
|
+
# - SASLauth and SASLauthclient
|
8
|
+
# - LineProtocol, LineAndTextProtocol and LineText2
|
9
|
+
# - HeaderAndContentProtocol
|
10
|
+
# - Postgres3
|
11
|
+
# - ObjectProtocol
|
12
|
+
#
|
13
|
+
# The protocol implementations live in separate files in the protocols/ subdirectory,
|
14
|
+
# but are auto-loaded when they are first referenced in your application.
|
15
|
+
#
|
16
|
+
# EventMachine::Protocols is also aliased to EM::P for easier usage.
|
17
|
+
#
|
18
|
+
module Protocols
|
19
|
+
# TODO : various autotools are completely useless with the lack of naming
|
20
|
+
# convention, we need to correct that!
|
21
|
+
autoload :TcpConnectTester, 'em/protocols/tcptest'
|
22
|
+
autoload :HttpClient, 'em/protocols/httpclient'
|
23
|
+
autoload :HttpClient2, 'em/protocols/httpclient2'
|
24
|
+
autoload :LineAndTextProtocol, 'em/protocols/line_and_text'
|
25
|
+
autoload :HeaderAndContentProtocol, 'em/protocols/header_and_content'
|
26
|
+
autoload :LineText2, 'em/protocols/linetext2'
|
27
|
+
autoload :Stomp, 'em/protocols/stomp'
|
28
|
+
autoload :SmtpClient, 'em/protocols/smtpclient'
|
29
|
+
autoload :SmtpServer, 'em/protocols/smtpserver'
|
30
|
+
autoload :SASLauth, 'em/protocols/saslauth'
|
31
|
+
autoload :Memcache, 'em/protocols/memcache'
|
32
|
+
autoload :Postgres3, 'em/protocols/postgres3'
|
33
|
+
autoload :ObjectProtocol, 'em/protocols/object_protocol'
|
34
|
+
autoload :Socks4, 'em/protocols/socks4'
|
35
|
+
autoload :LineProtocol, 'em/protocols/line_protocol'
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +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
|