32 typedef int socklen_t;
33 int pipe(
int *phandles) {
return _pipe(phandles, 10,
O_BINARY); }
37 #include <sys/ioctl.h>
38 #include <netinet/in.h>
39 #include <netinet/tcp.h>
40 #include <arpa/inet.h>
45 #define ioctlsocket ioctl
46 #define closesocket close
47 #define SOCKET_ERROR (-1)
52 #pragma warning (disable : 4355)
56 #if !defined(IPV6_ADD_MEMBERSHIP) && defined(IPV6_JOIN_GROUP)
57 #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
58 #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
62 #include <linux/in6.h>
63 #include <linux/if_addr.h>
66 #define IPV6_ADDR_LOOPBACK 0x0010U
67 #define IPV6_ADDR_LINKLOCAL 0x0020U
68 #define IPV6_ADDR_SITELOCAL 0x0040U
85 case WSAEACCES:
return "Permission denied.";
86 case WSAEADDRINUSE:
return "Address already in use.";
87 case WSAEADDRNOTAVAIL:
return "Cannot assign requested address.";
88 case WSAEAFNOSUPPORT:
return "Address family not supported by protocol family.";
89 case WSAEALREADY:
return "Operation already in progress.";
90 case WSAECONNABORTED:
return "Software caused connection abort.";
91 case WSAECONNREFUSED:
return "Connection refused.";
92 case WSAECONNRESET:
return "Connection reset by peer.";
93 case WSAEDESTADDRREQ:
return "Destination address required.";
94 case WSAEFAULT:
return "Bad address.";
95 case WSAEHOSTDOWN:
return "Host is down.";
96 case WSAEHOSTUNREACH:
return "No route to host.";
97 case WSAEINPROGRESS:
return "Operation now in progress.";
98 case WSAEINTR:
return "Interrupted function call.";
99 case WSAEINVAL:
return "Invalid argument.";
100 case WSAEISCONN:
return "Socket is already connected.";
101 case WSAEMFILE:
return "Too many open files.";
102 case WSAEMSGSIZE:
return "Message too long.";
103 case WSAENETDOWN:
return "Network is down.";
104 case WSAENETRESET:
return "Network dropped connection on reset.";
105 case WSAENETUNREACH:
return "Network is unreachable.";
106 case WSAENOBUFS:
return "No buffer space available.";
107 case WSAENOPROTOOPT:
return "Bad protocol option.";
108 case WSAENOTCONN:
return "Socket is not connected.";
109 case WSAENOTSOCK:
return "Socket operation on non-socket.";
110 case WSAEOPNOTSUPP:
return "Operation not supported.";
111 case WSAEPFNOSUPPORT:
return "Protocol family not supported.";
112 case WSAEPROCLIM:
return "Too many processes.";
113 case WSAEPROTONOSUPPORT:
return "Protocol not supported.";
114 case WSAEPROTOTYPE:
return "Protocol wrong type for socket.";
115 case WSAESHUTDOWN:
return "Cannot send after socket shutdown.";
116 case WSAESOCKTNOSUPPORT:
return "Socket type not supported.";
117 case WSAETIMEDOUT:
return "Connection timed out.";
118 case WSATYPE_NOT_FOUND:
return "Class type not found.";
119 case WSAEWOULDBLOCK:
return "Resource temporarily unavailable.";
120 case WSAHOST_NOT_FOUND:
return "Host not found.";
121 case WSA_INVALID_HANDLE:
return "Specified event object handle is invalid.";
122 case WSA_INVALID_PARAMETER:
return "One or more parameters are invalid.";
123 case WSA_IO_INCOMPLETE:
return "Overlapped I/O event object not in signaled state.";
124 case WSA_IO_PENDING:
return "Overlapped operations will complete later.";
125 case WSA_NOT_ENOUGH_MEMORY:
return "Insufficient memory available.";
126 case WSANOTINITIALISED:
return "Successful WSAStartup not yet performed.";
127 case WSANO_DATA:
return "Valid name, no data record of requested type.";
128 case WSANO_RECOVERY:
return "This is a non-recoverable error.";
129 case WSASYSCALLFAILURE:
return "System call failure.";
130 case WSASYSNOTREADY:
return "Network subsystem is unavailable.";
131 case WSATRY_AGAIN:
return "Non-authoritative host not found.";
132 case WSAVERNOTSUPPORTED:
return "WINSOCK.DLL version out of range.";
133 case WSAEDISCON:
return "Graceful shutdown in progress.";
134 case WSA_OPERATION_ABORTED:
return "Overlapped operation aborted.";
135 case 0:
return "no error";
136 default:
return "Stupid Error.";
145 return !! WSAGetLastError();
149 return WSAGetLastError() == WSAEWOULDBLOCK;
153 return WSAGetLastError() == WSAECONNRESET;
160 static int iWSockUseCounter = 0;
162 bool AcquireWinSock()
164 if (!iWSockUseCounter)
168 int res = WSAStartup(WINSOCK_VERSION, &data);
180 void ReleaseWinSock()
184 if (!iWSockUseCounter)
192 return strerror(iError);
205 return errno == EINPROGRESS || errno == EWOULDBLOCK;
209 return errno == ECONNRESET;
221 v6.sin6_family = AF_INET6;
222 v6.sin6_flowinfo = 0;
223 v6.sin6_scope_id = 0;
224 memset(&v6.sin6_addr, 0,
sizeof(v6.sin6_addr));
234 SetPort(IPPORT_NONE);
244 if (gen.sa_family == AF_INET6)
245 return IN6_IS_ADDR_MULTICAST(&v6.sin6_addr) != 0;
246 if (gen.sa_family == AF_INET)
247 return (ntohl(v4.sin_addr.s_addr) >> 24) == 239;
253 if (gen.sa_family == AF_INET6)
254 return IN6_IS_ADDR_LOOPBACK(&v6.sin6_addr) != 0;
255 if (gen.sa_family == AF_INET)
256 return (ntohl(v4.sin_addr.s_addr) >> 24) == 127;
262 if (gen.sa_family == AF_INET6)
263 return IN6_IS_ADDR_LINKLOCAL(&v6.sin6_addr) != 0;
273 if (gen.sa_family == AF_INET6)
274 return (v6.sin6_addr.s6_addr[0] & 0xfe) == 0xfc;
275 if (gen.sa_family == AF_INET)
277 uint32_t addr = ntohl(v4.sin_addr.s_addr);
278 uint32_t
s = (addr >> 16) & 0xff;
281 case 10:
return true;
282 case 172:
return s >= 16 &&
s <= 31;
283 case 192:
return s == 168;
291 if (gen.sa_family != AF_INET6)
return;
292 if (IN6_IS_ADDR_LINKLOCAL(&v6.sin6_addr) != 0)
293 v6.sin6_scope_id = scopeId;
298 if (gen.sa_family == AF_INET6)
299 return v6.sin6_scope_id;
305 static const uint8_t v6_mapped_v4_prefix[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
308 switch (gen.sa_family)
314 memmove(((
char*)&nrv.v6.sin6_addr) +
sizeof(v6_mapped_v4_prefix), &v4.sin_addr,
sizeof(v4.sin_addr));
315 nrv.v6.sin6_family = AF_INET6;
316 memcpy(&nrv.v6.sin6_addr, v6_mapped_v4_prefix,
sizeof(v6_mapped_v4_prefix));
317 nrv.v6.sin6_flowinfo = 0;
318 nrv.v6.sin6_scope_id = 0;
320 default: assert(!
"Shouldn't reach this");
break;
328 if (gen.sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&v6.sin6_addr))
330 nrv.v4.sin_family = AF_INET;
331 memcpy((
char*) &nrv.v4.sin_addr, (
char*) &v6.sin6_addr.s6_addr[12],
sizeof(v4.sin_addr));
349 if (addr->sa_family == AF_INET6)
351 v6.sin6_family = ((
const sockaddr_in6*)addr)->sin6_family;
352 v6.sin6_flowinfo = ((
const sockaddr_in6*)addr)->sin6_flowinfo;
353 memcpy(&v6.sin6_addr, &((
const sockaddr_in6*)addr)->sin6_addr,
sizeof(v6.sin6_addr));
354 v6.sin6_scope_id = ((
const sockaddr_in6*)addr)->sin6_scope_id;
356 else if (addr->sa_family == AF_INET)
358 v4.sin_family = ((
const sockaddr_in*)addr)->sin_family;
359 v4.sin_addr.s_addr = ((
const sockaddr_in*)addr)->sin_addr.s_addr;
360 memset(&v4.sin_zero, 0,
sizeof(v4.sin_zero));
366 switch (addr->sa_family)
368 case AF_INET: memcpy(&v4, addr,
sizeof(v4));
break;
369 case AF_INET6: memcpy(&v6, addr,
sizeof(v6));
break;
371 assert(!
"Unexpected address family");
372 memcpy(&gen, addr,
sizeof(gen));
break;
381 v6.sin6_family = AF_INET6;
382 memset(&v6.sin6_addr, 0,
sizeof(v6.sin6_addr));
383 v6.sin6_flowinfo = 0;
384 v6.sin6_scope_id = 0;
387 v4.sin_family = AF_INET;
388 v4.sin_addr.s_addr = 0;
389 memset(&v4.sin_zero, 0,
sizeof(v4.sin_zero));
392 v6.sin6_family = AF_INET6;
393 memset(&v6.sin6_addr, 0,
sizeof(v6.sin6_addr)); v6.sin6_addr.s6_addr[15] = 1;
394 v6.sin6_flowinfo = 0;
395 v6.sin6_scope_id = 0;
402 v4.sin_family = AF_INET;
403 v4.sin_addr.s_addr = v4addr;
404 memset(&v4.sin_zero, 0,
sizeof(v4.sin_zero));
409 addrinfo hints = addrinfo();
410 hints.ai_family = family;
411 addrinfo *addresses =
nullptr;
412 if (getaddrinfo(addr.
getData(),
nullptr, &hints, &addresses) != 0)
415 SetHost(addresses->ai_addr);
416 freeaddrinfo(addresses);
423 if (addr.
isNull())
return;
425 const char *begin = addr.
getData();
426 const char *end = begin + addr.
getLength();
428 const char *ab = begin;
429 const char *ae = end;
431 const char *pb = end;
432 const char *pe = end;
440 const char *cbracket = std::find(ab, ae,
']');
445 if (cbracket != end && cbracket[0] ==
':')
456 else if (std::count(ab, ae,
':') > 1)
463 const char *colon = std::find(ab, ae,
':');
474 addrinfo hints = addrinfo();
475 hints.ai_family = family;
477 addrinfo *addresses =
nullptr;
478 if (getaddrinfo(std::string(ab, ae).c_str(), pb != end ? std::string(pb, pe).c_str() :
nullptr, &hints, &addresses) != 0)
481 SetAddress(addresses->ai_addr);
482 freeaddrinfo(addresses);
505 return IsNullHost() && GetPort() == IPPORT_NONE;
510 switch (gen.sa_family)
512 case AF_INET:
return v4.sin_addr.s_addr == 0;
514 return !!IN6_IS_ADDR_UNSPECIFIED(&v6.sin6_addr);
516 assert(!
"Shouldn't reach this");
522 return gen.sa_family == AF_INET ? IPv4 :
523 gen.sa_family == AF_INET6 ? IPv6 : UnknownFamily;
528 return GetFamily() == IPv4 ?
sizeof(sockaddr_in) :
sizeof(sockaddr_in6);
533 switch (gen.sa_family)
535 case AF_INET: v4.sin_port = htons(port);
break;
536 case AF_INET6: v6.sin6_port = htons(port);
break;
537 default: assert(!
"Shouldn't reach this");
break;
543 if (GetPort() == IPPORT_NONE)
549 switch (gen.sa_family)
551 case AF_INET:
return ntohs(v4.sin_port);
552 case AF_INET6:
return ntohs(v6.sin6_port);
554 assert(!
"Shouldn't reach this");
561 if (gen.sa_family != rhs.gen.sa_family)
562 return AsIPv6() == rhs.
AsIPv6();
563 if (gen.sa_family == AF_INET)
564 return v4.sin_addr.s_addr == rhs.v4.sin_addr.s_addr;
565 if (gen.sa_family == AF_INET6)
566 return memcmp(&v6.sin6_addr, &rhs.v6.sin6_addr,
sizeof(v6.sin6_addr)) == 0 &&
567 v6.sin6_scope_id == rhs.v6.sin6_scope_id;
568 assert(!
"Shouldn't reach this");
574 if (!HostAddress::operator==(rhs))
return false;
575 if (gen.sa_family == AF_INET)
577 return v4.sin_port == rhs.v4.sin_port;
579 else if (gen.sa_family == AF_INET6)
581 return v6.sin6_port == rhs.v6.sin6_port &&
582 v6.sin6_scope_id == rhs.v6.sin6_scope_id;
584 assert(!
"Shouldn't reach this");
590 if (gen.sa_family == AF_INET6 && v6.sin6_scope_id != 0 && (flags & TSF_SkipZoneId))
593 addr.v6.sin6_scope_id = 0;
597 char buf[INET6_ADDRSTRLEN];
598 if (getnameinfo(&gen, GetAddrLen(), buf,
sizeof(buf),
nullptr, 0, NI_NUMERICHOST) != 0)
606 if (flags & TSF_SkipPort)
613 default: assert(!
"Shouldn't reach this");
633 std::vector<HostAddress> result;
637 const size_t BUFFER_SIZE = 16000;
638 PIP_ADAPTER_ADDRESSES addresses =
nullptr;
639 for (
int i = 0; i < 3; ++i)
641 addresses = (PIP_ADAPTER_ADDRESSES) realloc(addresses, BUFFER_SIZE * (i+1));
645 ULONG bufsz = BUFFER_SIZE * (i+1);
646 DWORD rv = GetAdaptersAddresses(AF_UNSPEC,
647 GAA_FLAG_SKIP_ANYCAST|GAA_FLAG_SKIP_MULTICAST|GAA_FLAG_SKIP_DNS_SERVER|GAA_FLAG_SKIP_FRIENDLY_NAME,
648 nullptr, addresses, &bufsz);
649 if (rv == ERROR_BUFFER_OVERFLOW)
659 for (PIP_ADAPTER_ADDRESSES address = addresses; address; address = address->Next)
661 for (PIP_ADAPTER_UNICAST_ADDRESS unicast = address->FirstUnicastAddress; unicast; unicast = unicast->Next)
663 addr.
SetHost(unicast->Address.lpSockaddr);
666 result.push_back(addr);
672 bool have_ipv6 =
false;
676 FILE *f = fopen(
"/proc/net/if_inet6",
"r");
679 sockaddr_in6 sa6 = sockaddr_in6();
680 sa6.sin6_family = AF_INET6;
681 auto a6 = sa6.sin6_addr.s6_addr;
682 uint8_t if_idx, plen, scope, flags;
684 while (fscanf(f,
"%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx %02hhx %02hhx %02hhx %02hhx %20s\n",
685 &a6[0], &a6[1], &a6[2], &a6[3], &a6[4], &a6[5], &a6[6], &a6[7],
686 &a6[8], &a6[9], &a6[10], &a6[11], &a6[12], &a6[13], &a6[14], &a6[15],
687 &if_idx, &plen, &scope, &flags, devname) != EOF)
690 if (scope == IPV6_ADDR_LOOPBACK || flags & IFA_F_DEPRECATED)
692 sa6.sin6_scope_id = scope == IPV6_ADDR_LINKLOCAL ? if_idx : 0;
693 result.emplace_back((sockaddr*) &sa6);
695 have_ipv6 = result.size() > 0;
700 struct ifaddrs* addrs;
701 if (getifaddrs(&addrs) < 0)
703 for (
struct ifaddrs* ifaddr = addrs; ifaddr !=
nullptr; ifaddr = ifaddr->ifa_next)
705 struct sockaddr* ad = ifaddr->ifa_addr;
706 if (ad ==
nullptr)
continue;
708 if ((ad->sa_family == AF_INET || (!have_ipv6 && ad->sa_family == AF_INET6)) && (~ifaddr->ifa_flags & IFF_LOOPBACK))
710 result.emplace_back(ad);
733 if (setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY,
reinterpret_cast<char*
>(&opt),
sizeof(opt)) ==
SOCKET_ERROR)
735 SetError(
"could not enable dual-stack socket",
true);
739 #ifdef IPV6_ADDR_PREFERENCES
743 opt = IPV6_PREFER_SRC_PUBLIC;
744 setsockopt(socket, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES,
reinterpret_cast<char*
>(&opt),
sizeof(opt));
766 :
StdCopyBuf(pnData, inSize, fCopy), addr(naddr)
778 New(
sizeof(cStatusByte) + inSize);
780 *getMBufPtr<uint8_t>(*
this) = cStatusByte;
781 Write(pnData, inSize,
sizeof(cStatusByte));
818 if (!AcquireWinSock())
820 SetError(
"could not start winsock");
825 #ifdef STDSCHEDULER_USE_EVENTS
827 if ((Event = WSACreateEvent()) == WSA_INVALID_EVENT)
829 SetError(
"could not create socket event",
true);
836 SetError(
"could not create pipe",
true);
862 if (!
fInit)
return false;
870 if (pCB) pCB->
OnDisconn(pPeer->GetAddr(),
this,
"owner class closed");
882 #ifdef STDSCHEDULER_USE_EVENTS
884 if (Event !=
nullptr)
886 WSACloseEvent(Event);
911 static int fix_poll_timeout(
int timeout) {
912 if (timeout < 0 || timeout > 1000)
922 if (!
fInit)
return false;
924 #ifdef STDSCHEDULER_USE_EVENTS
929 WSAResetEvent(Event);
931 WSANETWORKEVENTS wsaEvents;
935 iMaxTime = fix_poll_timeout(iMaxTime);
938 std::vector<pollfd> fdvec;
939 std::map<SOCKET, const pollfd*> fdmap;
946 int ret = poll(fds, fdvec.size(), iMaxTime);
962 std::copy(fds, fds + fdvec.size(), fdvec.begin());
966 assert(fdvec[0].fd ==
Pipe[0]);
967 if (fdvec[0].events & fdvec[0].revents)
970 if (::read(
Pipe[0], &c, 1) == -1)
974 for (std::vector<pollfd>::const_iterator i = fdvec.begin(); i != fdvec.end(); ++i)
976 std::map<SOCKET, const pollfd*>::const_iterator cur_fd;
985 #ifdef STDSCHEDULER_USE_EVENTS
991 if (wsaEvents.lNetworkEvents & FD_ACCEPT)
993 cur_fd = fdmap.find(
lsock);
995 if (cur_fd != fdmap.end() && (cur_fd->second->events & cur_fd->second->revents))
1001 #ifdef STDSCHEDULER_USE_EVENTS
1003 if (wsaEvents.lNetworkEvents & FD_CLOSE)
1011 for (
ConnectWait *pWait = pConnectWaits, *pNext; pWait; pWait = pNext)
1013 pNext = pWait->Next;
1018 #ifdef STDSCHEDULER_USE_EVENTS
1020 if (::WSAEnumNetworkEvents(pWait->sock,
nullptr, &wsaEvents) ==
SOCKET_ERROR)
1023 if (wsaEvents.lNetworkEvents & FD_CONNECT)
1026 cur_fd = fdmap.find(pWait->sock);
1027 if (cur_fd != fdmap.end() && (cur_fd->second->events & cur_fd->second->revents))
1031 SOCKET sock = pWait->sock; pWait->sock = 0;
1033 #ifdef STDSCHEDULER_USE_EVENTS
1035 if (wsaEvents.iErrorCode[FD_CONNECT_BIT])
1043 int iErrCode; socklen_t iErrCodeLen =
sizeof(iErrCode);
1044 if (getsockopt(sock, SOL_SOCKET, SO_ERROR,
reinterpret_cast<char *
>(&iErrCode), &iErrCodeLen) != 0)
1058 if (!
Accept(sock, pWait->addr))
1069 SOCKET sock = pPeer->GetSocket();
1071 #ifdef STDSCHEDULER_USE_EVENTS
1073 if (::WSAEnumNetworkEvents(sock,
nullptr, &wsaEvents) ==
SOCKET_ERROR)
1077 if (wsaEvents.lNetworkEvents & FD_READ)
1080 cur_fd = fdmap.find(sock);
1081 if (cur_fd != fdmap.end() && (POLLIN & cur_fd->second->revents))
1105 void *pBuf = pPeer->GetRecvBuf(iBytesToRead);
1108 if ((iBytesRead = ::recv(sock,
reinterpret_cast<char *
>(pBuf), iBytesToRead, 0)) ==
SOCKET_ERROR)
1121 if (pCB) pCB->
OnDisconn(pPeer->GetAddr(),
this,
"connection closed");
1125 pPeer->OnRecv(iBytesRead);
1129 #ifdef STDSCHEDULER_USE_EVENTS
1130 if (wsaEvents.lNetworkEvents & FD_WRITE)
1132 if (cur_fd != fdmap.end() && (POLLOUT & cur_fd->second->revents))
1137 #ifdef STDSCHEDULER_USE_EVENTS
1139 if (wsaEvents.lNetworkEvents & FD_CLOSE)
1141 const char *szReason = wsaEvents.iErrorCode[FD_CLOSE_BIT] ?
GetSocketErrorMsg(wsaEvents.iErrorCode[FD_CLOSE_BIT]) :
"closed by peer";
1145 if (pCB) pCB->
OnDisconn(pPeer->GetAddr(),
this, szReason);
1163 socklen_t address_len =
sizeof addr;
1165 if (::getsockname(sock, (sockaddr*) &addr, &address_len) !=
SOCKET_ERROR)
1178 SetError(
"socket creation failed",
true);
1200 SetError(
"binding the socket failed",
true);
1204 return std::unique_ptr<Socket>(
new Socket(nsock));
1209 SOCKET nsock = socket->sock;
1225 #ifdef STDSCHEDULER_USE_EVENTS
1227 if (::WSAEventSelect(nsock, Event, FD_CONNECT) ==
SOCKET_ERROR)
1230 SetError(
"connect failed: could not set event",
true);
1238 #elif defined(HAVE_WINSOCK)
1240 unsigned long iBlock = 1;
1244 SetError(
"connect failed: could not disable blocking",
true);
1250 if (::fcntl(nsock, F_SETFL, fcntl(nsock, F_GETFL) | O_NONBLOCK) ==
SOCKET_ERROR)
1253 SetError(
"connect failed: could not disable blocking",
true);
1264 SetError(
"socket connection failed",
true);
1270 #ifndef STDSCHEDULER_USE_EVENTS
1300 if (pCB) pCB->
OnDisconn(addr,
this,
"closed");
1316 if (!pPeer)
return false;
1318 return pPeer->
Send(rPacket);
1326 if (!pPeer)
return false;
1336 bool fSuccess =
true;
1338 if (pPeer->Open() && pPeer->doBroadcast())
1345 #ifdef STDSCHEDULER_USE_EVENTS
1353 if (write(
Pipe[1], &c, 1) == -1)
1358 #ifdef STDSCHEDULER_USE_EVENTS
1359 HANDLE C4NetIOTCP::GetEvent()
1366 pollfd pfd; pfd.revents = 0;
1368 pfd.fd =
Pipe[0]; pfd.events = POLLIN;
1373 pfd.fd =
lsock; pfd.events = POLLIN;
1380 pfd.fd = pWait->sock; pfd.events = POLLOUT;
1385 if (pPeer->GetSocket())
1388 pfd.fd = pPeer->GetSocket(); pfd.events = POLLIN;
1390 if (pPeer->hasWaitingData())
1392 pfd.events |= POLLOUT;
1402 if (pBroadcastRate) *pBroadcastRate = 0;
1411 if (!pPeer || !pPeer->
Open())
return false;
1413 if (pIRate) *pIRate = pPeer->
GetIRate();
1414 if (pORate) *pORate = pPeer->
GetORate();
1415 if (pLoss) *pLoss = 0;
1424 pPeer->ClearStatistics();
1430 addr_t caddr = ConnectAddr;
1444 SetError(
"socket accept failed",
true);
1453 if (::getpeername(nsock, &addr, &iAddrSize) ==
SOCKET_ERROR)
1455 #ifndef HAVE_WINSOCK
1457 if (errno != ENOTCONN)
1461 SetError(
"could not get peer address for connected socket",
true);
1463 #ifndef HAVE_WINSOCK
1473 SetError(
"socket accept failed: invalid address returned");
1480 ::setsockopt(nsock, IPPROTO_TCP, TCP_NODELAY,
reinterpret_cast<const char *
>(&iNoDelay),
sizeof(iNoDelay));
1482 #ifdef STDSCHEDULER_USE_EVENTS
1484 if (::WSAEventSelect(nsock, Event, FD_READ | FD_WRITE | FD_CLOSE) ==
SOCKET_ERROR)
1487 SetError(
"connection accept failed: could not set event",
true);
1491 #elif defined(HAVE_WINSOCK)
1493 unsigned long iBlock = 1;
1497 SetError(
"connect failed: could not disable blocking",
true);
1503 if (::fcntl(nsock, F_SETFL, fcntl(nsock, F_GETFL) | O_NONBLOCK) ==
SOCKET_ERROR)
1506 SetError(
"connection accept failed: could not disable blocking",
true);
1514 Peer *pnPeer =
new Peer(addr, nsock,
this);
1525 PeerListAddLock.
Clear();
1530 if (pCB && !pCB->
OnConn(addr, caddr,
nullptr,
this))
1549 SetError(
"socket creation failed",
true);
1555 #if !defined(_DEBUG) && !defined(_WIN32)
1557 setsockopt(
lsock, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<const char *
>(&reuseaddr),
sizeof(reuseaddr));
1564 SetError(
"socket bind failed",
true);
1569 #ifdef STDSCHEDULER_USE_EVENTS
1573 SetError(
"could not set event for listen socket",
true);
1582 SetError(
"socket listen failed",
true);
1598 if (pPeer->GetAddr() == addr)
1615 Peer *pDelete = pPeer;
1616 pPeer = pPeer->
Next;
1617 (pLast ? pLast->Next :
pPeerList) = pPeer;
1625 pPeer = pPeer->
Next;
1628 ConnectWait *pWait = pConnectWaits, *pWLast =
nullptr;
1636 pWait = pWait->
Next;
1637 (pWLast ? pWLast->Next : pConnectWaits) = pWait;
1645 pWait = pWait->
Next;
1657 pnWait->
sock = sock; pnWait->
addr = addr;
1658 pnWait->
Next = pConnectWaits;
1659 pConnectWaits = pnWait;
1660 #ifndef STDSCHEDULER_USE_EVENTS
1672 if (pWait->addr == addr)
1691 uint8_t cFirstByte = 0xff;
1693 uint32_t iOASize =
sizeof(cFirstByte) +
sizeof(
iSize) +
iSize;
1697 rOutBuf.
Grow(iOASize);
1700 *getMBufPtr<uint8_t>(rOutBuf, iPos) = cFirstByte; iPos +=
sizeof(uint8_t);
1701 *getMBufPtr<uint32_t>(rOutBuf, iPos) =
iSize; iPos +=
sizeof(uint32_t);
1702 rOutBuf.
Write(rPacket, iPos);
1709 if (*getBufPtr<uint8_t>(IBuf, iPos) != (uint8_t) 0xff)
1712 iPos +=
sizeof(char);
1714 uint32_t iPacketSize;
1715 if (iPos +
sizeof(uint32_t) > IBuf.
getSize())
1717 iPacketSize = *getBufPtr<uint32_t>(IBuf, iPos);
1718 iPos +=
sizeof(uint32_t);
1720 if (iPos + iPacketSize > IBuf.
getSize())
1725 return iPos + iPacketSize;
1736 : pParent(pnParent),
1737 addr(naddr), sock(nsock),
1738 iIBufUsage(0), iIRate(0), iORate(0),
1739 fOpen(true), fDoBroadcast(false), Next(
nullptr)
1756 if (!OBuf.isNull())
Send();
1757 bool fSend = OBuf.isNull();
1760 pParent->PackPacket(rPacket, OBuf);
1763 return fSend ?
Send() :
true;
1769 if (OBuf.isNull())
return true;
1773 if ((iBytesSent = ::send(sock, getBufPtr<char>(OBuf), OBuf.getSize(), 0)) ==
SOCKET_ERROR)
1776 pParent->SetError(
"send failed",
true);
1781 if (iBytesSent ==
SOCKET_ERROR || !iBytesSent)
return true;
1784 iORate += iBytesSent + iTCPHeaderSize;
1787 if (
unsigned(iBytesSent) < OBuf.getSize())
1790 OBuf.Move(iBytesSent, OBuf.getSize() - iBytesSent);
1791 OBuf.Shrink(iBytesSent);
1792 #ifndef STDSCHEDULER_USE_EVENTS
1809 size_t iIBufSize = std::max<size_t>(iMinIBufSize, IBuf.getSize());
1810 while ((
size_t)(iIBufUsage +
iSize) > iIBufSize)
1812 if (iIBufSize != IBuf.getSize())
1813 IBuf.SetSize(iIBufSize);
1815 return IBuf.getMPtr(iIBufUsage);
1822 iIRate += iTCPHeaderSize +
iSize;
1823 iIBufUsage +=
iSize;
1825 assert(
static_cast<size_t>(iIBufUsage) <= IBuf.getSize());
1827 size_t iPos = 0, iPacketPos;
1828 while ((iPacketPos = iPos) < (
size_t)iIBufUsage)
1832 int32_t iBytes = pParent->UnpackPacket(IBufPart, addr);
1840 if (iPacketPos < (
size_t) iIBufUsage)
1843 if (!iPacketPos)
return;
1845 IBuf.
Move(iPacketPos, IBuf.getSize() - iPacketPos);
1846 iIBufUsage -= iPacketPos;
1848 size_t iIBufSize = IBuf.getSize();
1849 while ((
size_t) iIBufUsage <= iIBufSize / 2)
1851 if (iIBufSize != IBuf.getSize())
1852 IBuf.Shrink(iPacketPos);
1859 if (IBuf.getSize() > iMinIBufSize)
1860 IBuf.SetSize(iMinIBufSize);
1873 IBuf.Clear(); OBuf.Clear();
1876 iIRate = iORate = 0;
1882 iIRate = iORate = 0;
1908 if (!AcquireWinSock())
1910 SetError(
"could not start winsock");
1918 SetError(
"could not create socket",
true);
1926 if (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<char *
>(&fAllowReUse),
sizeof fAllowReUse) ==
SOCKET_ERROR)
1928 SetError(
"could not set reuse options",
true);
1936 if (::bind(sock, &naddr,
sizeof(naddr)) ==
SOCKET_ERROR)
1938 SetError(
"could not bind socket",
true);
1942 #ifdef STDSCHEDULER_USE_EVENTS
1945 if ((hEvent = WSACreateEvent()) == WSA_INVALID_EVENT)
1947 SetError(
"could not create event",
true);
1952 if (WSAEventSelect(sock, hEvent, FD_READ | FD_CLOSE) ==
SOCKET_ERROR)
1954 SetError(
"could not select event",
true);
1961 if (::fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK) ==
SOCKET_ERROR)
1964 SetError(
"could not disable blocking",
true);
1969 if (pipe(Pipe) != 0)
1971 SetError(
"could not create pipe",
true);
1992 if (!pBroadcastAddr)
return false;
1995 if (!fInit)
return false;
2002 SetError(
"invalid broadcast address (only IPv6 multicast addresses are supported)");
2005 if (pBroadcastAddr->
GetPort() != iPort)
2007 SetError(
"invalid broadcast address (different port)");
2013 if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
reinterpret_cast<char*
>(&TTL),
sizeof(TTL)) ==
SOCKET_ERROR)
2015 SetError(
"could not set mc ttl",
true);
2020 this->MCAddr = *pBroadcastAddr;
2021 MCGrpInfo.ipv6mr_multiaddr =
static_cast<sockaddr_in6
>(MCAddr).sin6_addr;
2023 MCGrpInfo.ipv6mr_interface = 0;
2026 if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
2027 reinterpret_cast<const char *
>(&MCGrpInfo),
sizeof(MCGrpInfo)) ==
SOCKET_ERROR)
2029 SetError(
"could not join multicast group");
2044 if (!fInit)
return true;
2059 #ifdef STDSCHEDULER_USE_EVENTS
2061 if (hEvent !=
nullptr)
2063 WSACloseEvent(hEvent);
2085 if (!fMultiCast)
return true;
2088 if (setsockopt(sock, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP,
2089 reinterpret_cast<const char *
>(&MCGrpInfo),
sizeof(MCGrpInfo)) ==
SOCKET_ERROR)
2091 SetError(
"could not leave multicast group");
2102 if (!fInit) {
SetError(
"not yet initialized");
return false; }
2106 iMaxTime = fix_poll_timeout(iMaxTime);
2110 WaitResult eWR = WaitForSocket(iMaxTime);
2111 if (eWR == WR_Error)
return false;
2114 if (eWR == WR_Cancelled || eWR == WR_Timeout)
return true;
2115 assert(eWR == WR_Readable);
2129 SetError(
"Could not determine the amount of data that can be read from socket",
true);
2139 addr_t SrcAddr; socklen_t iSrcAddrLen =
sizeof(sockaddr_in6);
2140 int iMsgSize = ::recvfrom(sock, getMBufPtr<char>(Pkt), iMaxMsgSize, 0, &SrcAddr, &iSrcAddrLen);
2154 SetError(
"could not receive data from socket",
true);
2161 SetError(
"recvfrom returned an invalid address");
2182 if (!fInit) {
SetError(
"not yet initialized");
return false; }
2186 if (::sendto(sock, getBufPtr<char>(rPacket), rPacket.
getSize(), 0,
2191 SetError(
"socket sendto failed",
true);
2206 #ifdef STDSCHEDULER_USE_EVENTS
2212 WSASetEvent(hEvent);
2215 HANDLE C4NetIOSimpleUDP::GetEvent()
2220 enum C4NetIOSimpleUDP::WaitResult C4NetIOSimpleUDP::WaitForSocket(
int iTimeout)
2224 if (ret == WAIT_TIMEOUT)
2226 if (ret == WAIT_FAILED)
2227 {
SetError(
"Wait for Event failed");
return WR_Error; }
2229 WSANETWORKEVENTS wsaEvents;
2230 if (WSAEnumNetworkEvents(sock, hEvent, &wsaEvents) ==
SOCKET_ERROR)
2231 {
SetError(
"could not enumerate network events!");
return WR_Error; }
2233 if (wsaEvents.lNetworkEvents | FD_READ)
2237 WSAResetEvent(hEvent);
2238 return WR_Cancelled;
2248 if (write(Pipe[1], &c, 1) == -1)
2255 pollfd pfd = { Pipe[0], POLLIN, 0 };
2260 pollfd pfd = { sock, POLLIN, 0 };
2265 enum C4NetIOSimpleUDP::WaitResult C4NetIOSimpleUDP::WaitForSocket(
int iTimeout)
2268 std::vector<pollfd> fds;
2271 int ret = poll(&fds[0], fds.size(), iTimeout);
2274 {
SetError(
"poll failed",
true);
return WR_Error; }
2278 if (fds[0].revents & POLLIN)
2281 if (::read(Pipe[0], &c, 1) == -1)
2285 return (sock !=
INVALID_SOCKET) && (fds[1].revents & POLLIN) ? WR_Readable : WR_Cancelled;
2293 setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
reinterpret_cast<char *
>(&fLoopback),
sizeof fLoopback);
2295 socklen_t
iSize =
sizeof(fLoopback);
2296 if (getsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
reinterpret_cast<char *
>(&fLoopback), &
iSize) ==
SOCKET_ERROR)
2298 fMCLoopback = !! fLoopback;
2304 fAllowReUse = fAllow;
2312 #define C4NETIOUDP_OPT_RECV_CHECK_IMMEDIATE
2328 #pragma pack (push, 1)
2344 auto addr4 =
static_cast<const sockaddr_in*
>(&addr);
2345 static_assert(
sizeof(v4) ==
sizeof(addr4->sin_addr),
"unexpected IPv4 address size");
2346 memcpy(&v4, &addr4->sin_addr,
sizeof(v4));
2352 auto addr6 =
static_cast<const sockaddr_in6*
>(&addr);
2353 static_assert(
sizeof(v6) ==
sizeof(addr6->sin6_addr),
"unexpected IPv6 address size");
2354 memcpy(&v6, &addr6->sin6_addr,
sizeof(v6));
2358 assert(!
"Unexpected address family");
2370 sockaddr_in addr4 = sockaddr_in();
2371 addr4.sin_family = AF_INET;
2372 memcpy(&addr4.sin_addr, &v4,
sizeof(v4));
2373 result.
SetAddress(
reinterpret_cast<sockaddr*
>(&addr4));
2378 sockaddr_in6 addr6 = sockaddr_in6();
2379 addr6.sin6_family = AF_INET6;
2380 memcpy(&addr6.sin6_addr, &v6,
sizeof(v6));
2381 result.
SetAddress(
reinterpret_cast<sockaddr*
>(&addr6));
2385 assert(!
"Invalid address type");
2459 : PeerListCSec(this),
2462 OPackets(iMaxOPacketBacklog)
2477 #ifdef C4NETIO_DEBUG
2507 if (!pBroadcastAddr)
return false;
2510 if (!
fInit)
return false;
2523 SetError(
"broadcast address is not valid");
2527 sockaddr_in6 saddrgen = sockaddr_in6();
2528 saddrgen.sin6_family = AF_INET6;
2529 uint8_t *addrgen = saddrgen.sin6_addr.s6_addr;
2531 static const uint8_t mcast_prefix[4] = { 0xff, 0x3e, 0, 64};
2532 memcpy(addrgen, mcast_prefix,
sizeof(mcast_prefix));
2533 addrgen +=
sizeof(mcast_prefix);
2544 SetError(
"no IPv6 unicast address available");
2547 static const size_t network_prefix_size = 8;
2548 memcpy(addrgen, &
static_cast<sockaddr_in6*
>(&prefixAddr)->sin6_addr, network_prefix_size);
2549 addrgen += network_prefix_size;
2551 for (
int iRetries = 1000; iRetries; iRetries--)
2554 memcpy(addrgen, &rnd,
sizeof(rnd));
2577 bool fSuccess =
false;
2599 if (fSuccess)
break;
2604 *pBroadcastAddr = MCAddr;
2611 SetError(
"invalid multicast address: wrong port");
2642 if (!
fInit)
return false;
2647 pPeer->Close(
"owner class closed");
2648 PeerListLock.
Clear();
2657 #ifdef C4NETIO_DEBUG
2681 if (!
fInit) {
SetError(
"not yet initialized");
return false; }
2690 uint32_t iMaxBlock = std::max(tNow,
GetNextTick(tNow)) - tNow;
2691 if (iMaxTime ==
TO_INF || iMaxTime > (
int) iMaxBlock) iMaxTime = iMaxBlock;
2702 if (!pPeer->Closed())
2703 pPeer->CheckTimeout();
2728 if (!pPeer)
return false;
2730 pPeer->
Close(
"closed");
2740 if (!pPeer)
return false;
2742 return pPeer->
Send(rPacket);
2753 bool fSuccess =
true;
2768 pPeer->
Send(rPacket);
2777 if (!pPeer)
return false;
2791 if (!pPeer->Closed())
2792 if (!pPeer->GetTimeout().IsInfinite())
2793 tTiming = std::min(tTiming, pPeer->GetTimeout());
2810 if (!pPeer || !pPeer->
Open())
return false;
2812 if (pIRate) *pIRate = pPeer->
GetIRate();
2813 if (pORate) *pORate = pPeer->
GetORate();
2814 if (pLoss) *pLoss = 0;
2823 pPeer->ClearStatistics();
2831 assert(pNetIO ==
this);
2832 #ifdef C4NETIO_DEBUG
2834 DebugLogPkt(
false,
Packet);
2858 PacketHdr PingPacket = { uint8_t(
IPID_Ping | (
Packet.getStatus() & 0x80)), 0 };
2874 { OnAddAddress(
Packet.getAddr(), *getBufPtr<AddAddrPacket>(
Packet));
return; }
2881 bool C4NetIOUDP::OnConn(
const addr_t &AddrPeer,
const addr_t &AddrConnect,
const addr_t *pOwnAddr,
C4NetIO *pNetIO)
2887 void C4NetIOUDP::OnDisconn(
const addr_t &AddrPeer,
C4NetIO *pNetIO,
const char *szReason)
2889 assert(pNetIO ==
this);
2899 pPeer->Close(szReason);
2902 void C4NetIOUDP::OnAddAddress(
const addr_t &FromAddr,
const AddAddrPacket &Packet)
2905 if (FromAddr !=
Packet.Addr && FromAddr !=
Packet.NewAddr)
return;
2910 if (!pPeer || pPeer == pPeer2)
return;
2912 pPeer->SetAltAddr(
Packet.NewAddr);
2915 pPeer2->Close(
"address equivalence detected");
2932 pFragmentGot(nullptr)
2939 delete [] pFragmentGot; pFragmentGot =
nullptr;
2949 return Data.getSize() ? (Data.getSize() - 1) / MaxDataSize + 1 : 1;
2954 assert(iFNr < FragmentCnt());
2956 uint16_t iFragmentSize = FragmentSize(iFNr);
2961 pnHdr->
Nr = iNr + iFNr;
2963 pnHdr->
Size = Data.getSize();
2965 Packet.Write(Data.getPart(iFNr * MaxDataSize, iFragmentSize),
2973 if (Empty())
return false;
2974 for (
unsigned int i = 0; i < FragmentCnt(); i++)
2975 if (!FragmentPresent(i))
2982 return !Empty() && iFNr < FragmentCnt() && (!pFragmentGot || pFragmentGot[iFNr]);
2993 bool fFirstFragment = Empty();
2998 Data.New(pHdr->
Size); Data.SetAddr(addr);
3000 if (FragmentCnt() > 1)
3001 memset(pFragmentGot =
new bool [FragmentCnt()],
false, FragmentCnt());
3003 if (pHdr->
Nr < iNr || pHdr->
Nr >= iNr + FragmentCnt()) { Data.Clear();
return false; }
3008 if (pHdr->
FNr != iNr)
return false;
3009 if (pHdr->
Size != Data.getSize())
return false;
3010 if (pHdr->
Nr < iNr || pHdr->
Nr >= iNr + FragmentCnt())
return false;
3013 nr_t iFNr = pHdr->
Nr - iNr;
3014 if (iPacketDataSize != FragmentSize(iFNr))
return false;
3017 if (!fFirstFragment && FragmentPresent(iFNr))
3020 if (Data.Compare(PacketData, iFNr * MaxDataSize))
3026 Data.Write(PacketData, iFNr * MaxDataSize);
3029 pFragmentGot[iFNr] =
true;
3040 assert(iFNr < FragmentCnt());
3041 return std::min(MaxDataSize, Data.getSize() - iFNr * MaxDataSize);
3049 : iMaxPacketCnt(inMaxPacketCnt)
3062 for (
Packet *pPkt = pBack; pPkt; pPkt = pPkt->
Prev)
3063 if (pPkt->GetNr() == iNr)
3065 else if (pPkt->GetNr() < iNr)
3073 for (
Packet *pPkt = pBack; pPkt; pPkt = pPkt->
Prev)
3074 if (pPkt->GetNr() <= iNr && pPkt->GetNr() + pPkt->FragmentCnt() > iNr)
3076 else if (pPkt->GetNr() < iNr)
3084 return pFront && pFront->Complete() ? pFront :
nullptr;
3090 Packet *pPkt = GetPacketFrgm(iNr);
3098 Packet *pInsertAfter = pBack, *pInsertBefore =
nullptr;
3099 for (; pInsertAfter; pInsertBefore = pInsertAfter, pInsertAfter = pInsertAfter->
Prev)
3103 if (pInsertBefore && pInsertBefore->GetNr() < pPacket->
GetNr() + pPacket->
FragmentCnt())
3106 (pInsertAfter ? pInsertAfter->
Next : pFront) = pPacket;
3107 (pInsertBefore ? pInsertBefore->Prev : pBack) = pPacket;
3108 pPacket->
Next = pInsertBefore;
3109 pPacket->
Prev = pInsertAfter;
3112 while (iPacketCnt > iMaxPacketCnt)
3113 DeletePacket(pFront);
3124 while (pPos && pPos != pFront) pPos = pPos->
Prev;
3141 while (pFront && pFront->GetNr() < iUntil)
3142 DeletePacket(pFront);
3149 DeletePacket(pFront);
3162 : pParent(pnParent), addr(naddr),
3167 iIPacketCounter(0), iRIPacketCounter(0),
3168 iIMCPacketCounter(0), iRIMCPacketCounter(0),
3169 iMCAckPacketCounter(0),
3171 iIRate(0), iORate(0), iLoss(0)
3184 fMultiCast =
false; fConnFailCallback = fFailCallback;
3185 return DoConn(
false);
3201 if (eStatus != CS_Works)
return true;
3204 Close(
"failed to send packet");
3213 if (eStatus != CS_Works)
return true;
3217 if (!fNoReCheck) iLastPacketAsked = iLastMCPacketAsked = 0;
3218 unsigned int iStartAt = fNoReCheck ? std::max(iLastPacketAsked + 1, iIPacketCounter) : iIPacketCounter;
3219 unsigned int iStartAtMC = fNoReCheck ? std::max(iLastMCPacketAsked + 1, iIMCPacketCounter) : iIMCPacketCounter;
3221 const unsigned int iMaxAskCnt = 10;
3222 unsigned int i, iAskList[iMaxAskCnt], iAskCnt = 0, iMCAskCnt = 0;
3223 for (i = iStartAt; i < iRIPacketCounter; i++)
3224 if (!IPackets.FragmentPresent(i))
3225 if (iAskCnt < iMaxAskCnt)
3226 iLastPacketAsked = iAskList[iAskCnt++] = i;
3227 for (i = iStartAtMC; i < iRIMCPacketCounter; i++)
3228 if (!IMCPackets.FragmentPresent(i))
3229 if (iAskCnt + iMCAskCnt < iMaxAskCnt)
3230 iLastMCPacketAsked = iAskList[iAskCnt + iMCAskCnt++] = i;
3231 int iEAskCnt = iAskCnt + iMCAskCnt;
3241 if (iEAskCnt || fForceCheck)
3242 return DoCheck(iAskCnt, iMCAskCnt, iAskList);
3252 const PacketHdr *pHdr = getBufPtr<PacketHdr>(rPacket);
3253 bool fBroadcasted = !!(pHdr->
StatusByte & 0x80);
3255 (fBroadcasted ? iRIMCPacketCounter : iRIPacketCounter) = std::max<unsigned int>((fBroadcasted ? iRIMCPacketCounter : iRIPacketCounter), pHdr->
Nr);
3256 #ifdef C4NETIOUDP_OPT_RECV_CHECK_IMMEDIATE
3258 if (eStatus == CS_Works)
3269 const ConnPacket *pPkt = getBufPtr<ConnPacket>(rPacket);
3271 if (pPkt->
ProtocolVer != pParent->iVersion)
break;
3275 if (!PeerAddr.IsNull() && PeerAddr != pPkt->
Addr)
3281 Pkt.
Addr = PeerAddr;
3288 else if (eStatus == CS_Works && iIPacketCounter != pPkt->
Nr)
3291 OnClose(
"reconnect"); eStatus =
CS_Closed;
3296 PeerAddr = pPkt->
Addr;
3300 iRIMCPacketCounter = iIMCPacketCounter = pPkt->
Nr;
3302 iRIPacketCounter = iIPacketCounter = pPkt->
Nr;
3309 iLastPacketAsked = iLastMCPacketAsked = 0;
3311 if (!pParent->fMultiCast)
3317 pParent->fDelayedLoopbackTest =
true;
3318 if (!pParent->InitBroadcast(&MCAddr))
3319 pParent->fDelayedLoopbackTest =
false;
3324 bool fullyConnected =
false;
3331 else if (pParent->fMultiCast && addr.GetPort() == pParent->iPort)
3337 fullyConnected =
true;
3342 if (fullyConnected) OnConn();
3348 if (eStatus != CS_Conn)
break;
3351 const ConnOKPacket *pPkt = getBufPtr<ConnOKPacket>(rPacket);
3353 PeerAddr = pPkt->
Addr;
3359 if (pParent->fMultiCast)
3384 const DataPacketHdr *pHdr = getBufPtr<DataPacketHdr>(rPacket);
3386 if (pHdr->
Nr < (fBroadcasted ? iIMCPacketCounter : iIPacketCounter))
break;
3388 bool fAddPacket =
false;
3389 PacketList *pPacketList = fBroadcasted ? &IMCPackets : &IPackets;
3391 if (!pPkt) { pPkt =
new Packet(); fAddPacket =
true; }
3396 if (fAddPacket)
if (!pPacketList->
AddPacket(pPkt)) {
delete pPkt;
break; }
3398 CheckCompleteIPackets();
3402 if (fAddPacket)
delete pPkt;
3416 if (pPkt->
MCAckNr > iMCAckPacketCounter)
3418 iMCAckPacketCounter = pPkt->
MCAckNr;
3419 pParent->ClearMCPackets();
3423 const int *pAskList = getBufPtr<int>(rPacket,
sizeof(
CheckPacketHdr));
3429 bool fMCPacket = i >= pPkt->
AskCount;
3431 Packet *pPkt2Send = (fMCPacket ? pParent->OPackets :
OPackets).GetPacketFrgm(pAskList[i]);
3432 if (!pPkt2Send) {
Close(
"starvation");
break; }
3435 pParent->BroadcastDirect(*pPkt2Send, pAskList[i]);
3446 const ClosePacket *pPkt = getBufPtr<ClosePacket>(rPacket);
3448 if (!PeerAddr.IsNull() && PeerAddr != pPkt->
Addr)
3451 OnClose(
"connection closed by peer");
3483 iIRate = iORate = 0;
3499 if (pParent->fMultiCast)
3500 Pkt.
MCAddr = pParent->C4NetIOSimpleUDP::getMCAddr();
3509 if (!pAskList) iAskCnt = iMCAskCnt = 0;
3513 int iAskListSize = (iAskCnt + iMCAskCnt) *
sizeof(*pAskList);
3519 pChkPkt->
AckNr = iIPacketCounter;
3520 pChkPkt->
MCAckNr = iIMCPacketCounter;
3536 bool fSuccess =
true;
3537 for (
unsigned int i = 0; i < rPacket.
FragmentCnt(); i++)
3546 if (!(rPacket.getStatus() & 0x80)) rPacket.SetAddr(v6Addr);
3550 return pParent->SendDirect(std::move(rPacket));
3561 if (pCB && !pCB->
OnConn(addr, addr, &PeerAddr, pParent))
3567 CheckCompleteIPackets();
3574 if (eStatus == CS_Works || (eStatus == CS_Conn && fConnFailCallback))
3576 pCB->
OnDisconn(addr, pParent, szReason);
3584 if (eStatus != CS_Works)
return;
3593 while ((pPkt = IPackets.GetFirstPacketComplete()))
3596 if (pPkt->
GetNr() != iIPacketCounter)
break;
3599 pParent->pCB->OnPacket(pPkt->
GetData(), pParent);
3603 int iNr = pPkt->
GetNr();
3604 IPackets.DeletePacket(pPkt);
3605 assert(!IPackets.GetPacketFrgm(iNr)); (void)iNr;
3607 while ((pPkt = IMCPackets.GetFirstPacketComplete()))
3610 if (pPkt->
GetNr() != iIMCPacketCounter)
break;
3613 pParent->pCB->OnPacket(pPkt->
GetData(), pParent);
3617 int iNr = pPkt->
GetNr();
3618 IMCPackets.DeletePacket(pPkt);
3619 assert(!IMCPackets.GetPacketFrgm(iNr)); (void)iNr;
3633 iRetries = iRetryCnt;
3639 if (eStatus == CS_Conn)
3644 int iRetryCnt = iRetries - 1;
3648 iRetries = iRetryCnt;
3652 Close(
"connection timeout");
3666 bool fSuccess =
true;
3667 for (
unsigned int iFrgm = 0; iFrgm < rPacket.
FragmentCnt(); iFrgm++)
3674 addr_t toaddr = rPacket.getAddr();
3676 if (rPacket.getStatus() & 0x80)
3686 #ifdef C4NETIO_DEBUG
3690 #ifdef C4NETIO_SIMULATE_PACKETLOSS
3691 if ((rPacket.getStatus() & 0x7F) !=
IPID_Test)
3692 if (
UnsyncedRandom(100) < C4NETIO_SIMULATE_PACKETLOSS)
return true;
3725 SetError(
"Multicast disabled: loopback test failed");
3778 Peer *pDelete = pPeer;
3787 pPeer = pPeer->
Next;
3797 if (!pPeer->Closed())
3798 if (pPeer->GetAddr() == addr || pPeer->GetAltAddr() == addr)
3810 if (pnPeer)
return pnPeer;
3812 pnPeer =
new Peer(PeerAddr,
this);
3813 if (!pnPeer)
return nullptr;
3816 PeerListAddLock.
Clear();
3818 if (!pnPeer->
Connect(fFailCallback)) { pnPeer->
Close(
"connect failed");
return nullptr; }
3855 #ifdef C4NETIO_DEBUG
3857 #define _O_SEQUENTIAL 0
3860 void C4NetIOUDP::OpenDebugLog()
3862 const char *szFileBase =
"NetIOUDP%d.log";
3864 for (
int i = 0; i < 1000; i++)
3866 sprintf(szFilePath, szFileBase, i);
3867 hDebugLog = open(szFilePath, O_CREAT | O_EXCL | O_TRUNC | _O_SEQUENTIAL | _O_TEXT | O_WRONLY, S_IREAD | S_IWRITE);
3868 if (hDebugLog != -1)
break;
3871 if (hDebugLog != -1)
3874 time_t tTime; time(&tTime);
3875 struct tm *pLocalTime;
3876 pLocalTime=localtime(&tTime);
3878 sprintf(O,
"C4NetIOUDP debuglog starting at %d/%d/%d %d:%2d:%2d - (Daylight %d)\n",
3879 pLocalTime->tm_mon+1,
3880 pLocalTime->tm_mday,
3881 pLocalTime->tm_year+1900,
3882 pLocalTime->tm_hour,
3885 pLocalTime->tm_isdst);
3886 else sprintf(O,
"C4NetIOUDP debuglog; time not available\n");
3887 write(hDebugLog, O, strlen(O));
3891 void C4NetIOUDP::CloseDebugLog()
3896 void C4NetIOUDP::DebugLogPkt(
bool fOut,
const C4NetIOPacket &Pkt)
3899 O.
Format(
"%s %s %s:", fOut ?
"out" :
"in ",
3904 if (Pkt.
getSize() >=
sizeof(PacketHdr))
3906 const PacketHdr &Hdr = *getBufPtr<PacketHdr>(Pkt);
3908 switch (Hdr.StatusByte & 0x07f)
3917 default: O.
Append(
" UNKN");
break;
3919 O.
AppendFormat(
" %s %04d", (Hdr.StatusByte & 0x80) ?
"MC" :
"DU", Hdr.Nr);
3921 #define UPACK(type) \
3922 const type &P = *getBufPtr<type>(Pkt);
3924 switch (Hdr.StatusByte)
3927 case IPID_Conn: { UPACK(ConnPacket); O.
AppendFormat(
" (Ver %d, MC: %s)", P.ProtocolVer, P.MCAddr.ToString().getData());
break; }
3930 UPACK(ConnOKPacket);
3936 default: O.
Append(
" (??""?)");
3942 UPACK(DataPacketHdr); O.
AppendFormat(
" (f: %d s: %d)", P.FNr, P.Size);
3943 for (
int iPos =
sizeof(DataPacketHdr); iPos < std::min<int>(Pkt.
getSize(),
sizeof(DataPacketHdr) + 16); iPos++)
3944 O.
AppendFormat(
" %02x", *getBufPtr<unsigned char>(Pkt, iPos));
3949 UPACK(CheckPacketHdr);
3950 O.
AppendFormat(
" (ack: %d, mcack: %d, ask: %d mcask: %d, ", P.AckNr, P.MCAckNr, P.AskCount, P.MCAskCount);
3951 if (Pkt.
getSize() <
sizeof(CheckPacketHdr) +
sizeof(
unsigned int) * (P.AskCount + P.MCAskCount))
3956 for (
unsigned int i = 0; i < P.AskCount + P.MCAskCount; i++)
3957 O.
AppendFormat(
"%s%d", i ?
", " :
"", *getBufPtr<unsigned int>(Pkt,
sizeof(CheckPacketHdr) + i *
sizeof(
unsigned int)));
4024 void C4NetIOMan::EnlargeIO(
int iBy)
bool HaveWouldBlockError()
const char * GetSocketErrorMsg(int iError)
bool HaveConnResetError()
uint32_t UnsyncedRandom()
StdStrBuf FormatString(const char *szFmt,...)
virtual void OnPacket(const class C4NetIOPacket &rPacket, C4NetIO *pNetIO)=0
virtual bool OnConn(const addr_t &AddrPeer, const addr_t &AddrConnect, const addr_t *pOwnAddr, C4NetIO *pNetIO)
virtual void OnDisconn(const addr_t &AddrPeer, C4NetIO *pNetIO, const char *szReason)
virtual void SetCallback(CBClass *pnCallback)=0
virtual const char * GetError() const
void SetError(const char *strnError, bool fSockErr=false)
bool InitIPv6Socket(SOCKET socket)
static std::vector< HostAddress > GetLocalAddresses()
void AddIO(C4NetIO *pNetIO, bool fSetCallback=true)
void RemoveIO(C4NetIO *pNetIO)
virtual void OnError(const char *strError, C4NetIO *pNetIO)
const C4NetIO::addr_t & getAddr() const
void SetAddr(const C4NetIO::addr_t &naddr)
C4NetIOPacket Duplicate() const
C4NetIOPacket getRef() const
bool Init(uint16_t iPort=addr_t::IPPORT_NONE) override
bool Execute(int iMaxTime=TO_INF, pollfd *=nullptr) override
void GetFDs(std::vector< struct pollfd > &FDs) override
bool Send(const C4NetIOPacket &rPacket) override
bool SetMCLoopback(int fLoopback)
void SetCallback(CBClass *pnCallback) override
void SetReUseAddress(bool fAllow)
~C4NetIOSimpleUDP() override
bool Broadcast(const C4NetIOPacket &rPacket) override
bool getMCLoopback() const
const addr_t & getMCAddr() const
virtual bool InitBroadcast(addr_t *pBroadcastAddr)
virtual bool CloseBroadcast()
static const unsigned int iMinIBufSize
void * GetRecvBuf(int iSize)
const C4NetIO::addr_t & GetAddr() const
bool Send(const C4NetIOPacket &rPacket)
void SetBroadcast(bool fSet)
static const unsigned int iTCPHeaderSize
Peer(const C4NetIO::addr_t &naddr, SOCKET nsock, C4NetIOTCP *pnParent)
C4NetIO::addr_t GetAddress()
bool Send(const C4NetIOPacket &rPacket) override
bool Init(uint16_t iPort=addr_t::IPPORT_NONE) override
Peer * GetPeer(const addr_t &addr)
virtual bool InitBroadcast(addr_t *pBroadcastAddr)
virtual bool CloseBroadcast()
void ClearStatistic() override
void OnShareFree(CStdCSecEx *pCSec) override
void AddConnectWait(SOCKET sock, const addr_t &addr)
bool GetStatistic(int *pBroadcastRate) override
bool Listen(uint16_t inListenPort)
virtual void PackPacket(const C4NetIOPacket &rPacket, StdBuf &rOutBuf)
std::unique_ptr< Socket > Bind(const addr_t &addr)
SOCKET CreateSocket(addr_t::AddressFamily family)
ConnectWait * GetConnectWait(const addr_t &addr)
void GetFDs(std::vector< struct pollfd > &FDs) override
virtual size_t UnpackPacket(const StdBuf &rInBuf, const C4NetIO::addr_t &Addr)
bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss) override
bool Broadcast(const C4NetIOPacket &rPacket) override
struct C4NetIOTCP::ConnectWait nullptr
bool Execute(int iMaxTime=TO_INF, pollfd *readyfds=nullptr) override
bool Connect(const addr_t &addr, std::unique_ptr< Socket > socket)
Peer * Accept(SOCKET nsock=INVALID_SOCKET, const addr_t &ConnectAddr=addr_t())
bool SetBroadcast(const addr_t &addr, bool fSet=true) override
::size_t FragmentSize(nr_t iFNr) const
C4NetIOPacket GetFragment(nr_t iFNr, bool fBroadcastFlag=false) const
static const size_t MaxDataSize
C4NetIOPacket & GetData()
bool AddFragment(const C4NetIOPacket &Packet, const C4NetIO::addr_t &addr)
bool FragmentPresent(nr_t iFNr) const
static const size_t MaxSize
bool DeletePacket(Packet *pPacket)
PacketList(unsigned int iMaxPacketCnt=~0)
bool FragmentPresent(unsigned int iNr)
bool AddPacket(Packet *pPacket)
Packet * GetFirstPacketComplete()
Packet * GetPacket(unsigned int iNr)
Packet * GetPacketFrgm(unsigned int iNr)
void ClearPackets(unsigned int iUntil)
bool DoCheck(int iAskCnt=0, int iMCAskCnt=0, unsigned int *pAskList=nullptr)
void Close(const char *szReason)
static const unsigned int iReCheckInterval
bool SendDirect(const Packet &rPacket, unsigned int iNr=~0)
void SetTimeout(int iLength=iStdTimeout, int iRetryCnt=0)
void OnClose(const char *szReason)
void OnRecv(const C4NetIOPacket &Packet)
void CheckCompleteIPackets()
bool Check(bool fForceCheck=true)
void SetBroadcast(bool fSet)
bool Send(const C4NetIOPacket &rPacket)
bool Connect(bool fFailCallback)
Peer(const C4NetIO::addr_t &naddr, C4NetIOUDP *pnParent)
unsigned int GetMCAckPacketCounter() const
static const unsigned int iConnectRetries
static const unsigned int iCheckInterval
bool fDelayedLoopbackTest
bool Execute(int iMaxTime=TO_INF, pollfd *=nullptr) override
C4TimeMilliseconds GetNextTick(C4TimeMilliseconds tNow) override
bool Send(const C4NetIOPacket &rPacket) override
static const unsigned int iUDPHeaderSize
C4TimeMilliseconds tNextCheck
bool SetBroadcast(const addr_t &addr, bool fSet=true) override
static const unsigned int iStdTimeout
Peer * ConnectPeer(const addr_t &PeerAddr, bool fFailCallback)
bool Connect(const addr_t &addr) override
bool CloseBroadcast() override
bool SendDirect(C4NetIOPacket &&rPacket)
bool GetConnStatistic(const addr_t &addr, int *pIRate, int *pORate, int *pLoss) override
unsigned int iOPacketCounter
bool BroadcastDirect(const Packet &rPacket, unsigned int iNr=~0u)
bool InitBroadcast(addr_t *pBroadcastAddr) override
bool Init(uint16_t iPort=addr_t::IPPORT_NONE) override
void ClearStatistic() override
static const unsigned int iVersion
bool GetStatistic(int *pBroadcastRate) override
static const unsigned int iMaxOPacketBacklog
void OnShareFree(CStdCSecEx *pCSec) override
void AddPeer(Peer *pPeer)
Peer * GetPeer(const addr_t &addr)
bool Broadcast(const C4NetIOPacket &rPacket) override
static C4TimeMilliseconds Now()
void SetSize(size_t inSize)
void Write(const void *pnData, size_t inSize, size_t iAt=0)
int Compare(const void *pCData, size_t iCSize, size_t iAt=0) const
void Move(size_t iFrom, size_t inSize, size_t iTo=0)
StdBuf getPart(size_t iStart, size_t inSize) const
void Value(const T &rStruct)
virtual bool isDeserializer()
void Add(StdSchedulerProc *pProc)
void AppendFormat(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
const char * getData() const
void Append(const char *pnData, size_t iChars)
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
void SetAddress(const sockaddr *addr)
void CompileFunc(StdCompiler *comp)
EndpointAddress AsIPv6() const
void SetPort(uint16_t port)
StdStrBuf ToString(int flags=0) const
void SetDefaultPort(uint16_t port)
static const uint16_t IPPORT_NONE
bool operator==(const EndpointAddress &rhs) const
EndpointAddress AsIPv4() const
const EndpointAddressPtr operator&() const
void SetScopeId(int scopeId)
void SetHost(const sockaddr *addr)
StdStrBuf ToString(int flags=0) const
bool operator==(const HostAddress &rhs) const
C4NetIO::HostAddress AsIPv4() const
AddressFamily GetFamily() const
C4NetIO::HostAddress AsIPv6() const
size_t GetAddrLen() const
BinAddr(const C4NetIO::addr_t &addr)
StdStrBuf ToString() const
enum C4NetIOUDP::ConnOKPacket::@67 MCMode