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.
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;