eventmachine 1.0.9.1-java → 1.2.0.1-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/README.md +2 -2
- data/ext/cmain.cpp +77 -5
- data/ext/ed.cpp +112 -42
- data/ext/ed.h +27 -13
- data/ext/em.cpp +105 -163
- data/ext/em.h +10 -7
- data/ext/eventmachine.h +13 -1
- data/ext/extconf.rb +23 -14
- data/ext/fastfilereader/extconf.rb +1 -2
- data/ext/fastfilereader/rubymain.cpp +6 -6
- data/ext/project.h +9 -4
- data/ext/rubymain.cpp +155 -36
- data/ext/ssl.cpp +157 -13
- data/ext/ssl.h +7 -2
- data/lib/em/channel.rb +5 -0
- data/lib/em/completion.rb +2 -2
- data/lib/em/connection.rb +61 -3
- data/lib/em/iterator.rb +26 -5
- data/lib/em/pool.rb +1 -1
- data/lib/em/protocols/line_and_text.rb +1 -1
- data/lib/em/pure_ruby.rb +6 -1
- data/lib/em/queue.rb +16 -7
- data/lib/em/resolver.rb +46 -23
- data/lib/em/threaded_resource.rb +2 -2
- data/lib/em/version.rb +1 -1
- data/lib/eventmachine.rb +59 -42
- data/lib/rubyeventmachine.jar +0 -0
- data/rakelib/package.rake +23 -1
- data/tests/dhparam.pem +13 -0
- data/tests/em_test_helper.rb +79 -0
- data/tests/test_basic.rb +17 -26
- data/tests/test_channel.rb +14 -1
- data/tests/test_connection_write.rb +2 -2
- data/tests/test_defer.rb +17 -0
- data/tests/test_epoll.rb +1 -1
- data/tests/test_fork.rb +75 -0
- data/tests/test_ipv4.rb +125 -0
- data/tests/test_ipv6.rb +131 -0
- data/tests/test_iterator.rb +18 -0
- data/tests/test_many_fds.rb +1 -1
- data/tests/test_queue.rb +14 -0
- data/tests/test_resolver.rb +23 -0
- data/tests/test_set_sock_opt.rb +2 -0
- data/tests/test_ssl_dhparam.rb +83 -0
- data/tests/test_ssl_ecdh_curve.rb +79 -0
- data/tests/test_ssl_extensions.rb +49 -0
- data/tests/test_ssl_methods.rb +19 -0
- data/tests/test_ssl_protocols.rb +246 -0
- data/tests/test_ssl_verify.rb +44 -0
- data/tests/test_system.rb +4 -0
- data/tests/test_unbind_reason.rb +5 -1
- metadata +101 -20
- data/.gitignore +0 -21
- data/.travis.yml +0 -22
- data/.yardopts +0 -7
- data/Gemfile +0 -2
- data/Rakefile +0 -20
- data/eventmachine.gemspec +0 -38
- data/rakelib/cpp.rake_example +0 -77
data/ext/ssl.cpp
CHANGED
@@ -120,7 +120,8 @@ static void InitializeDefaultCredentials()
|
|
120
120
|
SslContext_t::SslContext_t
|
121
121
|
**************************/
|
122
122
|
|
123
|
-
SslContext_t::SslContext_t (bool is_server, const string &privkeyfile, const string &certchainfile):
|
123
|
+
SslContext_t::SslContext_t (bool is_server, const string &privkeyfile, const string &certchainfile, const string &cipherlist, const string &ecdh_curve, const string &dhparam, int ssl_version) :
|
124
|
+
bIsServer (is_server),
|
124
125
|
pCtx (NULL),
|
125
126
|
PrivateKey (NULL),
|
126
127
|
Certificate (NULL)
|
@@ -144,18 +145,47 @@ SslContext_t::SslContext_t (bool is_server, const string &privkeyfile, const str
|
|
144
145
|
InitializeDefaultCredentials();
|
145
146
|
}
|
146
147
|
|
147
|
-
|
148
|
-
pCtx = SSL_CTX_new (is_server ? SSLv23_server_method() : SSLv23_client_method());
|
148
|
+
pCtx = SSL_CTX_new (bIsServer ? SSLv23_server_method() : SSLv23_client_method());
|
149
149
|
if (!pCtx)
|
150
150
|
throw std::runtime_error ("no SSL context");
|
151
151
|
|
152
152
|
SSL_CTX_set_options (pCtx, SSL_OP_ALL);
|
153
|
-
|
154
|
-
#ifdef
|
153
|
+
|
154
|
+
#ifdef SSL_CTRL_CLEAR_OPTIONS
|
155
|
+
SSL_CTX_clear_options (pCtx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1);
|
156
|
+
# ifdef SSL_OP_NO_TLSv1_1
|
157
|
+
SSL_CTX_clear_options (pCtx, SSL_OP_NO_TLSv1_1);
|
158
|
+
# endif
|
159
|
+
# ifdef SSL_OP_NO_TLSv1_2
|
160
|
+
SSL_CTX_clear_options (pCtx, SSL_OP_NO_TLSv1_2);
|
161
|
+
# endif
|
162
|
+
#endif
|
163
|
+
|
164
|
+
if (!(ssl_version & EM_PROTO_SSLv2))
|
165
|
+
SSL_CTX_set_options (pCtx, SSL_OP_NO_SSLv2);
|
166
|
+
|
167
|
+
if (!(ssl_version & EM_PROTO_SSLv3))
|
168
|
+
SSL_CTX_set_options (pCtx, SSL_OP_NO_SSLv3);
|
169
|
+
|
170
|
+
if (!(ssl_version & EM_PROTO_TLSv1))
|
171
|
+
SSL_CTX_set_options (pCtx, SSL_OP_NO_TLSv1);
|
172
|
+
|
173
|
+
#ifdef SSL_OP_NO_TLSv1_1
|
174
|
+
if (!(ssl_version & EM_PROTO_TLSv1_1))
|
175
|
+
SSL_CTX_set_options (pCtx, SSL_OP_NO_TLSv1_1);
|
176
|
+
#endif
|
177
|
+
|
178
|
+
#ifdef SSL_OP_NO_TLSv1_2
|
179
|
+
if (!(ssl_version & EM_PROTO_TLSv1_2))
|
180
|
+
SSL_CTX_set_options (pCtx, SSL_OP_NO_TLSv1_2);
|
181
|
+
#endif
|
182
|
+
|
183
|
+
#ifdef SSL_MODE_RELEASE_BUFFERS
|
155
184
|
SSL_CTX_set_mode (pCtx, SSL_MODE_RELEASE_BUFFERS);
|
156
|
-
#endif
|
185
|
+
#endif
|
186
|
+
|
187
|
+
if (bIsServer) {
|
157
188
|
|
158
|
-
if (is_server) {
|
159
189
|
// The SSL_CTX calls here do NOT allocate memory.
|
160
190
|
int e;
|
161
191
|
if (privkeyfile.length() > 0)
|
@@ -171,11 +201,69 @@ SslContext_t::SslContext_t (bool is_server, const string &privkeyfile, const str
|
|
171
201
|
e = SSL_CTX_use_certificate (pCtx, DefaultCertificate);
|
172
202
|
if (e <= 0) ERR_print_errors_fp(stderr);
|
173
203
|
assert (e > 0);
|
204
|
+
|
205
|
+
if (dhparam.length() > 0) {
|
206
|
+
DH *dh;
|
207
|
+
BIO *bio;
|
208
|
+
|
209
|
+
bio = BIO_new_file(dhparam.c_str(), "r");
|
210
|
+
if (bio == NULL) {
|
211
|
+
char buf [500];
|
212
|
+
snprintf (buf, sizeof(buf)-1, "dhparam: BIO_new_file(%s) failed", dhparam.c_str());
|
213
|
+
throw std::runtime_error (buf);
|
214
|
+
}
|
215
|
+
|
216
|
+
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
|
217
|
+
|
218
|
+
if (dh == NULL) {
|
219
|
+
BIO_free(bio);
|
220
|
+
char buf [500];
|
221
|
+
snprintf (buf, sizeof(buf)-1, "dhparam: PEM_read_bio_DHparams(%s) failed", dhparam.c_str());
|
222
|
+
throw new std::runtime_error(buf);
|
223
|
+
}
|
224
|
+
|
225
|
+
SSL_CTX_set_tmp_dh(pCtx, dh);
|
226
|
+
|
227
|
+
DH_free(dh);
|
228
|
+
BIO_free(bio);
|
229
|
+
}
|
230
|
+
|
231
|
+
if (ecdh_curve.length() > 0) {
|
232
|
+
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL && !defined(OPENSSL_NO_ECDH)
|
233
|
+
int nid;
|
234
|
+
EC_KEY *ecdh;
|
235
|
+
|
236
|
+
nid = OBJ_sn2nid((const char *) ecdh_curve.c_str());
|
237
|
+
if (nid == 0) {
|
238
|
+
char buf [200];
|
239
|
+
snprintf (buf, sizeof(buf)-1, "ecdh_curve: Unknown curve name: %s", ecdh_curve.c_str());
|
240
|
+
throw std::runtime_error (buf);
|
241
|
+
}
|
242
|
+
|
243
|
+
ecdh = EC_KEY_new_by_curve_name(nid);
|
244
|
+
if (ecdh == NULL) {
|
245
|
+
char buf [200];
|
246
|
+
snprintf (buf, sizeof(buf)-1, "ecdh_curve: Unable to create: %s", ecdh_curve.c_str());
|
247
|
+
throw std::runtime_error (buf);
|
248
|
+
}
|
249
|
+
|
250
|
+
SSL_CTX_set_options(pCtx, SSL_OP_SINGLE_ECDH_USE);
|
251
|
+
|
252
|
+
SSL_CTX_set_tmp_ecdh(pCtx, ecdh);
|
253
|
+
|
254
|
+
EC_KEY_free(ecdh);
|
255
|
+
#else
|
256
|
+
throw std::runtime_error ("No openssl ECDH support");
|
257
|
+
#endif
|
258
|
+
}
|
174
259
|
}
|
175
260
|
|
176
|
-
|
261
|
+
if (cipherlist.length() > 0)
|
262
|
+
SSL_CTX_set_cipher_list (pCtx, cipherlist.c_str());
|
263
|
+
else
|
264
|
+
SSL_CTX_set_cipher_list (pCtx, "ALL:!ADH:!LOW:!EXP:!DES-CBC3-SHA:@STRENGTH");
|
177
265
|
|
178
|
-
if (
|
266
|
+
if (bIsServer) {
|
179
267
|
SSL_CTX_sess_set_cache_size (pCtx, 128);
|
180
268
|
SSL_CTX_set_session_id_context (pCtx, (unsigned char*)"eventmachine", 12);
|
181
269
|
}
|
@@ -216,10 +304,11 @@ SslContext_t::~SslContext_t()
|
|
216
304
|
SslBox_t::SslBox_t
|
217
305
|
******************/
|
218
306
|
|
219
|
-
SslBox_t::SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile, bool verify_peer, const uintptr_t binding):
|
307
|
+
SslBox_t::SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile, bool verify_peer, bool fail_if_no_peer_cert, const string &snihostname, const string &cipherlist, const string &ecdh_curve, const string &dhparam, int ssl_version, const uintptr_t binding):
|
220
308
|
bIsServer (is_server),
|
221
309
|
bHandshakeCompleted (false),
|
222
310
|
bVerifyPeer (verify_peer),
|
311
|
+
bFailIfNoPeerCert (fail_if_no_peer_cert),
|
223
312
|
pSSL (NULL),
|
224
313
|
pbioRead (NULL),
|
225
314
|
pbioWrite (NULL)
|
@@ -228,7 +317,7 @@ SslBox_t::SslBox_t (bool is_server, const string &privkeyfile, const string &cer
|
|
228
317
|
* a new one every time we come here.
|
229
318
|
*/
|
230
319
|
|
231
|
-
Context = new SslContext_t (bIsServer, privkeyfile, certchainfile);
|
320
|
+
Context = new SslContext_t (bIsServer, privkeyfile, certchainfile, cipherlist, ecdh_curve, dhparam, ssl_version);
|
232
321
|
assert (Context);
|
233
322
|
|
234
323
|
pbioRead = BIO_new (BIO_s_mem());
|
@@ -239,13 +328,22 @@ SslBox_t::SslBox_t (bool is_server, const string &privkeyfile, const string &cer
|
|
239
328
|
|
240
329
|
pSSL = SSL_new (Context->pCtx);
|
241
330
|
assert (pSSL);
|
331
|
+
|
332
|
+
if (snihostname.length() > 0) {
|
333
|
+
SSL_set_tlsext_host_name (pSSL, snihostname.c_str());
|
334
|
+
}
|
335
|
+
|
242
336
|
SSL_set_bio (pSSL, pbioRead, pbioWrite);
|
243
337
|
|
244
338
|
// Store a pointer to the binding signature in the SSL object so we can retrieve it later
|
245
339
|
SSL_set_ex_data(pSSL, 0, (void*) binding);
|
246
340
|
|
247
|
-
if (bVerifyPeer)
|
248
|
-
|
341
|
+
if (bVerifyPeer) {
|
342
|
+
int mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
|
343
|
+
if (bFailIfNoPeerCert)
|
344
|
+
mode = mode | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
|
345
|
+
SSL_set_verify(pSSL, mode, ssl_verify_wrapper);
|
346
|
+
}
|
249
347
|
|
250
348
|
if (!bIsServer)
|
251
349
|
SSL_connect (pSSL);
|
@@ -437,6 +535,52 @@ X509 *SslBox_t::GetPeerCert()
|
|
437
535
|
return cert;
|
438
536
|
}
|
439
537
|
|
538
|
+
/**********************
|
539
|
+
SslBox_t::GetCipherBits
|
540
|
+
**********************/
|
541
|
+
|
542
|
+
int SslBox_t::GetCipherBits()
|
543
|
+
{
|
544
|
+
int bits = -1;
|
545
|
+
if (pSSL)
|
546
|
+
SSL_get_cipher_bits(pSSL, &bits);
|
547
|
+
return bits;
|
548
|
+
}
|
549
|
+
|
550
|
+
/**********************
|
551
|
+
SslBox_t::GetCipherName
|
552
|
+
**********************/
|
553
|
+
|
554
|
+
const char *SslBox_t::GetCipherName()
|
555
|
+
{
|
556
|
+
if (pSSL)
|
557
|
+
return SSL_get_cipher_name(pSSL);
|
558
|
+
return NULL;
|
559
|
+
}
|
560
|
+
|
561
|
+
/**********************
|
562
|
+
SslBox_t::GetCipherProtocol
|
563
|
+
**********************/
|
564
|
+
|
565
|
+
const char *SslBox_t::GetCipherProtocol()
|
566
|
+
{
|
567
|
+
if (pSSL)
|
568
|
+
return SSL_get_cipher_version(pSSL);
|
569
|
+
return NULL;
|
570
|
+
}
|
571
|
+
|
572
|
+
/**********************
|
573
|
+
SslBox_t::GetSNIHostname
|
574
|
+
**********************/
|
575
|
+
|
576
|
+
const char *SslBox_t::GetSNIHostname()
|
577
|
+
{
|
578
|
+
#ifdef TLSEXT_NAMETYPE_host_name
|
579
|
+
if (pSSL)
|
580
|
+
return SSL_get_servername (pSSL, TLSEXT_NAMETYPE_host_name);
|
581
|
+
#endif
|
582
|
+
return NULL;
|
583
|
+
}
|
440
584
|
|
441
585
|
/******************
|
442
586
|
ssl_verify_wrapper
|
data/ext/ssl.h
CHANGED
@@ -33,7 +33,7 @@ class SslContext_t
|
|
33
33
|
class SslContext_t
|
34
34
|
{
|
35
35
|
public:
|
36
|
-
SslContext_t (bool is_server, const string &privkeyfile, const string &certchainfile);
|
36
|
+
SslContext_t (bool is_server, const string &privkeyfile, const string &certchainfile, const string &cipherlist, const string &ecdh_curve, const string &dhparam, int ssl_version);
|
37
37
|
virtual ~SslContext_t();
|
38
38
|
|
39
39
|
private:
|
@@ -61,7 +61,7 @@ class SslBox_t
|
|
61
61
|
class SslBox_t
|
62
62
|
{
|
63
63
|
public:
|
64
|
-
SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile, bool verify_peer, const uintptr_t binding);
|
64
|
+
SslBox_t (bool is_server, const string &privkeyfile, const string &certchainfile, bool verify_peer, bool fail_if_no_peer_cert, const string &snihostname, const string &cipherlist, const string &ecdh_curve, const string &dhparam, int ssl_version, const uintptr_t binding);
|
65
65
|
virtual ~SslBox_t();
|
66
66
|
|
67
67
|
int PutPlaintext (const char*, int);
|
@@ -73,6 +73,10 @@ class SslBox_t
|
|
73
73
|
bool IsHandshakeCompleted() {return bHandshakeCompleted;}
|
74
74
|
|
75
75
|
X509 *GetPeerCert();
|
76
|
+
int GetCipherBits();
|
77
|
+
const char *GetCipherName();
|
78
|
+
const char *GetCipherProtocol();
|
79
|
+
const char *GetSNIHostname();
|
76
80
|
|
77
81
|
void Shutdown();
|
78
82
|
|
@@ -82,6 +86,7 @@ class SslBox_t
|
|
82
86
|
bool bIsServer;
|
83
87
|
bool bHandshakeCompleted;
|
84
88
|
bool bVerifyPeer;
|
89
|
+
bool bFailIfNoPeerCert;
|
85
90
|
SSL *pSSL;
|
86
91
|
BIO *pbioRead;
|
87
92
|
BIO *pbioWrite;
|
data/lib/em/channel.rb
CHANGED
@@ -17,6 +17,11 @@ module EventMachine
|
|
17
17
|
@uid = 0
|
18
18
|
end
|
19
19
|
|
20
|
+
# Return the number of current subscribers.
|
21
|
+
def num_subscribers
|
22
|
+
return @subs.size
|
23
|
+
end
|
24
|
+
|
20
25
|
# Takes any arguments suitable for EM::Callback() and returns a subscriber
|
21
26
|
# id for use when unsubscribing.
|
22
27
|
#
|
data/lib/em/completion.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# = EM::Completion
|
2
2
|
#
|
3
3
|
# A completion is a callback container for various states of completion. In
|
4
|
-
#
|
4
|
+
# its most basic form it has a start state and a finish state.
|
5
5
|
#
|
6
6
|
# This implementation includes some hold-back from the EM::Deferrable
|
7
7
|
# interface in order to be compatible - but it has a much cleaner
|
@@ -50,7 +50,7 @@
|
|
50
50
|
# @completion.fail :unknown, line
|
51
51
|
# end
|
52
52
|
# end
|
53
|
-
#
|
53
|
+
#
|
54
54
|
# def unbind
|
55
55
|
# @completion.fail :disconnected unless @completion.completed?
|
56
56
|
# end
|
data/lib/em/connection.rb
CHANGED
@@ -376,10 +376,21 @@ module EventMachine
|
|
376
376
|
#
|
377
377
|
# @option args [String] :private_key_file (nil) local path of a readable file that must contain a private key in the [PEM format](http://en.wikipedia.org/wiki/Privacy_Enhanced_Mail).
|
378
378
|
#
|
379
|
-
# @option args [
|
379
|
+
# @option args [Boolean] :verify_peer (false) indicates whether a server should request a certificate from a peer, to be verified by user code.
|
380
380
|
# If true, the {#ssl_verify_peer} callback on the {EventMachine::Connection} object is called with each certificate
|
381
381
|
# in the certificate chain provided by the peer. See documentation on {#ssl_verify_peer} for how to use this.
|
382
382
|
#
|
383
|
+
# @option args [Boolean] :fail_if_no_peer_cert (false) Used in conjunction with verify_peer. If set the SSL handshake will be terminated if the peer does not provide a certificate.
|
384
|
+
#
|
385
|
+
#
|
386
|
+
# @option args [String] :cipher_list ("ALL:!ADH:!LOW:!EXP:!DES-CBC3-SHA:@STRENGTH") indicates the available SSL cipher values. Default value is "ALL:!ADH:!LOW:!EXP:!DES-CBC3-SHA:@STRENGTH". Check the format of the OpenSSL cipher string at http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT.
|
387
|
+
#
|
388
|
+
# @option args [String] :ecdh_curve (nil) The curve for ECDHE ciphers. See available ciphers with 'openssl ecparam -list_curves'
|
389
|
+
#
|
390
|
+
# @option args [String] :dhparam (nil) The local path of a file containing DH parameters for EDH ciphers in [PEM format](http://en.wikipedia.org/wiki/Privacy_Enhanced_Mail) See: 'openssl dhparam'
|
391
|
+
#
|
392
|
+
# @option args [Array] :ssl_version (TLSv1 TLSv1_1 TLSv1_2) indicates the allowed SSL/TLS versions. Possible values are: {SSLv2}, {SSLv3}, {TLSv1}, {TLSv1_1}, {TLSv1_2}.
|
393
|
+
#
|
383
394
|
# @example Using TLS with EventMachine
|
384
395
|
#
|
385
396
|
# require 'rubygems'
|
@@ -404,7 +415,15 @@ module EventMachine
|
|
404
415
|
#
|
405
416
|
# @see #ssl_verify_peer
|
406
417
|
def start_tls args={}
|
407
|
-
priv_key
|
418
|
+
priv_key = args[:private_key_file]
|
419
|
+
cert_chain = args[:cert_chain_file]
|
420
|
+
verify_peer = args[:verify_peer]
|
421
|
+
sni_hostname = args[:sni_hostname]
|
422
|
+
cipher_list = args[:cipher_list]
|
423
|
+
ssl_version = args[:ssl_version]
|
424
|
+
ecdh_curve = args[:ecdh_curve]
|
425
|
+
dhparam = args[:dhparam]
|
426
|
+
fail_if_no_peer_cert = args[:fail_if_no_peer_cert]
|
408
427
|
|
409
428
|
[priv_key, cert_chain].each do |file|
|
410
429
|
next if file.nil? or file.empty?
|
@@ -412,7 +431,31 @@ module EventMachine
|
|
412
431
|
"Could not find #{file} for start_tls" unless File.exist? file
|
413
432
|
end
|
414
433
|
|
415
|
-
|
434
|
+
protocols_bitmask = 0
|
435
|
+
if ssl_version.nil?
|
436
|
+
protocols_bitmask |= EventMachine::EM_PROTO_TLSv1
|
437
|
+
protocols_bitmask |= EventMachine::EM_PROTO_TLSv1_1
|
438
|
+
protocols_bitmask |= EventMachine::EM_PROTO_TLSv1_2
|
439
|
+
else
|
440
|
+
[ssl_version].flatten.each do |p|
|
441
|
+
case p.to_s.downcase
|
442
|
+
when 'sslv2'
|
443
|
+
protocols_bitmask |= EventMachine::EM_PROTO_SSLv2
|
444
|
+
when 'sslv3'
|
445
|
+
protocols_bitmask |= EventMachine::EM_PROTO_SSLv3
|
446
|
+
when 'tlsv1'
|
447
|
+
protocols_bitmask |= EventMachine::EM_PROTO_TLSv1
|
448
|
+
when 'tlsv1_1'
|
449
|
+
protocols_bitmask |= EventMachine::EM_PROTO_TLSv1_1
|
450
|
+
when 'tlsv1_2'
|
451
|
+
protocols_bitmask |= EventMachine::EM_PROTO_TLSv1_2
|
452
|
+
else
|
453
|
+
raise("Unrecognized SSL/TLS Protocol: #{p}")
|
454
|
+
end
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
EventMachine::set_tls_parms(@signature, priv_key || '', cert_chain || '', verify_peer, fail_if_no_peer_cert, sni_hostname || '', cipher_list || '', ecdh_curve || '', dhparam || '', protocols_bitmask)
|
416
459
|
EventMachine::start_tls @signature
|
417
460
|
end
|
418
461
|
|
@@ -488,6 +531,21 @@ module EventMachine
|
|
488
531
|
EventMachine::get_peer_cert @signature
|
489
532
|
end
|
490
533
|
|
534
|
+
def get_cipher_bits
|
535
|
+
EventMachine::get_cipher_bits @signature
|
536
|
+
end
|
537
|
+
|
538
|
+
def get_cipher_name
|
539
|
+
EventMachine::get_cipher_name @signature
|
540
|
+
end
|
541
|
+
|
542
|
+
def get_cipher_protocol
|
543
|
+
EventMachine::get_cipher_protocol @signature
|
544
|
+
end
|
545
|
+
|
546
|
+
def get_sni_hostname
|
547
|
+
EventMachine::get_sni_hostname @signature
|
548
|
+
end
|
491
549
|
|
492
550
|
# Sends UDP messages.
|
493
551
|
#
|
data/lib/em/iterator.rb
CHANGED
@@ -41,6 +41,7 @@ module EventMachine
|
|
41
41
|
# end
|
42
42
|
#
|
43
43
|
class Iterator
|
44
|
+
Stop = "EM::Stop"
|
44
45
|
# Create a new parallel async iterator with specified concurrency.
|
45
46
|
#
|
46
47
|
# i = EM::Iterator.new(1..100, 10)
|
@@ -48,10 +49,21 @@ module EventMachine
|
|
48
49
|
# will create an iterator over the range that processes 10 items at a time. Iteration
|
49
50
|
# is started via #each, #map or #inject
|
50
51
|
#
|
52
|
+
# The list may either be an array-like object, or a proc that returns a new object
|
53
|
+
# to be processed each time it is called. If a proc is used, it must return
|
54
|
+
# EventMachine::Iterator::Stop to signal the end of the iterations.
|
55
|
+
#
|
51
56
|
def initialize(list, concurrency = 1)
|
52
|
-
raise ArgumentError, 'argument must be an array' unless list.respond_to?(:to_a)
|
53
57
|
raise ArgumentError, 'concurrency must be bigger than zero' unless (concurrency > 0)
|
54
|
-
|
58
|
+
if list.respond_to?(:call)
|
59
|
+
@list = nil
|
60
|
+
@list_proc = list
|
61
|
+
elsif list.respond_to?(:to_a)
|
62
|
+
@list = list.to_a.dup
|
63
|
+
@list_proc = nil
|
64
|
+
else
|
65
|
+
raise ArgumentError, 'argument must be a proc or an array'
|
66
|
+
end
|
55
67
|
@concurrency = concurrency
|
56
68
|
|
57
69
|
@started = false
|
@@ -98,12 +110,12 @@ module EventMachine
|
|
98
110
|
@process_next = proc{
|
99
111
|
# p [:process_next, :pending=, @pending, :workers=, @workers, :ended=, @ended, :concurrency=, @concurrency, :list=, @list]
|
100
112
|
unless @ended or @workers > @concurrency
|
101
|
-
|
113
|
+
item = next_item()
|
114
|
+
if item.equal?(Stop)
|
102
115
|
@ended = true
|
103
116
|
@workers -= 1
|
104
117
|
all_done.call
|
105
118
|
else
|
106
|
-
item = @list.shift
|
107
119
|
@pending += 1
|
108
120
|
|
109
121
|
is_done = false
|
@@ -222,10 +234,19 @@ module EventMachine
|
|
222
234
|
})
|
223
235
|
nil
|
224
236
|
end
|
237
|
+
|
238
|
+
# Return the next item from @list or @list_proc.
|
239
|
+
# Once items have run out, will return EM::Iterator::Stop. Procs must supply this themselves
|
240
|
+
def next_item
|
241
|
+
if @list_proc
|
242
|
+
@list_proc.call
|
243
|
+
else
|
244
|
+
@list.empty? ? Stop : @list.shift
|
245
|
+
end
|
246
|
+
end
|
225
247
|
end
|
226
248
|
end
|
227
249
|
|
228
250
|
# TODO: pass in one object instead of two? .each{ |iter| puts iter.current; iter.next }
|
229
251
|
# TODO: support iter.pause/resume/stop/break/continue?
|
230
252
|
# TODO: create some exceptions instead of using RuntimeError
|
231
|
-
# TODO: support proc instead of enumerable? EM::Iterator.new(proc{ return queue.pop })
|