extern int SH_CmpSockAddr(SockBase base, struct sockaddr *sa1, struct sockaddr *sa2) { sa_family_t fam = sa1->sa_family; if (fam != sa2->sa_family) return (fam - sa2->sa_family); int len1 = SockAddrLen(sa1); int len2 = SockAddrLen(sa2); if (len1 <= 0 || len2 <= 0) { return Gleep(base->debug, "SH_CmpSockAddr"); } int delta = len1-len2; if (delta != 0) return delta; return memcmp(sa1, sa2, len1); }
static int InnerConnect(SockBase base, struct sockaddr *sap) { int fd = socket(sap->sa_family, SOCK_STREAM, IPPROTO_TCP); if (fd >= 0) { // we've got a socket, so try for a connection int timeout = base->robustTimeout; uint64_t start = GetCurrentTime(); for (;;) { int connRes = connect(fd, sap, SockAddrLen(sap)); if (connRes >= 0) { // success! return fd; } MilliSleep(RobustMillis); uint64_t now = GetCurrentTime(); double dt = DeltaTime(start, now); int e = errno; if (dt > timeout || (e != EAGAIN && e != EINTR)) { // failed, so give back the socket and report the failure close(fd); return connRes; } } } return fd; }
extern int SH_CopySockAddr(SockBase base, struct sockaddr *dst, struct sockaddr *src) { int len = SockAddrLen(src); if (len <= 0) { return Gleep(base->debug, "SH_CopySockAddr"); } memcpy(dst, src, len); return 0; }
/** * Try to extract an AF_INET address from a sockaddr. If successful, sa points * to the next sockaddr and true is returned. */ bool ExtractIPV4AddressFromSockAddr(const uint8_t **data, IPV4Address *ip) { const struct sockaddr *sa = reinterpret_cast<const struct sockaddr*>(*data); if (sa->sa_family != AF_INET) { return false; } *ip = IPV4Address( reinterpret_cast<const struct sockaddr_in*>(*data)->sin_addr.s_addr); *data += SockAddrLen(*sa); return true; }
/** * Performs a robust connect, restarting when interrupted. * Requires a valid socket (se->fd >= 0). */ extern int SH_RobustConnect(SockEntry se, struct sockaddr *sap) { int timeout = se->base->robustTimeout; uint64_t start = GetCurrentTime(); for (;;) { int connRes = connect(se->fd, sap, SockAddrLen(sap)); if (connRes >= 0) { se->lastUsed = GetCurrentTime(); return connRes; } int e = errno; if (e != EAGAIN && e != EINTR) break; MilliSleep(RobustMillis); uint64_t now = GetCurrentTime(); double dt = DeltaTime(start, now); if (dt > timeout) break; } se->errCount++; return -1; }