INT_PTR NetlibAddressToStringSrv(WPARAM wParam, LPARAM lParam) { if (wParam) { SOCKADDR_INET_M iaddr = {0}; iaddr.Ipv4.sin_family = AF_INET; iaddr.Ipv4.sin_addr.s_addr = htonl((unsigned)lParam); return (INT_PTR)NetlibAddressToString(&iaddr); } else return (INT_PTR)NetlibAddressToString((SOCKADDR_INET_M*)lParam); }
void NetlibGetConnectionInfo(NetlibConnection *nlc, NETLIBCONNINFO *connInfo) { if (!nlc || !connInfo || connInfo->cbSize < sizeof(NETLIBCONNINFO)) return; SOCKADDR_INET_M sin = { 0 }; int len = sizeof(sin); if (!getsockname(nlc->s, (PSOCKADDR)&sin, &len)) { connInfo->wPort = ntohs(sin.Ipv4.sin_port); connInfo->dwIpv4 = sin.si_family == AF_INET ? htonl(sin.Ipv4.sin_addr.s_addr) : 0; strncpy_s(connInfo->szIpPort, ptrA(NetlibAddressToString(&sin)), _TRUNCATE); } }
void NetlibGetConnectionInfo(NetlibConnection *nlc, NETLIBCONNINFO *connInfo) { if (!nlc || !connInfo || connInfo->cbSize < sizeof(NETLIBCONNINFO)) return; SOCKADDR_INET_M sin = { 0 }; int len = sizeof(sin); if (!getsockname(nlc->s, (PSOCKADDR)&sin, &len)) { connInfo->wPort = ntohs(sin.Ipv4.sin_port); connInfo->dwIpv4 = sin.si_family == AF_INET ? htonl(sin.Ipv4.sin_addr.s_addr) : 0; char *szTmp = NetlibAddressToString(&sin); strncpy(connInfo->szIpPort, szTmp, sizeof(connInfo->szIpPort)); connInfo->szIpPort[sizeof(connInfo->szIpPort) - 1] = 0; mir_free(szTmp); } }
static NETLIBIPLIST* GetMyIpv6(unsigned flags) { addrinfo *air = NULL, *ai, hints = { 0 }; const char *szMyHost = ""; hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_PASSIVE; if (GetAddrInfoA(szMyHost, NULL, &hints, &air)) return NULL; unsigned n = 0; for (ai = air; ai; ai = ai->ai_next) { SOCKADDR_INET_M *iaddr = (SOCKADDR_INET_M*)ai->ai_addr; if (ai->ai_family == AF_INET || (ai->ai_family == AF_INET6 && (!(flags & 1) || IsAddrGlobal(&iaddr->Ipv6.sin6_addr)))) ++n; } NETLIBIPLIST *addr = (NETLIBIPLIST*)mir_calloc(n * 64 + 4); addr->cbNum = n; unsigned i = 0; for (ai = air; ai; ai = ai->ai_next) { SOCKADDR_INET_M *iaddr = (SOCKADDR_INET_M*)ai->ai_addr; if (ai->ai_family == AF_INET || (ai->ai_family == AF_INET6 && (!(flags & 1) || IsAddrGlobal(&iaddr->Ipv6.sin6_addr)))) { char *szIp = NetlibAddressToString(iaddr); if (szIp) strncpy_s(addr->szIp[i++], szIp, _TRUNCATE); mir_free(szIp); } } FreeAddrInfoA(air); return addr; }
static bool my_connectIPv6(NetlibConnection *nlc, NETLIBOPENCONNECTION * nloc) { int rc = SOCKET_ERROR, retrycnt = 0; u_long notblocking = 1; DWORD lasterr = 0; static const TIMEVAL tv = { 1, 0 }; unsigned int dwTimeout = (nloc->cbSize == sizeof(NETLIBOPENCONNECTION) && nloc->flags & NLOCF_V2) ? nloc->timeout : 0; // if dwTimeout is zero then its an old style connection or new with a 0 timeout, select() will error quicker anyway if (dwTimeout == 0) dwTimeout = 30; // this is for XP SP2 where there is a default connection attempt limit of 10/second if (connectionTimeout) { WaitForSingleObject(hConnectionOpenMutex, 10000); int waitdiff = GetTickCount() - g_LastConnectionTick; if (waitdiff < connectionTimeout) SleepEx(connectionTimeout, TRUE); g_LastConnectionTick = GetTickCount(); ReleaseMutex(hConnectionOpenMutex); // might of died in between the wait if (Miranda_Terminated()) return false; } char szPort[6]; addrinfo *air = NULL, *ai, hints = {0}; hints.ai_family = AF_UNSPEC; if (nloc->flags & NLOCF_UDP) { hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; } else { hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; } if (nlc->proxyType) { if (!nlc->szProxyServer) return false; if (nloc) NetlibLogf(nlc->nlu, "(%p) Connecting to proxy %s:%d for %s:%d ....", nlc, nlc->szProxyServer, nlc->wProxyPort, nloc->szHost, nloc->wPort); else NetlibLogf(nlc->nlu, "(%p) Connecting to proxy %s:%d ....", nlc, nlc->szProxyServer, nlc->wProxyPort); _itoa(nlc->wProxyPort, szPort, 10); if (GetAddrInfoA(nlc->szProxyServer, szPort, &hints, &air)) { NetlibLogf(nlc->nlu, "%s %d: %s() for host %s failed (%u)", __FILE__, __LINE__, "getaddrinfo", nlc->szProxyServer, WSAGetLastError()); return false; } } else { if (!nloc || !nloc->szHost) return false; NetlibLogf(nlc->nlu, "(%p) Connecting to server %s:%d....", nlc, nloc->szHost, nloc->wPort); _itoa(nlc->nloc.wPort, szPort, 10); if (GetAddrInfoA(nlc->nloc.szHost, szPort, &hints, &air)) { NetlibLogf(nlc->nlu, "%s %d: %s() for host %s failed (%u)", __FILE__, __LINE__, "getaddrinfo", nlc->nloc.szHost, WSAGetLastError()); return false; } } for (ai = air; ai && !Miranda_Terminated(); ai = ai->ai_next) { NetlibLogf(nlc->nlu, "(%p) Connecting to ip %s ....", nlc, ptrA( NetlibAddressToString((SOCKADDR_INET_M*)ai->ai_addr))); retry: nlc->s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (nlc->s == INVALID_SOCKET) return false; // return the socket to non blocking if (ioctlsocket(nlc->s, FIONBIO, ¬blocking) != 0) return false; if (nlc->nlu->settings.specifyOutgoingPorts && nlc->nlu->settings.szOutgoingPorts && nlc->nlu->settings.szOutgoingPorts[0]) { SOCKET s = ai->ai_family == AF_INET ? nlc->s : INVALID_SOCKET; SOCKET s6 = ai->ai_family == AF_INET6 ? nlc->s : INVALID_SOCKET; if (!BindSocketToPort(nlc->nlu->settings.szOutgoingPorts, s, s6, &nlc->nlu->inportnum)) NetlibLogf(nlc->nlu, "Netlib connect: Not enough ports for outgoing connections specified"); } // try a connect if (connect(nlc->s, ai->ai_addr, (int)ai->ai_addrlen) == 0) { rc = 0; break; } // didn't work, was it cos of nonblocking? if (WSAGetLastError() != WSAEWOULDBLOCK) { rc = SOCKET_ERROR; closesocket(nlc->s); nlc->s = INVALID_SOCKET; continue; } while (true) { // timeout loop fd_set r, w, e; FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e); FD_SET(nlc->s, &r); FD_SET(nlc->s, &w); FD_SET(nlc->s, &e); if ((rc = select(0, &r, &w, &e, &tv)) == SOCKET_ERROR) break; if (rc > 0) { if (FD_ISSET(nlc->s, &w)){ // connection was successful rc = 0; lasterr = 0; } if (FD_ISSET(nlc->s, &r)) { // connection was closed rc = SOCKET_ERROR; lasterr = WSAECONNRESET; } if (FD_ISSET(nlc->s, &e)) { // connection failed. int len = sizeof(lasterr); rc = SOCKET_ERROR; getsockopt(nlc->s, SOL_SOCKET, SO_ERROR, (char*)&lasterr, &len); if (lasterr == WSAEADDRINUSE && ++retrycnt <= 2) { closesocket(nlc->s); nlc->s = INVALID_SOCKET; goto retry; } } break; } else if (Miranda_Terminated()) { rc = SOCKET_ERROR; lasterr = ERROR_TIMEOUT; break; } else if (nloc->cbSize == sizeof(NETLIBOPENCONNECTION) && nloc->flags & NLOCF_V2 && nloc->waitcallback != NULL && nloc->waitcallback(&dwTimeout) == 0) { rc = SOCKET_ERROR; lasterr = ERROR_TIMEOUT; break; } if (--dwTimeout == 0) { rc = SOCKET_ERROR; lasterr = ERROR_TIMEOUT; break; } } if (rc == 0) break; closesocket(nlc->s); nlc->s = INVALID_SOCKET; } FreeAddrInfoA(air); notblocking = 0; if (nlc->s != INVALID_SOCKET) ioctlsocket(nlc->s, FIONBIO, ¬blocking); if (rc && lasterr) SetLastError(lasterr); return rc == 0; }
static bool my_connectIPv4(NetlibConnection *nlc, NETLIBOPENCONNECTION * nloc) { int rc = 0, retrycnt = 0; u_long notblocking = 1; DWORD lasterr = 0; static const TIMEVAL tv = { 1, 0 }; unsigned int dwTimeout = (nloc->cbSize == sizeof(NETLIBOPENCONNECTION) && nloc->flags & NLOCF_V2) ? nloc->timeout : 0; // if dwTimeout is zero then its an old style connection or new with a 0 timeout, select() will error quicker anyway if (dwTimeout == 0) dwTimeout = 30; // this is for XP SP2 where there is a default connection attempt limit of 10/second if (connectionTimeout) { WaitForSingleObject(hConnectionOpenMutex, 10000); int waitdiff = GetTickCount() - g_LastConnectionTick; if (waitdiff < connectionTimeout) SleepEx(connectionTimeout, TRUE); g_LastConnectionTick = GetTickCount(); ReleaseMutex(hConnectionOpenMutex); // might of died in between the wait if (Miranda_Terminated()) return false; } PHOSTENT he; SOCKADDR_IN sin = {0}; sin.sin_family = AF_INET; if (nlc->proxyType) { if (!nlc->szProxyServer) return false; if (nloc) NetlibLogf(nlc->nlu, "(%p) Connecting to proxy %s:%d for %s:%d ....", nlc, nlc->szProxyServer, nlc->wProxyPort, nloc->szHost, nloc->wPort); else NetlibLogf(nlc->nlu, "(%p) Connecting to proxy %s:%d ....", nlc, nlc->szProxyServer, nlc->wProxyPort); sin.sin_port = htons(nlc->wProxyPort); he = gethostbyname(nlc->szProxyServer); } else { if (!nloc || !nloc->szHost || nloc->szHost[0] == '[' || strchr(nloc->szHost, ':')) return false; NetlibLogf(nlc->nlu, "(%p) Connecting to server %s:%d....", nlc, nloc->szHost, nloc->wPort); sin.sin_port = htons(nloc->wPort); he = gethostbyname(nloc->szHost); } for (char** har = he->h_addr_list; *har && !Miranda_Terminated(); ++har) { sin.sin_addr.s_addr = *(u_long*)*har; char* szIp = NetlibAddressToString((SOCKADDR_INET_M*)&sin); NetlibLogf(nlc->nlu, "(%p) Connecting to ip %s ....", nlc, szIp); mir_free(szIp); retry: nlc->s = socket(AF_INET, nloc->flags & NLOCF_UDP ? SOCK_DGRAM : SOCK_STREAM, 0); if (nlc->s == INVALID_SOCKET) return false; // return the socket to non blocking if (ioctlsocket(nlc->s, FIONBIO, ¬blocking) != 0) return false; if (nlc->nlu->settings.specifyOutgoingPorts && nlc->nlu->settings.szOutgoingPorts && nlc->nlu->settings.szOutgoingPorts[0]) { if (!BindSocketToPort(nlc->nlu->settings.szOutgoingPorts, nlc->s, INVALID_SOCKET, &nlc->nlu->inportnum)) NetlibLogf(nlc->nlu, "Netlib connect: Not enough ports for outgoing connections specified"); } // try a connect if (connect(nlc->s, (LPSOCKADDR)&sin, sizeof(sin)) == 0) { rc = 0; break; } // didn't work, was it cos of nonblocking? if (WSAGetLastError() != WSAEWOULDBLOCK) { rc = SOCKET_ERROR; closesocket(nlc->s); nlc->s = INVALID_SOCKET; continue; } while (true) { fd_set r, w, e; FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e); FD_SET(nlc->s, &r); FD_SET(nlc->s, &w); FD_SET(nlc->s, &e); if ((rc = select(0, &r, &w, &e, &tv)) == SOCKET_ERROR) break; if (rc > 0) { if (FD_ISSET(nlc->s, &w)){ // connection was successful rc = 0; } if (FD_ISSET(nlc->s, &r)) { // connection was closed rc = SOCKET_ERROR; lasterr = WSAECONNRESET; } if (FD_ISSET(nlc->s, &e)) { // connection failed. int len = sizeof(lasterr); rc = SOCKET_ERROR; getsockopt(nlc->s, SOL_SOCKET, SO_ERROR, (char*)&lasterr, &len); if (lasterr == WSAEADDRINUSE && ++retrycnt <= 2) { closesocket(nlc->s); goto retry; } } break; } else if (Miranda_Terminated()) { rc = SOCKET_ERROR; lasterr = ERROR_TIMEOUT; break; } else if (nloc->cbSize == sizeof(NETLIBOPENCONNECTION) && nloc->flags & NLOCF_V2 && nloc->waitcallback != NULL && nloc->waitcallback(&dwTimeout) == 0) { rc = SOCKET_ERROR; lasterr = ERROR_TIMEOUT; break; } if (--dwTimeout == 0) { rc = SOCKET_ERROR; lasterr = ERROR_TIMEOUT; break; } } if (rc == 0) break; closesocket(nlc->s); nlc->s = INVALID_SOCKET; } notblocking = 0; if (nlc->s != INVALID_SOCKET) ioctlsocket(nlc->s, FIONBIO, ¬blocking); if (rc && lasterr) SetLastError(lasterr); return rc == 0; }