eventmachine 0.5.3 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/RELEASE_NOTES CHANGED
@@ -1,7 +1,20 @@
1
- $Id: RELEASE_NOTES 64 2006-05-17 07:00:16Z blackhedd $
1
+ $Id: RELEASE_NOTES 223 2006-08-08 20:30:41Z blackhedd $
2
2
 
3
3
  RUBY/EventMachine RELEASE NOTES
4
4
 
5
+ --------------------------------------------------
6
+ Version: 0.7.0, released xxAug06
7
+ Added a fix in em.cpp/ConnectToServer to fix a fatal exception that
8
+ occurred in FreeBSD when connecting successfully to a remote server.
9
+
10
+ --------------------------------------------------
11
+ Version: 0.6.0, released xxJul06
12
+ Added deferred operations, suggested by Don Stocks, amillionhitpoints@yahoo.com.
13
+
14
+ --------------------------------------------------
15
+ Version: 0.5.4, released xxJun06
16
+ Added get_peername support for streams and datagrams.
17
+
5
18
  --------------------------------------------------
6
19
  Version: 0.5.3, released 17May06
7
20
  Fixed bugs in extconf.rb, thanks to Daniel Harple, dharple@generalconsumption.org.
data/TODO ADDED
@@ -0,0 +1,10 @@
1
+ $Id: TODO 231 2006-08-13 17:15:53Z blackhedd $
2
+
3
+ TODO List:
4
+
5
+ 12Aug06: Noticed by Don Stocks. A TCP connect-request that results
6
+ in a failed DNS resolution fires a fatal error back to user code.
7
+ Uuuuuugly. We should probably cause an unbind event to get fired
8
+ instead, and add some parameterization so the caller can detect
9
+ the nature of the failure.
10
+
data/ext/cmain.cpp CHANGED
@@ -1,6 +1,6 @@
1
1
  /*****************************************************************************
2
2
 
3
- $Id: cmain.cpp 47 2006-05-15 21:42:38Z blackhedd $
3
+ $Id: cmain.cpp 265 2006-10-05 19:07:45Z blackhedd $
4
4
 
5
5
  File: libmain.cpp
6
6
  Date: 06Apr06
@@ -105,6 +105,17 @@ extern "C" const char *evma_create_tcp_server (const char *address, int port)
105
105
  return EventMachine->CreateTcpServer (address, port);
106
106
  }
107
107
 
108
+ /******************************
109
+ evma_create_unix_domain_server
110
+ ******************************/
111
+
112
+ extern "C" const char *evma_create_unix_domain_server (const char *filename)
113
+ {
114
+ if (!EventMachine)
115
+ throw std::runtime_error ("not initialized");
116
+ return EventMachine->CreateUnixDomainServer (filename);
117
+ }
118
+
108
119
  /*************************
109
120
  evma_open_datagram_socket
110
121
  *************************/
@@ -173,10 +184,95 @@ extern "C" void evma_start_tls (const char *binding)
173
184
  {
174
185
  if (!EventMachine)
175
186
  throw std::runtime_error ("not initialized");
176
- EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
177
- if (ed)
178
- ed->StartTls();
187
+ EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
188
+ if (ed)
189
+ ed->StartTls();
190
+ }
191
+
192
+
193
+ /*****************
194
+ evma_get_peername
195
+ *****************/
196
+
197
+ extern "C" int evma_get_peername (const char *binding, struct sockaddr *sa)
198
+ {
199
+ if (!EventMachine)
200
+ throw std::runtime_error ("not initialized");
201
+ EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
202
+ if (ed) {
203
+ return ed->GetPeername (sa) ? 1 : 0;
204
+ }
205
+ else
206
+ return 0;
207
+ }
208
+
209
+
210
+ /*********************
211
+ evma_signal_loopbreak
212
+ *********************/
213
+
214
+ extern "C" void evma_signal_loopbreak()
215
+ {
216
+ if (!EventMachine)
217
+ throw std::runtime_error ("not initialized");
218
+ EventMachine->SignalLoopBreaker();
219
+ }
220
+
221
+
222
+
223
+ /****************
224
+ evma__write_file
225
+ ****************/
226
+
227
+ extern "C" const char *evma__write_file (const char *filename)
228
+ {
229
+ if (!EventMachine)
230
+ throw std::runtime_error ("not initialized");
231
+ return EventMachine->_OpenFileForWriting (filename);
232
+ }
233
+
234
+
235
+ /********************************
236
+ evma_get_comm_inactivity_timeout
237
+ ********************************/
238
+
239
+ extern "C" int evma_get_comm_inactivity_timeout (const char *binding, int *value)
240
+ {
241
+ if (!EventMachine)
242
+ throw std::runtime_error ("not initialized");
243
+ EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
244
+ if (ed) {
245
+ return ed->GetCommInactivityTimeout (value);
246
+ }
247
+ else
248
+ return 0; //Perhaps this should be an exception. Access to an unknown binding.
179
249
  }
180
250
 
251
+ /********************************
252
+ evma_set_comm_inactivity_timeout
253
+ ********************************/
181
254
 
255
+ extern "C" int evma_set_comm_inactivity_timeout (const char *binding, int *value)
256
+ {
257
+ if (!EventMachine)
258
+ throw std::runtime_error ("not initialized");
259
+ EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
260
+ if (ed) {
261
+ return ed->SetCommInactivityTimeout (value);
262
+ }
263
+ else
264
+ return 0; //Perhaps this should be an exception. Access to an unknown binding.
265
+ }
266
+
267
+
268
+ /**********************
269
+ evma_set_timer_quantum
270
+ **********************/
271
+
272
+ extern "C" void evma_set_timer_quantum (int interval)
273
+ {
274
+ if (!EventMachine)
275
+ throw std::runtime_error ("not initialized");
276
+ EventMachine->SetTimerQuantum (interval);
277
+ }
182
278
 
data/ext/ed.cpp CHANGED
@@ -1,6 +1,6 @@
1
1
  /*****************************************************************************
2
2
 
3
- $Id: ed.cpp 47 2006-05-15 21:42:38Z blackhedd $
3
+ $Id: ed.cpp 255 2006-09-15 11:21:15Z blackhedd $
4
4
 
5
5
  File: ed.cpp
6
6
  Date: 06Apr06
@@ -159,13 +159,16 @@ ConnectionDescriptor::ConnectionDescriptor
159
159
  ******************************************/
160
160
 
161
161
  ConnectionDescriptor::ConnectionDescriptor (int sd):
162
- EventableDescriptor (sd),
163
- bConnectPending (false),
164
- OutboundDataSize (0),
162
+ EventableDescriptor (sd),
163
+ bConnectPending (false),
164
+ bReadAttemptedAfterClose (false),
165
+ OutboundDataSize (0),
165
166
  #ifdef WITH_SSL
166
167
  SslBox (NULL),
167
168
  #endif
168
- bIsServer (false)
169
+ bIsServer (false),
170
+ LastIo (gCurrentLoopTime),
171
+ InactivityTimeout (0)
169
172
  {
170
173
  }
171
174
 
@@ -333,10 +336,33 @@ void ConnectionDescriptor::Read()
333
336
  * a socket that has already been scheduled for closing or close-after-writing.
334
337
  * In those cases, we'll leave it up the to protocol handler to "do the
335
338
  * right thing" (which probably means to ignore the incoming data).
339
+ *
340
+ * 22Aug06: Chris Ochs reports that on FreeBSD, it's possible to come
341
+ * here with the socket already closed, after the process receives
342
+ * a ctrl-C signal (not sure if that's TERM or INT on BSD). The application
343
+ * was one in which network connections were doing a lot of interleaved reads
344
+ * and writes.
345
+ * Since we always write before reading (in order to keep the outbound queues
346
+ * as light as possible), I think what happened is that an interrupt caused
347
+ * the socket to be closed in ConnectionDescriptor::Write. We'll then
348
+ * come here in the same pass through the main event loop, and won't get
349
+ * cleaned up until immediately after.
350
+ * We originally asserted that the socket was valid when we got here.
351
+ * To deal properly with the possibility that we are closed when we get here,
352
+ * I removed the assert. HOWEVER, the potential for an infinite loop scares me,
353
+ * so even though this is really clunky, I added a flag to assert that we never
354
+ * come here more than once after being closed. (FCianfrocca)
336
355
  */
337
356
 
338
357
  int sd = GetSocket();
339
- assert (sd != INVALID_SOCKET);
358
+ //assert (sd != INVALID_SOCKET); (original, removed 22Aug06)
359
+ if (sd == INVALID_SOCKET) {
360
+ assert (!bReadAttemptedAfterClose);
361
+ bReadAttemptedAfterClose = true;
362
+ return;
363
+ }
364
+
365
+ LastIo = gCurrentLoopTime;
340
366
 
341
367
  int total_bytes_read = 0;
342
368
  char readbuffer [16 * 1024];
@@ -345,6 +371,10 @@ void ConnectionDescriptor::Read()
345
371
  // Don't read just one buffer and then move on. This is faster
346
372
  // if there is a lot of incoming.
347
373
  // But don't read indefinitely. Give other sockets a chance to run.
374
+ // NOTICE, we're reading one less than the buffer size.
375
+ // That's so we can put a guard byte at the end of what we send
376
+ // to user code.
377
+
348
378
 
349
379
  int r = recv (sd, readbuffer, sizeof(readbuffer) - 1, 0);
350
380
  //cerr << "<R:" << r << ">";
@@ -355,17 +385,18 @@ void ConnectionDescriptor::Read()
355
385
 
356
386
  // Add a null-terminator at the the end of the buffer
357
387
  // that we will send to the callback.
358
- // DO NOT CHANGE THIS. We want to explicitly allow users
388
+ // DO NOT EVER CHANGE THIS. We want to explicitly allow users
359
389
  // to be able to depend on this behavior, so they will have
360
- // the option to do some things faster.
390
+ // the option to do some things faster. Additionally it's
391
+ // a security guard against buffer overflows.
361
392
  readbuffer [r] = 0;
362
- _DispatchInboundData (readbuffer, r);
393
+ _DispatchInboundData (readbuffer, r);
363
394
  }
364
395
  else if (r == 0) {
365
396
  break;
366
397
  }
367
398
  else {
368
- // Basically a would-block, meaning we've everything there is to read.
399
+ // Basically a would-block, meaning we've read everything there is to read.
369
400
  break;
370
401
  }
371
402
 
@@ -424,19 +455,19 @@ ConnectionDescriptor::Write
424
455
 
425
456
  void ConnectionDescriptor::Write()
426
457
  {
427
- /* A socket which is in a pending-connect state will select
428
- * writable when the disposition of the connect is known.
429
- * At that point, check to be sure there are no errors,
430
- * and if none, then promote the socket out of the pending
431
- * state.
432
- * TODO: I haven't figured out how Windows signals errors on
433
- * unconnected sockets. Maybe it does the untraditional but
434
- * logical thing and makes the socket selectable for error.
435
- * If so, it's unsupported here for the time being, and connect
436
- * errors will have to be caught by the timeout mechanism.
437
- */
458
+ /* A socket which is in a pending-connect state will select
459
+ * writable when the disposition of the connect is known.
460
+ * At that point, check to be sure there are no errors,
461
+ * and if none, then promote the socket out of the pending
462
+ * state.
463
+ * TODO: I haven't figured out how Windows signals errors on
464
+ * unconnected sockets. Maybe it does the untraditional but
465
+ * logical thing and makes the socket selectable for error.
466
+ * If so, it's unsupported here for the time being, and connect
467
+ * errors will have to be caught by the timeout mechanism.
468
+ */
438
469
 
439
- if (bConnectPending) {
470
+ if (bConnectPending) {
440
471
  int error;
441
472
  socklen_t len;
442
473
  len = sizeof(error);
@@ -446,14 +477,17 @@ void ConnectionDescriptor::Write()
446
477
  #ifdef OS_WIN32
447
478
  int o = getsockopt (MySocket, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
448
479
  #endif
449
- if ((o == 0) && (error == 0))
450
- bConnectPending = false;
451
- else
452
- bCloseNow = true;
453
- }
454
- else {
455
- _WriteOutboundData();
456
- }
480
+ if ((o == 0) && (error == 0)) {
481
+ if (EventCallback)
482
+ (*EventCallback)(GetBinding().c_str(), EventMachine_t::CONNECTION_COMPLETED, "", 0);
483
+ bConnectPending = false;
484
+ }
485
+ else
486
+ bCloseNow = true;
487
+ }
488
+ else {
489
+ _WriteOutboundData();
490
+ }
457
491
  }
458
492
 
459
493
 
@@ -473,6 +507,7 @@ void ConnectionDescriptor::_WriteOutboundData()
473
507
  int sd = GetSocket();
474
508
  assert (sd != INVALID_SOCKET);
475
509
 
510
+ LastIo = gCurrentLoopTime;
476
511
  char output_buffer [16 * 1024];
477
512
  size_t nbytes = 0;
478
513
 
@@ -617,14 +652,20 @@ ConnectionDescriptor::Heartbeat
617
652
 
618
653
  void ConnectionDescriptor::Heartbeat()
619
654
  {
620
- /* Only allow a certain amount of time to go by while waiting
621
- * for a pending connect. If it expires, then kill the socket.
622
- */
655
+ /* Only allow a certain amount of time to go by while waiting
656
+ * for a pending connect. If it expires, then kill the socket.
657
+ * For a connected socket, close it if its inactivity timer
658
+ * has expired.
659
+ */
623
660
 
624
- if (bConnectPending) {
625
- if ((gCurrentLoopTime - CreatedAt) >= PendingConnectTimeout)
626
- bCloseNow = true;
627
- }
661
+ if (bConnectPending) {
662
+ if ((gCurrentLoopTime - CreatedAt) >= PendingConnectTimeout)
663
+ bCloseNow = true;
664
+ }
665
+ else {
666
+ if (InactivityTimeout && ((gCurrentLoopTime - LastIo) >= InactivityTimeout))
667
+ bCloseNow = true;
668
+ }
628
669
  }
629
670
 
630
671
 
@@ -748,7 +789,9 @@ DatagramDescriptor::DatagramDescriptor
748
789
 
749
790
  DatagramDescriptor::DatagramDescriptor (int sd):
750
791
  EventableDescriptor (sd),
751
- OutboundDataSize (0)
792
+ OutboundDataSize (0),
793
+ LastIo (gCurrentLoopTime),
794
+ InactivityTimeout (0)
752
795
  {
753
796
  memset (&ReturnAddress, 0, sizeof(ReturnAddress));
754
797
  }
@@ -766,6 +809,19 @@ DatagramDescriptor::~DatagramDescriptor()
766
809
  }
767
810
 
768
811
 
812
+ /*****************************
813
+ DatagramDescriptor::Heartbeat
814
+ *****************************/
815
+
816
+ void DatagramDescriptor::Heartbeat()
817
+ {
818
+ // Close it if its inactivity timer has expired.
819
+
820
+ if (InactivityTimeout && ((gCurrentLoopTime - LastIo) >= InactivityTimeout))
821
+ bCloseNow = true;
822
+ }
823
+
824
+
769
825
  /************************
770
826
  DatagramDescriptor::Read
771
827
  ************************/
@@ -774,6 +830,7 @@ void DatagramDescriptor::Read()
774
830
  {
775
831
  int sd = GetSocket();
776
832
  assert (sd != INVALID_SOCKET);
833
+ LastIo = gCurrentLoopTime;
777
834
 
778
835
  // This is an extremely large read buffer.
779
836
  // In many cases you wouldn't expect to get any more than 4K.
@@ -783,6 +840,9 @@ void DatagramDescriptor::Read()
783
840
  // Don't read just one buffer and then move on. This is faster
784
841
  // if there is a lot of incoming.
785
842
  // But don't read indefinitely. Give other sockets a chance to run.
843
+ // NOTICE, we're reading one less than the buffer size.
844
+ // That's so we can put a guard byte at the end of what we send
845
+ // to user code.
786
846
 
787
847
  struct sockaddr_in sin;
788
848
  socklen_t slen = sizeof (sin);
@@ -797,9 +857,10 @@ void DatagramDescriptor::Read()
797
857
 
798
858
  // Add a null-terminator at the the end of the buffer
799
859
  // that we will send to the callback.
800
- // DO NOT CHANGE THIS. We want to explicitly allow users
860
+ // DO NOT EVER CHANGE THIS. We want to explicitly allow users
801
861
  // to be able to depend on this behavior, so they will have
802
- // the option to do some things faster.
862
+ // the option to do some things faster. Additionally it's
863
+ // a security guard against buffer overflows.
803
864
  readbuffer [r] = 0;
804
865
 
805
866
 
@@ -819,7 +880,7 @@ void DatagramDescriptor::Read()
819
880
 
820
881
  }
821
882
  else {
822
- // Basically a would-block, meaning we've everything there is to read.
883
+ // Basically a would-block, meaning we've read everything there is to read.
823
884
  break;
824
885
  }
825
886
 
@@ -848,6 +909,7 @@ void DatagramDescriptor::Write()
848
909
 
849
910
  int sd = GetSocket();
850
911
  assert (sd != INVALID_SOCKET);
912
+ LastIo = gCurrentLoopTime;
851
913
 
852
914
  assert (OutboundPages.size() > 0);
853
915
 
@@ -923,7 +985,7 @@ int DatagramDescriptor::SendOutboundDatagram (const char *data, int length, cons
923
985
  {
924
986
  // This is an exact clone of ConnectionDescriptor::SendOutboundData.
925
987
  // That means it needs to move to a common ancestor.
926
- // TODO: Refactor this so there's no overlap with SendOutboundData.
988
+ // TODO: Refactor this so there's no overlap with SendOutboundData.
927
989
 
928
990
  if (bCloseNow || bCloseAfterWriting)
929
991
  return 0;
@@ -972,7 +1034,129 @@ int DatagramDescriptor::SendDatagram (const char *binding, const char *data, int
972
1034
  DatagramDescriptor *dd = dynamic_cast <DatagramDescriptor*> (Bindable_t::GetObject (binding));
973
1035
  if (dd)
974
1036
  return dd->SendOutboundDatagram (data, length, address, port);
975
- else
976
- return -1;
1037
+ else
1038
+ return -1;
1039
+ }
1040
+
1041
+
1042
+ /*********************************
1043
+ ConnectionDescriptor::GetPeername
1044
+ *********************************/
1045
+
1046
+ bool ConnectionDescriptor::GetPeername (struct sockaddr *s)
1047
+ {
1048
+ bool ok = false;
1049
+ if (s) {
1050
+ socklen_t len = sizeof(*s);
1051
+ int gp = getpeername (GetSocket(), s, &len);
1052
+ if (gp == 0)
1053
+ ok = true;
1054
+ }
1055
+ return ok;
1056
+ }
1057
+
1058
+
1059
+ /**********************************************
1060
+ ConnectionDescriptor::GetCommInactivityTimeout
1061
+ **********************************************/
1062
+
1063
+ int ConnectionDescriptor::GetCommInactivityTimeout (int *value)
1064
+ {
1065
+ if (value) {
1066
+ *value = InactivityTimeout;
1067
+ return 1;
1068
+ }
1069
+ else {
1070
+ // TODO, extended logging, got bad parameter.
1071
+ return 0;
1072
+ }
1073
+ }
1074
+
1075
+
1076
+ /**********************************************
1077
+ ConnectionDescriptor::SetCommInactivityTimeout
1078
+ **********************************************/
1079
+
1080
+ int ConnectionDescriptor::SetCommInactivityTimeout (int *value)
1081
+ {
1082
+ int out = 0;
1083
+
1084
+ if (value) {
1085
+ if ((*value==0) || (*value >= 2)) {
1086
+ // Replace the value and send the old one back to the caller.
1087
+ int v = *value;
1088
+ *value = InactivityTimeout;
1089
+ InactivityTimeout = v;
1090
+ out = 1;
1091
+ }
1092
+ else {
1093
+ // TODO, extended logging, got bad value.
1094
+ }
1095
+ }
1096
+ else {
1097
+ // TODO, extended logging, got bad parameter.
1098
+ }
1099
+
1100
+ return out;
1101
+ }
1102
+
1103
+ /*******************************
1104
+ DatagramDescriptor::GetPeername
1105
+ *******************************/
1106
+
1107
+ bool DatagramDescriptor::GetPeername (struct sockaddr *s)
1108
+ {
1109
+ bool ok = false;
1110
+ if (s) {
1111
+ memset (s, 0, sizeof(struct sockaddr));
1112
+ memcpy (s, &ReturnAddress, sizeof(ReturnAddress));
1113
+ ok = true;
1114
+ }
1115
+ return ok;
1116
+ }
1117
+
1118
+
1119
+
1120
+ /********************************************
1121
+ DatagramDescriptor::GetCommInactivityTimeout
1122
+ ********************************************/
1123
+
1124
+ int DatagramDescriptor::GetCommInactivityTimeout (int *value)
1125
+ {
1126
+ if (value) {
1127
+ *value = InactivityTimeout;
1128
+ return 1;
1129
+ }
1130
+ else {
1131
+ // TODO, extended logging, got bad parameter.
1132
+ return 0;
1133
+ }
1134
+ }
1135
+
1136
+ /********************************************
1137
+ DatagramDescriptor::SetCommInactivityTimeout
1138
+ ********************************************/
1139
+
1140
+ int DatagramDescriptor::SetCommInactivityTimeout (int *value)
1141
+ {
1142
+ int out = 0;
1143
+
1144
+ if (value) {
1145
+ if ((*value==0) || (*value >= 2)) {
1146
+ // Replace the value and send the old one back to the caller.
1147
+ int v = *value;
1148
+ *value = InactivityTimeout;
1149
+ InactivityTimeout = v;
1150
+ out = 1;
1151
+ }
1152
+ else {
1153
+ // TODO, extended logging, got bad value.
1154
+ }
1155
+ }
1156
+ else {
1157
+ // TODO, extended logging, got bad parameter.
1158
+ }
1159
+
1160
+ return out;
977
1161
  }
978
1162
 
data/ext/ed.h CHANGED
@@ -1,6 +1,6 @@
1
1
  /*****************************************************************************
2
2
 
3
- $Id: ed.h 47 2006-05-15 21:42:38Z blackhedd $
3
+ $Id: ed.h 254 2006-09-15 11:17:01Z blackhedd $
4
4
 
5
5
  File: ed.h
6
6
  Date: 06Apr06
@@ -67,8 +67,15 @@ class EventableDescriptor: public Bindable_t
67
67
 
68
68
  void SetEventCallback (void (*cb)(const char*, int, const char*, int));
69
69
 
70
+ virtual bool GetPeername (struct sockaddr*) {return false;}
71
+
70
72
  virtual void StartTls() {}
71
73
 
74
+ // Properties: return 0/1 to signify T/F, and handle the values
75
+ // through arguments.
76
+ virtual int GetCommInactivityTimeout (int *value) {return 0;}
77
+ virtual int SetCommInactivityTimeout (int *value) {return 0;}
78
+
72
79
  protected:
73
80
  enum {
74
81
  PendingConnectTimeout = 4 // can easily be made an instance variable
@@ -116,6 +123,10 @@ class ConnectionDescriptor: public EventableDescriptor
116
123
  virtual void StartTls();
117
124
  void SetServerMode() {bIsServer = true;}
118
125
 
126
+ virtual bool GetPeername (struct sockaddr*);
127
+
128
+ virtual int GetCommInactivityTimeout (int *value);
129
+ virtual int SetCommInactivityTimeout (int *value);
119
130
 
120
131
  protected:
121
132
  struct OutboundPage {
@@ -128,6 +139,7 @@ class ConnectionDescriptor: public EventableDescriptor
128
139
 
129
140
  protected:
130
141
  bool bConnectPending;
142
+ bool bReadAttemptedAfterClose;
131
143
 
132
144
  deque<OutboundPage> OutboundPages;
133
145
  int OutboundDataSize;
@@ -137,6 +149,9 @@ class ConnectionDescriptor: public EventableDescriptor
137
149
  #endif
138
150
  bool bIsServer;
139
151
 
152
+ time_t LastIo;
153
+ int InactivityTimeout;
154
+
140
155
  private:
141
156
  void _WriteOutboundData();
142
157
  void _DispatchInboundData (const char *buffer, int size);
@@ -158,7 +173,7 @@ class DatagramDescriptor: public EventableDescriptor
158
173
 
159
174
  virtual void Read();
160
175
  virtual void Write();
161
- virtual void Heartbeat() {}
176
+ virtual void Heartbeat();
162
177
 
163
178
  virtual bool SelectForRead() {return true;}
164
179
  virtual bool SelectForWrite();
@@ -169,6 +184,11 @@ class DatagramDescriptor: public EventableDescriptor
169
184
  // Do we have any data to write? This is used by ShouldDelete.
170
185
  virtual int GetOutboundDataSize() {return OutboundDataSize;}
171
186
 
187
+ virtual bool GetPeername (struct sockaddr*);
188
+
189
+ virtual int GetCommInactivityTimeout (int *value);
190
+ virtual int SetCommInactivityTimeout (int *value);
191
+
172
192
  static int SendDatagram (const char*, const char*, int, const char*, int);
173
193
 
174
194
 
@@ -186,6 +206,9 @@ class DatagramDescriptor: public EventableDescriptor
186
206
  int OutboundDataSize;
187
207
 
188
208
  struct sockaddr_in ReturnAddress;
209
+
210
+ time_t LastIo;
211
+ int InactivityTimeout;
189
212
  };
190
213
 
191
214