eventmachine 1.0.9.1-java → 1.2.0.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/README.md +2 -2
  4. data/ext/cmain.cpp +77 -5
  5. data/ext/ed.cpp +112 -42
  6. data/ext/ed.h +27 -13
  7. data/ext/em.cpp +105 -163
  8. data/ext/em.h +10 -7
  9. data/ext/eventmachine.h +13 -1
  10. data/ext/extconf.rb +23 -14
  11. data/ext/fastfilereader/extconf.rb +1 -2
  12. data/ext/fastfilereader/rubymain.cpp +6 -6
  13. data/ext/project.h +9 -4
  14. data/ext/rubymain.cpp +155 -36
  15. data/ext/ssl.cpp +157 -13
  16. data/ext/ssl.h +7 -2
  17. data/lib/em/channel.rb +5 -0
  18. data/lib/em/completion.rb +2 -2
  19. data/lib/em/connection.rb +61 -3
  20. data/lib/em/iterator.rb +26 -5
  21. data/lib/em/pool.rb +1 -1
  22. data/lib/em/protocols/line_and_text.rb +1 -1
  23. data/lib/em/pure_ruby.rb +6 -1
  24. data/lib/em/queue.rb +16 -7
  25. data/lib/em/resolver.rb +46 -23
  26. data/lib/em/threaded_resource.rb +2 -2
  27. data/lib/em/version.rb +1 -1
  28. data/lib/eventmachine.rb +59 -42
  29. data/lib/rubyeventmachine.jar +0 -0
  30. data/rakelib/package.rake +23 -1
  31. data/tests/dhparam.pem +13 -0
  32. data/tests/em_test_helper.rb +79 -0
  33. data/tests/test_basic.rb +17 -26
  34. data/tests/test_channel.rb +14 -1
  35. data/tests/test_connection_write.rb +2 -2
  36. data/tests/test_defer.rb +17 -0
  37. data/tests/test_epoll.rb +1 -1
  38. data/tests/test_fork.rb +75 -0
  39. data/tests/test_ipv4.rb +125 -0
  40. data/tests/test_ipv6.rb +131 -0
  41. data/tests/test_iterator.rb +18 -0
  42. data/tests/test_many_fds.rb +1 -1
  43. data/tests/test_queue.rb +14 -0
  44. data/tests/test_resolver.rb +23 -0
  45. data/tests/test_set_sock_opt.rb +2 -0
  46. data/tests/test_ssl_dhparam.rb +83 -0
  47. data/tests/test_ssl_ecdh_curve.rb +79 -0
  48. data/tests/test_ssl_extensions.rb +49 -0
  49. data/tests/test_ssl_methods.rb +19 -0
  50. data/tests/test_ssl_protocols.rb +246 -0
  51. data/tests/test_ssl_verify.rb +44 -0
  52. data/tests/test_system.rb +4 -0
  53. data/tests/test_unbind_reason.rb +5 -1
  54. metadata +101 -20
  55. data/.gitignore +0 -21
  56. data/.travis.yml +0 -22
  57. data/.yardopts +0 -7
  58. data/Gemfile +0 -2
  59. data/Rakefile +0 -20
  60. data/eventmachine.gemspec +0 -38
  61. data/rakelib/cpp.rake_example +0 -77
data/ext/ed.h CHANGED
@@ -36,10 +36,10 @@ class EventableDescriptor
36
36
  class EventableDescriptor: public Bindable_t
37
37
  {
38
38
  public:
39
- EventableDescriptor (int, EventMachine_t*);
39
+ EventableDescriptor (SOCKET, EventMachine_t*);
40
40
  virtual ~EventableDescriptor();
41
41
 
42
- int GetSocket() {return MySocket;}
42
+ SOCKET GetSocket() {return MySocket;}
43
43
  void SetSocketInvalid() { MySocket = INVALID_SOCKET; }
44
44
  void Close();
45
45
 
@@ -69,10 +69,14 @@ class EventableDescriptor: public Bindable_t
69
69
  virtual bool GetSubprocessPid (pid_t*) {return false;}
70
70
 
71
71
  virtual void StartTls() {}
72
- virtual void SetTlsParms (const char *, const char *, bool) {}
72
+ virtual void SetTlsParms (const char *, const char *, bool, bool, const char *, const char *, const char *, const char *, int) {}
73
73
 
74
74
  #ifdef WITH_SSL
75
75
  virtual X509 *GetPeerCert() {return NULL;}
76
+ virtual int GetCipherBits() {return -1;}
77
+ virtual const char *GetCipherName() {return NULL;}
78
+ virtual const char *GetCipherProtocol() {return NULL;}
79
+ virtual const char *GetSNIHostname() {return NULL;}
76
80
  #endif
77
81
 
78
82
  virtual uint64_t GetCommInactivityTimeout() {return 0;}
@@ -108,7 +112,7 @@ class EventableDescriptor: public Bindable_t
108
112
  bool bCloseAfterWriting;
109
113
 
110
114
  protected:
111
- int MySocket;
115
+ SOCKET MySocket;
112
116
  bool bAttached;
113
117
  bool bWatchOnly;
114
118
 
@@ -151,7 +155,7 @@ class LoopbreakDescriptor
151
155
  class LoopbreakDescriptor: public EventableDescriptor
152
156
  {
153
157
  public:
154
- LoopbreakDescriptor (int, EventMachine_t*);
158
+ LoopbreakDescriptor (SOCKET, EventMachine_t*);
155
159
  virtual ~LoopbreakDescriptor() {}
156
160
 
157
161
  virtual void Read();
@@ -170,7 +174,7 @@ class ConnectionDescriptor
170
174
  class ConnectionDescriptor: public EventableDescriptor
171
175
  {
172
176
  public:
173
- ConnectionDescriptor (int, EventMachine_t*);
177
+ ConnectionDescriptor (SOCKET, EventMachine_t*);
174
178
  virtual ~ConnectionDescriptor();
175
179
 
176
180
  int SendOutboundData (const char*, unsigned long);
@@ -201,10 +205,14 @@ class ConnectionDescriptor: public EventableDescriptor
201
205
  virtual int GetOutboundDataSize() {return OutboundDataSize;}
202
206
 
203
207
  virtual void StartTls();
204
- virtual void SetTlsParms (const char *privkey_filename, const char *certchain_filename, bool verify_peer);
208
+ virtual void SetTlsParms (const char *, const char *, bool, bool, const char *, const char *, const char *, const char *, int);
205
209
 
206
210
  #ifdef WITH_SSL
207
211
  virtual X509 *GetPeerCert();
212
+ virtual int GetCipherBits();
213
+ virtual const char *GetCipherName();
214
+ virtual const char *GetCipherProtocol();
215
+ virtual const char *GetSNIHostname();
208
216
  virtual bool VerifySslPeer(const char*);
209
217
  virtual void AcceptSslPeer();
210
218
  #endif
@@ -245,8 +253,14 @@ class ConnectionDescriptor: public EventableDescriptor
245
253
  SslBox_t *SslBox;
246
254
  std::string CertChainFilename;
247
255
  std::string PrivateKeyFilename;
256
+ std::string CipherList;
257
+ std::string EcdhCurve;
258
+ std::string DhParam;
259
+ int Protocols;
248
260
  bool bHandshakeSignaled;
249
261
  bool bSslVerifyPeer;
262
+ bool bSslFailIfNoPeerCert;
263
+ std::string SniHostName;
250
264
  bool bSslPeerAccepted;
251
265
  #endif
252
266
 
@@ -275,7 +289,7 @@ class DatagramDescriptor
275
289
  class DatagramDescriptor: public EventableDescriptor
276
290
  {
277
291
  public:
278
- DatagramDescriptor (int, EventMachine_t*);
292
+ DatagramDescriptor (SOCKET, EventMachine_t*);
279
293
  virtual ~DatagramDescriptor();
280
294
 
281
295
  virtual void Read();
@@ -299,18 +313,18 @@ class DatagramDescriptor: public EventableDescriptor
299
313
 
300
314
  protected:
301
315
  struct OutboundPage {
302
- OutboundPage (const char *b, int l, struct sockaddr_in f, int o=0): Buffer(b), Length(l), Offset(o), From(f) {}
316
+ OutboundPage (const char *b, int l, struct sockaddr_in6 f, int o=0): Buffer(b), Length(l), Offset(o), From(f) {}
303
317
  void Free() {if (Buffer) free (const_cast<char*>(Buffer)); }
304
318
  const char *Buffer;
305
319
  int Length;
306
320
  int Offset;
307
- struct sockaddr_in From;
321
+ struct sockaddr_in6 From;
308
322
  };
309
323
 
310
324
  deque<OutboundPage> OutboundPages;
311
325
  int OutboundDataSize;
312
326
 
313
- struct sockaddr_in ReturnAddress;
327
+ struct sockaddr_in6 ReturnAddress;
314
328
  };
315
329
 
316
330
 
@@ -321,7 +335,7 @@ class AcceptorDescriptor
321
335
  class AcceptorDescriptor: public EventableDescriptor
322
336
  {
323
337
  public:
324
- AcceptorDescriptor (int, EventMachine_t*);
338
+ AcceptorDescriptor (SOCKET, EventMachine_t*);
325
339
  virtual ~AcceptorDescriptor();
326
340
 
327
341
  virtual void Read();
@@ -344,7 +358,7 @@ class PipeDescriptor
344
358
  class PipeDescriptor: public EventableDescriptor
345
359
  {
346
360
  public:
347
- PipeDescriptor (int, pid_t, EventMachine_t*);
361
+ PipeDescriptor (SOCKET, pid_t, EventMachine_t*);
348
362
  virtual ~PipeDescriptor();
349
363
 
350
364
  virtual void Read();
data/ext/em.cpp CHANGED
@@ -32,22 +32,15 @@ static unsigned int MaxOutstandingTimers = 100000;
32
32
  */
33
33
  static unsigned int SimultaneousAcceptCount = 10;
34
34
 
35
-
36
- /* Internal helper to convert strings to internet addresses. IPv6-aware.
37
- * Not reentrant or threadsafe, optimized for speed.
38
- */
39
- static struct sockaddr *name2address (const char *server, int port, int *family, int *bind_size);
40
-
41
35
  /* Internal helper to create a socket with SOCK_CLOEXEC set, and fall
42
36
  * back to fcntl'ing it if the headers/runtime don't support it.
43
37
  */
44
-
45
- int EmSocket (int domain, int type, int protocol)
38
+ SOCKET EmSocket (int domain, int type, int protocol)
46
39
  {
47
- int sd;
40
+ SOCKET sd;
48
41
  #ifdef HAVE_SOCKET_CLOEXEC
49
42
  sd = socket (domain, type | SOCK_CLOEXEC, protocol);
50
- if (sd < 0) {
43
+ if (sd == INVALID_SOCKET) {
51
44
  sd = socket (domain, type, protocol);
52
45
  if (sd < 0) {
53
46
  return sd;
@@ -56,7 +49,7 @@ int EmSocket (int domain, int type, int protocol)
56
49
  }
57
50
  #else
58
51
  sd = socket (domain, type, protocol);
59
- if (sd < 0) {
52
+ if (sd == INVALID_SOCKET) {
60
53
  return sd;
61
54
  }
62
55
  SetFdCloexec(sd);
@@ -114,8 +107,8 @@ EventMachine_t::EventMachine_t (EMCallback event_callback, Poller_t poller):
114
107
  NumCloseScheduled (0),
115
108
  HeartbeatInterval(2000000),
116
109
  EventCallback (event_callback),
117
- LoopBreakerReader (-1),
118
- LoopBreakerWriter (-1),
110
+ LoopBreakerReader (INVALID_SOCKET),
111
+ LoopBreakerWriter (INVALID_SOCKET),
119
112
  bTerminateSignalReceived (false),
120
113
  Poller (poller),
121
114
  epfd (-1),
@@ -138,6 +131,11 @@ EventMachine_t::EventMachine_t (EMCallback event_callback, Poller_t poller):
138
131
  (void) mach_timebase_info(&mach_timebase);
139
132
  #endif
140
133
 
134
+ #ifdef OS_WIN32
135
+ TickCountTickover = 0;
136
+ LastTickCount = 0;
137
+ #endif
138
+
141
139
  // Make sure the current loop time is sane, in case we do any initializations of
142
140
  // objects before we start running.
143
141
  _UpdateTime();
@@ -217,7 +215,10 @@ void EventMachine_t::ScheduleHalt()
217
215
  SignalLoopBreaker();
218
216
  }
219
217
 
220
-
218
+ bool EventMachine_t::Stopping()
219
+ {
220
+ return bTerminateSignalReceived;
221
+ }
221
222
 
222
223
  /*******************************
223
224
  EventMachine_t::SetTimerQuantum
@@ -240,6 +241,7 @@ void EventMachine_t::SetTimerQuantum (int interval)
240
241
  (STATIC) EventMachine_t::SetuidString
241
242
  *************************************/
242
243
 
244
+ #ifdef OS_UNIX
243
245
  void EventMachine_t::SetuidString (const char *username)
244
246
  {
245
247
  /* This method takes a caller-supplied username and tries to setuid
@@ -256,7 +258,6 @@ void EventMachine_t::SetuidString (const char *username)
256
258
  * A setuid failure here would be in the latter category.
257
259
  */
258
260
 
259
- #ifdef OS_UNIX
260
261
  if (!username || !*username)
261
262
  throw std::runtime_error ("setuid_string failed: no username specified");
262
263
 
@@ -276,17 +277,18 @@ void EventMachine_t::SetuidString (const char *username)
276
277
  throw std::runtime_error ("setuid_string failed: no setuid");
277
278
 
278
279
  // Success.
279
- #endif
280
280
  }
281
-
281
+ #else
282
+ void EventMachine_t::SetuidString (const char *username UNUSED) { }
283
+ #endif
282
284
 
283
285
  /****************************************
284
286
  (STATIC) EventMachine_t::SetRlimitNofile
285
287
  ****************************************/
286
288
 
289
+ #ifdef OS_UNIX
287
290
  int EventMachine_t::SetRlimitNofile (int nofiles)
288
291
  {
289
- #ifdef OS_UNIX
290
292
  struct rlimit rlim;
291
293
  getrlimit (RLIMIT_NOFILE, &rlim);
292
294
  if (nofiles >= 0) {
@@ -299,14 +301,10 @@ int EventMachine_t::SetRlimitNofile (int nofiles)
299
301
  }
300
302
  getrlimit (RLIMIT_NOFILE, &rlim);
301
303
  return rlim.rlim_cur;
302
- #endif
303
-
304
- #ifdef OS_WIN32
305
- // No meaningful implementation on Windows.
306
- return 0;
307
- #endif
308
304
  }
309
-
305
+ #else
306
+ int EventMachine_t::SetRlimitNofile (int nofiles UNUSED) { return 0; }
307
+ #endif
310
308
 
311
309
  /*********************************
312
310
  EventMachine_t::SignalLoopBreaker
@@ -361,7 +359,7 @@ void EventMachine_t::_InitializeLoopBreaker()
361
359
  #endif
362
360
 
363
361
  #ifdef OS_WIN32
364
- int sd = EmSocket (AF_INET, SOCK_DGRAM, 0);
362
+ SOCKET sd = EmSocket (AF_INET, SOCK_DGRAM, 0);
365
363
  if (sd == INVALID_SOCKET)
366
364
  throw std::runtime_error ("no loop breaker socket");
367
365
  SetSocketNonblocking (sd);
@@ -914,7 +912,7 @@ SelectData_t::~SelectData_t()
914
912
  _SelectDataSelect
915
913
  *****************/
916
914
 
917
- #if defined(HAVE_TBR) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
915
+ #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
918
916
  static VALUE _SelectDataSelect (void *v)
919
917
  {
920
918
  SelectData_t *sd = (SelectData_t*)v;
@@ -983,7 +981,7 @@ void EventMachine_t::_RunSelectOnce()
983
981
  for (i = 0; i < Descriptors.size(); i++) {
984
982
  EventableDescriptor *ed = Descriptors[i];
985
983
  assert (ed);
986
- int sd = ed->GetSocket();
984
+ SOCKET sd = ed->GetSocket();
987
985
  if (ed->IsWatchOnly() && sd == INVALID_SOCKET)
988
986
  continue;
989
987
  assert (sd != INVALID_SOCKET);
@@ -1028,7 +1026,7 @@ void EventMachine_t::_RunSelectOnce()
1028
1026
  for (i=0; i < Descriptors.size(); i++) {
1029
1027
  EventableDescriptor *ed = Descriptors[i];
1030
1028
  assert (ed);
1031
- int sd = ed->GetSocket();
1029
+ SOCKET sd = ed->GetSocket();
1032
1030
  if (ed->IsWatchOnly() && sd == INVALID_SOCKET)
1033
1031
  continue;
1034
1032
  assert (sd != INVALID_SOCKET);
@@ -1077,7 +1075,7 @@ void EventMachine_t::_CleanBadDescriptors()
1077
1075
  if (ed->ShouldDelete())
1078
1076
  continue;
1079
1077
 
1080
- int sd = ed->GetSocket();
1078
+ SOCKET sd = ed->GetSocket();
1081
1079
 
1082
1080
  struct timeval tv;
1083
1081
  tv.tv_sec = 0;
@@ -1194,16 +1192,15 @@ const uintptr_t EventMachine_t::ConnectToServer (const char *bind_addr, int bind
1194
1192
  if (!server || !*server || !port)
1195
1193
  throw std::runtime_error ("invalid server or port");
1196
1194
 
1197
- int family, bind_size;
1198
- struct sockaddr_storage bind_as, *bind_as_ptr = (struct sockaddr_storage*)name2address (server, port, &family, &bind_size);
1199
- if (!bind_as_ptr) {
1195
+ struct sockaddr_storage bind_as;
1196
+ size_t bind_as_len = sizeof bind_as;
1197
+ if (!name2address (server, port, (struct sockaddr *)&bind_as, &bind_as_len)) {
1200
1198
  char buf [200];
1201
1199
  snprintf (buf, sizeof(buf)-1, "unable to resolve server address: %s", strerror(errno));
1202
1200
  throw std::runtime_error (buf);
1203
1201
  }
1204
- bind_as = *bind_as_ptr; // copy because name2address points to a static
1205
1202
 
1206
- int sd = EmSocket (family, SOCK_STREAM, 0);
1203
+ SOCKET sd = EmSocket (bind_as.ss_family, SOCK_STREAM, 0);
1207
1204
  if (sd == INVALID_SOCKET) {
1208
1205
  char buf [200];
1209
1206
  snprintf (buf, sizeof(buf)-1, "unable to create new socket: %s", strerror(errno));
@@ -1223,23 +1220,23 @@ const uintptr_t EventMachine_t::ConnectToServer (const char *bind_addr, int bind
1223
1220
  setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, (char*) &one, sizeof(one));
1224
1221
 
1225
1222
  if (bind_addr) {
1226
- int bind_to_size, bind_to_family;
1227
- struct sockaddr *bind_to = name2address (bind_addr, bind_port, &bind_to_family, &bind_to_size);
1228
- if (!bind_to) {
1223
+ struct sockaddr_storage bind_to;
1224
+ size_t bind_to_len = sizeof bind_to;
1225
+ if (!name2address (bind_addr, bind_port, (struct sockaddr *)&bind_to, &bind_to_len)) {
1229
1226
  close (sd);
1230
1227
  throw std::runtime_error ("invalid bind address");
1231
1228
  }
1232
- if (bind (sd, bind_to, bind_to_size) < 0) {
1229
+ if (bind (sd, (struct sockaddr *)&bind_to, bind_to_len) < 0) {
1233
1230
  close (sd);
1234
1231
  throw std::runtime_error ("couldn't bind to address");
1235
1232
  }
1236
1233
  }
1237
1234
 
1238
1235
  uintptr_t out = 0;
1239
- int e = 0;
1240
1236
 
1241
1237
  #ifdef OS_UNIX
1242
- if (connect (sd, (struct sockaddr*)&bind_as, bind_size) == 0) {
1238
+ int e_reason = 0;
1239
+ if (connect (sd, (struct sockaddr *)&bind_as, bind_as_len) == 0) {
1243
1240
  // This is a connect success, which Linux appears
1244
1241
  // never to give when the socket is nonblocking,
1245
1242
  // even if the connection is intramachine or to
@@ -1285,13 +1282,13 @@ const uintptr_t EventMachine_t::ConnectToServer (const char *bind_addr, int bind
1285
1282
  out = cd->GetBinding();
1286
1283
  } else {
1287
1284
  // Fall through to the !out case below.
1288
- e = error;
1285
+ e_reason = error;
1289
1286
  }
1290
1287
  }
1291
1288
  else {
1292
1289
  // The error from connect was something other then EINPROGRESS (EHOSTDOWN, etc).
1293
1290
  // Fall through to the !out case below
1294
- e = errno;
1291
+ e_reason = errno;
1295
1292
  }
1296
1293
 
1297
1294
  if (!out) {
@@ -1310,7 +1307,7 @@ const uintptr_t EventMachine_t::ConnectToServer (const char *bind_addr, int bind
1310
1307
  ConnectionDescriptor *cd = new ConnectionDescriptor (sd, this);
1311
1308
  if (!cd)
1312
1309
  throw std::runtime_error ("no connection allocated");
1313
- cd->SetUnbindReasonCode(e);
1310
+ cd->SetUnbindReasonCode (e_reason);
1314
1311
  cd->ScheduleClose (false);
1315
1312
  Add (cd);
1316
1313
  out = cd->GetBinding();
@@ -1318,7 +1315,7 @@ const uintptr_t EventMachine_t::ConnectToServer (const char *bind_addr, int bind
1318
1315
  #endif
1319
1316
 
1320
1317
  #ifdef OS_WIN32
1321
- if (connect (sd, (struct sockaddr*)&bind_as, bind_size) == 0) {
1318
+ if (connect (sd, (struct sockaddr *)&bind_as, bind_as_len) == 0) {
1322
1319
  // This is a connect success, which Windows appears
1323
1320
  // never to give when the socket is nonblocking,
1324
1321
  // even if the connection is intramachine or to
@@ -1353,6 +1350,7 @@ const uintptr_t EventMachine_t::ConnectToServer (const char *bind_addr, int bind
1353
1350
  EventMachine_t::ConnectToUnixServer
1354
1351
  ***********************************/
1355
1352
 
1353
+ #ifdef OS_UNIX
1356
1354
  const uintptr_t EventMachine_t::ConnectToUnixServer (const char *server)
1357
1355
  {
1358
1356
  /* Connect to a Unix-domain server, which by definition is running
@@ -1362,14 +1360,6 @@ const uintptr_t EventMachine_t::ConnectToUnixServer (const char *server)
1362
1360
  * is always local and can always be fulfilled immediately.
1363
1361
  */
1364
1362
 
1365
- #ifdef OS_WIN32
1366
- throw std::runtime_error ("unix-domain connection unavailable on this platform");
1367
- return 0;
1368
- #endif
1369
-
1370
- // The whole rest of this function is only compiled on Unix systems.
1371
- #ifdef OS_UNIX
1372
-
1373
1363
  uintptr_t out = 0;
1374
1364
 
1375
1365
  if (!server || !*server)
@@ -1387,7 +1377,7 @@ const uintptr_t EventMachine_t::ConnectToUnixServer (const char *server)
1387
1377
 
1388
1378
  strcpy (pun.sun_path, server);
1389
1379
 
1390
- int fd = EmSocket (AF_LOCAL, SOCK_STREAM, 0);
1380
+ SOCKET fd = EmSocket (AF_LOCAL, SOCK_STREAM, 0);
1391
1381
  if (fd == INVALID_SOCKET)
1392
1382
  return 0;
1393
1383
 
@@ -1419,14 +1409,19 @@ const uintptr_t EventMachine_t::ConnectToUnixServer (const char *server)
1419
1409
  close (fd);
1420
1410
 
1421
1411
  return out;
1422
- #endif
1423
1412
  }
1413
+ #else
1414
+ const uintptr_t EventMachine_t::ConnectToUnixServer (const char *server UNUSED)
1415
+ {
1416
+ throw std::runtime_error ("unix-domain connection unavailable on this platform");
1417
+ }
1418
+ #endif
1424
1419
 
1425
1420
  /************************
1426
1421
  EventMachine_t::AttachFD
1427
1422
  ************************/
1428
1423
 
1429
- const uintptr_t EventMachine_t::AttachFD (int fd, bool watch_mode)
1424
+ const uintptr_t EventMachine_t::AttachFD (SOCKET fd, bool watch_mode)
1430
1425
  {
1431
1426
  #ifdef OS_UNIX
1432
1427
  if (fcntl(fd, F_GETFL, 0) < 0) {
@@ -1487,7 +1482,7 @@ int EventMachine_t::DetachFD (EventableDescriptor *ed)
1487
1482
  if (!ed)
1488
1483
  throw std::runtime_error ("detaching bad descriptor");
1489
1484
 
1490
- int fd = ed->GetSocket();
1485
+ SOCKET fd = ed->GetSocket();
1491
1486
 
1492
1487
  #ifdef HAVE_EPOLL
1493
1488
  if (Poller == Poller_Epoll) {
@@ -1544,66 +1539,30 @@ int EventMachine_t::DetachFD (EventableDescriptor *ed)
1544
1539
  name2address
1545
1540
  ************/
1546
1541
 
1547
- struct sockaddr *name2address (const char *server, int port, int *family, int *bind_size)
1542
+ bool EventMachine_t::name2address (const char *server, int port, struct sockaddr *addr, size_t *addr_len)
1548
1543
  {
1549
- // THIS IS NOT RE-ENTRANT OR THREADSAFE. Optimize for speed.
1550
- // Check the more-common cases first.
1551
- // Return NULL if no resolution.
1552
-
1553
- static struct sockaddr_in in4;
1554
- #ifndef __CYGWIN__
1555
- static struct sockaddr_in6 in6;
1556
- #endif
1557
- struct hostent *hp;
1558
-
1559
1544
  if (!server || !*server)
1560
1545
  server = "0.0.0.0";
1561
1546
 
1562
- memset (&in4, 0, sizeof(in4));
1563
- if ( (in4.sin_addr.s_addr = inet_addr (server)) != INADDR_NONE) {
1564
- if (family)
1565
- *family = AF_INET;
1566
- if (bind_size)
1567
- *bind_size = sizeof(in4);
1568
- in4.sin_family = AF_INET;
1569
- in4.sin_port = htons (port);
1570
- return (struct sockaddr*)&in4;
1571
- }
1572
-
1573
- #if defined(OS_UNIX) && !defined(__CYGWIN__)
1574
- memset (&in6, 0, sizeof(in6));
1575
- if (inet_pton (AF_INET6, server, in6.sin6_addr.s6_addr) > 0) {
1576
- if (family)
1577
- *family = AF_INET6;
1578
- if (bind_size)
1579
- *bind_size = sizeof(in6);
1580
- in6.sin6_family = AF_INET6;
1581
- in6.sin6_port = htons (port);
1582
- return (struct sockaddr*)&in6;
1583
- }
1584
- #endif
1547
+ struct addrinfo *ai;
1548
+ struct addrinfo hints;
1549
+ memset (&hints, 0, sizeof(hints));
1550
+ hints.ai_family = AF_UNSPEC;
1551
+ hints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG;
1585
1552
 
1586
- #ifdef OS_WIN32
1587
- // TODO, must complete this branch. Windows doesn't have inet_pton.
1588
- // A possible approach is to make a getaddrinfo call with the supplied
1589
- // server address, constraining the hints to ipv6 and seeing if we
1590
- // get any addresses.
1591
- // For the time being, Ipv6 addresses aren't supported on Windows.
1592
- #endif
1553
+ char portstr[12];
1554
+ snprintf(portstr, sizeof(portstr), "%u", port);
1555
+
1556
+ if (getaddrinfo (server, portstr, &hints, &ai) == 0) {
1557
+ assert (ai->ai_addrlen <= *addr_len);
1558
+ memcpy (addr, ai->ai_addr, ai->ai_addrlen);
1559
+ *addr_len = ai->ai_addrlen;
1593
1560
 
1594
- hp = gethostbyname ((char*)server); // Windows requires the cast.
1595
- if (hp) {
1596
- in4.sin_addr.s_addr = ((in_addr*)(hp->h_addr))->s_addr;
1597
- if (family)
1598
- *family = AF_INET;
1599
- if (bind_size)
1600
- *bind_size = sizeof(in4);
1601
- in4.sin_family = AF_INET;
1602
- in4.sin_port = htons (port);
1603
- return (struct sockaddr*)&in4;
1561
+ freeaddrinfo(ai);
1562
+ return true;
1604
1563
  }
1605
1564
 
1606
- return NULL;
1565
+ return false;
1607
1566
  }
1608
1567
 
1609
1568
 
@@ -1620,14 +1579,12 @@ const uintptr_t EventMachine_t::CreateTcpServer (const char *server, int port)
1620
1579
  */
1621
1580
 
1622
1581
 
1623
- int family, bind_size;
1624
- struct sockaddr *bind_here = name2address (server, port, &family, &bind_size);
1625
- if (!bind_here)
1582
+ struct sockaddr_storage bind_here;
1583
+ size_t bind_here_len = sizeof bind_here;
1584
+ if (!name2address (server, port, (struct sockaddr *)&bind_here, &bind_here_len))
1626
1585
  return 0;
1627
1586
 
1628
- //struct sockaddr_in sin;
1629
-
1630
- int sd_accept = EmSocket (family, SOCK_STREAM, 0);
1587
+ SOCKET sd_accept = EmSocket (bind_here.ss_family, SOCK_STREAM, 0);
1631
1588
  if (sd_accept == INVALID_SOCKET) {
1632
1589
  goto fail;
1633
1590
  }
@@ -1650,8 +1607,7 @@ const uintptr_t EventMachine_t::CreateTcpServer (const char *server, int port)
1650
1607
  }
1651
1608
 
1652
1609
 
1653
- //if (bind (sd_accept, (struct sockaddr*)&sin, sizeof(sin))) {
1654
- if (bind (sd_accept, bind_here, bind_size)) {
1610
+ if (bind (sd_accept, (struct sockaddr *)&bind_here, bind_here_len)) {
1655
1611
  //__warning ("binding failed");
1656
1612
  goto fail;
1657
1613
  }
@@ -1678,40 +1634,27 @@ const uintptr_t EventMachine_t::OpenDatagramSocket (const char *address, int por
1678
1634
  {
1679
1635
  uintptr_t output_binding = 0;
1680
1636
 
1681
- int sd = EmSocket (AF_INET, SOCK_DGRAM, 0);
1637
+ struct sockaddr_storage bind_here;
1638
+ size_t bind_here_len = sizeof bind_here;
1639
+ if (!name2address (address, port, (struct sockaddr *)&bind_here, &bind_here_len))
1640
+ return 0;
1641
+
1642
+ // from here on, early returns must close the socket!
1643
+ SOCKET sd = EmSocket (bind_here.ss_family, SOCK_DGRAM, 0);
1682
1644
  if (sd == INVALID_SOCKET)
1683
1645
  goto fail;
1684
- // from here on, early returns must close the socket!
1685
-
1686
-
1687
- struct sockaddr_in sin;
1688
- memset (&sin, 0, sizeof(sin));
1689
- sin.sin_family = AF_INET;
1690
- sin.sin_port = htons (port);
1691
-
1692
1646
 
1693
- if (address && *address) {
1694
- sin.sin_addr.s_addr = inet_addr (address);
1695
- if (sin.sin_addr.s_addr == INADDR_NONE) {
1696
- hostent *hp = gethostbyname ((char*)address); // Windows requires the cast.
1697
- if (hp == NULL)
1698
- goto fail;
1699
- sin.sin_addr.s_addr = ((in_addr*)(hp->h_addr))->s_addr;
1700
- }
1647
+ { // set the SO_REUSEADDR on the socket before we bind, otherwise it won't work for a second one
1648
+ int oval = 1;
1649
+ if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, (char*)&oval, sizeof(oval)) < 0)
1650
+ goto fail;
1701
1651
  }
1702
- else
1703
- sin.sin_addr.s_addr = htonl (INADDR_ANY);
1704
-
1705
1652
 
1706
1653
  // Set the new socket nonblocking.
1707
- {
1708
- if (!SetSocketNonblocking (sd))
1709
- //int val = fcntl (sd, F_GETFL, 0);
1710
- //if (fcntl (sd, F_SETFL, val | O_NONBLOCK) == -1)
1711
- goto fail;
1712
- }
1654
+ if (!SetSocketNonblocking (sd))
1655
+ goto fail;
1713
1656
 
1714
- if (bind (sd, (struct sockaddr*)&sin, sizeof(sin)) != 0)
1657
+ if (bind (sd, (struct sockaddr *)&bind_here, bind_here_len) != 0)
1715
1658
  goto fail;
1716
1659
 
1717
1660
  { // Looking good.
@@ -1953,6 +1896,7 @@ void EventMachine_t::Deregister (EventableDescriptor *ed)
1953
1896
  EventMachine_t::CreateUnixDomainServer
1954
1897
  **************************************/
1955
1898
 
1899
+ #ifdef OS_UNIX
1956
1900
  const uintptr_t EventMachine_t::CreateUnixDomainServer (const char *filename)
1957
1901
  {
1958
1902
  /* Create a UNIX-domain acceptor (server) socket and add it to the event machine.
@@ -1962,16 +1906,9 @@ const uintptr_t EventMachine_t::CreateUnixDomainServer (const char *filename)
1962
1906
  * THERE IS NO MEANINGFUL IMPLEMENTATION ON WINDOWS.
1963
1907
  */
1964
1908
 
1965
- #ifdef OS_WIN32
1966
- throw std::runtime_error ("unix-domain server unavailable on this platform");
1967
- #endif
1968
-
1969
- // The whole rest of this function is only compiled on Unix systems.
1970
- #ifdef OS_UNIX
1971
-
1972
1909
  struct sockaddr_un s_sun;
1973
1910
 
1974
- int sd_accept = EmSocket (AF_LOCAL, SOCK_STREAM, 0);
1911
+ SOCKET sd_accept = EmSocket (AF_LOCAL, SOCK_STREAM, 0);
1975
1912
  if (sd_accept == INVALID_SOCKET) {
1976
1913
  goto fail;
1977
1914
  }
@@ -2011,15 +1948,20 @@ const uintptr_t EventMachine_t::CreateUnixDomainServer (const char *filename)
2011
1948
  if (sd_accept != INVALID_SOCKET)
2012
1949
  close (sd_accept);
2013
1950
  return 0;
2014
- #endif // OS_UNIX
2015
1951
  }
1952
+ #else
1953
+ const uintptr_t EventMachine_t::CreateUnixDomainServer (const char *filename UNUSED)
1954
+ {
1955
+ throw std::runtime_error ("unix-domain server unavailable on this platform");
1956
+ }
1957
+ #endif
2016
1958
 
2017
1959
 
2018
1960
  /**************************************
2019
1961
  EventMachine_t::AttachSD
2020
1962
  **************************************/
2021
1963
 
2022
- const uintptr_t EventMachine_t::AttachSD (int sd_accept)
1964
+ const uintptr_t EventMachine_t::AttachSD (SOCKET sd_accept)
2023
1965
  {
2024
1966
  uintptr_t output_binding = 0;
2025
1967
 
@@ -2054,15 +1996,9 @@ const uintptr_t EventMachine_t::AttachSD (int sd_accept)
2054
1996
  EventMachine_t::Socketpair
2055
1997
  **************************/
2056
1998
 
2057
- const uintptr_t EventMachine_t::Socketpair (char * const*cmd_strings)
1999
+ #ifdef OS_UNIX
2000
+ const uintptr_t EventMachine_t::Socketpair (char * const * cmd_strings)
2058
2001
  {
2059
- #ifdef OS_WIN32
2060
- throw std::runtime_error ("socketpair is currently unavailable on this platform");
2061
- #endif
2062
-
2063
- // The whole rest of this function is only compiled on Unix systems.
2064
- // Eventually we need this functionality (or a full-duplex equivalent) on Windows.
2065
- #ifdef OS_UNIX
2066
2002
  // Make sure the incoming array of command strings is sane.
2067
2003
  if (!cmd_strings)
2068
2004
  return 0;
@@ -2110,8 +2046,14 @@ const uintptr_t EventMachine_t::Socketpair (char * const*cmd_strings)
2110
2046
  throw std::runtime_error ("no fork");
2111
2047
 
2112
2048
  return output_binding;
2113
- #endif
2114
2049
  }
2050
+ #else
2051
+ const uintptr_t EventMachine_t::Socketpair (char * const * cmd_strings UNUSED)
2052
+ {
2053
+ throw std::runtime_error ("socketpair is currently unavailable on this platform");
2054
+ }
2055
+ #endif
2056
+
2115
2057
 
2116
2058
 
2117
2059
  /****************************