eventmachine 1.0.3-x86-mingw32 → 1.2.0.dev.2-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +84 -1
  3. data/README.md +6 -7
  4. data/ext/binder.cpp +10 -10
  5. data/ext/binder.h +5 -5
  6. data/ext/cmain.cpp +173 -61
  7. data/ext/ed.cpp +262 -127
  8. data/ext/ed.h +50 -30
  9. data/ext/em.cpp +491 -445
  10. data/ext/em.h +101 -36
  11. data/ext/eventmachine.h +67 -51
  12. data/ext/extconf.rb +124 -31
  13. data/ext/fastfilereader/extconf.rb +9 -2
  14. data/ext/fastfilereader/mapper.cpp +3 -1
  15. data/ext/fastfilereader/rubymain.cpp +7 -7
  16. data/ext/kb.cpp +1 -1
  17. data/ext/pipe.cpp +11 -4
  18. data/ext/project.h +26 -6
  19. data/ext/rubymain.cpp +408 -201
  20. data/ext/ssl.cpp +167 -20
  21. data/ext/ssl.h +11 -2
  22. data/java/src/com/rubyeventmachine/EmReactor.java +16 -0
  23. data/java/src/com/rubyeventmachine/EventableChannel.java +2 -0
  24. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +6 -0
  25. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +55 -10
  26. data/lib/1.9/fastfilereaderext.so +0 -0
  27. data/lib/1.9/rubyeventmachine.so +0 -0
  28. data/lib/2.0/fastfilereaderext.so +0 -0
  29. data/lib/2.0/rubyeventmachine.so +0 -0
  30. data/lib/2.1/fastfilereaderext.so +0 -0
  31. data/lib/2.1/rubyeventmachine.so +0 -0
  32. data/lib/2.2/fastfilereaderext.so +0 -0
  33. data/lib/2.2/rubyeventmachine.so +0 -0
  34. data/lib/2.3/fastfilereaderext.so +0 -0
  35. data/lib/2.3/rubyeventmachine.so +0 -0
  36. data/lib/em/buftok.rb +34 -85
  37. data/lib/em/channel.rb +5 -0
  38. data/lib/em/completion.rb +2 -2
  39. data/lib/em/connection.rb +62 -4
  40. data/lib/em/iterator.rb +30 -48
  41. data/lib/em/pool.rb +1 -1
  42. data/lib/em/protocols/httpclient.rb +31 -11
  43. data/lib/em/protocols/line_and_text.rb +4 -4
  44. data/lib/em/protocols/linetext2.rb +44 -39
  45. data/lib/em/protocols/smtpclient.rb +60 -31
  46. data/lib/em/protocols/smtpserver.rb +32 -9
  47. data/lib/em/pure_ruby.rb +8 -3
  48. data/lib/em/queue.rb +16 -7
  49. data/lib/em/resolver.rb +64 -24
  50. data/lib/em/threaded_resource.rb +2 -2
  51. data/lib/em/tick_loop.rb +19 -19
  52. data/lib/em/version.rb +1 -1
  53. data/lib/eventmachine.rb +96 -49
  54. data/lib/jeventmachine.rb +17 -0
  55. data/rakelib/package.rake +31 -4
  56. data/tests/dhparam.pem +13 -0
  57. data/tests/em_test_helper.rb +87 -0
  58. data/tests/test_attach.rb +25 -0
  59. data/tests/test_basic.rb +27 -38
  60. data/tests/test_channel.rb +14 -1
  61. data/tests/test_completion.rb +1 -0
  62. data/tests/test_connection_count.rb +22 -1
  63. data/tests/test_connection_write.rb +35 -0
  64. data/tests/test_defer.rb +17 -0
  65. data/tests/test_epoll.rb +26 -14
  66. data/tests/test_file_watch.rb +1 -0
  67. data/tests/test_fork.rb +75 -0
  68. data/tests/test_httpclient.rb +43 -0
  69. data/tests/test_idle_connection.rb +6 -4
  70. data/tests/test_ipv4.rb +125 -0
  71. data/tests/test_ipv6.rb +131 -0
  72. data/tests/test_iterator.rb +115 -0
  73. data/tests/test_kb.rb +19 -25
  74. data/tests/test_ltp2.rb +20 -0
  75. data/tests/test_many_fds.rb +22 -0
  76. data/tests/test_pause.rb +29 -0
  77. data/tests/test_pool.rb +2 -0
  78. data/tests/test_process_watch.rb +2 -0
  79. data/tests/test_processes.rb +7 -7
  80. data/tests/test_queue.rb +14 -0
  81. data/tests/test_resolver.rb +56 -7
  82. data/tests/test_set_sock_opt.rb +2 -0
  83. data/tests/test_smtpclient.rb +20 -0
  84. data/tests/test_ssl_args.rb +2 -2
  85. data/tests/test_ssl_dhparam.rb +83 -0
  86. data/tests/test_ssl_ecdh_curve.rb +79 -0
  87. data/tests/test_ssl_extensions.rb +49 -0
  88. data/tests/test_ssl_methods.rb +22 -5
  89. data/tests/test_ssl_protocols.rb +246 -0
  90. data/tests/test_ssl_verify.rb +103 -59
  91. data/tests/test_system.rb +4 -0
  92. data/tests/test_threaded_resource.rb +8 -0
  93. data/tests/test_unbind_reason.rb +5 -1
  94. metadata +173 -107
  95. data/.gitignore +0 -21
  96. data/.travis.yml +0 -12
  97. data/.yardopts +0 -7
  98. data/Gemfile +0 -2
  99. data/Rakefile +0 -20
  100. data/eventmachine.gemspec +0 -36
  101. 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 (int sd, EventMachine_t *em):
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 unsigned long to, const unsigned long bufsize, const unsigned long length)
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, int size)
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, (unsigned long) size);
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 += (unsigned long) size;
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 (int sd, EventMachine_t *em):
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
- if (write && SelectForWrite())
452
- MyEventMachine->ArmKqueueWriter (this);
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
- bAttached = state;
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, int length)
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
- int w = SslBox->PutPlaintext (data, length);
568
- if (w < 0)
569
- ScheduleClose (false);
570
- else
571
- _DispatchCiphertext();
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, int length)
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
- /* A connection descriptor is always scheduled for read,
634
- * UNLESS it's in a pending-connect state.
635
- * On Linux, unlike Unix, a nonblocking socket on which
636
- * connect has been called, does NOT necessarily select
637
- * both readable and writable in case of error.
638
- * The socket will select writable when the disposition
639
- * of the connect is known. On the other hand, a socket
640
- * which successfully connects and selects writable may
641
- * indeed have some data available on it, so it will
642
- * select readable in that case, violating expectations!
643
- * So we will not poll for readability until the socket
644
- * is known to be in a connected state.
645
- */
646
-
647
- if (bPaused)
648
- return false;
649
- else if (bConnectPending)
650
- return false;
651
- else if (bWatchOnly)
652
- return bNotifyReadable ? true : false;
653
- else
654
- return true;
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
- /* Cf the notes under SelectForRead.
665
- * In a pending-connect state, we ALWAYS select for writable.
666
- * In a normal state, we only select for writable when we
667
- * have outgoing data to send.
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
- if (bPaused)
671
- return false;
672
- else if (bConnectPending)
673
- return true;
674
- else if (bWatchOnly)
675
- return bNotifyWritable ? true : false;
676
- else
677
- return (GetOutboundDataSize() > 0);
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
- int sd = GetSocket();
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
- void ConnectionDescriptor::_DispatchInboundData (const char *buffer, int size)
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
- #endif
849
-
850
- #ifdef WITHOUT_SSL
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->UsingKqueue()) {
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
- int sd = GetSocket();
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
- #ifdef CC_SUNWspro
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
- #ifdef WITHOUT_SSL
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
- void ConnectionDescriptor::SetTlsParms (const char *privkey_filename, const char *certchain_filename, bool verify_peer)
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 = verify_peer;
1160
- #endif
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
- #ifdef WITHOUT_SSL
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 [2048];
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 (int sd, EventMachine_t *parent_em):
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
- // Why are we here?
1349
- throw std::runtime_error ("bad code path in loopbreak");
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 (int sd, EventMachine_t *parent_em):
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 unsigned long binding)
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 < 10; i++) {
1415
- int sd = accept (GetSocket(), (struct sockaddr*)&pin, &addrlen);
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
- (cd->SelectForRead() ? EPOLLIN : 0) | (cd->SelectForWrite() ? EPOLLOUT : 0);
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
- if (cd->SelectForWrite())
1456
- MyEventMachine->ArmKqueueWriter (cd);
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
- // Why are we here?
1472
- throw std::runtime_error ("bad code path in acceptor");
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
- // No-op
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 (int sd, EventMachine_t *parent_em):
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
- int sd = GetSocket();
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
- int sd = GetSocket();
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), sizeof(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 = (EPOLLIN | (SelectForWrite() ? EPOLLOUT : 0));
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
- if (SelectForWrite())
1693
- MyEventMachine->ArmKqueueWriter (this);
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, int length)
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
- MyEventMachine->ArmKqueueWriter (this);
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, int length, const char *address, int port)
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
- sockaddr_in pin;
1769
- unsigned long HostAddr;
1770
-
1771
- HostAddr = inet_addr (address);
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, pin));
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
- MyEventMachine->ArmKqueueWriter (this);
1935
+ bKqueueArmWrite = true;
1936
+ assert (MyEventMachine);
1937
+ MyEventMachine->Modify (this);
1803
1938
  #endif
1804
1939
 
1805
1940
  return length;