Evo C++ Library v0.5.1
sysio_sock.h
Go to the documentation of this file.
1 // Evo C++ Library
2 /* Copyright 2019 Justin Crowell
3 Distributed under the BSD 2-Clause License -- see included file LICENSE.txt for details.
4 */
6 
7 #pragma once
8 #ifndef INCL_evo_impl_sysio_sock_h
9 #define INCL_evo_impl_sysio_sock_h
10 
11 #include "sysio.h"
12 #include "../string.h"
13 
14 #if defined(_WIN32)
15  // Windows
16  #include <winsock2.h>
17  #include <ws2tcpip.h>
18  #pragma comment(lib, "Ws2_32.lib")
19 #else
20  // Linux/Unix
21  #include <sys/socket.h>
22  #include <sys/un.h>
23  #include <netinet/in.h>
24  #include <arpa/inet.h>
25  #include <netdb.h>
26  #if defined(__APPLE__) && !defined(SOCK_NONBLOCK)
27  #define SOCK_NONBLOCK O_NONBLOCK
28  #endif
29 #endif
30 
31 namespace evo {
34 
36 
37 #if defined(_WIN32)
38  // Windows
39  struct SysWindows {
40  static void set_timeval_ms(struct timeval& tm, ulong ms) {
41  const ulong MSEC_PER_SEC = 1000;
42  const ulong USEC_PER_MSEC = 1000;
43  tm.tv_sec = ms / MSEC_PER_SEC;
44  tm.tv_usec = (ms - (tm.tv_sec * MSEC_PER_SEC)) * USEC_PER_MSEC;
45  }
46  };
47 #endif
48 
50 
57 inline const char* errormsg_socket(Error error) {
58  switch (error) {
59  case EAccess: return "Permission denied for socket (EAccess)";
60  case EClosed: return "Socket is closed (EClosed)";
61  case EExist: return "Socket address/port in use or not available (EExist)";
62  case ESize: return "Message too long (ESize)";
63  case ELimit: return "No more socket descriptors available (ELimit)";
64  case ELength: return "Host or address string too long (ELength)";
65  case EFail: return "Connection refused or reset (EFail)";
66  case ENotFound: return "Address not found (ENotFound)";
67  default: break;
68  }
69  return evo::errormsg(error);
70 }
71 
75 
79 
83 
87 
89 
96  socklen_t addrlen;
97 
102  virtual void set_maxsize()
103  { addrlen = 0; }
104 };
105 
107 
114  struct sockaddr addr;
115 };
116 
118 
126  struct addrinfo hints;
127  struct addrinfo* ptr;
128  int code;
129 
130  static const int NUMERIC = AI_NUMERICHOST | AI_NUMERICHOST;
131 
135  SocketAddressInfo(int family=AF_INET) {
136  memset(&hints, 0, sizeof(hints));
137  hints.ai_family = family;
138  ptr = NULL;
139  code = 0;
140  tcp();
141  }
142 
145  { free(); }
146 
151  SocketAddressInfo& reset(int family=AF_INET) {
152  memset(&hints, 0, sizeof(hints));
153  hints.ai_family = family;
154  ptr = NULL;
155  code = 0;
156  return *this;
157  }
158 
163  hints.ai_socktype = SOCK_STREAM;
164  hints.ai_protocol = IPPROTO_TCP;
165  return *this;
166  }
167 
172  hints.ai_socktype = SOCK_DGRAM;
173  hints.ai_protocol = IPPROTO_UDP;
174  return *this;
175  }
176 
185  Error resolve(const char* host, const char* port=NULL, int flags=AI_NUMERICSERV) {
186  free();
187  hints.ai_flags = flags;
188  code = ::getaddrinfo(host, port, &hints, &ptr);
189  Error err;
190  switch (code) {
191  case 0: err = ENone; break;
192  case EAI_NONAME: err = ENotFound; break;
193  case EAI_FAIL: err = EFail; break;
194  case EAI_SERVICE: // fallthrough
195  case EAI_SOCKTYPE: // fallthrough
196  case EAI_FAMILY: // fallthrough
197  case EAI_BADFLAGS: err = EInval; break;
198  case EAI_MEMORY: err = ESpace; break;
199  case EAI_AGAIN: err = ERetry; break;
200  #if defined(EAI_NODATA) && !defined(_WIN32) // win32: same as EAI_NONAME
201  case EAI_NODATA: err = ENotFound; break;
202  #endif
203  #if defined(EAI_ADDRFAMILY)
204  case EAI_ADDRFAMILY: err = ENotFound; break;
205  #endif
206  default: err = EUnknown; break;
207  }
208  return err;
209  }
210 
219  Error resolve(const char* host, ushort port, int flags=0) {
220  StringInt<ushort> port_str(port);
221  return resolve(host, port_str.data_, flags | AI_NUMERICSERV);
222  }
223 
232  Error resolve(const SubString& host, ushort port=0, int flags=0) {
233  const uint MAX_HOST_SIZE = 256; // See IETF RFC 1123
234  char hostbuf[MAX_HOST_SIZE];
235 
236  const SubString::Size hostlen = host.size();
237  if (hostlen < MAX_HOST_SIZE) {
238  memcpy(hostbuf, host.data(), hostlen);
239  hostbuf[hostlen] = '\0';
240 
241  flags |= AI_NUMERICSERV;
242  if (port > 0) {
243  StringInt<ushort> port_str(port);
244  return resolve(hostbuf, port_str.data_, flags);
245  } else
246  return resolve(hostbuf, EVO_CNULL, flags);
247  }
248  errno = ENAMETOOLONG;
249  return ELength;
250  }
251 
258  Error convert(const char* host)
259  { return resolve(host, EVO_CNULL, NUMERIC); }
260 
268  Error convert(const char* host, ushort port)
269  { return resolve(host, port, NUMERIC); }
270 
278  Error convert(const SubString& host, ushort port=0)
279  { return resolve(host, port, NUMERIC); }
280 
284  void free() {
285  if (ptr != NULL) {
286  ::freeaddrinfo(ptr);
287  ptr = NULL;
288  }
289  }
290 
291 private:
292  // Disable copying
294  SocketAddressInfo& operator=(const SocketAddressInfo&);
295 };
296 
298 
307 struct IoSocket : public IoDevice {
308  static const bool STREAM_SEEKABLE = false;
309  static const ulong TIMEOUT_DEFAULT = 30000;
310 
313 
314  ulong timeout_ms;
315 
316 #if defined(_WIN32)
317  // Windows
318 
319  enum Shutdown {
320  sIN = SD_RECEIVE,
321  sOUT = SD_SEND,
322  sINOUT = SD_BOTH
323  };
324 
325  struct Init {
326  bool active;
327  WSADATA data;
328 
329  Init() : active(false)
330  { init(); }
331 
332  ~Init()
333  { cleanup(); }
334 
335  void init() {
336  if (!active)
337  active = (::WSAStartup(MAKEWORD(2, 2), &data) == 0);
338  }
339 
340  void cleanup() {
341  if (active && ::WSACleanup() == 0)
342  active = false;
343  }
344  };
345 
346  typedef SOCKET Handle;
347  typedef DWORD OptNum;
348 
349  static const Handle INVALID = INVALID_SOCKET;
350  static const int SOCK_ERROR = SOCKET_ERROR;
351 
352  IoSocket() {
353  timeout_ms = TIMEOUT_DEFAULT;
354  handle = INVALID;
355  nonblock = false;
356  }
357 
358  IoSocket(Handle socket) {
359  timeout_ms = TIMEOUT_DEFAULT;
360  handle = socket;
361  nonblock = false;
362  }
363 
364  bool shutdown(Shutdown how=sINOUT) {
365  if (handle == INVALID)
366  errno = WSAENOTCONN;
367  else if (::shutdown(handle, how) != 0)
368  errno = WSAGetLastError();
369  else
370  return true;
371  return false;
372  }
373 
374  void close() {
375  if (handle == INVALID)
376  errno = WSAENOTCONN;
377  else if (::closesocket(handle) == SOCKET_ERROR)
378  errno = WSAGetLastError();
379  else
380  errno = 0;
381  }
382 
383  Error set_nonblock(bool enable=true) {
384  if (handle != INVALID) {
385  ulong flag = (enable ? 1 : 0);
386  if (::ioctlsocket(handle, FIONBIO, &flag) != 0) {
387  Error err;
388  const int last_error = WSAGetLastError();
389  errno = last_error;
390  switch (last_error) {
391  case WSANOTINITIALISED: // fallthrough
392  case WSAENOTSOCK: err = EClosed; break;
393  default: err = EUnknown; break;
394  }
395  return err;
396  }
397  }
398  nonblock = enable;
399  return ENone;
400  }
401 
402  bool accept(Error& err, IoSocket& client_socket, SocketAddressBase* client_address=NULL) {
403  if (handle == INVALID) {
404  err = EClosed;
405  errno = WSAENOTCONN;
406  } else {
407  if (timeout_ms == 0 || read_wait(err, timeout_ms)) {
408  Handle client_handle;
409  if (client_address != NULL)
410  client_handle = ::accept(handle, &((SocketAddress*)client_address)->addr, &client_address->addrlen);
411  else
412  client_handle = ::accept(handle, NULL, NULL);
413  if (client_handle != INVALID) {
414  client_socket.attach(client_handle);
415  err = ENone;
416  return true;
417  }
418  err = get_socket_error();
419  }
420  }
421  return false;
422  }
423 
424  bool accept_nonblock(Error& err, IoSocket& client_socket, SocketAddressBase* client_address=NULL) {
425  if (accept(err, client_socket, client_address)) {
426  err = set_nonblock();
427  return (err == ENone);
428  }
429  return false;
430  }
431 
432  bool read_wait(Error& err, ulong read_timeout_ms) {
433  fd_set read_set;
434  FD_ZERO(&read_set);
435  FD_SET(handle, &read_set);
436 
437  struct timeval timeout;
438  SysWindows::set_timeval_ms(timeout, read_timeout_ms);
439 
440  int waitresult = ::select(0, &read_set, NULL, NULL, &timeout);
441  if (waitresult == SOCK_ERROR) {
442  const int last_error = WSAGetLastError();
443  errno = last_error;
444  switch (last_error) {
445  case WSANOTINITIALISED: // fallthrough
446  case WSAENOTSOCK: err = EClosed; break;
447  default: err = EUnknown; break;
448  }
449  return false;
450  } else if (waitresult == 0) {
451  errno = WSAETIMEDOUT;
452  err = ETimeout;
453  return false;
454  }
455  return true;
456  }
457 
458  ulong read(Error& err, void* buf, ulong size) {
459  if (handle == INVALID) {
460  err = EClosed;
461  errno = ENOTCONN;
462  return 0;
463  }
464  if (size > (ulong)std::numeric_limits<int>::max())
465  size = (ulong)std::numeric_limits<int>::max();
466  if (timeout_ms > 0 && !read_wait(err, timeout_ms))
467  return 0;
468  int result = ::recv(handle, (char*)buf, size, 0);
469  if (result == SOCK_ERROR) {
470  const int last_error = WSAGetLastError();
471  errno = last_error;
472  switch (last_error) {
473  case WSANOTINITIALISED: // fallthrough
474  case WSAENOTSOCK: // fallthrough
475  case WSAEINVAL: // fallthrough
476  case WSAENOTCONN: err = EClosed; break;
477  case WSAEMSGSIZE: err = ESize; break;
478  case WSAEFAULT: err = EPtr; break;
479  case WSAEWOULDBLOCK: err = ENonBlock; break;
480  default: err = ERead; break;
481  }
482  return 0;
483  }
484  err = ENone;
485  return (ulong)result;
486  }
487 
488  ulong readfrom(Error& err, void* buf, ulong size, struct sockaddr* address=NULL, socklen_t* address_len=NULL, int flags=0) {
489  if (handle == INVALID) {
490  err = EClosed;
491  errno = ENOTCONN;
492  return 0;
493  }
494  if (size > (ulong)std::numeric_limits<int>::max())
495  size = (ulong)std::numeric_limits<int>::max();
496  if (timeout_ms > 0 && !read_wait(err, timeout_ms))
497  return 0;
498  int result = ::recvfrom(handle, (char*)buf, size, flags, address, address_len);
499  if (result == 0) {
500  err = EClosed;
501  errno = ENOTCONN;
502  return 0;
503  } else if (result < 0) {
504  const int last_error = WSAGetLastError();
505  errno = last_error;
506  switch (last_error) {
507  case WSANOTINITIALISED: // fallthrough
508  case WSAENOTSOCK: // fallthrough
509  case WSAEINVAL: // fallthrough
510  case WSAENOTCONN: err = EClosed; break;
511  case WSAEMSGSIZE: err = ESize; break;
512  case WSAEFAULT: err = EPtr; break;
513  case WSAEWOULDBLOCK: err = ENonBlock; break;
514  case WSAECONNRESET: err = EFail; break;
515  default: err = ERead; break;
516  }
517  return 0;
518  }
519  err = ENone;
520  return (ulong)result;
521  }
522 
523  bool write_wait(Error& err, ulong write_timeout_ms) {
524  fd_set write_set;
525  FD_ZERO(&write_set);
526  FD_SET(handle, &write_set);
527 
528  struct timeval timeout;
529  SysWindows::set_timeval_ms(timeout, write_timeout_ms);
530 
531  int waitresult = ::select(0, NULL, &write_set, NULL, &timeout);
532  if (waitresult == SOCK_ERROR) {
533  const int last_error = WSAGetLastError();
534  errno = last_error;
535  switch (last_error) {
536  case WSANOTINITIALISED: // fallthrough
537  case WSAENOTSOCK: err = EClosed; break;
538  default: err = EUnknown; break;
539  }
540  return false;
541  } else if (waitresult == 0) {
542  errno = WSAETIMEDOUT;
543  err = ETimeout;
544  return false;
545  }
546  return true;
547  }
548 
549  ulong write(Error& err, const void* buf, ulong size) {
550  if (handle == INVALID) {
551  err = EClosed;
552  errno = ENOTCONN;
553  return 0;
554  }
555  if (size > (ulong)std::numeric_limits<int>::max())
556  size = (ulong)std::numeric_limits<int>::max();
557  if (timeout_ms > 0 && !write_wait(err, timeout_ms))
558  return 0;
559  int result = ::send(handle, (const char*)buf, (int)size, 0);
560  if (result == SOCK_ERROR) {
561  const int last_error = WSAGetLastError();
562  errno = last_error;
563  switch (last_error) {
564  case WSANOTINITIALISED: // fallthrough
565  case WSAENOTSOCK: // fallthrough
566  case WSAEINVAL: // fallthrough
567  case WSAENOTCONN: err = EClosed; break;
568  case WSAENOBUFS: err = ESpace; break;
569  case WSAEMSGSIZE: err = ESize; break;
570  case WSAEFAULT: err = EPtr; break;
571  case WSAEWOULDBLOCK: err = ENonBlock; break;
572  default: err = EWrite; break;
573  }
574  return 0;
575  }
576  err = ENone;
577  return (ulong)result;
578  }
579 
580  ulong writeto(Error& err, const void* buf, ulong size, const struct sockaddr* address, socklen_t address_len, int flags=0) {
581  if (handle == INVALID) {
582  err = EClosed;
583  errno = ENOTCONN;
584  return 0;
585  }
586  if (size > (ulong)std::numeric_limits<int>::max()) {
587  err = ESize;
588  errno = WSAEMSGSIZE;
589  return 0;
590  }
591  if (timeout_ms > 0 && !write_wait(err, timeout_ms))
592  return 0;
593  int result = ::sendto(handle, (const char*)buf, (int)size, flags, address, address_len);
594  if (result < 0) {
595  const int last_error = WSAGetLastError();
596  errno = last_error;
597  switch (last_error) {
598  case WSANOTINITIALISED: // fallthrough
599  case WSAENOTSOCK: // fallthrough
600  case WSAEINVAL: // fallthrough
601  case WSAENOTCONN: err = EClosed; break;
602  case WSAEACCES: err = EAccess; break;
603  case WSAENOBUFS: err = ESpace; break;
604  case WSAEMSGSIZE: err = ESize; break;
605  case WSAEFAULT: err = EPtr; break;
606  case WSAEWOULDBLOCK: err = ENonBlock; break;
607  case WSAECONNABORTED: // fallthrough
608  case WSAECONNRESET: err = EFail; break;
609  case WSAEADDRNOTAVAIL: // fallthrough
610  case WSAEDESTADDRREQ: // fallthrough
611  case WSAEHOSTUNREACH: err = ENotFound; break;
612  case WSAEAFNOSUPPORT: err = EInvalOp; break;
613  default: err = EWrite; break;
614  }
615  return 0;
616  }
617  err = ENone;
618  return (ulong)result;
619  }
620 
621  Error getopt(int level, int optname, void* buf, uint& size) {
622  if (size > (uint)INT_MAX)
623  size = (uint)INT_MAX;
624  int optlen = (int)size;
625  int result = ::getsockopt(handle, level, optname, (char*)buf, &optlen);
626  if (result < 0) {
627  Error err;
628  const int last_error = WSAGetLastError();
629  errno = last_error;
630  switch (last_error) {
631  case WSANOTINITIALISED: // fallthrough
632  case WSAENOTSOCK: // fallthrough
633  case WSAENOTCONN: err = EClosed; break;
634  case WSAEFAULT: err = EPtr; break;
635  case WSAEINVAL: err = EInval; break;
636  case WSAENOPROTOOPT: err = EInvalOp; break;
637  default: err = EUnknown; break;
638  }
639  return err;
640  }
641  size = (optlen > 0) ? (uint)optlen : 0;
642  return ENone;
643  }
644 
645  Error setopt(int level, int optname, const void* buf, uint size) {
646  if (size > (uint)INT_MAX) {
647  errno = WSAEMSGSIZE;
648  return ESize;
649  }
650  int result = ::setsockopt(handle, level, optname, (const char*)buf, (int)size);
651  if (result < 0) {
652  Error err;
653  const int last_error = WSAGetLastError();
654  errno = last_error;
655  switch (last_error) {
656  case WSANOTINITIALISED: // fallthrough
657  case WSAENOTSOCK: // fallthrough
658  case WSAENOTCONN: err = EClosed; break;
659  case WSAEFAULT: err = EPtr; break;
660  case WSAEINVAL: err = EInval; break;
661  case WSAENOPROTOOPT: err = EInvalOp; break;
662  default: err = EUnknown; break;
663  }
664  return err;
665  }
666  return ENone;
667  }
668 
669  template<class TOut>
670  static TOut& errormsg_out(TOut& out, Error err) {
671  const int lasterror = errno;
672  out << errormsg_socket(err) << ListBase<char>(" (errno:", 8) << lasterror << ')';
673  if (err != ENone && lasterror != 0) {
674  const int BUF_SIZE = 256;
675  char buf[BUF_SIZE];
676  DWORD len = ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, lasterror, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, BUF_SIZE, NULL);
677  if (len > 0)
678  out << ListBase<char>(": ", 2) << ListBase<char>(buf, len);
679  }
680  return out;
681  }
682 
683 #else
684  // Linux/Unix
685 
687  enum Shutdown {
688  sIN = SHUT_RD,
689  sOUT = SHUT_WR,
690  sINOUT = SHUT_RDWR
691  };
692 
694  struct Init
695  { };
696 
697  typedef int Handle;
698  typedef int OptNum;
699 
700  static const Handle INVALID = -1;
701  static const int SOCK_ERROR = -1;
702 
705  timeout_ms = TIMEOUT_DEFAULT;
706  handle = INVALID;
707  nonblock = false;
708  autoresume = true;
709  }
710 
716  IoSocket(Handle socket) {
717  timeout_ms = TIMEOUT_DEFAULT;
718  handle = socket;
719  nonblock = false;
720  autoresume = true;
721  }
722 
730  bool shutdown(Shutdown how=sINOUT) {
731  if (handle == INVALID)
732  errno = ENOTCONN;
733  else if (::shutdown(handle, (int)how) == 0)
734  return true;
735  return false;
736  }
737 
741  void close() {
742  if (handle != INVALID) {
743  ::close(handle);
744  handle = INVALID;
745  }
746  }
747 
756  Error set_nonblock(bool enable=true) {
757  #if defined(SOCK_NONBLOCK)
758  if (handle != INVALID) {
759  bool error_flag; // init below
760  int flags = ::fcntl(handle, F_GETFL, NULL);
761  if (flags >= 0) {
762  if (enable)
763  flags |= O_NONBLOCK;
764  else
765  flags &= ~(int)O_NONBLOCK;
766  error_flag = (::fcntl(handle, F_SETFL, flags) != 0);
767  } else
768  error_flag = true;
769 
770  if (error_flag) {
771  Error err;
772  switch (errno) {
773  case EAGAIN: // fallthrough
774  case EACCES: err = EAccess; break;
775  case EINVAL: err = EInval; break;
776  case EBADF: err = EClosed; break;
777  default: err = EUnknown; break;
778  }
779  return err;
780  }
781  }
782  nonblock = enable;
783  return ENone;
784  #else
785  // Non-blocking I/O not supported on this system
786  errno = EINVAL;
787  return EInval;
788  #endif
789  }
790 
799  bool connect_wait(Error& err, ulong timeout_ms) {
800  if (handle == INVALID) {
801  err = EClosed;
802  errno = ENOTCONN;
803  } else if (write_wait(err, timeout_ms)) {
804  for (;;) {
805  int value = 0;
806  socklen_t len = sizeof(value);
807  if (::getsockopt(handle, SOL_SOCKET, SO_ERROR, &value, &len) == 0) {
808  if (value == EINTR && autoresume) {
809  continue;
810  } else if (value == 0 || value == EISCONN) {
811  err = ENone;
812  return true;
813  }
814  err = get_socket_error(value);
815  } else
816  err = get_socket_error();
817  break;
818  }
819  }
820  return false;
821  }
822 
831  bool read_wait(Error& err, ulong timeout_ms)
832  { return SysLinuxIo::read_wait(err, handle, timeout_ms, autoresume); }
833 
834  // Documented by parent
835  ulong read(Error& err, void* buf, ulong size)
836  { return SysLinuxIo::read(err, handle, buf, size, timeout_ms, autoresume); }
837 
850  ulong readfrom(Error& err, void* buf, ulong size, struct sockaddr* address=NULL, socklen_t* address_len=NULL, int flags=0) {
851  if (handle == INVALID) {
852  err = EClosed;
853  errno = ENOTCONN;
854  return 0;
855  }
856  if (size > SSIZE_MAX)
857  size = SSIZE_MAX;
858  ssize_t result;
859  for (;;) {
860  if (timeout_ms > 0 && !SysLinuxIo::read_wait(err, handle, timeout_ms, autoresume))
861  return 0;
862  result = ::recvfrom(handle, buf, size, flags, address, address_len);
863  if (result < 0) {
864  switch (errno) {
865  case EINTR:
866  if (autoresume)
867  continue;
868  err = ESignal; break;
869  case ENOSPC: err = ESpace; break;
870  case EFBIG: err = ESize; break;
871  case EFAULT: err = EPtr; break;
872  case EBADF: err = EClosed; break;
873  #if EAGAIN != EWOULDBLOCK
874  case EAGAIN: // fallthrough
875  #endif
876  case EWOULDBLOCK: err = ENonBlock; break;
877  default: err = ERead; break;
878  }
879  return 0;
880  }
881  break;
882  }
883  err = ENone;
884  return (ulong)result;
885  }
886 
895  bool write_wait(Error& err, ulong timeout_ms)
896  { return SysLinuxIo::write_wait(err, handle, timeout_ms, autoresume); }
897 
898  // Documented by parent
899  ulong write(Error& err, const void* buf, ulong size)
900  { return SysLinuxIo::write(err, handle, buf, size, timeout_ms, autoresume); }
901 
914  ulong writeto(Error& err, const void* buf, ulong size, const struct sockaddr* address, socklen_t address_len, int flags=0) {
915  if (handle == INVALID) {
916  err = EClosed;
917  errno = ENOTCONN;
918  return 0;
919  }
920  if (size > SSIZE_MAX) {
921  err = ESize;
922  errno = EMSGSIZE;
923  return -1;
924  }
925  ssize_t result;
926  for (;;) {
927  if (timeout_ms > 0 && !SysLinuxIo::write_wait(err, handle, timeout_ms, autoresume))
928  return 0;
929  result = ::sendto(handle, buf, size, flags, address, address_len);
930  if (result == 0) {
931  err = EFail;
932  return 0;
933  } else if (result < 0) {
934  switch (errno) {
935  case EINTR:
936  if (autoresume)
937  continue;
938  err = ESignal; break;
939  case EACCES: err = EAccess; break;
940  case ENOSPC: err = ESpace; break;
941  case EFBIG: err = ESize; break;
942  case EFAULT: err = EPtr; break;
943  case ENOTCONN: // fallthrough
944  case ENOTSOCK: // fallthrough
945  case EPIPE: // fallthrough
946  case EBADF: err = EClosed; break;
947  #if EAGAIN != EWOULDBLOCK
948  case EAGAIN: // fallthrough
949  #endif
950  case EWOULDBLOCK: err = ENonBlock; break;
951  case EOPNOTSUPP: err = EInvalOp; break;
952  case ECONNRESET: err = EFail; break;
953  case EDESTADDRREQ: err = ENotFound; break;
954  default: err = EWrite; break;
955  }
956  return 0;
957  }
958  break;
959  }
960  err = ENone;
961  return (ulong)result;
962  }
963 
972  bool accept(Error& err, IoSocket& client_socket, SocketAddressBase* client_address=NULL) {
973  if (handle == INVALID) {
974  err = EClosed;
975  errno = ENOTCONN;
976  } else {
977  if (SysLinuxIo::read_wait(err, handle, timeout_ms, autoresume)) {
978  for (;;) {
979  int client_handle;
980  if (client_address != NULL)
981  client_handle = ::accept(handle, &((SocketAddress*)client_address)->addr, &client_address->addrlen);
982  else
983  client_handle = ::accept(handle, NULL, NULL);
984 
985  if (client_handle > 0) {
986  client_socket.attach(client_handle);
987  err = ENone;
988  return true;
989  } else {
990  const int last_error = errno;
991  if (last_error == EINTR && autoresume)
992  continue;
993  err = get_socket_error(last_error);
994  }
995  break;
996  }
997  }
998  }
999  return false;
1000  }
1001 
1011  bool accept_nonblock(Error& err, IoSocket& client_socket, SocketAddressBase* client_address=NULL) {
1012  if (handle == INVALID) {
1013  err = EClosed;
1014  errno = ENOTCONN;
1015  return false;
1016  }
1017 
1018  #if defined(__linux) && defined(SOCK_NONBLOCK) && defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 10)) && !defined(EVO_SOCKET_NO_ACCEPT4)
1019  // Use GNU accept4() and set as non-blocking at the same time (less system calls) -- avoid this by defining EVO_SOCKET_NO_ACCEPT4
1020  for (;;) {
1021  int client_handle;
1022  if (client_address != NULL)
1023  client_handle = ::accept4(handle, &((SocketAddress*)client_address)->addr, &client_address->addrlen, SOCK_NONBLOCK);
1024  else
1025  client_handle = ::accept4(handle, NULL, NULL, SOCK_NONBLOCK);
1026  if (client_handle > 0) {
1027  client_socket.attach(client_handle);
1028  client_socket.nonblock = true;
1029  err = ENone;
1030  return true;
1031  } else {
1032  const int last_error = errno;
1033  if (last_error == EINTR && autoresume)
1034  continue;
1035  err = get_socket_error(last_error);
1036  }
1037  break;
1038  }
1039  #else
1040  if (accept(err, client_socket, client_address)) {
1041  err = set_nonblock();
1042  return (err == ENone);
1043  }
1044  #endif
1045  return false;
1046  }
1047 
1057  Error getopt(int level, int optname, void* buf, uint& size) {
1058  if (size > (uint)std::numeric_limits<socklen_t>::max())
1059  size = (uint)std::numeric_limits<socklen_t>::max();
1060  socklen_t optlen = (socklen_t)size;
1061  int result = ::getsockopt(handle, level, optname, buf, &optlen);
1062  if (result < 0) {
1063  Error err;
1064  switch (errno) {
1065  case EBADF: // fallthrough
1066  case ENOTSOCK: err = EClosed; break;
1067  case EFAULT: err = EPtr; break;
1068  case EINVAL: err = EInval; break;
1069  case ENOPROTOOPT: err = EInvalOp; break;
1070  default: err = EUnknown; break;
1071  }
1072  return err;
1073  }
1074  size = (optlen > 0) ? (uint)optlen : 0;
1075  return ENone;
1076  }
1077 
1087  Error setopt(int level, int optname, const void* buf, uint size) {
1088  if (size > (uint)std::numeric_limits<socklen_t>::max()) {
1089  errno = EMSGSIZE;
1090  return ESize;
1091  }
1092  const socklen_t optlen = (socklen_t)size;
1093  int result = ::setsockopt(handle, level, optname, buf, optlen);
1094  if (result < 0) {
1095  Error err;
1096  switch (errno) {
1097  case EBADF: // fallthrough
1098  case ENOTSOCK: err = EClosed; break;
1099  case EFAULT: err = EPtr; break;
1100  case EINVAL: err = EInval; break;
1101  case ENOPROTOOPT: err = EInvalOp; break;
1102  default: err = EUnknown; break;
1103  }
1104  return err;
1105  }
1106  return ENone;
1107  }
1108 
1117  template<class TOut>
1118  static TOut& errormsg_out(TOut& out, Error err) {
1119  const int lasterror = errno;
1120  out << errormsg_socket(err) << ListBase<char>(" (errno:", 8) << lasterror << ')';
1121  if (err != ENone && lasterror != 0) {
1122  const int BUF_SIZE = 256;
1123  char buf[BUF_SIZE];
1124  char* p;
1125  #if defined(__linux)
1126  p = strerror_r(lasterror, buf, BUF_SIZE);
1127  #else
1128  p = (strerror_r(lasterror, buf, BUF_SIZE) == 0 ? buf : NULL);
1129  #endif
1130  if (p && *p)
1131  out << ListBase<char>(": ", 2) << p;
1132  }
1133  return out;
1134  }
1135 
1136  bool autoresume;
1137 #endif
1138 
1141  { close(); }
1142 
1146  bool isopen() const
1147  { return (handle != INVALID); }
1148 
1156  bool listen(Error& err, struct addrinfo* address_info, int backlog=SOMAXCONN, bool all=true) {
1157  assert( address_info != NULL );
1158  close();
1159  err = EInval;
1160  uint best_state = 0; // Used to return error from loop that got closest to success: 0=null, 1=socket(), 2=bind()
1161  int best_errno = 0; // Used to set errno so it matches err
1162  for (ulong counter=0; (counter == 0 || all) && address_info != NULL; address_info=address_info->ai_next, ++counter) {
1163  Error sock_err = create_socket(address_info->ai_family, address_info->ai_socktype, address_info->ai_protocol);
1164  if (sock_err != ENone) {
1165  if (best_state == 0) {
1166  err = sock_err;
1167  best_errno = errno;
1168  }
1169  continue;
1170  }
1171 
1172  uint cur_state = 1;
1173  if (::bind(handle, address_info->ai_addr, (int)address_info->ai_addrlen) != SOCK_ERROR) {
1174  ++cur_state;
1175  if (::listen(handle, backlog) != SOCK_ERROR) {
1176  err = ENone;
1177  return true;
1178  }
1179  }
1180  if (cur_state >= best_state) {
1181  err = IoSocket::get_socket_error();
1182  best_errno = errno;
1183  best_state = cur_state;
1184  }
1185  close();
1186  }
1187  errno = best_errno;
1188  return false;
1189  }
1190 
1200  bool listen(Error& err, struct sockaddr* address, socklen_t address_len, int backlog=SOMAXCONN, int socktype=SOCK_STREAM, int protocol=0) {
1201  assert( address != NULL );
1202  assert( address_len > 0 );
1203  close();
1204  err = create_socket(address->sa_family, socktype, protocol);
1205  if (err == ENone) {
1206  if (::bind(handle, address, address_len) != SOCK_ERROR) {
1207  if (::listen(handle, backlog) != SOCK_ERROR) {
1208  err = ENone;
1209  return true;
1210  }
1211  }
1212  err = IoSocket::get_socket_error();
1213  const int last_errno = errno;
1214  close();
1215  errno = last_errno;
1216  }
1217  return false;
1218  }
1219 
1228  bool bind(Error& err, struct sockaddr* address, socklen_t address_len, int socktype=SOCK_DGRAM, int protocol=0) {
1229  assert( address != NULL );
1230  assert( address_len > 0 );
1231  close();
1232  err = create_socket(address->sa_family, socktype, protocol);
1233  if (err == ENone) {
1234  if (::bind(handle, address, address_len) != SOCK_ERROR) {
1235  err = ENone;
1236  return true;
1237  }
1238  err = IoSocket::get_socket_error();
1239  const int last_errno = errno;
1240  close();
1241  errno = last_errno;
1242  }
1243  return false;
1244  }
1245 
1253  bool cast(Error& err, int family=AF_INET, int socktype=SOCK_DGRAM, int protocol=0) {
1254  close();
1255  err = create_socket(family, socktype, protocol);
1256  if (err == ENone)
1257  return true;
1258  err = IoSocket::get_socket_error();
1259  const int last_errno = errno;
1260  close();
1261  errno = last_errno;
1262  return false;
1263  }
1264 
1277  bool connect(Error& err, struct addrinfo* address_info, bool all=true) {
1278  close();
1279  err = EInval;
1280  uint best_state = 0; // Used to return error from loop that got closest to success: 0=null, 1=socket()
1281  int best_errno = 0; // Used to set errno so it matches err
1282  for (ulong counter=0; (counter == 0 || all) && address_info != NULL; address_info=address_info->ai_next, ++counter) {
1283  Error sock_err = create_socket(address_info->ai_family, address_info->ai_socktype, address_info->ai_protocol);
1284  if (sock_err != ENone) {
1285  if (best_state == 0) {
1286  err = sock_err;
1287  best_errno = errno;
1288  }
1289  continue;
1290  }
1291  best_state = 1; // use error from last connect
1292 
1293  const int result = ::connect(handle, address_info->ai_addr, (int)address_info->ai_addrlen);
1294  if (result != SOCK_ERROR) {
1295  err = ENone;
1296  return true;
1297  }
1298  err = IoSocket::get_socket_error();
1299  close();
1300  }
1301  errno = best_errno;
1302  return false;
1303  }
1304 
1316  bool connect(Error& err, struct sockaddr* address, socklen_t address_len, int socktype=SOCK_STREAM, int protocol=0) {
1317  assert( address != NULL );
1318  assert( address_len > 0 );
1319  close();
1320  err = create_socket(address->sa_family, socktype, protocol);
1321  if (err == ENone) {
1322  if (::connect(handle, address, address_len) != SOCK_ERROR) {
1323  err = ENone;
1324  return true;
1325  }
1326  err = IoSocket::get_socket_error();
1327  const int last_errno = errno;
1328  close();
1329  errno = last_errno;
1330  }
1331  return false;
1332  }
1333 
1339  void attach(Handle socket) {
1340  close();
1341  handle = socket;
1342  }
1343 
1347  Handle detach() {
1348  Handle result = handle;
1349  handle = INVALID;
1350  return result;
1351  }
1352 
1353  Handle handle;
1354  bool nonblock;
1355 
1360  static const Init& init() {
1361  static Init data;
1362  return data;
1363  }
1364 
1369  ulongl pos(Error& err) {
1370  errno = EINVAL;
1371  err = EInval;
1372  return 0;
1373  }
1374 
1379  ulongl seek(Error& err, ulongl, Seek) {
1380  errno = EINVAL;
1381  err = EInval;
1382  return 0;
1383  }
1384 
1385 private:
1386 #if defined(_WIN32)
1387  // Windows
1388 
1389  Error create_socket(int domain, int socktype, int protocol) {
1390  if ((handle=::socket(domain, socktype, protocol)) == INVALID) {
1391  return IoSocket::get_socket_error();
1392  } else if (nonblock)
1393  return set_nonblock(true);
1394  return ENone;
1395  }
1396 
1397  static Error get_socket_error() {
1398  Error err;
1399  const int code = WSAGetLastError();
1400  switch (code) {
1401  case WSAEACCES: err = EAccess; break;
1402  case WSANOTINITIALISED: // fallthrough
1403  case WSAENOTSOCK: // fallthrough
1404  case WSAENOTCONN: // fallthrough
1405  case WSAEPROTONOSUPPORT: // fallthrough
1406  case WSAEPROTOTYPE: // fallthrough
1407  case WSAESOCKTNOSUPPORT: // fallthrough
1408  case WSAEAFNOSUPPORT: // fallthrough
1409  case WSAEFAULT: // fallthrough
1410  case WSAEINVAL: // fallthrough
1411  case WSAEADDRNOTAVAIL: err = EInval; break;
1412  case WSAEOPNOTSUPP: err = EInvalOp; break;
1413  case WSAEADDRINUSE: err = EExist; break;
1414  case WSAENOBUFS: err = ESpace; break;
1415  case WSAEMFILE: err = ELimit; break;
1416  case WSAEHOSTUNREACH: // fallthrough
1417  case WSAENETUNREACH: // fallthrough
1418  case WSAECONNRESET: // fallthrough
1419  case WSAECONNREFUSED: err = EFail; break;
1420  case WSAETIMEDOUT: err = ETimeout; break;
1421  case WSAEALREADY: // fallthrough
1422  case WSAEWOULDBLOCK: err = ENonBlock; break;
1423  case WSAEISCONN: err = ENone; break;
1424  default: err = EUnknown; break;
1425  }
1426  errno = code;
1427  return err;
1428  }
1429 
1430 #else
1431  // Linux/Unix
1432 
1433  Error create_socket(int domain, int type, int protocol) {
1434  #if defined(SOCK_NONBLOCK)
1435  const int flags = (nonblock ? SOCK_NONBLOCK : 0);
1436  #else
1437  // Non-blocking I/O not supported on this system
1438  if (nonblock) {
1439  errno = EINVAL;
1440  return EInval;
1441  }
1442  const int flags = 0;
1443  #endif
1444  if ((handle=::socket(domain, type | flags, protocol)) == INVALID)
1445  return IoSocket::get_socket_error();
1446  return ENone;
1447  }
1448 
1449  static Error get_socket_error(int code) {
1450  Error err;
1451  switch (code) {
1452  case EPERM: // fallthrough
1453  case EACCES: err = EAccess; break;
1454  case EINVAL: // fallthrough
1455  case EPROTONOSUPPORT: // fallthrough
1456  case EPROTOTYPE: // fallthrough
1457  case EBADF: // fallthrough
1458  case EFAULT: // fallthrough
1459  case ENOTSOCK: // fallthrough
1460  case EAFNOSUPPORT: err = EInval; break;
1461  case EOPNOTSUPP: err = EInvalOp; break;
1462  case EADDRNOTAVAIL: // fallthrough
1463  case EADDRINUSE: err = EExist; break;
1464  case ENOMEM: // fallthrough
1465  case ENOBUFS: err = ESpace; break;
1466  case ENFILE: // fallthrough
1467  case EMFILE: err = ELimit; break;
1468  case ENETUNREACH: // fallthrough
1469  case ECONNABORTED: // fallthrough
1470  case ECONNREFUSED: err = EFail; break;
1471  case ETIMEDOUT: err = ETimeout; break;
1472  case EINPROGRESS: // fallthrough
1473  case EAGAIN: // fallthrough
1474  #if EAGAIN != EWOULDBLOCK
1475  case EWOULDBLOCK: // fallthrough
1476  #endif
1477  case EALREADY: err = ENonBlock; break;
1478  case EINTR: err = ESignal; break;
1479  default: err = EUnknown; break;
1480  }
1481  return err;
1482  }
1483 
1484  static Error get_socket_error()
1485  { return IoSocket::get_socket_error(errno); }
1486 #endif
1487 
1488  static const char* errormsg(Error error) {
1489  switch (error) {
1490  case EAccess: return "Permission denied for socket (EAccess)";
1491  case EClosed: return "Socket is closed (EClosed)";
1492  case EExist: return "Socket address/port in use or not available (EExist)";
1493  case ESize: return "Message too long (ESize)";
1494  case ELimit: return "No more socket descriptors available (ELimit)";
1495  case ELength: return "Host or address string too long (ELength)";
1496  case EFail: return "Connection refused or reset (EFail)";
1497  case ENotFound: return "Address not found (ENotFound)";
1498  default: break;
1499  }
1500  return evo::errormsg(error);
1501  }
1502 };
1503 
1505 
1506 }
1507 #endif
Error convert(const char *host)
Convert host address to one or more socket addresses.
Definition: sysio_sock.h:258
TOut & errormsg_out(TOut &out, Error err)
Write error message with errno to output stream/string.
Definition: sys.h:1203
ExceptionSocketIn ExceptionInT
Input exception type for socket stream.
Definition: sysio_sock.h:311
Base stream exception for all stream errors, see Exception.
Definition: sys.h:1389
Operation timed out.
Definition: sys.h:1131
T & max(T &a, T &b)
Returns highest of given values.
Definition: alg.h:47
Shutdown
Used with shutdown().
Definition: sysio_sock.h:687
Seek
Seek starting position.
Definition: sysio.h:203
System call interrupted by signal (Linux/Unix), auto-resume disabled.
Definition: sys.h:1132
General stream or resource read error.
Definition: sys.h:1143
Error convert(const char *host, ushort port)
Convert host address to one or more socket addresses.
Definition: sysio_sock.h:268
ulongl pos(Error &err)
Not supported with sockets.
Definition: sysio_sock.h:1369
Socket config exception for getopt() or setopt() errors, see Exception.
Definition: sysio_sock.h:73
Operation would block (non-blocking I/O)
Definition: sys.h:1118
Invalid argument or data.
Definition: sys.h:1123
bool autoresume
Whether to auto-resume I/O operation after signal received [Linux/Unix].
Definition: sysio_sock.h:1136
Permission denied.
Definition: sys.h:1135
ulong write(Error &err, const void *buf, ulong size)
Definition: sysio_sock.h:899
Invalid pointer used.
Definition: sys.h:1133
bool listen(Error &err, struct sockaddr *address, socklen_t address_len, int backlog=SOMAXCONN, int socktype=SOCK_STREAM, int protocol=0)
Create and bind socket to address and listen for connections.
Definition: sysio_sock.h:1200
socklen_t addrlen
Address length.
Definition: sysio_sock.h:96
Invalid or unsupported operation.
Definition: sys.h:1122
Socket open exception for socket connect/bind/listen errors, see Exception.
Definition: sysio_sock.h:77
Stream or resource is closed
Definition: sys.h:1130
void free()
Free results allocated from resolve() or resolve_address.
Definition: sysio_sock.h:284
bool accept_nonblock(Error &err, IoSocket &client_socket, SocketAddressBase *client_address=NULL)
Accept connection from listening socket and set the new connection as non-blocking.
Definition: sysio_sock.h:1011
Not enough space/memory available.
Definition: sys.h:1134
Output stream exception for stream write errors, see Exception.
Definition: sys.h:1401
String fixed-size buffer for formatting an integer.
Definition: string.h:54
ExceptionSocketOut ExceptionOutT
Output exception type for socket stream.
Definition: sysio_sock.h:312
ulong readfrom(Error &err, void *buf, ulong size, struct sockaddr *address=NULL, socklen_t *address_len=NULL, int flags=0)
Read message from socket device.
Definition: sysio_sock.h:850
Socket input stream exception for socket read errors, see Exception.
Definition: sysio_sock.h:81
Handle handle
Socket handle/descriptor.
Definition: sysio_sock.h:1353
bool listen(Error &err, struct addrinfo *address_info, int backlog=SOMAXCONN, bool all=true)
Create and bind socket using address info and listen for connections.
Definition: sysio_sock.h:1156
IoSocket(Handle socket)
Constructor attaching to existing socket.
Definition: sysio_sock.h:716
bool cast(Error &err, int family=AF_INET, int socktype=SOCK_DGRAM, int protocol=0)
Create unbound datagram socket for casting.
Definition: sysio_sock.h:1253
Resource not found.
Definition: sys.h:1137
int Handle
System socket handle.
Definition: sysio_sock.h:697
Size size() const
Get size.
System resource limit reached.
Definition: sys.h:1140
struct addrinfo * ptr
Pointer to first address in resolve results.
Definition: sysio_sock.h:127
Size limit exceeded.
Definition: sys.h:1139
Handle detach()
Detach and return socket handle.
Definition: sysio_sock.h:1347
No error.
Definition: sys.h:1115
bool connect(Error &err, struct addrinfo *address_info, bool all=true)
Create and connect socket using address info.
Definition: sysio_sock.h:1277
static const Init & init()
Initialize socket library.
Definition: sysio_sock.h:1360
int OptNum
General number type for socket options.
Definition: sysio_sock.h:698
Error
General Evo error code stored in exceptions, or used directly when exceptions are disabled...
Definition: sys.h:1113
Socket output stream exception for socket write errors, see Exception.
Definition: sysio_sock.h:85
static TOut & errormsg_out(TOut &out, Error err)
Write detailed error message with errno to output stream/string.
Definition: sysio_sock.h:1118
const char * errormsg_socket(Error error)
Get socket error message for error code.
Definition: sysio_sock.h:57
bool accept(Error &err, IoSocket &client_socket, SocketAddressBase *client_address=NULL)
Accept connection from listening socket.
Definition: sysio_sock.h:972
Error getopt(int level, int optname, void *buf, uint &size)
Get socket option value.
Definition: sysio_sock.h:1057
StrSizeT Size
List size integer type.
Definition: sublist.h:150
bool write_wait(Error &err, ulong timeout_ms)
Wait until socket is ready to write.
Definition: sysio_sock.h:895
Socket I/O device (used internally).
Definition: sysio_sock.h:307
static ulong read(Error &err, int handle, void *buf, ulong size, ulong timeout_ms, bool autoresume)
Definition: sysio.h:73
~IoSocket()
Destructor.
Definition: sysio_sock.h:1140
SocketAddressInfo(int family=AF_INET)
Constructor.
Definition: sysio_sock.h:135
IoSocket()
Constructor.
Definition: sysio_sock.h:704
Evo system I/O implementation.
SocketAddressInfo & reset(int family=AF_INET)
Reset data.
Definition: sysio_sock.h:151
SocketAddressInfo & tcp()
Setup for resolving to TCP address.
Definition: sysio_sock.h:162
String length limit exceeded
Definition: sys.h:1141
Used internally to initialize system socket API.
Definition: sysio_sock.h:694
int code
Internal return code from resolve()
Definition: sysio_sock.h:128
Temporary failure occurred, try again.
Definition: sys.h:1126
ulong timeout_ms
Current timeout in milliseconds, 0 for indefinite.
Definition: sysio_sock.h:314
bool read_wait(Error &err, ulong timeout_ms)
Wait until socket is ready to read.
Definition: sysio_sock.h:831
bool isopen() const
Get whether socket is open.
Definition: sysio_sock.h:1146
ulong writeto(Error &err, const void *buf, ulong size, const struct sockaddr *address, socklen_t address_len, int flags=0)
Write message to device and socket address.
Definition: sysio_sock.h:914
Error setopt(int level, int optname, const void *buf, uint size)
Set socket option with new value.
Definition: sysio_sock.h:1087
Unknown or unspecified error.
Definition: sys.h:1120
virtual void set_maxsize()
Set addrlen to max size for socket address.
Definition: sysio_sock.h:102
Evo C++ Library namespace.
Definition: alg.h:11
Input stream exception for stream read errors, see Exception.
Definition: sys.h:1397
static ulong write(Error &err, int handle, const void *buf, ulong size, ulong timeout_ms, bool autoresume)
Definition: sysio.h:143
static bool write_wait(Error &err, int handle, ulong timeout_ms, bool autoresume)
Definition: sysio.h:110
Resource already exists.
Definition: sys.h:1136
Error resolve(const char *host, const char *port=NULL, int flags=AI_NUMERICSERV)
Resolve or convert host name/address and port to one or more socket addresses.
Definition: sysio_sock.h:185
bool nonblock
Whether non-blocking I/O is enabled.
Definition: sysio_sock.h:1354
I/O device base class for streams.
Definition: sysio.h:230
bool connect_wait(Error &err, ulong timeout_ms)
Wait until socket connection is established and ready to write.
Definition: sysio_sock.h:799
Resolves socket name/address to socket address info.
Definition: sysio_sock.h:125
Error resolve(const SubString &host, ushort port=0, int flags=0)
Resolve or convert host name/address and port to one or more socket addresses.
Definition: sysio_sock.h:232
ulongl seek(Error &err, ulongl, Seek)
Not supported with sockets.
Definition: sysio_sock.h:1379
Error set_nonblock(bool enable=true)
Enable/Disable non-blocking I/O.
Definition: sysio_sock.h:756
char * data_
Data pointer, NULL if null.
Definition: sys.h:979
const char * errormsg(Error error)
Get general error message for error code.
Definition: sys.h:1155
Operation failed.
Definition: sys.h:1124
#define EVO_CREATE_EXCEPTION_IMPL_2(NAME, BASE, ERRMSG_FUNC)
Create an Evo exception implementation with custom errormsg() function.
Definition: sys.h:1338
void close()
Close connection and socket.
Definition: sysio_sock.h:741
Error convert(const SubString &host, ushort port=0)
Convert host address to one or more socket addresses.
Definition: sysio_sock.h:278
bool shutdown(Shutdown how=sINOUT)
Shutdown socket communication.
Definition: sysio_sock.h:730
static bool read_wait(Error &err, int handle, ulong timeout_ms, bool autoresume)
Definition: sysio.h:37
SocketAddressInfo & udp()
Setup for resolving to UDP address.
Definition: sysio_sock.h:171
Stream open exception for errors opening a stream, see Exception.
Definition: sys.h:1393
Reference and access existing string data.
Definition: substring.h:229
void attach(Handle socket)
Attach new socket handle.
Definition: sysio_sock.h:1339
#define EVO_CNULL
Shortcut for NULL as const-char pointer.
Definition: sys.h:611
Base for all Evo list types (used internally).
Definition: sys.h:976
bool bind(Error &err, struct sockaddr *address, socklen_t address_len, int socktype=SOCK_DGRAM, int protocol=0)
Create and bind datagram socket to address.
Definition: sysio_sock.h:1228
Base socket address.
Definition: sysio_sock.h:95
bool connect(Error &err, struct sockaddr *address, socklen_t address_len, int socktype=SOCK_STREAM, int protocol=0)
Create and connect socket using address.
Definition: sysio_sock.h:1316
Error resolve(const char *host, ushort port, int flags=0)
Resolve host name/address and port to one or more socket addresses.
Definition: sysio_sock.h:219
General stream or resource write error.
Definition: sys.h:1144
ulong read(Error &err, void *buf, ulong size)
Definition: sysio_sock.h:835
const char * data() const
Get data pointer.
Generic socket address (used internally).
Definition: sysio_sock.h:113
~SocketAddressInfo()
Destructor.
Definition: sysio_sock.h:144