eventmachine 1.0.3-x86-mingw32 → 1.2.0.dev.2-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +84 -1
- data/README.md +6 -7
- data/ext/binder.cpp +10 -10
- data/ext/binder.h +5 -5
- data/ext/cmain.cpp +173 -61
- data/ext/ed.cpp +262 -127
- data/ext/ed.h +50 -30
- data/ext/em.cpp +491 -445
- data/ext/em.h +101 -36
- data/ext/eventmachine.h +67 -51
- data/ext/extconf.rb +124 -31
- data/ext/fastfilereader/extconf.rb +9 -2
- data/ext/fastfilereader/mapper.cpp +3 -1
- data/ext/fastfilereader/rubymain.cpp +7 -7
- data/ext/kb.cpp +1 -1
- data/ext/pipe.cpp +11 -4
- data/ext/project.h +26 -6
- data/ext/rubymain.cpp +408 -201
- data/ext/ssl.cpp +167 -20
- data/ext/ssl.h +11 -2
- data/java/src/com/rubyeventmachine/EmReactor.java +16 -0
- data/java/src/com/rubyeventmachine/EventableChannel.java +2 -0
- data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +6 -0
- data/java/src/com/rubyeventmachine/EventableSocketChannel.java +55 -10
- data/lib/1.9/fastfilereaderext.so +0 -0
- data/lib/1.9/rubyeventmachine.so +0 -0
- data/lib/2.0/fastfilereaderext.so +0 -0
- data/lib/2.0/rubyeventmachine.so +0 -0
- data/lib/2.1/fastfilereaderext.so +0 -0
- data/lib/2.1/rubyeventmachine.so +0 -0
- data/lib/2.2/fastfilereaderext.so +0 -0
- data/lib/2.2/rubyeventmachine.so +0 -0
- data/lib/2.3/fastfilereaderext.so +0 -0
- data/lib/2.3/rubyeventmachine.so +0 -0
- data/lib/em/buftok.rb +34 -85
- data/lib/em/channel.rb +5 -0
- data/lib/em/completion.rb +2 -2
- data/lib/em/connection.rb +62 -4
- data/lib/em/iterator.rb +30 -48
- data/lib/em/pool.rb +1 -1
- data/lib/em/protocols/httpclient.rb +31 -11
- data/lib/em/protocols/line_and_text.rb +4 -4
- data/lib/em/protocols/linetext2.rb +44 -39
- data/lib/em/protocols/smtpclient.rb +60 -31
- data/lib/em/protocols/smtpserver.rb +32 -9
- data/lib/em/pure_ruby.rb +8 -3
- data/lib/em/queue.rb +16 -7
- data/lib/em/resolver.rb +64 -24
- data/lib/em/threaded_resource.rb +2 -2
- data/lib/em/tick_loop.rb +19 -19
- data/lib/em/version.rb +1 -1
- data/lib/eventmachine.rb +96 -49
- data/lib/jeventmachine.rb +17 -0
- data/rakelib/package.rake +31 -4
- data/tests/dhparam.pem +13 -0
- data/tests/em_test_helper.rb +87 -0
- data/tests/test_attach.rb +25 -0
- data/tests/test_basic.rb +27 -38
- data/tests/test_channel.rb +14 -1
- data/tests/test_completion.rb +1 -0
- data/tests/test_connection_count.rb +22 -1
- data/tests/test_connection_write.rb +35 -0
- data/tests/test_defer.rb +17 -0
- data/tests/test_epoll.rb +26 -14
- data/tests/test_file_watch.rb +1 -0
- data/tests/test_fork.rb +75 -0
- data/tests/test_httpclient.rb +43 -0
- data/tests/test_idle_connection.rb +6 -4
- data/tests/test_ipv4.rb +125 -0
- data/tests/test_ipv6.rb +131 -0
- data/tests/test_iterator.rb +115 -0
- data/tests/test_kb.rb +19 -25
- data/tests/test_ltp2.rb +20 -0
- data/tests/test_many_fds.rb +22 -0
- data/tests/test_pause.rb +29 -0
- data/tests/test_pool.rb +2 -0
- data/tests/test_process_watch.rb +2 -0
- data/tests/test_processes.rb +7 -7
- data/tests/test_queue.rb +14 -0
- data/tests/test_resolver.rb +56 -7
- data/tests/test_set_sock_opt.rb +2 -0
- data/tests/test_smtpclient.rb +20 -0
- data/tests/test_ssl_args.rb +2 -2
- 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 +22 -5
- data/tests/test_ssl_protocols.rb +246 -0
- data/tests/test_ssl_verify.rb +103 -59
- data/tests/test_system.rb +4 -0
- data/tests/test_threaded_resource.rb +8 -0
- data/tests/test_unbind_reason.rb +5 -1
- metadata +173 -107
- data/.gitignore +0 -21
- data/.travis.yml +0 -12
- data/.yardopts +0 -7
- data/Gemfile +0 -2
- data/Rakefile +0 -20
- data/eventmachine.gemspec +0 -36
- data/rakelib/cpp.rake_example +0 -77
data/ext/ed.cpp
CHANGED
@@ -31,7 +31,7 @@ bool SetSocketNonblocking (SOCKET sd)
|
|
31
31
|
int val = fcntl (sd, F_GETFL, 0);
|
32
32
|
return (fcntl (sd, F_SETFL, val | O_NONBLOCK) != SOCKET_ERROR) ? true : false;
|
33
33
|
#endif
|
34
|
-
|
34
|
+
|
35
35
|
#ifdef OS_WIN32
|
36
36
|
#ifdef BUILD_FOR_RUBY
|
37
37
|
// 14Jun09 Ruby provides its own wrappers for ioctlsocket. On 1.8 this is a simple wrapper,
|
@@ -45,12 +45,30 @@ bool SetSocketNonblocking (SOCKET sd)
|
|
45
45
|
#endif
|
46
46
|
}
|
47
47
|
|
48
|
+
/************
|
49
|
+
SetFdCloexec
|
50
|
+
************/
|
51
|
+
|
52
|
+
#ifdef OS_UNIX
|
53
|
+
bool SetFdCloexec (int fd)
|
54
|
+
{
|
55
|
+
int flags = fcntl(fd, F_GETFD, 0);
|
56
|
+
assert (flags >= 0);
|
57
|
+
flags |= FD_CLOEXEC;
|
58
|
+
return (fcntl(fd, F_SETFD, FD_CLOEXEC) == 0) ? true : false;
|
59
|
+
}
|
60
|
+
#else
|
61
|
+
bool SetFdCloexec (int fd UNUSED)
|
62
|
+
{
|
63
|
+
return true;
|
64
|
+
}
|
65
|
+
#endif
|
48
66
|
|
49
67
|
/****************************************
|
50
68
|
EventableDescriptor::EventableDescriptor
|
51
69
|
****************************************/
|
52
70
|
|
53
|
-
EventableDescriptor::EventableDescriptor (
|
71
|
+
EventableDescriptor::EventableDescriptor (SOCKET sd, EventMachine_t *em):
|
54
72
|
bCloseNow (false),
|
55
73
|
bCloseAfterWriting (false),
|
56
74
|
MySocket (sd),
|
@@ -217,6 +235,8 @@ EventableDescriptor::ScheduleClose
|
|
217
235
|
|
218
236
|
void EventableDescriptor::ScheduleClose (bool after_writing)
|
219
237
|
{
|
238
|
+
if (IsCloseScheduled())
|
239
|
+
return;
|
220
240
|
MyEventMachine->NumCloseScheduled++;
|
221
241
|
// KEEP THIS SYNCHRONIZED WITH ::IsCloseScheduled.
|
222
242
|
if (after_writing)
|
@@ -241,7 +261,7 @@ bool EventableDescriptor::IsCloseScheduled()
|
|
241
261
|
EventableDescriptor::StartProxy
|
242
262
|
*******************************/
|
243
263
|
|
244
|
-
void EventableDescriptor::StartProxy(const
|
264
|
+
void EventableDescriptor::StartProxy(const uintptr_t to, const unsigned long bufsize, const unsigned long length)
|
245
265
|
{
|
246
266
|
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (to));
|
247
267
|
if (ed) {
|
@@ -287,13 +307,13 @@ void EventableDescriptor::SetProxiedFrom(EventableDescriptor *from, const unsign
|
|
287
307
|
EventableDescriptor::_GenericInboundDispatch
|
288
308
|
********************************************/
|
289
309
|
|
290
|
-
void EventableDescriptor::_GenericInboundDispatch(const char *buf,
|
310
|
+
void EventableDescriptor::_GenericInboundDispatch(const char *buf, unsigned long size)
|
291
311
|
{
|
292
312
|
assert(EventCallback);
|
293
313
|
|
294
314
|
if (ProxyTarget) {
|
295
315
|
if (BytesToProxy > 0) {
|
296
|
-
unsigned long proxied = min(BytesToProxy,
|
316
|
+
unsigned long proxied = min(BytesToProxy, size);
|
297
317
|
ProxyTarget->SendOutboundData(buf, proxied);
|
298
318
|
ProxiedBytes += (unsigned long) proxied;
|
299
319
|
BytesToProxy -= proxied;
|
@@ -306,7 +326,7 @@ void EventableDescriptor::_GenericInboundDispatch(const char *buf, int size)
|
|
306
326
|
}
|
307
327
|
} else {
|
308
328
|
ProxyTarget->SendOutboundData(buf, size);
|
309
|
-
ProxiedBytes +=
|
329
|
+
ProxiedBytes += size;
|
310
330
|
}
|
311
331
|
} else {
|
312
332
|
(*EventCallback)(GetBinding(), EM_CONNECTION_READ, buf, size);
|
@@ -369,7 +389,7 @@ uint64_t EventableDescriptor::GetNextHeartbeat()
|
|
369
389
|
ConnectionDescriptor::ConnectionDescriptor
|
370
390
|
******************************************/
|
371
391
|
|
372
|
-
ConnectionDescriptor::ConnectionDescriptor (
|
392
|
+
ConnectionDescriptor::ConnectionDescriptor (SOCKET sd, EventMachine_t *em):
|
373
393
|
EventableDescriptor (sd, em),
|
374
394
|
bConnectPending (false),
|
375
395
|
bNotifyReadable (false),
|
@@ -424,6 +444,9 @@ void ConnectionDescriptor::_UpdateEvents(bool read, bool write)
|
|
424
444
|
if (MySocket == INVALID_SOCKET)
|
425
445
|
return;
|
426
446
|
|
447
|
+
if (!read && !write)
|
448
|
+
return;
|
449
|
+
|
427
450
|
#ifdef HAVE_EPOLL
|
428
451
|
unsigned int old = EpollEvent.events;
|
429
452
|
|
@@ -448,8 +471,9 @@ void ConnectionDescriptor::_UpdateEvents(bool read, bool write)
|
|
448
471
|
#ifdef HAVE_KQUEUE
|
449
472
|
if (read && SelectForRead())
|
450
473
|
MyEventMachine->ArmKqueueReader (this);
|
451
|
-
|
452
|
-
|
474
|
+
bKqueueArmWrite = SelectForWrite();
|
475
|
+
if (write && bKqueueArmWrite)
|
476
|
+
MyEventMachine->Modify (this);
|
453
477
|
#endif
|
454
478
|
}
|
455
479
|
|
@@ -471,7 +495,7 @@ ConnectionDescriptor::SetAttached
|
|
471
495
|
|
472
496
|
void ConnectionDescriptor::SetAttached(bool state)
|
473
497
|
{
|
474
|
-
|
498
|
+
bAttached = state;
|
475
499
|
}
|
476
500
|
|
477
501
|
|
@@ -553,7 +577,7 @@ void ConnectionDescriptor::SetNotifyWritable(bool writable)
|
|
553
577
|
ConnectionDescriptor::SendOutboundData
|
554
578
|
**************************************/
|
555
579
|
|
556
|
-
int ConnectionDescriptor::SendOutboundData (const char *data,
|
580
|
+
int ConnectionDescriptor::SendOutboundData (const char *data, unsigned long length)
|
557
581
|
{
|
558
582
|
if (bWatchOnly)
|
559
583
|
throw std::runtime_error ("cannot send data on a 'watch only' connection");
|
@@ -564,11 +588,25 @@ int ConnectionDescriptor::SendOutboundData (const char *data, int length)
|
|
564
588
|
#ifdef WITH_SSL
|
565
589
|
if (SslBox) {
|
566
590
|
if (length > 0) {
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
591
|
+
unsigned long writed = 0;
|
592
|
+
char *p = (char*)data;
|
593
|
+
|
594
|
+
while (writed < length) {
|
595
|
+
int to_write = SSLBOX_INPUT_CHUNKSIZE;
|
596
|
+
int remaining = length - writed;
|
597
|
+
|
598
|
+
if (remaining < SSLBOX_INPUT_CHUNKSIZE)
|
599
|
+
to_write = remaining;
|
600
|
+
|
601
|
+
int w = SslBox->PutPlaintext (p, to_write);
|
602
|
+
if (w < 0) {
|
603
|
+
ScheduleClose (false);
|
604
|
+
}else
|
605
|
+
_DispatchCiphertext();
|
606
|
+
|
607
|
+
p += to_write;
|
608
|
+
writed += to_write;
|
609
|
+
}
|
572
610
|
}
|
573
611
|
// TODO: What's the correct return value?
|
574
612
|
return 1; // That's a wild guess, almost certainly wrong.
|
@@ -584,7 +622,7 @@ int ConnectionDescriptor::SendOutboundData (const char *data, int length)
|
|
584
622
|
ConnectionDescriptor::_SendRawOutboundData
|
585
623
|
******************************************/
|
586
624
|
|
587
|
-
int ConnectionDescriptor::_SendRawOutboundData (const char *data,
|
625
|
+
int ConnectionDescriptor::_SendRawOutboundData (const char *data, unsigned long length)
|
588
626
|
{
|
589
627
|
/* This internal method is called to schedule bytes that
|
590
628
|
* will be sent out to the remote peer.
|
@@ -600,7 +638,6 @@ int ConnectionDescriptor::_SendRawOutboundData (const char *data, int length)
|
|
600
638
|
|
601
639
|
if (IsCloseScheduled())
|
602
640
|
return 0;
|
603
|
-
|
604
641
|
// 25Mar10: Ignore 0 length packets as they are not meaningful in TCP (as opposed to UDP)
|
605
642
|
// and can cause the assert(nbytes>0) to fail when OutboundPages has a bunch of 0 length pages.
|
606
643
|
if (length == 0)
|
@@ -630,28 +667,28 @@ ConnectionDescriptor::SelectForRead
|
|
630
667
|
|
631
668
|
bool ConnectionDescriptor::SelectForRead()
|
632
669
|
{
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
670
|
+
/* A connection descriptor is always scheduled for read,
|
671
|
+
* UNLESS it's in a pending-connect state.
|
672
|
+
* On Linux, unlike Unix, a nonblocking socket on which
|
673
|
+
* connect has been called, does NOT necessarily select
|
674
|
+
* both readable and writable in case of error.
|
675
|
+
* The socket will select writable when the disposition
|
676
|
+
* of the connect is known. On the other hand, a socket
|
677
|
+
* which successfully connects and selects writable may
|
678
|
+
* indeed have some data available on it, so it will
|
679
|
+
* select readable in that case, violating expectations!
|
680
|
+
* So we will not poll for readability until the socket
|
681
|
+
* is known to be in a connected state.
|
682
|
+
*/
|
683
|
+
|
684
|
+
if (bPaused)
|
685
|
+
return false;
|
686
|
+
else if (bConnectPending)
|
687
|
+
return false;
|
688
|
+
else if (bWatchOnly)
|
689
|
+
return bNotifyReadable ? true : false;
|
690
|
+
else
|
691
|
+
return true;
|
655
692
|
}
|
656
693
|
|
657
694
|
|
@@ -661,20 +698,20 @@ ConnectionDescriptor::SelectForWrite
|
|
661
698
|
|
662
699
|
bool ConnectionDescriptor::SelectForWrite()
|
663
700
|
{
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
701
|
+
/* Cf the notes under SelectForRead.
|
702
|
+
* In a pending-connect state, we ALWAYS select for writable.
|
703
|
+
* In a normal state, we only select for writable when we
|
704
|
+
* have outgoing data to send.
|
705
|
+
*/
|
669
706
|
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
707
|
+
if (bPaused)
|
708
|
+
return false;
|
709
|
+
else if (bConnectPending)
|
710
|
+
return true;
|
711
|
+
else if (bWatchOnly)
|
712
|
+
return bNotifyWritable ? true : false;
|
713
|
+
else
|
714
|
+
return (GetOutboundDataSize() > 0);
|
678
715
|
}
|
679
716
|
|
680
717
|
/***************************
|
@@ -736,7 +773,7 @@ void ConnectionDescriptor::Read()
|
|
736
773
|
* come here more than once after being closed. (FCianfrocca)
|
737
774
|
*/
|
738
775
|
|
739
|
-
|
776
|
+
SOCKET sd = GetSocket();
|
740
777
|
//assert (sd != INVALID_SOCKET); (original, removed 22Aug06)
|
741
778
|
if (sd == INVALID_SOCKET) {
|
742
779
|
assert (!bReadAttemptedAfterClose);
|
@@ -765,7 +802,11 @@ void ConnectionDescriptor::Read()
|
|
765
802
|
|
766
803
|
|
767
804
|
int r = read (sd, readbuffer, sizeof(readbuffer) - 1);
|
805
|
+
#ifdef OS_WIN32
|
806
|
+
int e = WSAGetLastError();
|
807
|
+
#else
|
768
808
|
int e = errno;
|
809
|
+
#endif
|
769
810
|
//cerr << "<R:" << r << ">";
|
770
811
|
|
771
812
|
if (r > 0) {
|
@@ -779,6 +820,8 @@ void ConnectionDescriptor::Read()
|
|
779
820
|
// a security guard against buffer overflows.
|
780
821
|
readbuffer [r] = 0;
|
781
822
|
_DispatchInboundData (readbuffer, r);
|
823
|
+
if (bPaused)
|
824
|
+
break;
|
782
825
|
}
|
783
826
|
else if (r == 0) {
|
784
827
|
break;
|
@@ -819,9 +862,9 @@ void ConnectionDescriptor::Read()
|
|
819
862
|
ConnectionDescriptor::_DispatchInboundData
|
820
863
|
******************************************/
|
821
864
|
|
822
|
-
|
865
|
+
#ifdef WITH_SSL
|
866
|
+
void ConnectionDescriptor::_DispatchInboundData (const char *buffer, unsigned long size)
|
823
867
|
{
|
824
|
-
#ifdef WITH_SSL
|
825
868
|
if (SslBox) {
|
826
869
|
SslBox->PutCiphertext (buffer, size);
|
827
870
|
|
@@ -835,6 +878,12 @@ void ConnectionDescriptor::_DispatchInboundData (const char *buffer, int size)
|
|
835
878
|
|
836
879
|
// If our SSL handshake had a problem, shut down the connection.
|
837
880
|
if (s == -2) {
|
881
|
+
#ifdef OS_UNIX
|
882
|
+
UnbindReasonCode = EPROTO;
|
883
|
+
#endif
|
884
|
+
#ifdef OS_WIN32
|
885
|
+
UnbindReasonCode = WSAECONNABORTED;
|
886
|
+
#endif
|
838
887
|
ScheduleClose(false);
|
839
888
|
return;
|
840
889
|
}
|
@@ -845,12 +894,13 @@ void ConnectionDescriptor::_DispatchInboundData (const char *buffer, int size)
|
|
845
894
|
else {
|
846
895
|
_GenericInboundDispatch(buffer, size);
|
847
896
|
}
|
848
|
-
|
849
|
-
|
850
|
-
|
897
|
+
}
|
898
|
+
#else
|
899
|
+
void ConnectionDescriptor::_DispatchInboundData (const char *buffer, unsigned long size)
|
900
|
+
{
|
851
901
|
_GenericInboundDispatch(buffer, size);
|
852
|
-
#endif
|
853
902
|
}
|
903
|
+
#endif
|
854
904
|
|
855
905
|
|
856
906
|
|
@@ -932,7 +982,7 @@ void ConnectionDescriptor::Write()
|
|
932
982
|
::Write to be called in a busy-loop.
|
933
983
|
*/
|
934
984
|
#ifdef HAVE_KQUEUE
|
935
|
-
if (MyEventMachine->
|
985
|
+
if (MyEventMachine->GetPoller() == Poller_Kqueue) {
|
936
986
|
if (OutboundDataSize == 0 && !bGotExtraKqueueEvent) {
|
937
987
|
bGotExtraKqueueEvent = true;
|
938
988
|
return;
|
@@ -965,7 +1015,7 @@ void ConnectionDescriptor::_WriteOutboundData()
|
|
965
1015
|
* doing it to address some reports of crashing under heavy loads.
|
966
1016
|
*/
|
967
1017
|
|
968
|
-
|
1018
|
+
SOCKET sd = GetSocket();
|
969
1019
|
//assert (sd != INVALID_SOCKET);
|
970
1020
|
if (sd == INVALID_SOCKET) {
|
971
1021
|
assert (!bWriteAttemptedAfterClose);
|
@@ -981,15 +1031,13 @@ void ConnectionDescriptor::_WriteOutboundData()
|
|
981
1031
|
// Max of 16 outbound pages at a time
|
982
1032
|
if (iovcnt > 16) iovcnt = 16;
|
983
1033
|
|
984
|
-
|
985
|
-
struct iovec iov[16];
|
986
|
-
#else
|
987
|
-
struct iovec iov[ iovcnt ];
|
988
|
-
#endif
|
1034
|
+
iovec iov[16];
|
989
1035
|
|
990
1036
|
for(int i = 0; i < iovcnt; i++){
|
991
1037
|
OutboundPage *op = &(OutboundPages[i]);
|
992
1038
|
#ifdef CC_SUNWspro
|
1039
|
+
// TODO: The void * cast works fine on Solaris 11, but
|
1040
|
+
// I don't know at what point that changed from older Solaris.
|
993
1041
|
iov[i].iov_base = (char *)(op->Buffer + op->Offset);
|
994
1042
|
#else
|
995
1043
|
iov[i].iov_base = (void *)(op->Buffer + op->Offset);
|
@@ -1032,7 +1080,11 @@ void ConnectionDescriptor::_WriteOutboundData()
|
|
1032
1080
|
#endif
|
1033
1081
|
|
1034
1082
|
bool err = false;
|
1083
|
+
#ifdef OS_WIN32
|
1084
|
+
int e = WSAGetLastError();
|
1085
|
+
#else
|
1035
1086
|
int e = errno;
|
1087
|
+
#endif
|
1036
1088
|
if (bytes_written < 0) {
|
1037
1089
|
err = true;
|
1038
1090
|
bytes_written = 0;
|
@@ -1127,42 +1179,57 @@ int ConnectionDescriptor::ReportErrorStatus()
|
|
1127
1179
|
ConnectionDescriptor::StartTls
|
1128
1180
|
******************************/
|
1129
1181
|
|
1182
|
+
#ifdef WITH_SSL
|
1130
1183
|
void ConnectionDescriptor::StartTls()
|
1131
1184
|
{
|
1132
|
-
#ifdef WITH_SSL
|
1133
1185
|
if (SslBox)
|
1134
1186
|
throw std::runtime_error ("SSL/TLS already running on connection");
|
1135
1187
|
|
1136
|
-
SslBox = new SslBox_t (bIsServer, PrivateKeyFilename, CertChainFilename, bSslVerifyPeer, GetBinding());
|
1188
|
+
SslBox = new SslBox_t (bIsServer, PrivateKeyFilename, CertChainFilename, bSslVerifyPeer, bSslFailIfNoPeerCert, SniHostName, CipherList, EcdhCurve, DhParam, Protocols, GetBinding());
|
1137
1189
|
_DispatchCiphertext();
|
1138
|
-
#endif
|
1139
1190
|
|
1140
|
-
|
1191
|
+
}
|
1192
|
+
#else
|
1193
|
+
void ConnectionDescriptor::StartTls()
|
1194
|
+
{
|
1141
1195
|
throw std::runtime_error ("Encryption not available on this event-machine");
|
1142
|
-
#endif
|
1143
1196
|
}
|
1197
|
+
#endif
|
1144
1198
|
|
1145
1199
|
|
1146
1200
|
/*********************************
|
1147
1201
|
ConnectionDescriptor::SetTlsParms
|
1148
1202
|
*********************************/
|
1149
1203
|
|
1150
|
-
|
1204
|
+
#ifdef WITH_SSL
|
1205
|
+
void ConnectionDescriptor::SetTlsParms (const char *privkey_filename, const char *certchain_filename, bool verify_peer, bool fail_if_no_peer_cert, const char *sni_hostname, const char *cipherlist, const char *ecdh_curve, const char *dhparam, int protocols)
|
1151
1206
|
{
|
1152
|
-
#ifdef WITH_SSL
|
1153
1207
|
if (SslBox)
|
1154
1208
|
throw std::runtime_error ("call SetTlsParms before calling StartTls");
|
1155
1209
|
if (privkey_filename && *privkey_filename)
|
1156
1210
|
PrivateKeyFilename = privkey_filename;
|
1157
1211
|
if (certchain_filename && *certchain_filename)
|
1158
1212
|
CertChainFilename = certchain_filename;
|
1159
|
-
bSslVerifyPeer
|
1160
|
-
|
1213
|
+
bSslVerifyPeer = verify_peer;
|
1214
|
+
bSslFailIfNoPeerCert = fail_if_no_peer_cert;
|
1215
|
+
|
1216
|
+
if (sni_hostname && *sni_hostname)
|
1217
|
+
SniHostName = sni_hostname;
|
1218
|
+
if (cipherlist && *cipherlist)
|
1219
|
+
CipherList = cipherlist;
|
1220
|
+
if (ecdh_curve && *ecdh_curve)
|
1221
|
+
EcdhCurve = ecdh_curve;
|
1222
|
+
if (dhparam && *dhparam)
|
1223
|
+
DhParam = dhparam;
|
1161
1224
|
|
1162
|
-
|
1225
|
+
Protocols = protocols;
|
1226
|
+
}
|
1227
|
+
#else
|
1228
|
+
void ConnectionDescriptor::SetTlsParms (const char *privkey_filename UNUSED, const char *certchain_filename UNUSED, bool verify_peer UNUSED, bool fail_if_no_peer_cert UNUSED, const char *sni_hostname UNUSED, const char *cipherlist UNUSED, const char *ecdh_curve UNUSED, const char *dhparam UNUSED, int protocols UNUSED)
|
1229
|
+
{
|
1163
1230
|
throw std::runtime_error ("Encryption not available on this event-machine");
|
1164
|
-
#endif
|
1165
1231
|
}
|
1232
|
+
#endif
|
1166
1233
|
|
1167
1234
|
|
1168
1235
|
/*********************************
|
@@ -1179,6 +1246,62 @@ X509 *ConnectionDescriptor::GetPeerCert()
|
|
1179
1246
|
#endif
|
1180
1247
|
|
1181
1248
|
|
1249
|
+
/*********************************
|
1250
|
+
ConnectionDescriptor::GetCipherBits
|
1251
|
+
*********************************/
|
1252
|
+
|
1253
|
+
#ifdef WITH_SSL
|
1254
|
+
int ConnectionDescriptor::GetCipherBits()
|
1255
|
+
{
|
1256
|
+
if (!SslBox)
|
1257
|
+
throw std::runtime_error ("SSL/TLS not running on this connection");
|
1258
|
+
return SslBox->GetCipherBits();
|
1259
|
+
}
|
1260
|
+
#endif
|
1261
|
+
|
1262
|
+
|
1263
|
+
/*********************************
|
1264
|
+
ConnectionDescriptor::GetCipherName
|
1265
|
+
*********************************/
|
1266
|
+
|
1267
|
+
#ifdef WITH_SSL
|
1268
|
+
const char *ConnectionDescriptor::GetCipherName()
|
1269
|
+
{
|
1270
|
+
if (!SslBox)
|
1271
|
+
throw std::runtime_error ("SSL/TLS not running on this connection");
|
1272
|
+
return SslBox->GetCipherName();
|
1273
|
+
}
|
1274
|
+
#endif
|
1275
|
+
|
1276
|
+
|
1277
|
+
/*********************************
|
1278
|
+
ConnectionDescriptor::GetCipherProtocol
|
1279
|
+
*********************************/
|
1280
|
+
|
1281
|
+
#ifdef WITH_SSL
|
1282
|
+
const char *ConnectionDescriptor::GetCipherProtocol()
|
1283
|
+
{
|
1284
|
+
if (!SslBox)
|
1285
|
+
throw std::runtime_error ("SSL/TLS not running on this connection");
|
1286
|
+
return SslBox->GetCipherProtocol();
|
1287
|
+
}
|
1288
|
+
#endif
|
1289
|
+
|
1290
|
+
|
1291
|
+
/*********************************
|
1292
|
+
ConnectionDescriptor::GetSNIHostname
|
1293
|
+
*********************************/
|
1294
|
+
|
1295
|
+
#ifdef WITH_SSL
|
1296
|
+
const char *ConnectionDescriptor::GetSNIHostname()
|
1297
|
+
{
|
1298
|
+
if (!SslBox)
|
1299
|
+
throw std::runtime_error ("SSL/TLS not running on this connection");
|
1300
|
+
return SslBox->GetSNIHostname();
|
1301
|
+
}
|
1302
|
+
#endif
|
1303
|
+
|
1304
|
+
|
1182
1305
|
/***********************************
|
1183
1306
|
ConnectionDescriptor::VerifySslPeer
|
1184
1307
|
***********************************/
|
@@ -1218,7 +1341,7 @@ void ConnectionDescriptor::_DispatchCiphertext()
|
|
1218
1341
|
assert (SslBox);
|
1219
1342
|
|
1220
1343
|
|
1221
|
-
char BigBuf [
|
1344
|
+
char BigBuf [SSLBOX_OUTPUT_CHUNKSIZE];
|
1222
1345
|
bool did_work;
|
1223
1346
|
|
1224
1347
|
do {
|
@@ -1290,14 +1413,14 @@ void ConnectionDescriptor::Heartbeat()
|
|
1290
1413
|
UnbindReasonCode = ETIMEDOUT;
|
1291
1414
|
ScheduleClose (false);
|
1292
1415
|
//bCloseNow = true;
|
1293
|
-
|
1416
|
+
}
|
1294
1417
|
}
|
1295
1418
|
else {
|
1296
1419
|
if (InactivityTimeout && ((MyEventMachine->GetCurrentLoopTime() - LastActivity) >= InactivityTimeout)) {
|
1297
1420
|
UnbindReasonCode = ETIMEDOUT;
|
1298
1421
|
ScheduleClose (false);
|
1299
1422
|
//bCloseNow = true;
|
1300
|
-
|
1423
|
+
}
|
1301
1424
|
}
|
1302
1425
|
}
|
1303
1426
|
|
@@ -1306,7 +1429,7 @@ void ConnectionDescriptor::Heartbeat()
|
|
1306
1429
|
LoopbreakDescriptor::LoopbreakDescriptor
|
1307
1430
|
****************************************/
|
1308
1431
|
|
1309
|
-
LoopbreakDescriptor::LoopbreakDescriptor (
|
1432
|
+
LoopbreakDescriptor::LoopbreakDescriptor (SOCKET sd, EventMachine_t *parent_em):
|
1310
1433
|
EventableDescriptor (sd, parent_em)
|
1311
1434
|
{
|
1312
1435
|
/* This is really bad and ugly. Change someday if possible.
|
@@ -1345,15 +1468,15 @@ LoopbreakDescriptor::Write
|
|
1345
1468
|
|
1346
1469
|
void LoopbreakDescriptor::Write()
|
1347
1470
|
{
|
1348
|
-
|
1349
|
-
|
1471
|
+
// Why are we here?
|
1472
|
+
throw std::runtime_error ("bad code path in loopbreak");
|
1350
1473
|
}
|
1351
1474
|
|
1352
1475
|
/**************************************
|
1353
1476
|
AcceptorDescriptor::AcceptorDescriptor
|
1354
1477
|
**************************************/
|
1355
1478
|
|
1356
|
-
AcceptorDescriptor::AcceptorDescriptor (
|
1479
|
+
AcceptorDescriptor::AcceptorDescriptor (SOCKET sd, EventMachine_t *parent_em):
|
1357
1480
|
EventableDescriptor (sd, parent_em)
|
1358
1481
|
{
|
1359
1482
|
#ifdef HAVE_EPOLL
|
@@ -1377,7 +1500,7 @@ AcceptorDescriptor::~AcceptorDescriptor()
|
|
1377
1500
|
STATIC: AcceptorDescriptor::StopAcceptor
|
1378
1501
|
****************************************/
|
1379
1502
|
|
1380
|
-
void AcceptorDescriptor::StopAcceptor (const
|
1503
|
+
void AcceptorDescriptor::StopAcceptor (const uintptr_t binding)
|
1381
1504
|
{
|
1382
1505
|
// TODO: This is something of a hack, or at least it's a static method of the wrong class.
|
1383
1506
|
AcceptorDescriptor *ad = dynamic_cast <AcceptorDescriptor*> (Bindable_t::GetObject (binding));
|
@@ -1410,9 +1533,19 @@ void AcceptorDescriptor::Read()
|
|
1410
1533
|
|
1411
1534
|
struct sockaddr_in pin;
|
1412
1535
|
socklen_t addrlen = sizeof (pin);
|
1536
|
+
int accept_count = EventMachine_t::GetSimultaneousAcceptCount();
|
1413
1537
|
|
1414
|
-
for (int i=0; i <
|
1415
|
-
|
1538
|
+
for (int i=0; i < accept_count; i++) {
|
1539
|
+
#if defined(HAVE_CONST_SOCK_CLOEXEC) && defined(HAVE_ACCEPT4)
|
1540
|
+
SOCKET sd = accept4 (GetSocket(), (struct sockaddr*)&pin, &addrlen, SOCK_CLOEXEC);
|
1541
|
+
if (sd == INVALID_SOCKET) {
|
1542
|
+
// We may be running in a kernel where
|
1543
|
+
// SOCK_CLOEXEC is not supported - fall back:
|
1544
|
+
sd = accept (GetSocket(), (struct sockaddr*)&pin, &addrlen);
|
1545
|
+
}
|
1546
|
+
#else
|
1547
|
+
SOCKET sd = accept (GetSocket(), (struct sockaddr*)&pin, &addrlen);
|
1548
|
+
#endif
|
1416
1549
|
if (sd == INVALID_SOCKET) {
|
1417
1550
|
// This breaks the loop when we've accepted everything on the kernel queue,
|
1418
1551
|
// up to 10 new connections. But what if the *first* accept fails?
|
@@ -1421,10 +1554,10 @@ void AcceptorDescriptor::Read()
|
|
1421
1554
|
break;
|
1422
1555
|
}
|
1423
1556
|
|
1424
|
-
// Set the newly-accepted socket non-blocking.
|
1557
|
+
// Set the newly-accepted socket non-blocking and to close on exec.
|
1425
1558
|
// On Windows, this may fail because, weirdly, Windows inherits the non-blocking
|
1426
1559
|
// attribute that we applied to the acceptor socket into the accepted one.
|
1427
|
-
if (!SetSocketNonblocking (sd)) {
|
1560
|
+
if (!SetFdCloexec(sd) || !SetSocketNonblocking (sd)) {
|
1428
1561
|
//int val = fcntl (sd, F_GETFL, 0);
|
1429
1562
|
//if (fcntl (sd, F_SETFL, val | O_NONBLOCK) == -1) {
|
1430
1563
|
shutdown (sd, 1);
|
@@ -1432,7 +1565,6 @@ void AcceptorDescriptor::Read()
|
|
1432
1565
|
continue;
|
1433
1566
|
}
|
1434
1567
|
|
1435
|
-
|
1436
1568
|
// Disable slow-start (Nagle algorithm). Eventually make this configurable.
|
1437
1569
|
int one = 1;
|
1438
1570
|
setsockopt (sd, IPPROTO_TCP, TCP_NODELAY, (char*) &one, sizeof(one));
|
@@ -1446,14 +1578,18 @@ void AcceptorDescriptor::Read()
|
|
1446
1578
|
(*EventCallback) (GetBinding(), EM_CONNECTION_ACCEPTED, NULL, cd->GetBinding());
|
1447
1579
|
}
|
1448
1580
|
#ifdef HAVE_EPOLL
|
1449
|
-
cd->GetEpollEvent()->events =
|
1450
|
-
|
1581
|
+
cd->GetEpollEvent()->events = 0;
|
1582
|
+
if (cd->SelectForRead())
|
1583
|
+
cd->GetEpollEvent()->events |= EPOLLIN;
|
1584
|
+
if (cd->SelectForWrite())
|
1585
|
+
cd->GetEpollEvent()->events |= EPOLLOUT;
|
1451
1586
|
#endif
|
1452
1587
|
assert (MyEventMachine);
|
1453
1588
|
MyEventMachine->Add (cd);
|
1454
1589
|
#ifdef HAVE_KQUEUE
|
1455
|
-
|
1456
|
-
|
1590
|
+
bKqueueArmWrite = cd->SelectForWrite();
|
1591
|
+
if (bKqueueArmWrite)
|
1592
|
+
MyEventMachine->Modify (cd);
|
1457
1593
|
if (cd->SelectForRead())
|
1458
1594
|
MyEventMachine->ArmKqueueReader (cd);
|
1459
1595
|
#endif
|
@@ -1468,8 +1604,8 @@ AcceptorDescriptor::Write
|
|
1468
1604
|
|
1469
1605
|
void AcceptorDescriptor::Write()
|
1470
1606
|
{
|
1471
|
-
|
1472
|
-
|
1607
|
+
// Why are we here?
|
1608
|
+
throw std::runtime_error ("bad code path in acceptor");
|
1473
1609
|
}
|
1474
1610
|
|
1475
1611
|
|
@@ -1479,7 +1615,7 @@ AcceptorDescriptor::Heartbeat
|
|
1479
1615
|
|
1480
1616
|
void AcceptorDescriptor::Heartbeat()
|
1481
1617
|
{
|
1482
|
-
|
1618
|
+
// No-op
|
1483
1619
|
}
|
1484
1620
|
|
1485
1621
|
|
@@ -1504,7 +1640,7 @@ bool AcceptorDescriptor::GetSockname (struct sockaddr *s, socklen_t *len)
|
|
1504
1640
|
DatagramDescriptor::DatagramDescriptor
|
1505
1641
|
**************************************/
|
1506
1642
|
|
1507
|
-
DatagramDescriptor::DatagramDescriptor (
|
1643
|
+
DatagramDescriptor::DatagramDescriptor (SOCKET sd, EventMachine_t *parent_em):
|
1508
1644
|
EventableDescriptor (sd, parent_em),
|
1509
1645
|
OutboundDataSize (0)
|
1510
1646
|
{
|
@@ -1572,7 +1708,7 @@ DatagramDescriptor::Read
|
|
1572
1708
|
|
1573
1709
|
void DatagramDescriptor::Read()
|
1574
1710
|
{
|
1575
|
-
|
1711
|
+
SOCKET sd = GetSocket();
|
1576
1712
|
assert (sd != INVALID_SOCKET);
|
1577
1713
|
LastActivity = MyEventMachine->GetCurrentLoopTime();
|
1578
1714
|
|
@@ -1649,7 +1785,7 @@ void DatagramDescriptor::Write()
|
|
1649
1785
|
* TODO, we are currently suppressing the EMSGSIZE error!!!
|
1650
1786
|
*/
|
1651
1787
|
|
1652
|
-
|
1788
|
+
SOCKET sd = GetSocket();
|
1653
1789
|
assert (sd != INVALID_SOCKET);
|
1654
1790
|
LastActivity = MyEventMachine->GetCurrentLoopTime();
|
1655
1791
|
|
@@ -1662,8 +1798,13 @@ void DatagramDescriptor::Write()
|
|
1662
1798
|
OutboundPage *op = &(OutboundPages[0]);
|
1663
1799
|
|
1664
1800
|
// The nasty cast to (char*) is needed because Windows is brain-dead.
|
1665
|
-
int s = sendto (sd, (char*)op->Buffer, op->Length, 0, (struct sockaddr*)&(op->From),
|
1801
|
+
int s = sendto (sd, (char*)op->Buffer, op->Length, 0, (struct sockaddr*)&(op->From),
|
1802
|
+
(op->From.sin6_family == AF_INET6 ? sizeof (struct sockaddr_in6) : sizeof (struct sockaddr_in)));
|
1803
|
+
#ifdef OS_WIN32
|
1804
|
+
int e = WSAGetLastError();
|
1805
|
+
#else
|
1666
1806
|
int e = errno;
|
1807
|
+
#endif
|
1667
1808
|
|
1668
1809
|
OutboundDataSize -= op->Length;
|
1669
1810
|
op->Free();
|
@@ -1684,13 +1825,16 @@ void DatagramDescriptor::Write()
|
|
1684
1825
|
}
|
1685
1826
|
|
1686
1827
|
#ifdef HAVE_EPOLL
|
1687
|
-
EpollEvent.events =
|
1828
|
+
EpollEvent.events = EPOLLIN;
|
1829
|
+
if (SelectForWrite())
|
1830
|
+
EpollEvent.events |= EPOLLOUT;
|
1688
1831
|
assert (MyEventMachine);
|
1689
1832
|
MyEventMachine->Modify (this);
|
1690
1833
|
#endif
|
1691
1834
|
#ifdef HAVE_KQUEUE
|
1692
|
-
|
1693
|
-
|
1835
|
+
bKqueueArmWrite = SelectForWrite();
|
1836
|
+
assert (MyEventMachine);
|
1837
|
+
MyEventMachine->Modify (this);
|
1694
1838
|
#endif
|
1695
1839
|
}
|
1696
1840
|
|
@@ -1716,7 +1860,7 @@ bool DatagramDescriptor::SelectForWrite()
|
|
1716
1860
|
DatagramDescriptor::SendOutboundData
|
1717
1861
|
************************************/
|
1718
1862
|
|
1719
|
-
int DatagramDescriptor::SendOutboundData (const char *data,
|
1863
|
+
int DatagramDescriptor::SendOutboundData (const char *data, unsigned long length)
|
1720
1864
|
{
|
1721
1865
|
// This is almost an exact clone of ConnectionDescriptor::_SendRawOutboundData.
|
1722
1866
|
// That means most of it could be factored to a common ancestor. Note that
|
@@ -1741,7 +1885,9 @@ int DatagramDescriptor::SendOutboundData (const char *data, int length)
|
|
1741
1885
|
MyEventMachine->Modify (this);
|
1742
1886
|
#endif
|
1743
1887
|
#ifdef HAVE_KQUEUE
|
1744
|
-
|
1888
|
+
bKqueueArmWrite = true;
|
1889
|
+
assert (MyEventMachine);
|
1890
|
+
MyEventMachine->Modify (this);
|
1745
1891
|
#endif
|
1746
1892
|
|
1747
1893
|
return length;
|
@@ -1752,7 +1898,7 @@ int DatagramDescriptor::SendOutboundData (const char *data, int length)
|
|
1752
1898
|
DatagramDescriptor::SendOutboundDatagram
|
1753
1899
|
****************************************/
|
1754
1900
|
|
1755
|
-
int DatagramDescriptor::SendOutboundDatagram (const char *data,
|
1901
|
+
int DatagramDescriptor::SendOutboundDatagram (const char *data, unsigned long length, const char *address, int port)
|
1756
1902
|
{
|
1757
1903
|
// This is an exact clone of ConnectionDescriptor::SendOutboundData.
|
1758
1904
|
// That means it needs to move to a common ancestor.
|
@@ -1765,23 +1911,10 @@ int DatagramDescriptor::SendOutboundDatagram (const char *data, int length, cons
|
|
1765
1911
|
if (!address || !*address || !port)
|
1766
1912
|
return 0;
|
1767
1913
|
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
if (HostAddr == INADDR_NONE) {
|
1773
|
-
// The nasty cast to (char*) is because Windows is brain-dead.
|
1774
|
-
hostent *hp = gethostbyname ((char*)address);
|
1775
|
-
if (!hp)
|
1776
|
-
return 0;
|
1777
|
-
HostAddr = ((in_addr*)(hp->h_addr))->s_addr;
|
1778
|
-
}
|
1779
|
-
|
1780
|
-
memset (&pin, 0, sizeof(pin));
|
1781
|
-
pin.sin_family = AF_INET;
|
1782
|
-
pin.sin_addr.s_addr = HostAddr;
|
1783
|
-
pin.sin_port = htons (port);
|
1784
|
-
|
1914
|
+
struct sockaddr_in6 addr_here;
|
1915
|
+
size_t addr_here_len = sizeof addr_here;
|
1916
|
+
if (!EventMachine_t::name2address (address, port, (struct sockaddr *)&addr_here, &addr_here_len))
|
1917
|
+
return -1;
|
1785
1918
|
|
1786
1919
|
if (!data && (length > 0))
|
1787
1920
|
throw std::runtime_error ("bad outbound data");
|
@@ -1790,7 +1923,7 @@ int DatagramDescriptor::SendOutboundDatagram (const char *data, int length, cons
|
|
1790
1923
|
throw std::runtime_error ("no allocation for outbound data");
|
1791
1924
|
memcpy (buffer, data, length);
|
1792
1925
|
buffer [length] = 0;
|
1793
|
-
OutboundPages.push_back (OutboundPage (buffer, length,
|
1926
|
+
OutboundPages.push_back (OutboundPage (buffer, length, addr_here));
|
1794
1927
|
OutboundDataSize += length;
|
1795
1928
|
|
1796
1929
|
#ifdef HAVE_EPOLL
|
@@ -1799,7 +1932,9 @@ int DatagramDescriptor::SendOutboundDatagram (const char *data, int length, cons
|
|
1799
1932
|
MyEventMachine->Modify (this);
|
1800
1933
|
#endif
|
1801
1934
|
#ifdef HAVE_KQUEUE
|
1802
|
-
|
1935
|
+
bKqueueArmWrite = true;
|
1936
|
+
assert (MyEventMachine);
|
1937
|
+
MyEventMachine->Modify (this);
|
1803
1938
|
#endif
|
1804
1939
|
|
1805
1940
|
return length;
|