eventmachine 0.12.6 → 0.12.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/{docs/README → README} +21 -13
  2. data/Rakefile +14 -4
  3. data/docs/DEFERRABLES +0 -5
  4. data/docs/INSTALL +2 -4
  5. data/docs/LEGAL +1 -1
  6. data/docs/LIGHTWEIGHT_CONCURRENCY +0 -2
  7. data/docs/PURE_RUBY +0 -2
  8. data/docs/RELEASE_NOTES +0 -2
  9. data/docs/SMTP +0 -7
  10. data/docs/SPAWNED_PROCESSES +0 -4
  11. data/docs/TODO +0 -2
  12. data/eventmachine.gemspec +17 -8
  13. data/examples/ex_channel.rb +43 -0
  14. data/examples/ex_queue.rb +2 -0
  15. data/examples/helper.rb +2 -0
  16. data/ext/cmain.cpp +119 -20
  17. data/ext/cplusplus.cpp +15 -6
  18. data/ext/ed.cpp +303 -93
  19. data/ext/ed.h +49 -22
  20. data/ext/em.cpp +368 -42
  21. data/ext/em.h +43 -6
  22. data/ext/eventmachine.h +21 -8
  23. data/ext/eventmachine_cpp.h +1 -0
  24. data/ext/extconf.rb +4 -0
  25. data/ext/kb.cpp +1 -2
  26. data/ext/pipe.cpp +1 -3
  27. data/ext/project.h +21 -0
  28. data/ext/rubymain.cpp +232 -32
  29. data/ext/ssl.cpp +38 -1
  30. data/ext/ssl.h +5 -1
  31. data/java/src/com/rubyeventmachine/Application.java +7 -3
  32. data/java/src/com/rubyeventmachine/EmReactor.java +16 -1
  33. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +25 -3
  34. data/lib/{protocols → em}/buftok.rb +16 -5
  35. data/lib/em/callback.rb +26 -0
  36. data/lib/em/channel.rb +57 -0
  37. data/lib/em/connection.rb +505 -0
  38. data/lib/em/deferrable.rb +144 -165
  39. data/lib/em/file_watch.rb +54 -0
  40. data/lib/em/future.rb +24 -25
  41. data/lib/em/messages.rb +1 -1
  42. data/lib/em/process_watch.rb +44 -0
  43. data/lib/em/processes.rb +58 -52
  44. data/lib/em/protocols.rb +35 -0
  45. data/lib/em/protocols/header_and_content.rb +138 -0
  46. data/lib/em/protocols/httpclient.rb +263 -0
  47. data/lib/em/protocols/httpclient2.rb +582 -0
  48. data/lib/{protocols → em/protocols}/line_and_text.rb +2 -2
  49. data/lib/em/protocols/linetext2.rb +160 -0
  50. data/lib/{protocols → em/protocols}/memcache.rb +37 -7
  51. data/lib/em/protocols/object_protocol.rb +39 -0
  52. data/lib/em/protocols/postgres3.rb +247 -0
  53. data/lib/em/protocols/saslauth.rb +175 -0
  54. data/lib/em/protocols/smtpclient.rb +331 -0
  55. data/lib/em/protocols/smtpserver.rb +547 -0
  56. data/lib/em/protocols/stomp.rb +200 -0
  57. data/lib/{protocols → em/protocols}/tcptest.rb +21 -25
  58. data/lib/em/queue.rb +61 -0
  59. data/lib/em/spawnable.rb +53 -56
  60. data/lib/em/streamer.rb +92 -74
  61. data/lib/em/timers.rb +55 -0
  62. data/lib/em/version.rb +3 -0
  63. data/lib/eventmachine.rb +1008 -1298
  64. data/lib/evma.rb +1 -1
  65. data/lib/jeventmachine.rb +106 -101
  66. data/lib/pr_eventmachine.rb +47 -36
  67. data/tasks/project.rake +2 -1
  68. data/tests/client.crt +31 -0
  69. data/tests/client.key +51 -0
  70. data/tests/test_attach.rb +18 -0
  71. data/tests/test_basic.rb +108 -54
  72. data/tests/test_channel.rb +63 -0
  73. data/tests/test_connection_count.rb +2 -2
  74. data/tests/test_epoll.rb +109 -110
  75. data/tests/test_errors.rb +36 -36
  76. data/tests/test_exc.rb +22 -25
  77. data/tests/test_file_watch.rb +49 -0
  78. data/tests/test_futures.rb +77 -93
  79. data/tests/test_hc.rb +2 -2
  80. data/tests/test_httpclient.rb +55 -52
  81. data/tests/test_httpclient2.rb +110 -112
  82. data/tests/test_inactivity_timeout.rb +30 -0
  83. data/tests/test_kb.rb +8 -9
  84. data/tests/test_ltp2.rb +274 -277
  85. data/tests/test_next_tick.rb +91 -65
  86. data/tests/test_object_protocol.rb +37 -0
  87. data/tests/test_process_watch.rb +48 -0
  88. data/tests/test_processes.rb +56 -23
  89. data/tests/test_proxy_connection.rb +92 -0
  90. data/tests/test_pure.rb +1 -5
  91. data/tests/test_queue.rb +44 -0
  92. data/tests/test_running.rb +9 -14
  93. data/tests/test_sasl.rb +32 -34
  94. data/tests/test_send_file.rb +175 -176
  95. data/tests/test_servers.rb +37 -41
  96. data/tests/test_smtpserver.rb +47 -55
  97. data/tests/test_spawn.rb +284 -291
  98. data/tests/test_ssl_args.rb +1 -1
  99. data/tests/test_ssl_methods.rb +1 -1
  100. data/tests/test_ssl_verify.rb +82 -0
  101. data/tests/test_timers.rb +81 -88
  102. data/tests/test_ud.rb +0 -7
  103. data/tests/testem.rb +1 -1
  104. metadata +68 -39
  105. data/lib/em/eventable.rb +0 -39
  106. data/lib/eventmachine_version.rb +0 -31
  107. data/lib/protocols/header_and_content.rb +0 -129
  108. data/lib/protocols/httpcli2.rb +0 -803
  109. data/lib/protocols/httpclient.rb +0 -270
  110. data/lib/protocols/linetext2.rb +0 -161
  111. data/lib/protocols/postgres.rb +0 -261
  112. data/lib/protocols/saslauth.rb +0 -179
  113. data/lib/protocols/smtpclient.rb +0 -308
  114. data/lib/protocols/smtpserver.rb +0 -556
  115. data/lib/protocols/stomp.rb +0 -153
  116. data/tests/test_eventables.rb +0 -77
@@ -1,179 +0,0 @@
1
- # $Id$
2
- #
3
- # Author:: Francis Cianfrocca (gmail: blackhedd)
4
- # Homepage:: http://rubyeventmachine.com
5
- # Date:: 15 November 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
-
27
-
28
-
29
- module EventMachine
30
- module Protocols
31
-
32
- # Implements SASL authd.
33
- # This is a very, very simple protocol that mimics the one used
34
- # by saslauthd and pwcheck, two outboard daemons included in the
35
- # standard SASL library distro.
36
- # The only thing this is really suitable for is SASL PLAIN
37
- # (user+password) authentication, but the SASL libs that are
38
- # linked into standard servers (like imapd and sendmail) implement
39
- # the other ones.
40
- #
41
- # SASL-auth is intended for reasonably fast operation inside a
42
- # single machine, so it has no transport-security (although there
43
- # have been multi-machine extensions incorporating transport-layer
44
- # encryption).
45
- #
46
- # The standard saslauthd module generally runs privileged and does
47
- # its work by referring to the system-account files.
48
- #
49
- # This feature was added to EventMachine to enable the development
50
- # of custom authentication/authorization engines for standard servers.
51
- #
52
- # To use SASLauth, include it in a class that subclasses EM::Connection,
53
- # and reimplement the validate method.
54
- #
55
- # The typical way to incorporate this module into an authentication
56
- # daemon would be to set it as the handler for a UNIX-domain socket.
57
- # The code might look like this:
58
- #
59
- # EM.start_unix_domain_server( "/var/run/saslauthd/mux", MyHandler )
60
- # File.chmod( 0777, "/var/run/saslauthd/mux")
61
- #
62
- # The chmod is probably needed to ensure that unprivileged clients can
63
- # access the UNIX-domain socket.
64
- #
65
- # It's also a very good idea to drop superuser privileges (if any), after
66
- # the UNIX-domain socket has been opened.
67
- #--
68
- # Implementation details: assume the client can send us pipelined requests,
69
- # and that the client will close the connection.
70
- #
71
- # The client sends us four values, each encoded as a two-byte length field in
72
- # network order followed by the specified number of octets.
73
- # The fields specify the username, password, service name (such as imap),
74
- # and the "realm" name. We send back the barest minimum reply, a single
75
- # field also encoded as a two-octet length in network order, followed by
76
- # either "NO" or "OK" - simplicity itself.
77
- #
78
- # We enforce a maximum field size just as a sanity check.
79
- # We do NOT automatically time out the connection.
80
- #
81
- # The code we use to parse out the values is ugly and probably slow.
82
- # Improvements welcome.
83
- #
84
- module SASLauth
85
-
86
- MaxFieldSize = 128*1024
87
- def post_init
88
- super
89
- @sasl_data = ""
90
- @sasl_values = []
91
- end
92
-
93
- def receive_data data
94
- @sasl_data << data
95
- while @sasl_data.length >= 2
96
- len = (@sasl_data[0,2].unpack("n")).first
97
- raise "SASL Max Field Length exceeded" if len > MaxFieldSize
98
- if @sasl_data.length >= (len + 2)
99
- @sasl_values << @sasl_data[2,len]
100
- @sasl_data.slice!(0...(2+len))
101
- if @sasl_values.length == 4
102
- send_data( validate(*@sasl_values) ? "\0\002OK" : "\0\002NO" )
103
- @sasl_values.clear
104
- end
105
- else
106
- break
107
- end
108
- end
109
- end
110
-
111
- def validate username, psw, sysname, realm
112
- p username
113
- p psw
114
- p sysname
115
- p realm
116
- true
117
- end
118
- end
119
-
120
- # Implements the SASL authd client protocol.
121
- # This is a very, very simple protocol that mimics the one used
122
- # by saslauthd and pwcheck, two outboard daemons included in the
123
- # standard SASL library distro.
124
- # The only thing this is really suitable for is SASL PLAIN
125
- # (user+password) authentication, but the SASL libs that are
126
- # linked into standard servers (like imapd and sendmail) implement
127
- # the other ones.
128
- #
129
- # You can use this module directly as a handler for EM Connections,
130
- # or include it in a module or handler class of your own.
131
- #
132
- # First connect to a SASL server (it's probably a TCP server, or more
133
- # likely a Unix-domain socket). Then call the #validate? method,
134
- # passing at least a username and a password. #validate? returns
135
- # a Deferrable which will either succeed or fail, depending
136
- # on the status of the authentication operation.
137
- #
138
- module SASLauthclient
139
- MaxFieldSize = 128*1024
140
-
141
- def validate? username, psw, sysname=nil, realm=nil
142
-
143
- str = [username, psw, sysname, realm].map {|m|
144
- [(m || "").length, (m || "")]
145
- }.flatten.pack( "nA*" * 4 )
146
- send_data str
147
-
148
- d = EM::DefaultDeferrable.new
149
- @queries.unshift d
150
- d
151
- end
152
-
153
- def post_init
154
- @sasl_data = ""
155
- @queries = []
156
- end
157
-
158
- def receive_data data
159
- @sasl_data << data
160
-
161
- while @sasl_data.length > 2
162
- len = (@sasl_data[0,2].unpack("n")).first
163
- raise "SASL Max Field Length exceeded" if len > MaxFieldSize
164
- if @sasl_data.length >= (len + 2)
165
- val = @sasl_data[2,len]
166
- @sasl_data.slice!(0...(2+len))
167
- q = @queries.pop
168
- (val == "NO") ? q.fail : q.succeed
169
- else
170
- break
171
- end
172
- end
173
- end
174
- end
175
-
176
- end
177
- end
178
-
179
-
@@ -1,308 +0,0 @@
1
- # $Id$
2
- #
3
- # Author:: Francis Cianfrocca (gmail: blackhedd)
4
- # Homepage:: http://rubyeventmachine.com
5
- # Date:: 16 July 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
-
27
- #require 'base64'
28
- require 'ostruct'
29
-
30
- module EventMachine
31
- module Protocols
32
-
33
-
34
- class SmtpClient < Connection
35
- include EventMachine::Deferrable
36
- include EventMachine::Protocols::LineText2
37
-
38
- # This is the external entry point.
39
- #
40
- # The argument is a hash containing these values:
41
- # :host => a string containing the IP address or host name of the SMTP server to connect to.
42
- # :port => optional, defaults to 25.
43
- # :domain => required String. This is passed as the argument to the EHLO command.
44
- # :starttls => optional. If it evaluates true, then the client will initiate STARTTLS with
45
- # the server, and abort the connection if the negotiation doesn't succeed.
46
- # TODO, need to be able to pass certificate parameters with this option.
47
- # :auth => optional hash of auth parameters. If not given, then no auth will be attempted.
48
- # (In that case, the connection will be aborted if the server requires auth.)
49
- # Specify the hash value :type to determine the auth type, along with additional parameters
50
- # depending on the type.
51
- # Currently only :type => :plain is supported. Pass additional parameters :username (String),
52
- # and :password (either a String or a Proc that will be called at auth-time).
53
- # Example: :auth => {:type=>:plain, :username=>"mickey@disney.com", :password=>"mouse"}
54
- # :from => required String. Specifies the sender of the message. Will be passed as the argument
55
- # to the MAIL FROM. Do NOT enclose the argument in angle-bracket (<>) characters.
56
- # The connection will abort if the server rejects the value.
57
- # :to => required String or Array of Strings. The recipient(s) of the message. Do NOT enclose
58
- # any of the values in angle-brackets (<>) characters. It's NOT a fatal error if one or more
59
- # recipients are rejected by the server. (Of course, if ALL of them are, the server will most
60
- # likely trigger an error when we try to send data.) An array of codes containing the status
61
- # of each requested recipient is available after the call completes. TODO, we should define
62
- # an overridable stub that will be called on rejection of a recipient or a sender, giving
63
- # user code the chance to try again or abort the connection.
64
- # :header => Required hash of values to be transmitted in the header of the message. The hash
65
- # keys are the names of the headers (do NOT append a trailing colon), and the values are strings
66
- # containing the header values. TODO, support Arrays of header values, which would cause us to
67
- # send that specific header line more than once.
68
- # Example: :header => {"Subject" => "Bogus", "CC" => "myboss@example.com"}
69
- # :body => Optional string, defaults blank. This will be passed as the body of the email message.
70
- # TODO, this needs to be significantly beefed up. As currently written, this requires the caller
71
- # to properly format the input into CRLF-delimited lines of 7-bit characters in the standard
72
- # SMTP transmission format. We need to be able to automatically convert binary data, and add
73
- # correct line-breaks to text data. I think the :body parameter should remain as it is, and we
74
- # should add a :content parameter that contains autoconversions and/or conversion parameters.
75
- # Then we can check if either :body or :content is present and do the right thing.
76
- # :verbose => Optional. If true, will cause a lot of information (including the server-side of the
77
- # conversation) to be dumped to $>.
78
- #
79
- def self.send args={}
80
- args[:port] ||= 25
81
- args[:body] ||= ""
82
-
83
- =begin
84
- (I don't think it's possible for EM#connect to throw an exception under normal
85
- circumstances, so this original code is stubbed out. A connect-failure will result
86
- in the #unbind method being called without calling #connection_completed.)
87
- begin
88
- EventMachine.connect( args[:host], args[:port], self) {|c|
89
- # According to the EM docs, we will get here AFTER post_init is called.
90
- c.args = args
91
- c.set_comm_inactivity_timeout 60
92
- }
93
- rescue
94
- # We'll get here on a connect error. This code mimics the effect
95
- # of a call to invoke_internal_error. Would be great to DRY this up.
96
- # (Actually, it may be that we never get here, if EM#connect catches
97
- # its errors internally.)
98
- d = EM::DefaultDeferrable.new
99
- d.set_deferred_status(:failed, {:error=>[:connect, 500, "unable to connect to server"]})
100
- d
101
- end
102
- =end
103
- EventMachine.connect( args[:host], args[:port], self) {|c|
104
- # According to the EM docs, we will get here AFTER post_init is called.
105
- c.args = args
106
- c.set_comm_inactivity_timeout 60
107
- }
108
-
109
- end
110
-
111
- attr_writer :args
112
-
113
- def post_init
114
- @return_values = OpenStruct.new
115
- @return_values.start_time = Time.now
116
- end
117
-
118
- def connection_completed
119
- @responder = :receive_signon
120
- @msg = []
121
- end
122
-
123
- # We can get here in a variety of ways, all of them being failures unless
124
- # the @succeeded flag is set. If a protocol success was recorded, then don't
125
- # set a deferred success because the caller will already have done it
126
- # (no need to wait until the connection closes to invoke the callbacks).
127
- #
128
- def unbind
129
- unless @succeeded
130
- @return_values.elapsed_time = Time.now - @return_values.start_time
131
- @return_values.responder = @responder
132
- @return_values.code = @code
133
- @return_values.message = @msg
134
- set_deferred_status(:failed, @return_values)
135
- end
136
- end
137
-
138
- def receive_line ln
139
- $>.puts ln if @args[:verbose]
140
- @range = ln[0...1].to_i
141
- @code = ln[0...3].to_i
142
- @msg << ln[4..-1]
143
- unless ln[3...4] == '-'
144
- $>.puts @responder if @args[:verbose]
145
- send @responder
146
- @msg.clear
147
- end
148
- end
149
-
150
- # We encountered an error from the server and will close the connection.
151
- # Use the error and message the server returned.
152
- #
153
- def invoke_error
154
- @return_values.elapsed_time = Time.now - @return_values.start_time
155
- @return_values.responder = @responder
156
- @return_values.code = @code
157
- @return_values.message = @msg
158
- set_deferred_status :failed, @return_values
159
- send_data "QUIT\r\n"
160
- close_connection_after_writing
161
- end
162
-
163
- # We encountered an error on our side of the protocol and will close the connection.
164
- # Use an extra-protocol error code (900) and use the message from the caller.
165
- #
166
- def invoke_internal_error msg = "???"
167
- @return_values.elapsed_time = Time.now - @return_values.start_time
168
- @return_values.responder = @responder
169
- @return_values.code = 900
170
- @return_values.message = msg
171
- set_deferred_status :failed, @return_values
172
- send_data "QUIT\r\n"
173
- close_connection_after_writing
174
- end
175
-
176
- def receive_signon
177
- return invoke_error unless @range == 2
178
- send_data "EHLO #{@args[:domain]}\r\n"
179
- @responder = :receive_ehlo_response
180
- end
181
-
182
- def receive_ehlo_response
183
- return invoke_error unless @range == 2
184
- @server_caps = @msg
185
- invoke_starttls
186
- end
187
-
188
- def invoke_starttls
189
- if @args[:starttls]
190
- # It would be more sociable to first ask if @server_caps contains
191
- # the string "STARTTLS" before we invoke it, but hey, life's too short.
192
- send_data "STARTTLS\r\n"
193
- @responder = :receive_starttls_response
194
- else
195
- invoke_auth
196
- end
197
- end
198
- def receive_starttls_response
199
- return invoke_error unless @range == 2
200
- start_tls
201
- invoke_auth
202
- end
203
-
204
-
205
-
206
- # Perform an authentication. If the caller didn't request one, then fall through
207
- # to the mail-from state.
208
- def invoke_auth
209
- if @args[:auth]
210
- if @args[:auth][:type] == :plain
211
- psw = @args[:auth][:password]
212
- if psw.respond_to?(:call)
213
- psw = psw.call
214
- end
215
- #str = Base64::encode64("\0#{@args[:auth][:username]}\0#{psw}").chomp
216
- str = ["\0#{@args[:auth][:username]}\0#{psw}"].pack("m").chomp
217
- send_data "AUTH PLAIN #{str}\r\n"
218
- @responder = :receive_auth_response
219
- else
220
- return invoke_internal_error("unsupported auth type")
221
- end
222
- else
223
- invoke_mail_from
224
- end
225
- end
226
- def receive_auth_response
227
- return invoke_error unless @range == 2
228
- invoke_mail_from
229
- end
230
-
231
- def invoke_mail_from
232
- send_data "MAIL FROM: <#{@args[:from]}>\r\n"
233
- @responder = :receive_mail_from_response
234
- end
235
- def receive_mail_from_response
236
- return invoke_error unless @range == 2
237
- invoke_rcpt_to
238
- end
239
-
240
- def invoke_rcpt_to
241
- @rcpt_responses ||= []
242
- l = @rcpt_responses.length
243
- to = @args[:to].is_a?(Array) ? @args[:to] : [@args[:to].to_s]
244
- if l < to.length
245
- send_data "RCPT TO: <#{to[l]}>\r\n"
246
- @responder = :receive_rcpt_to_response
247
- else
248
- e = @rcpt_responses.select {|rr| rr.last == 2}
249
- if e and e.length > 0
250
- invoke_data
251
- else
252
- invoke_error
253
- end
254
- end
255
- end
256
- def receive_rcpt_to_response
257
- @rcpt_responses << [@code, @msg, @range]
258
- invoke_rcpt_to
259
- end
260
-
261
- def invoke_data
262
- send_data "DATA\r\n"
263
- @responder = :receive_data_response
264
- end
265
- def receive_data_response
266
- return invoke_error unless @range == 3
267
-
268
- # The data to send can be given either in @args[:content] (an array or string of raw data
269
- # which MUST be in correct SMTP body format, including a trailing dot line), or a header and
270
- # body given in @args[:header] and @args[:body].
271
- #
272
- if @args[:content]
273
- send_data @args[:content].to_s
274
- else
275
- # The header can be a hash or an array.
276
- if @args[:header].is_a?(Hash)
277
- (@args[:header] || {}).each {|k,v| send_data "#{k}: #{v}\r\n" }
278
- else
279
- send_data @args[:header].to_s
280
- end
281
- send_data "\r\n"
282
-
283
- if @args[:body].is_a?(Array)
284
- @args[:body].each {|e| send_data e}
285
- else
286
- send_data @args[:body].to_s
287
- end
288
-
289
- send_data "\r\n.\r\n"
290
- end
291
-
292
- @responder = :receive_message_response
293
- end
294
- def receive_message_response
295
- return invoke_error unless @range == 2
296
- send_data "QUIT\r\n"
297
- close_connection_after_writing
298
- @succeeded = true
299
- @return_values.elapsed_time = Time.now - @return_values.start_time
300
- @return_values.responder = @responder
301
- @return_values.code = @code
302
- @return_values.message = @msg
303
- set_deferred_status :succeeded, @return_values
304
- end
305
- end
306
- end
307
- end
308
-