eventmachine 0.3.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.
Files changed (72) hide show
  1. data/COPYING +281 -0
  2. data/README +69 -0
  3. data/RELEASE_NOTES +18 -0
  4. data/doc/classes/Echo.html +180 -0
  5. data/doc/classes/Echo.src/M000033.html +23 -0
  6. data/doc/classes/Echo.src/M000034.html +19 -0
  7. data/doc/classes/Echo.src/M000035.html +19 -0
  8. data/doc/classes/Echo.src/M000036.html +18 -0
  9. data/doc/classes/EventMachine.html +369 -0
  10. data/doc/classes/EventMachine.src/M000002.html +24 -0
  11. data/doc/classes/EventMachine.src/M000003.html +24 -0
  12. data/doc/classes/EventMachine.src/M000004.html +26 -0
  13. data/doc/classes/EventMachine.src/M000005.html +21 -0
  14. data/doc/classes/EventMachine.src/M000006.html +23 -0
  15. data/doc/classes/EventMachine.src/M000007.html +28 -0
  16. data/doc/classes/EventMachine.src/M000008.html +20 -0
  17. data/doc/classes/EventMachine.src/M000009.html +19 -0
  18. data/doc/classes/EventMachine.src/M000010.html +18 -0
  19. data/doc/classes/EventMachine.src/M000011.html +18 -0
  20. data/doc/classes/EventMachine/Connection.html +341 -0
  21. data/doc/classes/EventMachine/Connection.src/M000020.html +19 -0
  22. data/doc/classes/EventMachine/Connection.src/M000021.html +17 -0
  23. data/doc/classes/EventMachine/Connection.src/M000022.html +18 -0
  24. data/doc/classes/EventMachine/Connection.src/M000023.html +17 -0
  25. data/doc/classes/EventMachine/Connection.src/M000024.html +18 -0
  26. data/doc/classes/EventMachine/Connection.src/M000025.html +18 -0
  27. data/doc/classes/EventMachine/Connection.src/M000026.html +18 -0
  28. data/doc/classes/EventMachine/Connection.src/M000027.html +18 -0
  29. data/doc/classes/EventMachine/Connection.src/M000028.html +17 -0
  30. data/doc/classes/EventMachine/Connection.src/M000029.html +18 -0
  31. data/doc/classes/EventMachine/Connection.src/M000030.html +18 -0
  32. data/doc/classes/EventMachine/Connection.src/M000031.html +18 -0
  33. data/doc/classes/EventMachine/Connection.src/M000032.html +18 -0
  34. data/doc/classes/EventMachine/ConnectionAlreadyBound.html +111 -0
  35. data/doc/classes/EventMachine/ConnectionNotBound.html +111 -0
  36. data/doc/classes/EventMachine/Connections.html +292 -0
  37. data/doc/classes/EventMachine/Connections.src/M000012.html +20 -0
  38. data/doc/classes/EventMachine/Connections.src/M000013.html +23 -0
  39. data/doc/classes/EventMachine/Connections.src/M000014.html +23 -0
  40. data/doc/classes/EventMachine/Connections.src/M000015.html +24 -0
  41. data/doc/classes/EventMachine/Connections.src/M000016.html +19 -0
  42. data/doc/classes/EventMachine/Connections.src/M000017.html +21 -0
  43. data/doc/classes/EventMachine/Connections.src/M000018.html +19 -0
  44. data/doc/classes/EventMachine/Connections.src/M000019.html +20 -0
  45. data/doc/classes/EventMachine/EventCodes.html +133 -0
  46. data/doc/classes/EventMachine/NoConnectionMade.html +111 -0
  47. data/doc/classes/EventMachine/NoHandlerForAcceptedConnection.html +111 -0
  48. data/doc/classes/EventMachine/NoServerCreated.html +111 -0
  49. data/doc/classes/EventMachine/TimerNotInstalled.html +111 -0
  50. data/doc/classes/EventMachine/TooManyAcceptors.html +111 -0
  51. data/doc/classes/EventMachine/TooManyTimersPending.html +111 -0
  52. data/doc/classes/EventMachine/UnknownTimerFired.html +111 -0
  53. data/doc/classes/Zzz.html +131 -0
  54. data/doc/classes/Zzz.src/M000001.html +18 -0
  55. data/doc/created.rid +1 -0
  56. data/doc/files/binder_cpp.html +101 -0
  57. data/doc/files/ed_cpp.html +101 -0
  58. data/doc/files/em_cpp.html +101 -0
  59. data/doc/files/event_machine_rb.html +118 -0
  60. data/doc/files/g_rb.html +108 -0
  61. data/doc/files/lib/eventmachine_rb.html +114 -0
  62. data/doc/files/libmain_cpp.html +101 -0
  63. data/doc/files/sigs_cpp.html +101 -0
  64. data/doc/files/tests/testem_rb.html +110 -0
  65. data/doc/fr_class_index.html +41 -0
  66. data/doc/fr_file_index.html +35 -0
  67. data/doc/fr_method_index.html +62 -0
  68. data/doc/index.html +24 -0
  69. data/ext/libeventmachine.so +0 -0
  70. data/lib/eventmachine.rb +631 -0
  71. data/tests/testem.rb +5 -0
  72. metadata +121 -0
@@ -0,0 +1,41 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Classes
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Classes</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Classes</h1>
22
+ <div id="index-entries">
23
+ <a href="classes/Echo.html">Echo</a><br />
24
+ <a href="classes/EventMachine.html">EventMachine</a><br />
25
+ <a href="classes/EventMachine/Connection.html">EventMachine::Connection</a><br />
26
+ <a href="classes/EventMachine/ConnectionAlreadyBound.html">EventMachine::ConnectionAlreadyBound</a><br />
27
+ <a href="classes/EventMachine/ConnectionNotBound.html">EventMachine::ConnectionNotBound</a><br />
28
+ <a href="classes/EventMachine/Connections.html">EventMachine::Connections</a><br />
29
+ <a href="classes/EventMachine/EventCodes.html">EventMachine::EventCodes</a><br />
30
+ <a href="classes/EventMachine/NoConnectionMade.html">EventMachine::NoConnectionMade</a><br />
31
+ <a href="classes/EventMachine/NoHandlerForAcceptedConnection.html">EventMachine::NoHandlerForAcceptedConnection</a><br />
32
+ <a href="classes/EventMachine/NoServerCreated.html">EventMachine::NoServerCreated</a><br />
33
+ <a href="classes/EventMachine/TimerNotInstalled.html">EventMachine::TimerNotInstalled</a><br />
34
+ <a href="classes/EventMachine/TooManyAcceptors.html">EventMachine::TooManyAcceptors</a><br />
35
+ <a href="classes/EventMachine/TooManyTimersPending.html">EventMachine::TooManyTimersPending</a><br />
36
+ <a href="classes/EventMachine/UnknownTimerFired.html">EventMachine::UnknownTimerFired</a><br />
37
+ <a href="classes/Zzz.html">Zzz</a><br />
38
+ </div>
39
+ </div>
40
+ </body>
41
+ </html>
@@ -0,0 +1,35 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Files
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Files</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Files</h1>
22
+ <div id="index-entries">
23
+ <a href="files/binder_cpp.html">binder.cpp</a><br />
24
+ <a href="files/ed_cpp.html">ed.cpp</a><br />
25
+ <a href="files/em_cpp.html">em.cpp</a><br />
26
+ <a href="files/event_machine_rb.html">event_machine.rb</a><br />
27
+ <a href="files/g_rb.html">g.rb</a><br />
28
+ <a href="files/lib/eventmachine_rb.html">lib/eventmachine.rb</a><br />
29
+ <a href="files/libmain_cpp.html">libmain.cpp</a><br />
30
+ <a href="files/sigs_cpp.html">sigs.cpp</a><br />
31
+ <a href="files/tests/testem_rb.html">tests/testem.rb</a><br />
32
+ </div>
33
+ </div>
34
+ </body>
35
+ </html>
@@ -0,0 +1,62 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Methods
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Methods</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Methods</h1>
22
+ <div id="index-entries">
23
+ <a href="classes/EventMachine/Connections.html#M000019">accept_connection (EventMachine::Connections)</a><br />
24
+ <a href="classes/EventMachine.html#M000004">add_periodic_timer (EventMachine)</a><br />
25
+ <a href="classes/EventMachine/Connections.html#M000017">add_timer (EventMachine::Connections)</a><br />
26
+ <a href="classes/EventMachine.html#M000003">add_timer (EventMachine)</a><br />
27
+ <a href="classes/EventMachine.html#M000008">add_timer (EventMachine)</a><br />
28
+ <a href="classes/EventMachine/Connection.html#M000031">close_connection (EventMachine::Connection)</a><br />
29
+ <a href="classes/EventMachine/Connection.html#M000024">close_connection (EventMachine::Connection)</a><br />
30
+ <a href="classes/EventMachine/Connection.html#M000032">close_connection_after_writing (EventMachine::Connection)</a><br />
31
+ <a href="classes/EventMachine/Connection.html#M000025">close_connection_after_writing (EventMachine::Connection)</a><br />
32
+ <a href="classes/EventMachine/Connections.html#M000013">connect (EventMachine::Connections)</a><br />
33
+ <a href="classes/EventMachine.html#M000006">connect (EventMachine)</a><br />
34
+ <a href="classes/EventMachine.html#M000010">connect (EventMachine)</a><br />
35
+ <a href="classes/EventMachine.html#M000007">connection_callback (EventMachine)</a><br />
36
+ <a href="classes/EventMachine/Connection.html#M000027">new (EventMachine::Connection)</a><br />
37
+ <a href="classes/EventMachine/Connections.html#M000012">new (EventMachine::Connections)</a><br />
38
+ <a href="classes/EventMachine/Connection.html#M000020">new (EventMachine::Connection)</a><br />
39
+ <a href="classes/Echo.html#M000034">post_init (Echo)</a><br />
40
+ <a href="classes/EventMachine/Connection.html#M000021">post_init (EventMachine::Connection)</a><br />
41
+ <a href="classes/Zzz.html#M000001">receive_data (Zzz)</a><br />
42
+ <a href="classes/Echo.html#M000033">receive_data (Echo)</a><br />
43
+ <a href="classes/EventMachine/Connections.html#M000016">receive_data (EventMachine::Connections)</a><br />
44
+ <a href="classes/EventMachine/Connection.html#M000022">receive_data (EventMachine::Connection)</a><br />
45
+ <a href="classes/EventMachine/Connection.html#M000030">receive_data (EventMachine::Connection)</a><br />
46
+ <a href="classes/Echo.html#M000035">receive_data (Echo)</a><br />
47
+ <a href="classes/EventMachine.html#M000009">run (EventMachine)</a><br />
48
+ <a href="classes/EventMachine.html#M000002">run (EventMachine)</a><br />
49
+ <a href="classes/EventMachine/Connections.html#M000018">run_timer (EventMachine::Connections)</a><br />
50
+ <a href="classes/EventMachine/Connection.html#M000029">send_data (EventMachine::Connection)</a><br />
51
+ <a href="classes/EventMachine/Connection.html#M000026">send_data (EventMachine::Connection)</a><br />
52
+ <a href="classes/EventMachine.html#M000011">start_server (EventMachine)</a><br />
53
+ <a href="classes/EventMachine/Connections.html#M000014">start_server (EventMachine::Connections)</a><br />
54
+ <a href="classes/EventMachine.html#M000005">start_server (EventMachine)</a><br />
55
+ <a href="classes/EventMachine/Connection.html#M000028">unbind (EventMachine::Connection)</a><br />
56
+ <a href="classes/Echo.html#M000036">unbind (Echo)</a><br />
57
+ <a href="classes/EventMachine/Connection.html#M000023">unbind (EventMachine::Connection)</a><br />
58
+ <a href="classes/EventMachine/Connections.html#M000015">unbind_connection (EventMachine::Connections)</a><br />
59
+ </div>
60
+ </div>
61
+ </body>
62
+ </html>
data/doc/index.html ADDED
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
5
+
6
+ <!--
7
+
8
+ RDoc Documentation
9
+
10
+ -->
11
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
12
+ <head>
13
+ <title>RDoc Documentation</title>
14
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
15
+ </head>
16
+ <frameset rows="20%, 80%">
17
+ <frameset cols="25%,35%,45%">
18
+ <frame src="fr_file_index.html" title="Files" name="Files" />
19
+ <frame src="fr_class_index.html" name="Classes" />
20
+ <frame src="fr_method_index.html" name="Methods" />
21
+ </frameset>
22
+ <frame src="files/binder_cpp.html" name="docwin" />
23
+ </frameset>
24
+ </html>
Binary file
@@ -0,0 +1,631 @@
1
+ # $Id: eventmachine.rb 2281 2006-04-13 05:09:13Z francis $
2
+ #
3
+ # Author:: blackhedd (gmail address: garbagecat20).
4
+ # Date:: 8 Apr 2006
5
+ #
6
+ # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
7
+ #
8
+ # This program is made available under the terms of the GPL version 2.
9
+ #
10
+ # See EventMachine and EventMachine::Connection for documentation and
11
+ # usage examples.
12
+ #
13
+
14
+ require 'libeventmachine'
15
+
16
+ # == Introduction
17
+ # EventMachine provides a fast, lightweight framework for implementing
18
+ # Ruby programs that can use the network to communicate with other
19
+ # processes. Using EventMachine, Ruby programmers can easily connect
20
+ # to remote servers and act as servers themselves. EventMachine does not
21
+ # supplant the Ruby IP libraries. It does provide an alternate technique
22
+ # for those applications requiring better performance, scalability,
23
+ # and discipline over the behavior of network sockets, than is easily
24
+ # obtainable using the built-in libraries, especially in applications
25
+ # which are structurally well-suited for the event-driven programming model.
26
+ #
27
+ # EventMachine provides a perpetual event-loop which your programs can
28
+ # start and stop. Within the event loop, TCP network connections are
29
+ # initiated and accepted, based on EventMachine methods called by your
30
+ # program. You also define callback methods which are called by EventMachine
31
+ # when events of interest occur within the event-loop.
32
+ #
33
+ # User programs will be called back when the following events occur:
34
+ # * When the event loop accepts network connections from remote peers
35
+ # * When data is received from network connections
36
+ # * When connections are closed, either by the local or the remote side
37
+ # * When user-defined timers expire
38
+ #
39
+ # == Usage example
40
+ #
41
+ # Here's a fully-functional echo server implemented in EventMachine:
42
+ #
43
+ # require 'rubygems'
44
+ # require_gem 'eventmachine'
45
+ #
46
+ # module EchoServer
47
+ # def receive_data data
48
+ # send_data ">>>you sent: #{data}"
49
+ # close_connection if data =~ /quit/i
50
+ # end
51
+ # end
52
+ #
53
+ # EventMachine::run {
54
+ # EventMachine::start_server "192.168.0.100", 8081, EchoServer
55
+ # }
56
+ #
57
+ # What's going on here? Well, we have defined the module EchoServer to
58
+ # implement the semantics of the echo protocol (more about that shortly).
59
+ # The last three lines invoke the event-machine itself, which runs forever
60
+ # unless one of your callbacks terminates it. The block that you supply
61
+ # to EventMachine::run contains code that runs immediately after the event
62
+ # machine is initialized and before it starts looping. This is the place
63
+ # to open up a TCP server by specifying the address and port it will listen
64
+ # on, together with the module that will process the data.
65
+ #
66
+ # Our EchoServer is extremely simple as the echo protocol doesn't require
67
+ # much work. Basically you want to send back to the remote peer whatever
68
+ # data it sends you. We'll dress it up with a little extra text to make it
69
+ # interesting. Also, we'll close the connection in case the received data
70
+ # contains the word "quit."
71
+ #
72
+ # So what about this module EchoServer? Well, whenever a network connection
73
+ # (either a client or a server) starts up, EventMachine instantiates an anonymous
74
+ # class, that your module has been mixed into. Exactly one of these class
75
+ # instances is created for each connection. Whenever an event occurs on a
76
+ # given connection, its corresponding object automatically calls specific
77
+ # instance methods which your module may redefine. The code in your module
78
+ # always runs in the context of a class instance, so you can create instance
79
+ # variables as you wish and they will be carried over to other callbacks
80
+ # made on that same connection.
81
+ #
82
+ # Looking back up at EchoServer, you can see that we've defined the method
83
+ # receive_data which (big surprise) is called whenever data has been received
84
+ # from the remote end of the connection. Very simple. We get the data
85
+ # (a String object) and can do whatever we wish with it. In this case,
86
+ # we use the method send_data to return the received data to the caller,
87
+ # with some extra text added in. And if the user sends the word "quit,"
88
+ # we'll close the connection with (naturally) close_connection.
89
+ # (Notice that closing the connection doesn't terminate the processing loop,
90
+ # or change the fact that your echo server is still accepting connections!)
91
+ #
92
+ #
93
+ # == Questions and Futures
94
+ # Encryption: EventMachine needs the capability to run SSL/TLS on any
95
+ # of its clients and servers. Coming soon.
96
+ #
97
+ # <tt>epoll(4):</tt> EventMachine currently is based on the <tt>select(2)</tt>
98
+ # system call in order to be compatible with the widest variety of platforms,
99
+ # but it would be interesting to re-base it on <tt>epoll(4).</tt>
100
+ # While requiring a Linux 2.6 kernel, this might possibly give much better
101
+ # performance and scalability. EventMachine's C++ antecedents already work
102
+ # with <tt>kqueue</tt> from the BSD world, but it's not yet clear that this
103
+ # is worth doing. Depends on how many people ask for it.
104
+ #
105
+ # Would it be useful for EventMachine to incorporate the Observer pattern
106
+ # and make use of the corresponding Ruby <tt>observer</tt> package?
107
+ # Interesting thought.
108
+ #
109
+ #
110
+ module EventMachine
111
+
112
+
113
+ # EventMachine::run initializes and runs an event loop.
114
+ # This method only returns if user-callback code calls stop_event_loop.
115
+ # Use the supplied block to define your clients and servers.
116
+ # The block is called by EventMachine::run immediately after initializing
117
+ # its internal event loop but <i>before</i> running the loop.
118
+ # Therefore this block is the right place to call start_server if you
119
+ # want to accept connections from remote clients.
120
+ #
121
+ # For programs that are structured as servers, it's usually appropriate
122
+ # to start an event loop by calling EventMachine::run, and let it
123
+ # run forever. It's also possible to use EventMachine::run to make a single
124
+ # client-connection to a remote server, process the data flow from that
125
+ # single connection, and then call stop_event_loop to force EventMachine::run
126
+ # to return. Your program will then continue from the point immediately
127
+ # following the call to EventMachine::run.
128
+ #
129
+ # You can of course do both client and servers simultaneously in the same program.
130
+ # One of the strengths of the event-driven programming model is that the
131
+ # handling of network events on many different connections will be interleaved,
132
+ # and scheduled according to the actual events themselves. This maximizes
133
+ # efficiency.
134
+ #
135
+ # === Server usage example
136
+ #
137
+ # See the text at the top of this file for an example of an echo server.
138
+ #
139
+ # === Client usage example
140
+ #
141
+ # See the description of stop_event_loop for an extremely simple client example.
142
+ #
143
+
144
+ def EventMachine::run &block
145
+ @conns = {}
146
+ @acceptors = {}
147
+ @timers = {}
148
+ initialize_event_machine
149
+ block and add_timer 0, block
150
+ run_machine
151
+ release_machine
152
+ end
153
+
154
+ # EventMachine#add_timer adds a one-shot timer to the event loop.
155
+ # Call it with one or two parameters. The first parameters is a delay-time
156
+ # expressed in <i>seconds</i> (not milliseconds). The second parameter, if
157
+ # present, must be a proc object. If a proc object is not given, then you
158
+ # can also simply pass a block to the method call.
159
+ #
160
+ # EventMachine#add_timer may be called from the block passed to EventMachine#run
161
+ # or from any callback method. It schedules execution of the proc or block
162
+ # passed to add_timer, after the passage of an interval of time equal to
163
+ # <i>at least</i> the number of seconds specified in the first parameter to
164
+ # the call.
165
+ #
166
+ # EventMachine#add_timer is a <i>non-blocking</i> call. Callbacks can and will
167
+ # be called during the interval of time that the timer is in effect.
168
+ # There is no built-in limit to the number of timers that can be outstanding at
169
+ # any given time.
170
+ #
171
+ # === Usage example
172
+ #
173
+ # This example shows how easy timers are to use. Observe that two timers are
174
+ # initiated simultaneously. Also, notice that the event loop will continue
175
+ # to run even after the second timer event is processed, since there was
176
+ # no call to EventMachine#stop_event_loop. There will be no activity, of
177
+ # course, since no network clients or servers are defined. Stop the program
178
+ # with Ctrl-C.
179
+ #
180
+ # require 'rubygems'
181
+ # require_gem 'eventmachine'
182
+ #
183
+ # EventMachine::run {
184
+ # puts "Starting the run now: #{Time.now}"
185
+ # EventMachine::add_timer 5, proc { puts "Executing timer event: #{Time.now}" }
186
+ # EventMachine::add_timer( 10 ) { puts "Executing timer event: #{Time.now}" }
187
+ # }
188
+ #
189
+ #
190
+ def EventMachine::add_timer *args, &block
191
+ interval = args.shift
192
+ code = args.shift || block
193
+ if code
194
+ # check too many timers!
195
+ s = add_oneshot_timer interval
196
+ @timers[s] = code
197
+ end
198
+ end
199
+
200
+ # EventMachine#add_periodic_timer adds a periodic timer to the event loop.
201
+ # It takes the same parameters as the one-shot timer method, EventMachine#add_timer.
202
+ # This method schedules execution of the given block repeatedly, at intervals
203
+ # of time <i>at least</i> as great as the number of seconds given in the first
204
+ # parameter to the call.
205
+ #
206
+ # === Usage example
207
+ #
208
+ # The following sample program will write a dollar-sign to stderr every five seconds.
209
+ # (Of course if the program defined network clients and/or servers, they would
210
+ # be doing their work while the periodic timer is counting off.)
211
+ #
212
+ # EventMachine::run {
213
+ # EventMachine::add_periodic_timer( 5 ) { $stderr.write "$" }
214
+ # }
215
+ #
216
+ def EventMachine::add_periodic_timer *args, &block
217
+ interval = args.shift
218
+ code = args.shift || block
219
+ if code
220
+ block_1 = proc {
221
+ code.call
222
+ EventMachine::add_periodic_timer interval, code
223
+ }
224
+ add_timer interval, block_1
225
+ end
226
+ end
227
+
228
+
229
+ # stop_event_loop may called from within a callback method
230
+ # while EventMachine's processing loop is running.
231
+ # It causes the processing loop to stop executing, which
232
+ # will cause all open connections and accepting servers
233
+ # to be run down and closed. <i>Callbacks for connection-termination
234
+ # will be called</i> as part of the processing of stop_event_loop.
235
+ # (There currently is no option to panic-stop the loop without
236
+ # closing connections.) When all of this processing is complete,
237
+ # the call to EventMachine::run which started the processing loop
238
+ # will return and program flow will resume from the statement
239
+ # following EventMachine::run call.
240
+ #
241
+ # === Usage example
242
+ #
243
+ # require 'rubygems'
244
+ # require_gem 'eventmachine'
245
+ #
246
+ # module Redmond
247
+ #
248
+ # def post_init
249
+ # puts "We're sending a dumb HTTP request to the remote peer."
250
+ # send_data "GET / HTTP/1.1\r\nHost: www.microsoft.com\r\n\r\n"
251
+ # end
252
+ #
253
+ # def receive_data data
254
+ # puts "We received #{data.length} bytes from the remote peer."
255
+ # puts "We're going to stop the event loop now."
256
+ # EventMachine::stop_event_loop
257
+ # end
258
+ #
259
+ # def unbind
260
+ # puts "A connection has terminated."
261
+ # end
262
+ #
263
+ # end
264
+ #
265
+ # puts "We're starting the event loop now."
266
+ # EventMachine::run {
267
+ # EventMachine::connect "www.microsoft.com", 80, Redmond
268
+ # }
269
+ # puts "The event loop has stopped."
270
+ #
271
+ # This program will produce approximately the following output:
272
+ #
273
+ # We're starting the event loop now.
274
+ # We're sending a dumb HTTP request to the remote peer.
275
+ # We received 1440 bytes from the remote peer.
276
+ # We're going to stop the event loop now.
277
+ # A connection has terminated.
278
+ # The event loop has stopped.
279
+ #
280
+ #
281
+ def EventMachine::stop_event_loop
282
+ EventMachine::stop
283
+ end
284
+
285
+ # EventMachine::start_server initiates a TCP server (socket
286
+ # acceptor) on the specified IP address and port.
287
+ # The IP address must be valid on the machine where the program
288
+ # runs, and the process must be privileged enough to listen
289
+ # on the specified port (on Unix-like systems, superuser privileges
290
+ # are usually required to listen on any port lower than 1024).
291
+ # Only one listener may be running on any given address/port
292
+ # combination. start_server will fail if the given address and port
293
+ # are already listening on the machine, either because of a prior call
294
+ # to start_server or some unrelated process running on the machine.
295
+ # If start_server succeeds, the new network listener becomes active
296
+ # immediately and starts accepting connections from remote peers,
297
+ # and these connections generate callback events that are processed
298
+ # by the code specified in the handler parameter to start_server.
299
+ #
300
+ # The optional handler which is passed to start_server is the key
301
+ # to EventMachine's ability to handle particular network protocols.
302
+ # The handler parameter passed to start_server must be a Ruby Module
303
+ # that you must define. When the network server that is started by
304
+ # start_server accepts a new connection, it instantiates a new
305
+ # object of an anonymous class that is inherited from EventMachine::Connection,
306
+ # <i>into which the methods from your handler have been mixed.</i>
307
+ # Your handler module may redefine any of the methods in EventMachine::Connection
308
+ # in order to implement the specific behavior of the network protocol.
309
+ #
310
+ # Callbacks invoked in response to network events <i>always</i> take place
311
+ # within the execution context of the object derived from EventMachine::Connection
312
+ # extended by your handler module. There is one object per connection, and
313
+ # all of the callbacks invoked for a particular connection take the form
314
+ # of instance methods called against the corresponding EventMachine::Connection
315
+ # object. Therefore, you are free to define whatever instance variables you
316
+ # wish, in order to contain the per-connection state required by the network protocol you are
317
+ # implementing.
318
+ #
319
+ # start_server is often called inside the block passed to EventMachine::run,
320
+ # but it can be called from any EventMachine callback. start_server will fail
321
+ # unless the EventMachine event loop is currently running (which is why
322
+ # it's often called in the block suppled to EventMachine::run).
323
+ #
324
+ # You may call start_server any number of times to start up network
325
+ # listeners on different address/port combinations. The servers will
326
+ # all run simultaneously. More interestingly, each individual call to start_server
327
+ # can specify a different handler module and thus implement a different
328
+ # network protocol from all the others.
329
+ #
330
+ # === Usage example
331
+ # Here is an example of a server that counts lines of input from the remote
332
+ # peer and sends back the total number of lines received, after each line.
333
+ # Try the example with more than one client connection opened via telnet,
334
+ # and you will see that the line count increments independently on each
335
+ # of the client connections. Also very important to note, is that the
336
+ # handler for the receive_data function, which our handler redefines, may
337
+ # not assume that the data it receives observes any kind of message boundaries.
338
+ # Also, to use this example, be sure to change the server and port parameters
339
+ # to the start_server call to values appropriate for your environment.
340
+ #
341
+ # require 'rubygems'
342
+ # require_gem 'eventmachine'
343
+ #
344
+ # module LineCounter
345
+ #
346
+ # MaxLinesPerConnection = 10
347
+ #
348
+ # def post_init
349
+ # puts "Received a new connection"
350
+ # @data_received = ""
351
+ # @line_count = 0
352
+ # end
353
+ #
354
+ # def receive_data data
355
+ # @data_received << data
356
+ # while @data_received.slice!( /^[^\n]*[\n]/m )
357
+ # @line_count += 1
358
+ # send_data "received #{@line_count} lines so far\r\n"
359
+ # @line_count == MaxLinesPerConnection and close_connection_after_writing
360
+ # end
361
+ # end
362
+ #
363
+ # end # module LineCounter
364
+ #
365
+ # EventMachine::run {
366
+ # host,port = "192.168.0.100", 8090
367
+ # EventMachine::start_server host, port, LineCounter
368
+ # puts "Now accepting connections on address #{host}, port #{port}..."
369
+ # EventMachine::add_periodic_timer( 10 ) { $stderr.write "*" }
370
+ # }
371
+ #
372
+ #
373
+ def EventMachine::start_server server, port, handler=nil
374
+ s = start_tcp_server server, port
375
+ @acceptors[s] = Class.new( Connection ) {
376
+ handler and include handler
377
+ }
378
+ end
379
+
380
+ # EventMachine#connect initiates a TCP connection to a remote
381
+ # server and sets up event-handling for the connection.
382
+ # You can call EventMachine#connect in the block supplied
383
+ # to EventMachine#run or in any callback method.
384
+ #
385
+ # EventMachine#connect takes the IP address (or hostname) and
386
+ # port of the remote server you want to connect to.
387
+ # It also takes an optional handler Module which you must define, that
388
+ # contains the callbacks that will be invoked by the event loop
389
+ # on behalf of the connection.
390
+ #
391
+ # See the description of EventMachine#start_server for a discussion
392
+ # of the handler Module. All of the details given in that description
393
+ # apply for connections created with EventMachine#connect.
394
+ #
395
+ # === Usage Example
396
+ #
397
+ # Here's a program which connects to a web server, sends a naive
398
+ # request, parses the HTTP header of the response, and then
399
+ # (antisocially) ends the event loop, which automatically drops the connection
400
+ # (and incidentally calls the connection's unbind method).
401
+ #
402
+ # require 'rubygems'
403
+ # require_gem 'eventmachine'
404
+ #
405
+ # module DumbHttpClient
406
+ #
407
+ # def post_init
408
+ # send_data "GET / HTTP/1.1\r\nHost: _\r\n\r\n"
409
+ # @data = ""
410
+ # end
411
+ #
412
+ # def receive_data data
413
+ # @data << data
414
+ # if @data =~ /[\n][\r]*[\n]/m
415
+ # puts "RECEIVED HTTP HEADER:"
416
+ # $`.each {|line| puts ">>> #{line}" }
417
+ #
418
+ # puts "Now we'll terminate the loop, which will also close the connection"
419
+ # EventMachine::stop_event_loop
420
+ # end
421
+ # end
422
+ #
423
+ # def unbind
424
+ # puts "A connection has terminated"
425
+ # end
426
+ #
427
+ # end # DumbHttpClient
428
+ #
429
+ #
430
+ # EventMachine::run {
431
+ # EventMachine::connect "www.bayshorenetworks.com", 80, DumbHttpClient
432
+ # }
433
+ # puts "The event loop has ended"
434
+ #
435
+ #--
436
+ # EventMachine::connect initiates a TCP connection to a remote
437
+ # server and sets up event-handling for the connection.
438
+ # It internally creates an object that should not be handled
439
+ # by the caller. HOWEVER, it's often convenient to get the
440
+ # object to set up interfacing to other objects in the system.
441
+ # We return the newly-created anonymous-class object to the caller.
442
+ # It's expected that a considerable amount of code will depend
443
+ # on this behavior, so don't change it.
444
+ #
445
+ def EventMachine::connect server, port, handler=nil
446
+ s = connect_server server, port
447
+ klass = Class.new( Connection ) {
448
+ handler and include handler
449
+ }
450
+ c = klass.new s
451
+ @conns[s] = c
452
+ end
453
+
454
+
455
+ private
456
+ def EventMachine::event_callback conn_binding, opcode, data
457
+ case opcode
458
+ when ConnectionData
459
+ c = @conns[conn_binding] or raise ConnectionNotBound
460
+ c.receive_data data
461
+ when ConnectionUnbound
462
+ if c = @conns.delete( conn_binding )
463
+ c.unbind
464
+ elsif c = @acceptors.delete( conn_binding )
465
+ # no-op
466
+ else
467
+ raise ConnectionNotBound
468
+ end
469
+ when ConnectionAccepted
470
+ accep = @acceptors[conn_binding] or raise NoHandlerForAcceptedConnection
471
+ c = accep.new data
472
+ @conns[data] = c
473
+ when TimerFired
474
+ t = @timers.delete( data ) or raise UnknownTimerFired
475
+ t.call
476
+ end
477
+ end
478
+
479
+
480
+
481
+ # EventMachine::Connection is a class that is instantiated
482
+ # by EventMachine's processing loop whenever a new connection
483
+ # is created. (New connections can be either initiated locally
484
+ # to a remote server or accepted locally from a remote client.)
485
+ # When a Connection object is instantiated, it <i>mixes in</i>
486
+ # the functionality contained in the user-defined module
487
+ # specified in calls to EventMachine#connect or EventMachine#start_server.
488
+ # User-defined handler modules may redefine any or all of the standard
489
+ # methods defined here, as well as add arbitrary additional code
490
+ # that will also be mixed in.
491
+ #
492
+ # EventMachine manages one object inherited from EventMachine::Connection
493
+ # (and containing the mixed-in user code) for every network connection
494
+ # that is active at any given time.
495
+ # The event loop will automatically call methods on EventMachine::Connection
496
+ # objects whenever specific events occur on the corresponding connections,
497
+ # as described below.
498
+ #
499
+ # This class is never instantiated by user code, and does not publish an
500
+ # initialize method. The instance methods of EventMachine::Connection
501
+ # which may be called by the event loop are: post_init, receive_data,
502
+ # and unbind. All of the other instance methods defined here are called
503
+ # only by user code.
504
+ #
505
+ class Connection
506
+
507
+ def initialize sig #:nodoc:
508
+ @signature = sig
509
+ post_init
510
+ end
511
+
512
+ # EventMachine::Connection#post_init is called by the event loop
513
+ # immediately after the network connection has been established,
514
+ # and before resumption of the network loop.
515
+ # This method is generally not called by user code, but is called automatically
516
+ # by the event loop. The base-class implementation is a no-op.
517
+ # This is a very good place to initialize instance variables that will
518
+ # be used throughout the lifetime of the network connection.
519
+ #
520
+ def post_init
521
+ end
522
+
523
+ # EventMachine::Connection#receive_data is called by the event loop
524
+ # whenever data has been received by the network connection.
525
+ # It is never called by user code.
526
+ # receive_data is called with a single parameter, a String containing
527
+ # the network protocol data, which may of course be binary. You will
528
+ # generally redefine this method to perform your own processing of the incoming data.
529
+ #
530
+ # Here's a key point which is essential to understanding the event-driven
531
+ # programming model: <i>EventMachine knows absolutely nothing about the protocol
532
+ # which your code implements.</i> You must not make any assumptions about
533
+ # the size of the incoming data packets, or about their alignment on any
534
+ # particular intra-message or PDU boundaries (such as line breaks).
535
+ # receive_data can and will send you arbitrary chunks of data, with the
536
+ # only guarantee being that the data is presented to your code in the order
537
+ # it was collected from the network. Don't even assume that the chunks of
538
+ # data will correspond to network packets, as EventMachine can and will coalesce
539
+ # several incoming packets into one, to improve performance. The implication for your
540
+ # code is that you generally will need to implement some kind of a state machine
541
+ # in your redefined implementation of receive_data. For a better understanding
542
+ # of this, read through the examples of specific protocol handlers given
543
+ # elsewhere in this package. (STUB, WE MUST ADD THESE!)
544
+ #
545
+ # The base-class implementation of receive_data (which will be invoked if
546
+ # you don't redefine it) simply prints the size of each incoming data packet
547
+ # to stdout.
548
+ #
549
+ def receive_data data
550
+ puts "............>>>#{data.length}"
551
+ end
552
+
553
+ # EventMachine::Connection#unbind is called by the framework whenever a connection
554
+ # (either a server or client connection) is closed. The close can occur because
555
+ # your code intentionally closes it (see close_connection and close_connection_after_writing),
556
+ # because the remote peer closed the connection, or because of a network error.
557
+ # You may not assume that the network connection is still open and able to send or
558
+ # receive data when the callback to unbind is made. This is intended only to give
559
+ # you a chance to clean up associations your code may have made to the connection
560
+ # object while it was open.
561
+ #
562
+ def unbind
563
+ end
564
+
565
+ # EventMachine::Connection#close_connection is called only by user code, and never
566
+ # by the event loop. You may call this method against a connection object in any
567
+ # callback handler, whether or not the callback was made against the connection
568
+ # you want to close. close_connection <i>schedules</i> the connection to be closed
569
+ # at the next available opportunity within the event loop. You may not assume that
570
+ # the connection is closed when close_connection returns. In particular, the framework
571
+ # will callback the unbind method for the particular connection at a point shortly
572
+ # after you call close_connection. You may assume that the unbind callback will
573
+ # take place sometime after your call to close_connection completes. In other words,
574
+ # the unbind callback will not re-enter your code "inside" of your call to close_connection.
575
+ # However, it's not guaranteed that a future version of EventMachine will not change
576
+ # this behavior.
577
+ #
578
+ # close_connection will <i>silently discard</i> any outbound data which you have
579
+ # sent to the connection using EventMachine::Connection#send_data but which has not
580
+ # yet been sent across the network. If you want to avoid this behavior, use
581
+ # EventMachine::Connection#close_connection_after_writing.
582
+ #
583
+ def close_connection after_writing = false
584
+ EventMachine::close_connection @signature, after_writing
585
+ end
586
+
587
+ # EventMachine::Connection#close_connection_after_writing is a variant of close_connection.
588
+ # All of the descriptive comments given for close_connection also apply to
589
+ # close_connection_after_writing, <i>with one exception:</i> If the connection has
590
+ # outbound data sent using send_dat but which has not yet been sent across the network,
591
+ # close_connection_after_writing will schedule the connection to be closed <i>after</i>
592
+ # all of the outbound data has been safely written to the remote peer.
593
+ #
594
+ # Depending on the amount of outgoing data and the speed of the network,
595
+ # considerable time may elapse between your call to close_connection_after_writing
596
+ # and the actual closing of the socket (at which time the unbind callback will be called
597
+ # by the event loop). During this time, you <i>may not</i> call send_data to transmit
598
+ # additional data (that is, the connection is closed for further writes). In very
599
+ # rare cases, you may experience a receive_data callback after your call to close_connection_after_writing,
600
+ # depending on whether incoming data was in the process of being received on the connection
601
+ # at the moment when you called close_connection_after_writing. Your protocol handler must
602
+ # be prepared to properly deal with such data (probably by ignoring it).
603
+ #
604
+ def close_connection_after_writing
605
+ close_connection true
606
+ end
607
+
608
+ # EventMachine::Connection#send_data is only called by user code, never by
609
+ # the event loop. You call this method to send data to the remote end of the
610
+ # network connection. send_data is called with a single String argument, which
611
+ # may of course contain binary data. You can call send_data any number of times.
612
+ # send_data is an instance method of an object derived from EventMachine::Connection
613
+ # and containing your mixed-in handler code), so if you call it without qualification
614
+ # within a callback function, the data will be sent to the same network connection
615
+ # that generated the callback. Calling self.send_data is exactly equivalent.
616
+ #
617
+ # You can also call send_data to write to a connection <i>other than the one
618
+ # whose callback you are calling send_data from.</i> This is done by recording
619
+ # the value of the connection in any callback function (the value self), in any
620
+ # variable visible to other callback invocations on the same or different
621
+ # connection objects. (Need an example to make that clear.)
622
+ #
623
+ def send_data data
624
+ EventMachine::send_data @signature, data, data.length
625
+ end
626
+
627
+ end
628
+
629
+
630
+ end # module EventMachine
631
+