eventmachine 0.12.6 → 0.12.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/{docs/README → README} +21 -13
  2. data/Rakefile +14 -4
  3. data/docs/DEFERRABLES +0 -5
  4. data/docs/INSTALL +2 -4
  5. data/docs/LEGAL +1 -1
  6. data/docs/LIGHTWEIGHT_CONCURRENCY +0 -2
  7. data/docs/PURE_RUBY +0 -2
  8. data/docs/RELEASE_NOTES +0 -2
  9. data/docs/SMTP +0 -7
  10. data/docs/SPAWNED_PROCESSES +0 -4
  11. data/docs/TODO +0 -2
  12. data/eventmachine.gemspec +17 -8
  13. data/examples/ex_channel.rb +43 -0
  14. data/examples/ex_queue.rb +2 -0
  15. data/examples/helper.rb +2 -0
  16. data/ext/cmain.cpp +119 -20
  17. data/ext/cplusplus.cpp +15 -6
  18. data/ext/ed.cpp +303 -93
  19. data/ext/ed.h +49 -22
  20. data/ext/em.cpp +368 -42
  21. data/ext/em.h +43 -6
  22. data/ext/eventmachine.h +21 -8
  23. data/ext/eventmachine_cpp.h +1 -0
  24. data/ext/extconf.rb +4 -0
  25. data/ext/kb.cpp +1 -2
  26. data/ext/pipe.cpp +1 -3
  27. data/ext/project.h +21 -0
  28. data/ext/rubymain.cpp +232 -32
  29. data/ext/ssl.cpp +38 -1
  30. data/ext/ssl.h +5 -1
  31. data/java/src/com/rubyeventmachine/Application.java +7 -3
  32. data/java/src/com/rubyeventmachine/EmReactor.java +16 -1
  33. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +25 -3
  34. data/lib/{protocols → em}/buftok.rb +16 -5
  35. data/lib/em/callback.rb +26 -0
  36. data/lib/em/channel.rb +57 -0
  37. data/lib/em/connection.rb +505 -0
  38. data/lib/em/deferrable.rb +144 -165
  39. data/lib/em/file_watch.rb +54 -0
  40. data/lib/em/future.rb +24 -25
  41. data/lib/em/messages.rb +1 -1
  42. data/lib/em/process_watch.rb +44 -0
  43. data/lib/em/processes.rb +58 -52
  44. data/lib/em/protocols.rb +35 -0
  45. data/lib/em/protocols/header_and_content.rb +138 -0
  46. data/lib/em/protocols/httpclient.rb +263 -0
  47. data/lib/em/protocols/httpclient2.rb +582 -0
  48. data/lib/{protocols → em/protocols}/line_and_text.rb +2 -2
  49. data/lib/em/protocols/linetext2.rb +160 -0
  50. data/lib/{protocols → em/protocols}/memcache.rb +37 -7
  51. data/lib/em/protocols/object_protocol.rb +39 -0
  52. data/lib/em/protocols/postgres3.rb +247 -0
  53. data/lib/em/protocols/saslauth.rb +175 -0
  54. data/lib/em/protocols/smtpclient.rb +331 -0
  55. data/lib/em/protocols/smtpserver.rb +547 -0
  56. data/lib/em/protocols/stomp.rb +200 -0
  57. data/lib/{protocols → em/protocols}/tcptest.rb +21 -25
  58. data/lib/em/queue.rb +61 -0
  59. data/lib/em/spawnable.rb +53 -56
  60. data/lib/em/streamer.rb +92 -74
  61. data/lib/em/timers.rb +55 -0
  62. data/lib/em/version.rb +3 -0
  63. data/lib/eventmachine.rb +1008 -1298
  64. data/lib/evma.rb +1 -1
  65. data/lib/jeventmachine.rb +106 -101
  66. data/lib/pr_eventmachine.rb +47 -36
  67. data/tasks/project.rake +2 -1
  68. data/tests/client.crt +31 -0
  69. data/tests/client.key +51 -0
  70. data/tests/test_attach.rb +18 -0
  71. data/tests/test_basic.rb +108 -54
  72. data/tests/test_channel.rb +63 -0
  73. data/tests/test_connection_count.rb +2 -2
  74. data/tests/test_epoll.rb +109 -110
  75. data/tests/test_errors.rb +36 -36
  76. data/tests/test_exc.rb +22 -25
  77. data/tests/test_file_watch.rb +49 -0
  78. data/tests/test_futures.rb +77 -93
  79. data/tests/test_hc.rb +2 -2
  80. data/tests/test_httpclient.rb +55 -52
  81. data/tests/test_httpclient2.rb +110 -112
  82. data/tests/test_inactivity_timeout.rb +30 -0
  83. data/tests/test_kb.rb +8 -9
  84. data/tests/test_ltp2.rb +274 -277
  85. data/tests/test_next_tick.rb +91 -65
  86. data/tests/test_object_protocol.rb +37 -0
  87. data/tests/test_process_watch.rb +48 -0
  88. data/tests/test_processes.rb +56 -23
  89. data/tests/test_proxy_connection.rb +92 -0
  90. data/tests/test_pure.rb +1 -5
  91. data/tests/test_queue.rb +44 -0
  92. data/tests/test_running.rb +9 -14
  93. data/tests/test_sasl.rb +32 -34
  94. data/tests/test_send_file.rb +175 -176
  95. data/tests/test_servers.rb +37 -41
  96. data/tests/test_smtpserver.rb +47 -55
  97. data/tests/test_spawn.rb +284 -291
  98. data/tests/test_ssl_args.rb +1 -1
  99. data/tests/test_ssl_methods.rb +1 -1
  100. data/tests/test_ssl_verify.rb +82 -0
  101. data/tests/test_timers.rb +81 -88
  102. data/tests/test_ud.rb +0 -7
  103. data/tests/testem.rb +1 -1
  104. metadata +68 -39
  105. data/lib/em/eventable.rb +0 -39
  106. data/lib/eventmachine_version.rb +0 -31
  107. data/lib/protocols/header_and_content.rb +0 -129
  108. data/lib/protocols/httpcli2.rb +0 -803
  109. data/lib/protocols/httpclient.rb +0 -270
  110. data/lib/protocols/linetext2.rb +0 -161
  111. data/lib/protocols/postgres.rb +0 -261
  112. data/lib/protocols/saslauth.rb +0 -179
  113. data/lib/protocols/smtpclient.rb +0 -308
  114. data/lib/protocols/smtpserver.rb +0 -556
  115. data/lib/protocols/stomp.rb +0 -153
  116. data/tests/test_eventables.rb +0 -77
@@ -33,7 +33,7 @@ EM::Run
33
33
 
34
34
  void EM::Run (void (*start_func)())
35
35
  {
36
- evma__epoll();
36
+ evma_set_epoll (1);
37
37
  evma_initialize_library (EM::Callback);
38
38
  if (start_func)
39
39
  AddTimer (0, start_func);
@@ -115,13 +115,13 @@ void EM::Connection::Close (bool afterWriting)
115
115
  }
116
116
 
117
117
 
118
- /***********************
119
- EM::Connection::Connect
120
- ***********************/
118
+ /***************************
119
+ EM::Connection::BindConnect
120
+ ***************************/
121
121
 
122
- void EM::Connection::Connect (const char *host, int port)
122
+ void EM::Connection::BindConnect (const char *bind_addr, int bind_port, const char *host, int port)
123
123
  {
124
- Signature = evma_connect_to_server (host, port);
124
+ Signature = evma_connect_to_server (bind_addr, bind_port, host, port);
125
125
  #ifdef OS_SOLARIS8
126
126
  Eventables.insert( std::map<std::string,EM::Eventable*>::value_type (Signature, this));
127
127
  #else
@@ -129,6 +129,15 @@ void EM::Connection::Connect (const char *host, int port)
129
129
  #endif
130
130
  }
131
131
 
132
+ /***********************
133
+ EM::Connection::Connect
134
+ ***********************/
135
+
136
+ void EM::Connection::Connect (const char *host, int port)
137
+ {
138
+ this->BindConnect(NULL, 0, host, port);
139
+ }
140
+
132
141
  /*******************
133
142
  EM::Acceptor::Start
134
143
  *******************/
data/ext/ed.cpp CHANGED
@@ -48,10 +48,9 @@ EventableDescriptor::EventableDescriptor (int sd, EventMachine_t *em):
48
48
  bCloseAfterWriting (false),
49
49
  MySocket (sd),
50
50
  EventCallback (NULL),
51
- LastRead (0),
52
- LastWritten (0),
53
51
  bCallbackUnbind (true),
54
52
  UnbindReasonCode (0),
53
+ ProxyTarget(NULL),
55
54
  MyEventMachine (em)
56
55
  {
57
56
  /* There are three ways to close a socket, all of which should
@@ -95,6 +94,7 @@ EventableDescriptor::~EventableDescriptor()
95
94
  {
96
95
  if (EventCallback && bCallbackUnbind)
97
96
  (*EventCallback)(GetBinding().c_str(), EM_CONNECTION_UNBOUND, NULL, UnbindReasonCode);
97
+ StopProxy();
98
98
  Close();
99
99
  }
100
100
 
@@ -168,6 +168,52 @@ bool EventableDescriptor::IsCloseScheduled()
168
168
  }
169
169
 
170
170
 
171
+ /*******************************
172
+ EventableDescriptor::StartProxy
173
+ *******************************/
174
+
175
+ void EventableDescriptor::StartProxy(const char *to)
176
+ {
177
+ EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (to));
178
+ if (ed) {
179
+ StopProxy();
180
+ ProxyTarget = strdup(to);
181
+ return;
182
+ }
183
+ throw std::runtime_error ("Tried to proxy to an invalid descriptor");
184
+ }
185
+
186
+
187
+ /******************************
188
+ EventableDescriptor::StopProxy
189
+ ******************************/
190
+
191
+ void EventableDescriptor::StopProxy()
192
+ {
193
+ if (ProxyTarget) {
194
+ free(ProxyTarget);
195
+ ProxyTarget = NULL;
196
+ }
197
+ }
198
+
199
+
200
+ /********************************************
201
+ EventableDescriptor::_GenericInboundDispatch
202
+ ********************************************/
203
+
204
+ void EventableDescriptor::_GenericInboundDispatch(const char *buf, int size)
205
+ {
206
+ assert(EventCallback);
207
+
208
+ if (!ProxyTarget)
209
+ (*EventCallback)(GetBinding().c_str(), EM_CONNECTION_READ, buf, size);
210
+ else if (ConnectionDescriptor::SendDataToConnection(ProxyTarget, buf, size) == -1) {
211
+ (*EventCallback)(GetBinding().c_str(), EM_PROXY_TARGET_UNBOUND, NULL, 0);
212
+ StopProxy();
213
+ }
214
+ }
215
+
216
+
171
217
  /******************************************
172
218
  ConnectionDescriptor::ConnectionDescriptor
173
219
  ******************************************/
@@ -183,15 +229,18 @@ ConnectionDescriptor::ConnectionDescriptor (int sd, EventMachine_t *em):
183
229
  #ifdef WITH_SSL
184
230
  SslBox (NULL),
185
231
  bHandshakeSignaled (false),
232
+ bSslVerifyPeer (false),
233
+ bSslPeerAccepted(false),
234
+ #endif
235
+ #ifdef HAVE_KQUEUE
236
+ bGotExtraKqueueEvent(false),
186
237
  #endif
187
238
  bIsServer (false),
188
239
  LastIo (gCurrentLoopTime),
189
240
  InactivityTimeout (0)
190
241
  {
191
- #ifdef HAVE_EPOLL
192
- EpollEvent.events = EPOLLOUT;
193
- #endif
194
242
  // 22Jan09: Moved ArmKqueueWriter into SetConnectPending() to fix assertion failure in _WriteOutboundData()
243
+ // 5May09: Moved EPOLLOUT into SetConnectPending() so it doesn't happen for attached read pipes
195
244
  }
196
245
 
197
246
 
@@ -270,9 +319,60 @@ ConnectionDescriptor::SetConnectPending
270
319
  void ConnectionDescriptor::SetConnectPending(bool f)
271
320
  {
272
321
  bConnectPending = f;
273
- #ifdef HAVE_KQUEUE
274
- MyEventMachine->ArmKqueueWriter (this);
275
- #endif
322
+
323
+ if (bConnectPending) { // not yet connected, select for writability
324
+ #ifdef HAVE_EPOLL
325
+ EpollEvent.events = EPOLLOUT;
326
+ #endif
327
+ #ifdef HAVE_KQUEUE
328
+ MyEventMachine->ArmKqueueWriter (this);
329
+ #endif
330
+ } else { // connected, wait for incoming data and write out any pending outgoing data
331
+ #ifdef HAVE_EPOLL
332
+ EpollEvent.events = EPOLLIN | (SelectForWrite() ? EPOLLOUT : 0);
333
+ #endif
334
+ #ifdef HAVE_KQUEUE
335
+ MyEventMachine->ArmKqueueReader (this);
336
+ if (SelectForWrite())
337
+ MyEventMachine->ArmKqueueWriter (this);
338
+ #endif
339
+ }
340
+ }
341
+
342
+
343
+ /***************************************
344
+ ConnectionDescriptor::SetNotifyReadable
345
+ ****************************************/
346
+
347
+ void ConnectionDescriptor::SetNotifyReadable(bool readable)
348
+ {
349
+ bNotifyReadable = readable;
350
+ if (bNotifyReadable) {
351
+ #ifdef HAVE_EPOLL
352
+ EpollEvent.events |= EPOLLIN;
353
+ #endif
354
+ #ifdef HAVE_KQUEUE
355
+ MyEventMachine->ArmKqueueReader (this);
356
+ #endif
357
+ }
358
+ }
359
+
360
+
361
+ /***************************************
362
+ ConnectionDescriptor::SetNotifyWritable
363
+ ****************************************/
364
+
365
+ void ConnectionDescriptor::SetNotifyWritable(bool writable)
366
+ {
367
+ bNotifyWritable = writable;
368
+ if (bNotifyWritable) {
369
+ #ifdef HAVE_EPOLL
370
+ EpollEvent.events |= EPOLLOUT;
371
+ #endif
372
+ #ifdef HAVE_KQUEUE
373
+ MyEventMachine->ArmKqueueWriter (this);
374
+ #endif
375
+ }
276
376
  }
277
377
 
278
378
 
@@ -328,10 +428,12 @@ int ConnectionDescriptor::_SendRawOutboundData (const char *data, int length)
328
428
  char *buffer = (char *) malloc (length + 1);
329
429
  if (!buffer)
330
430
  throw std::runtime_error ("no allocation for outbound data");
431
+
331
432
  memcpy (buffer, data, length);
332
433
  buffer [length] = 0;
333
434
  OutboundPages.push_back (OutboundPage (buffer, length));
334
435
  OutboundDataSize += length;
436
+
335
437
  #ifdef HAVE_EPOLL
336
438
  EpollEvent.events = (EPOLLIN | EPOLLOUT);
337
439
  assert (MyEventMachine);
@@ -340,6 +442,7 @@ int ConnectionDescriptor::_SendRawOutboundData (const char *data, int length)
340
442
  #ifdef HAVE_KQUEUE
341
443
  MyEventMachine->ArmKqueueWriter (this);
342
444
  #endif
445
+
343
446
  return length;
344
447
  }
345
448
 
@@ -446,12 +549,11 @@ void ConnectionDescriptor::Read()
446
549
  // to user code.
447
550
 
448
551
 
449
- int r = recv (sd, readbuffer, sizeof(readbuffer) - 1, 0);
552
+ int r = read (sd, readbuffer, sizeof(readbuffer) - 1);
450
553
  //cerr << "<R:" << r << ">";
451
554
 
452
555
  if (r > 0) {
453
556
  total_bytes_read += r;
454
- LastRead = gCurrentLoopTime;
455
557
 
456
558
  // Add a null-terminator at the the end of the buffer
457
559
  // that we will send to the callback.
@@ -499,22 +601,25 @@ void ConnectionDescriptor::_DispatchInboundData (const char *buffer, int size)
499
601
  while ((s = SslBox->GetPlaintext (B, sizeof(B) - 1)) > 0) {
500
602
  _CheckHandshakeStatus();
501
603
  B [s] = 0;
502
- if (EventCallback)
503
- (*EventCallback)(GetBinding().c_str(), EM_CONNECTION_READ, B, s);
604
+ _GenericInboundDispatch(B, s);
605
+ }
606
+
607
+ // If our SSL handshake had a problem, shut down the connection.
608
+ if (s == -2) {
609
+ ScheduleClose(false);
610
+ return;
504
611
  }
612
+
505
613
  _CheckHandshakeStatus();
506
- // INCOMPLETE, s may indicate an SSL error that would force the connection down.
507
614
  _DispatchCiphertext();
508
615
  }
509
616
  else {
510
- if (EventCallback)
511
- (*EventCallback)(GetBinding().c_str(), EM_CONNECTION_READ, buffer, size);
617
+ _GenericInboundDispatch(buffer, size);
512
618
  }
513
619
  #endif
514
620
 
515
621
  #ifdef WITHOUT_SSL
516
- if (EventCallback)
517
- (*EventCallback)(GetBinding().c_str(), EM_CONNECTION_READ, buffer, size);
622
+ _GenericInboundDispatch(buffer, size);
518
623
  #endif
519
624
  }
520
625
 
@@ -568,17 +673,10 @@ void ConnectionDescriptor::Write()
568
673
  if ((o == 0) && (error == 0)) {
569
674
  if (EventCallback)
570
675
  (*EventCallback)(GetBinding().c_str(), EM_CONNECTION_COMPLETED, "", 0);
571
- bConnectPending = false;
572
- #ifdef HAVE_EPOLL
573
- // The callback may have scheduled outbound data.
574
- EpollEvent.events = EPOLLIN | (SelectForWrite() ? EPOLLOUT : 0);
575
- #endif
576
- #ifdef HAVE_KQUEUE
577
- MyEventMachine->ArmKqueueReader (this);
578
- // The callback may have scheduled outbound data.
579
- if (SelectForWrite())
580
- MyEventMachine->ArmKqueueWriter (this);
581
- #endif
676
+
677
+ // 5May09: Moved epoll/kqueue read/write arming into SetConnectPending, so it can be called
678
+ // from EventMachine_t::AttachFD as well.
679
+ SetConnectPending (false);
582
680
  }
583
681
  else
584
682
  ScheduleClose (false);
@@ -592,6 +690,22 @@ void ConnectionDescriptor::Write()
592
690
  return;
593
691
  }
594
692
 
693
+ /* 5May09: Kqueue bugs on OSX cause one extra writable event to fire even though we're using
694
+ EV_ONESHOT. We ignore this extra event once, but only the first time. If it happens again,
695
+ we should fall through to the assert(nbytes>0) failure to catch any EM bugs which might cause
696
+ ::Write to be called in a busy-loop.
697
+ */
698
+ #ifdef HAVE_KQUEUE
699
+ if (MyEventMachine->UsingKqueue()) {
700
+ if (OutboundDataSize == 0 && !bGotExtraKqueueEvent) {
701
+ bGotExtraKqueueEvent = true;
702
+ return;
703
+ } else if (OutboundDataSize > 0) {
704
+ bGotExtraKqueueEvent = false;
705
+ }
706
+ }
707
+ #endif
708
+
595
709
  _WriteOutboundData();
596
710
  }
597
711
  }
@@ -624,9 +738,25 @@ void ConnectionDescriptor::_WriteOutboundData()
624
738
  }
625
739
 
626
740
  LastIo = gCurrentLoopTime;
627
- char output_buffer [16 * 1024];
628
741
  size_t nbytes = 0;
629
742
 
743
+ #ifdef HAVE_WRITEV
744
+ int iovcnt = OutboundPages.size();
745
+ // Max of 16 outbound pages at a time
746
+ if (iovcnt > 16) iovcnt = 16;
747
+
748
+ struct iovec iov[ iovcnt ];
749
+
750
+ for(int i = 0; i < iovcnt; i++){
751
+ OutboundPage *op = &(OutboundPages[i]);
752
+ iov[i].iov_base = (void *)(op->Buffer + op->Offset);
753
+ iov[i].iov_len = op->Length - op->Offset;
754
+
755
+ nbytes += iov[i].iov_len;
756
+ }
757
+ #else
758
+ char output_buffer [16 * 1024];
759
+
630
760
  while ((OutboundPages.size() > 0) && (nbytes < sizeof(output_buffer))) {
631
761
  OutboundPage *op = &(OutboundPages[0]);
632
762
  if ((nbytes + op->Length - op->Offset) < sizeof (output_buffer)) {
@@ -642,6 +772,7 @@ void ConnectionDescriptor::_WriteOutboundData()
642
772
  nbytes += len;
643
773
  }
644
774
  }
775
+ #endif
645
776
 
646
777
  // We should never have gotten here if there were no data to write,
647
778
  // so assert that as a sanity check.
@@ -650,7 +781,11 @@ void ConnectionDescriptor::_WriteOutboundData()
650
781
  assert (nbytes > 0);
651
782
 
652
783
  assert (GetSocket() != INVALID_SOCKET);
653
- int bytes_written = send (GetSocket(), output_buffer, nbytes, 0);
784
+ #ifdef HAVE_WRITEV
785
+ int bytes_written = writev (GetSocket(), iov, iovcnt);
786
+ #else
787
+ int bytes_written = write (GetSocket(), output_buffer, nbytes);
788
+ #endif
654
789
 
655
790
  bool err = false;
656
791
  if (bytes_written < 0) {
@@ -660,6 +795,31 @@ void ConnectionDescriptor::_WriteOutboundData()
660
795
 
661
796
  assert (bytes_written >= 0);
662
797
  OutboundDataSize -= bytes_written;
798
+
799
+ #ifdef HAVE_WRITEV
800
+ if (!err) {
801
+ int sent = bytes_written;
802
+ deque<OutboundPage>::iterator op = OutboundPages.begin();
803
+
804
+ for (int i = 0; i < iovcnt; i++) {
805
+ if (iov[i].iov_len <= sent) {
806
+ // Sent this page in full, free it.
807
+ op->Free();
808
+ OutboundPages.pop_front();
809
+
810
+ sent -= iov[i].iov_len;
811
+ } else {
812
+ // Sent part (or none) of this page, increment offset to send the remainder
813
+ op->Offset += sent;
814
+ break;
815
+ }
816
+
817
+ // Shouldn't be possible run out of pages before the loop ends
818
+ assert(op != OutboundPages.end());
819
+ *op++;
820
+ }
821
+ }
822
+ #else
663
823
  if ((size_t)bytes_written < nbytes) {
664
824
  int len = nbytes - bytes_written;
665
825
  char *buffer = (char*) malloc (len + 1);
@@ -669,6 +829,7 @@ void ConnectionDescriptor::_WriteOutboundData()
669
829
  buffer [len] = 0;
670
830
  OutboundPages.push_front (OutboundPage (buffer, len));
671
831
  }
832
+ #endif
672
833
 
673
834
  #ifdef HAVE_EPOLL
674
835
  EpollEvent.events = (EPOLLIN | (SelectForWrite() ? EPOLLOUT : 0));
@@ -725,7 +886,7 @@ void ConnectionDescriptor::StartTls()
725
886
  if (SslBox)
726
887
  throw std::runtime_error ("SSL/TLS already running on connection");
727
888
 
728
- SslBox = new SslBox_t (bIsServer, PrivateKeyFilename, CertChainFilename);
889
+ SslBox = new SslBox_t (bIsServer, PrivateKeyFilename, CertChainFilename, bSslVerifyPeer, GetBinding().c_str());
729
890
  _DispatchCiphertext();
730
891
  #endif
731
892
 
@@ -739,7 +900,7 @@ void ConnectionDescriptor::StartTls()
739
900
  ConnectionDescriptor::SetTlsParms
740
901
  *********************************/
741
902
 
742
- void ConnectionDescriptor::SetTlsParms (const char *privkey_filename, const char *certchain_filename)
903
+ void ConnectionDescriptor::SetTlsParms (const char *privkey_filename, const char *certchain_filename, bool verify_peer)
743
904
  {
744
905
  #ifdef WITH_SSL
745
906
  if (SslBox)
@@ -748,6 +909,7 @@ void ConnectionDescriptor::SetTlsParms (const char *privkey_filename, const char
748
909
  PrivateKeyFilename = privkey_filename;
749
910
  if (certchain_filename && *certchain_filename)
750
911
  CertChainFilename = certchain_filename;
912
+ bSslVerifyPeer = verify_peer;
751
913
  #endif
752
914
 
753
915
  #ifdef WITHOUT_SSL
@@ -770,6 +932,35 @@ X509 *ConnectionDescriptor::GetPeerCert()
770
932
  #endif
771
933
 
772
934
 
935
+ /***********************************
936
+ ConnectionDescriptor::VerifySslPeer
937
+ ***********************************/
938
+
939
+ #ifdef WITH_SSL
940
+ bool ConnectionDescriptor::VerifySslPeer(const char *cert)
941
+ {
942
+ bSslPeerAccepted = false;
943
+
944
+ if (EventCallback)
945
+ (*EventCallback)(GetBinding().c_str(), EM_SSL_VERIFY, cert, strlen(cert));
946
+
947
+ return bSslPeerAccepted;
948
+ }
949
+ #endif
950
+
951
+
952
+ /***********************************
953
+ ConnectionDescriptor::AcceptSslPeer
954
+ ***********************************/
955
+
956
+ #ifdef WITH_SSL
957
+ void ConnectionDescriptor::AcceptSslPeer()
958
+ {
959
+ bSslPeerAccepted = true;
960
+ }
961
+ #endif
962
+
963
+
773
964
  /*****************************************
774
965
  ConnectionDescriptor::_DispatchCiphertext
775
966
  *****************************************/
@@ -1156,7 +1347,6 @@ void DatagramDescriptor::Read()
1156
1347
 
1157
1348
  // In UDP, a zero-length packet is perfectly legal.
1158
1349
  if (r >= 0) {
1159
- LastRead = gCurrentLoopTime;
1160
1350
 
1161
1351
  // Add a null-terminator at the the end of the buffer
1162
1352
  // that we will send to the callback.
@@ -1178,8 +1368,7 @@ void DatagramDescriptor::Read()
1178
1368
  memset (&ReturnAddress, 0, sizeof(ReturnAddress));
1179
1369
  memcpy (&ReturnAddress, &sin, slen);
1180
1370
 
1181
- if (EventCallback)
1182
- (*EventCallback)(GetBinding().c_str(), EM_CONNECTION_READ, readbuffer, r);
1371
+ _GenericInboundDispatch(readbuffer, r);
1183
1372
 
1184
1373
  }
1185
1374
  else {
@@ -1290,11 +1479,13 @@ int DatagramDescriptor::SendOutboundData (const char *data, int length)
1290
1479
  buffer [length] = 0;
1291
1480
  OutboundPages.push_back (OutboundPage (buffer, length, ReturnAddress));
1292
1481
  OutboundDataSize += length;
1482
+
1293
1483
  #ifdef HAVE_EPOLL
1294
1484
  EpollEvent.events = (EPOLLIN | EPOLLOUT);
1295
1485
  assert (MyEventMachine);
1296
1486
  MyEventMachine->Modify (this);
1297
1487
  #endif
1488
+
1298
1489
  return length;
1299
1490
  }
1300
1491
 
@@ -1334,7 +1525,6 @@ int DatagramDescriptor::SendOutboundDatagram (const char *data, int length, cons
1334
1525
  pin.sin_port = htons (port);
1335
1526
 
1336
1527
 
1337
-
1338
1528
  if (!data && (length > 0))
1339
1529
  throw std::runtime_error ("bad outbound data");
1340
1530
  char *buffer = (char *) malloc (length + 1);
@@ -1344,11 +1534,13 @@ int DatagramDescriptor::SendOutboundDatagram (const char *data, int length, cons
1344
1534
  buffer [length] = 0;
1345
1535
  OutboundPages.push_back (OutboundPage (buffer, length, pin));
1346
1536
  OutboundDataSize += length;
1537
+
1347
1538
  #ifdef HAVE_EPOLL
1348
1539
  EpollEvent.events = (EPOLLIN | EPOLLOUT);
1349
1540
  assert (MyEventMachine);
1350
1541
  MyEventMachine->Modify (this);
1351
1542
  #endif
1543
+
1352
1544
  return length;
1353
1545
  }
1354
1546
 
@@ -1404,16 +1596,9 @@ bool ConnectionDescriptor::GetSockname (struct sockaddr *s)
1404
1596
  ConnectionDescriptor::GetCommInactivityTimeout
1405
1597
  **********************************************/
1406
1598
 
1407
- int ConnectionDescriptor::GetCommInactivityTimeout (int *value)
1599
+ float ConnectionDescriptor::GetCommInactivityTimeout()
1408
1600
  {
1409
- if (value) {
1410
- *value = InactivityTimeout;
1411
- return 1;
1412
- }
1413
- else {
1414
- // TODO, extended logging, got bad parameter.
1415
- return 0;
1416
- }
1601
+ return ((float)InactivityTimeout / 1000000);
1417
1602
  }
1418
1603
 
1419
1604
 
@@ -1421,27 +1606,13 @@ int ConnectionDescriptor::GetCommInactivityTimeout (int *value)
1421
1606
  ConnectionDescriptor::SetCommInactivityTimeout
1422
1607
  **********************************************/
1423
1608
 
1424
- int ConnectionDescriptor::SetCommInactivityTimeout (int *value)
1609
+ int ConnectionDescriptor::SetCommInactivityTimeout (float value)
1425
1610
  {
1426
- int out = 0;
1427
-
1428
- if (value) {
1429
- if ((*value==0) || (*value >= 2)) {
1430
- // Replace the value and send the old one back to the caller.
1431
- int v = *value;
1432
- *value = InactivityTimeout;
1433
- InactivityTimeout = v;
1434
- out = 1;
1435
- }
1436
- else {
1437
- // TODO, extended logging, got bad value.
1438
- }
1439
- }
1440
- else {
1441
- // TODO, extended logging, got bad parameter.
1611
+ if (value > 0) {
1612
+ InactivityTimeout = (Int64)(value * 1000000);
1613
+ return 1;
1442
1614
  }
1443
-
1444
- return out;
1615
+ return 0;
1445
1616
  }
1446
1617
 
1447
1618
  /*******************************
@@ -1481,42 +1652,81 @@ bool DatagramDescriptor::GetSockname (struct sockaddr *s)
1481
1652
  DatagramDescriptor::GetCommInactivityTimeout
1482
1653
  ********************************************/
1483
1654
 
1484
- int DatagramDescriptor::GetCommInactivityTimeout (int *value)
1655
+ float DatagramDescriptor::GetCommInactivityTimeout()
1485
1656
  {
1486
- if (value) {
1487
- *value = InactivityTimeout;
1488
- return 1;
1489
- }
1490
- else {
1491
- // TODO, extended logging, got bad parameter.
1492
- return 0;
1493
- }
1657
+ return ((float)InactivityTimeout / 1000000);
1494
1658
  }
1495
1659
 
1496
1660
  /********************************************
1497
1661
  DatagramDescriptor::SetCommInactivityTimeout
1498
1662
  ********************************************/
1499
1663
 
1500
- int DatagramDescriptor::SetCommInactivityTimeout (int *value)
1501
- {
1502
- int out = 0;
1503
-
1504
- if (value) {
1505
- if ((*value==0) || (*value >= 2)) {
1506
- // Replace the value and send the old one back to the caller.
1507
- int v = *value;
1508
- *value = InactivityTimeout;
1509
- InactivityTimeout = v;
1510
- out = 1;
1511
- }
1512
- else {
1513
- // TODO, extended logging, got bad value.
1514
- }
1515
- }
1516
- else {
1517
- // TODO, extended logging, got bad parameter.
1518
- }
1664
+ int DatagramDescriptor::SetCommInactivityTimeout (float value)
1665
+ {
1666
+ if (value > 0) {
1667
+ InactivityTimeout = (Int64)(value * 1000000);
1668
+ return 1;
1669
+ }
1670
+ return 0;
1671
+ }
1672
+
1673
+
1674
+ /************************************
1675
+ InotifyDescriptor::InotifyDescriptor
1676
+ *************************************/
1677
+
1678
+ InotifyDescriptor::InotifyDescriptor (EventMachine_t *em):
1679
+ EventableDescriptor(0, em)
1680
+ {
1681
+ bCallbackUnbind = false;
1682
+
1683
+ #ifndef HAVE_INOTIFY
1684
+ throw std::runtime_error("no inotify support on this system");
1685
+ #else
1519
1686
 
1520
- return out;
1687
+ int fd = inotify_init();
1688
+ if (fd == -1) {
1689
+ char buf[200];
1690
+ snprintf (buf, sizeof(buf)-1, "unable to create inotify descriptor: %s", strerror(errno));
1691
+ throw std::runtime_error (buf);
1692
+ }
1693
+
1694
+ MySocket = fd;
1695
+ SetSocketNonblocking(MySocket);
1696
+ #ifdef HAVE_EPOLL
1697
+ EpollEvent.events = EPOLLIN;
1698
+ #endif
1699
+
1700
+ #endif
1701
+ }
1702
+
1703
+
1704
+ /*************************************
1705
+ InotifyDescriptor::~InotifyDescriptor
1706
+ **************************************/
1707
+
1708
+ InotifyDescriptor::~InotifyDescriptor()
1709
+ {
1710
+ close(MySocket);
1711
+ MySocket = INVALID_SOCKET;
1521
1712
  }
1522
1713
 
1714
+ /***********************
1715
+ InotifyDescriptor::Read
1716
+ ************************/
1717
+
1718
+ void InotifyDescriptor::Read()
1719
+ {
1720
+ assert (MyEventMachine);
1721
+ MyEventMachine->_ReadInotifyEvents();
1722
+ }
1723
+
1724
+
1725
+ /************************
1726
+ InotifyDescriptor::Write
1727
+ *************************/
1728
+
1729
+ void InotifyDescriptor::Write()
1730
+ {
1731
+ throw std::runtime_error("bad code path in inotify");
1732
+ }