eventmachine 1.0.9.1-java → 1.2.0.1-java
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 +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 })
|