eventmachine 0.12.6-java → 0.12.8-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/{docs/README → README} +21 -13
- data/Rakefile +5 -3
- data/docs/DEFERRABLES +0 -5
- data/docs/INSTALL +2 -4
- data/docs/LEGAL +1 -1
- data/docs/LIGHTWEIGHT_CONCURRENCY +0 -2
- data/docs/PURE_RUBY +0 -2
- data/docs/RELEASE_NOTES +0 -2
- data/docs/SMTP +0 -7
- data/docs/SPAWNED_PROCESSES +0 -4
- data/docs/TODO +0 -2
- data/eventmachine.gemspec +17 -8
- data/examples/ex_channel.rb +43 -0
- data/examples/ex_queue.rb +2 -0
- data/examples/helper.rb +2 -0
- data/ext/cmain.cpp +119 -20
- data/ext/cplusplus.cpp +15 -6
- data/ext/ed.cpp +303 -93
- data/ext/ed.h +49 -22
- data/ext/em.cpp +368 -42
- data/ext/em.h +43 -6
- data/ext/eventmachine.h +21 -8
- data/ext/eventmachine_cpp.h +1 -0
- data/ext/extconf.rb +4 -0
- data/ext/kb.cpp +1 -2
- data/ext/pipe.cpp +1 -3
- data/ext/project.h +21 -0
- data/ext/rubymain.cpp +232 -32
- data/ext/ssl.cpp +38 -1
- data/ext/ssl.h +5 -1
- data/java/src/com/rubyeventmachine/Application.java +7 -3
- data/java/src/com/rubyeventmachine/EmReactor.java +16 -1
- data/java/src/com/rubyeventmachine/tests/ConnectTest.java +25 -3
- data/lib/{protocols → em}/buftok.rb +16 -5
- data/lib/em/callback.rb +26 -0
- data/lib/em/channel.rb +57 -0
- data/lib/em/connection.rb +505 -0
- data/lib/em/deferrable.rb +144 -165
- data/lib/em/file_watch.rb +54 -0
- data/lib/em/future.rb +24 -25
- data/lib/em/messages.rb +1 -1
- data/lib/em/process_watch.rb +44 -0
- data/lib/em/processes.rb +58 -52
- data/lib/em/protocols.rb +35 -0
- data/lib/em/protocols/header_and_content.rb +138 -0
- data/lib/em/protocols/httpclient.rb +263 -0
- data/lib/em/protocols/httpclient2.rb +582 -0
- data/lib/{protocols → em/protocols}/line_and_text.rb +2 -2
- data/lib/em/protocols/linetext2.rb +160 -0
- data/lib/{protocols → em/protocols}/memcache.rb +37 -7
- data/lib/em/protocols/object_protocol.rb +39 -0
- data/lib/em/protocols/postgres3.rb +247 -0
- data/lib/em/protocols/saslauth.rb +175 -0
- data/lib/em/protocols/smtpclient.rb +331 -0
- data/lib/em/protocols/smtpserver.rb +547 -0
- data/lib/em/protocols/stomp.rb +200 -0
- data/lib/{protocols → em/protocols}/tcptest.rb +21 -25
- data/lib/em/queue.rb +61 -0
- data/lib/em/spawnable.rb +53 -56
- data/lib/em/streamer.rb +92 -74
- data/lib/em/timers.rb +55 -0
- data/lib/em/version.rb +3 -0
- data/lib/eventmachine.rb +1008 -1298
- data/lib/evma.rb +1 -1
- data/lib/jeventmachine.rb +106 -101
- data/lib/pr_eventmachine.rb +47 -36
- data/tasks/project.rake +2 -1
- data/tests/client.crt +31 -0
- data/tests/client.key +51 -0
- data/tests/test_attach.rb +18 -0
- data/tests/test_basic.rb +108 -54
- data/tests/test_channel.rb +63 -0
- data/tests/test_connection_count.rb +2 -2
- data/tests/test_epoll.rb +109 -110
- data/tests/test_errors.rb +36 -36
- data/tests/test_exc.rb +22 -25
- data/tests/test_file_watch.rb +49 -0
- data/tests/test_futures.rb +77 -93
- data/tests/test_hc.rb +2 -2
- data/tests/test_httpclient.rb +55 -52
- data/tests/test_httpclient2.rb +110 -112
- data/tests/test_inactivity_timeout.rb +30 -0
- data/tests/test_kb.rb +8 -9
- data/tests/test_ltp2.rb +274 -277
- data/tests/test_next_tick.rb +91 -65
- data/tests/test_object_protocol.rb +37 -0
- data/tests/test_process_watch.rb +48 -0
- data/tests/test_processes.rb +56 -23
- data/tests/test_proxy_connection.rb +92 -0
- data/tests/test_pure.rb +1 -5
- data/tests/test_queue.rb +44 -0
- data/tests/test_running.rb +9 -14
- data/tests/test_sasl.rb +32 -34
- data/tests/test_send_file.rb +175 -176
- data/tests/test_servers.rb +37 -41
- data/tests/test_smtpserver.rb +47 -55
- data/tests/test_spawn.rb +284 -291
- data/tests/test_ssl_args.rb +1 -1
- data/tests/test_ssl_methods.rb +1 -1
- data/tests/test_ssl_verify.rb +82 -0
- data/tests/test_timers.rb +81 -88
- data/tests/test_ud.rb +0 -7
- data/tests/testem.rb +1 -1
- metadata +52 -36
- data/lib/em/eventable.rb +0 -39
- data/lib/eventmachine_version.rb +0 -31
- data/lib/protocols/header_and_content.rb +0 -129
- data/lib/protocols/httpcli2.rb +0 -803
- data/lib/protocols/httpclient.rb +0 -270
- data/lib/protocols/linetext2.rb +0 -161
- data/lib/protocols/postgres.rb +0 -261
- data/lib/protocols/saslauth.rb +0 -179
- data/lib/protocols/smtpclient.rb +0 -308
- data/lib/protocols/smtpserver.rb +0 -556
- data/lib/protocols/stomp.rb +0 -153
- data/tests/test_eventables.rb +0 -77
data/ext/cplusplus.cpp
CHANGED
|
@@ -33,7 +33,7 @@ EM::Run
|
|
|
33
33
|
|
|
34
34
|
void EM::Run (void (*start_func)())
|
|
35
35
|
{
|
|
36
|
-
|
|
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::
|
|
120
|
-
|
|
118
|
+
/***************************
|
|
119
|
+
EM::Connection::BindConnect
|
|
120
|
+
***************************/
|
|
121
121
|
|
|
122
|
-
void EM::Connection::
|
|
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
|
-
|
|
274
|
-
|
|
275
|
-
|
|
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 =
|
|
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
|
-
|
|
503
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
572
|
-
|
|
573
|
-
//
|
|
574
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1599
|
+
float ConnectionDescriptor::GetCommInactivityTimeout()
|
|
1408
1600
|
{
|
|
1409
|
-
|
|
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 (
|
|
1609
|
+
int ConnectionDescriptor::SetCommInactivityTimeout (float value)
|
|
1425
1610
|
{
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
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
|
-
|
|
1655
|
+
float DatagramDescriptor::GetCommInactivityTimeout()
|
|
1485
1656
|
{
|
|
1486
|
-
|
|
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 (
|
|
1501
|
-
{
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
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
|
-
|
|
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
|
+
}
|