📄 gxy.c
字号:
if (pHints) {
if (pHints->ai_addrlen || pHints->ai_canonname || pHints->ai_addr
|| pHints ->ai_next) {
Err = EAI_FAIL;
} else {
if ((AI_CANONNAME & (Flags = pHints->ai_flags)) && !pNodename) {
Err = EAI_BADFLAGS;
} else if ((PF_UNSPEC != (ProtFamily = pHints->ai_family)) &&
(PF_INET != ProtFamily) &&
(PF_INET6 != ProtFamily)) {
Err = EAI_FAMILY;
} else if ((SockType = pHints->ai_socktype) &&
(SOCK_STREAM != SockType) &&
(SOCK_DGRAM != SockType)) {
Err = EAI_SOCKTYPE;
} else
Proto = pHints->ai_protocol;
}
}
if (pServname) {
char *pEnd;
// CE doesn't currently support the getservbyname functionality so
// we'll only check to see if they gave us a port number to convert
ServicePort = (u_short)MyStrToUl((char *)pServname, &pEnd);
ServicePort = htons(ServicePort);
}
if (Err)
goto Exit;
fIPv6 = IsIp6Running();
if (! pNodename) {
if ((PF_UNSPEC == ProtFamily || PF_INET6 == ProtFamily) && fIPv6) {
if (pAddr = GetAI(PF_INET6, SockType, Proto, &ppAddr)) {
pSin6 = (SOCKADDR_IN6 *)pAddr->ai_addr;
if (AI_PASSIVE & Flags) {
IN6ADDR_SETANY(pSin6);
} else {
IN6ADDR_SETLOOPBACK(pSin6);
}
pSin6->sin6_port = ServicePort;
} else {
Err = EAI_MEMORY;
goto Exit;
} // else if (pAddr = GetAI...)
} // if (PF_UNSPEC || PF_INET6)
if (PF_UNSPEC == ProtFamily || PF_INET == ProtFamily) {
if (pAddr = GetAI(PF_INET, SockType, Proto, &ppAddr)) {
pSin = (SOCKADDR_IN *)pAddr->ai_addr;
pSin->sin_family = AF_INET;
if (AI_PASSIVE & Flags)
pSin->sin_addr.s_addr = htonl(INADDR_ANY);
else
pSin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
pSin->sin_port = ServicePort;
} else {
Err = EAI_MEMORY;
goto Exit;
} // else if (pAddr = GetAI...)
} // if (PF_UNSPEC || PF_INET)
goto Exit;
} else {
cLen = strlen(pNodename) + 1;
if (256 < cLen) {
Err = EAI_FAIL;
goto Exit;
}
if (pwszNodename = LocalAlloc(LPTR, sizeof(WCHAR) * cLen)) {
if (! MultiByteToWideChar(CP_ACP, 0, pNodename, -1, pwszNodename, cLen)) {
Err = EAI_FAIL;
}
} else
Err = EAI_MEMORY;
if (Err)
goto Exit;
if ((PF_UNSPEC == ProtFamily || PF_INET6 == ProtFamily) && fIPv6) {
Sin6.sin6_family = AF_INET6;
cLen = sizeof(Sin6);
if (SOCKET_ERROR != WSAStringToAddress(pwszNodename,
AF_INET6, NULL, (SOCKADDR *)&Sin6, &cLen)) {
if (pAddr = GetAI(Sin6.sin6_family, SockType, Proto,&ppAddr)){
// WSAStringToAddress can parse the port string but we
// need to put braces around the name and concat the port
// string, and we've already parsed the port above
Sin6.sin6_port = ServicePort;
memcpy(pAddr->ai_addr, &Sin6, cLen);
pAddr->ai_flags |= AI_NUMERICHOST;
if (AI_CANONNAME & Flags) {
ASSERT(pAddr == *ppRes);
Err = CanonizeNumAddress(pAddr);
}
} else {
Err = EAI_MEMORY;
} // else if (pAddr = GetAI...)
goto Exit;
}
}
if (PF_UNSPEC == ProtFamily || PF_INET == ProtFamily) {
pSin = (SOCKADDR_IN *)&Sin6;
pSin->sin_family = AF_INET;
cLen = sizeof(*pSin);
if (SOCKET_ERROR != WSAStringToAddress(pwszNodename,
AF_INET, NULL, (SOCKADDR *)pSin, &cLen)) {
if (pAddr = GetAI(PF_INET, SockType, Proto, &ppAddr)) {
pSin->sin_port = ServicePort;
memcpy(pAddr->ai_addr, pSin, min(cLen,sizeof(*pSin)));
// do we need to clear the sin_zero???
pAddr->ai_flags |= AI_NUMERICHOST;
if (AI_CANONNAME & Flags) {
ASSERT(pAddr == *ppRes);
Err = CanonizeNumAddress(pAddr);
}
} else {
Err = EAI_MEMORY;
} // else if (pAddr = GetAI...)
goto Exit;
}
}
if (AI_NUMERICHOST & Flags) {
// if we're still here and this is set then we failed the
// WSAStringToAddress calls
Err = EAI_NONAME;
goto Exit;
}
// ok we now need to query for the address:
if (pResults = (PWSAQUERYSETW)LocalAlloc(LPTR, DEFAULT_QUERY_SIZE)) {
if (AI_CANONNAME & Flags)
ppSvcInstName = &pSvcInstName;
// for PF_UNSPEC we'll do queries for both v6 and v4
if (PF_UNSPEC == ProtFamily) {
if (fIPv6) {
// Use heap allocated memory for inter thread communication to avoid
// access problems when we are called from within a PSL.
pAsyncQuery = (PASYNC_QUERY)LocalAlloc(0,sizeof(ASYNC_QUERY));
if (pAsyncQuery == NULL) {
Err = EAI_MEMORY;
goto Exit;
}
pAsyncQuery->bRunning = FALSE;
pAsyncQuery->Err = 0;
pAsyncQuery->Flags = Flags;
pAsyncQuery->pwszNodename = pwszNodename;
pAsyncQuery->pwszSvcInstName = NULL;
pAsyncQuery->hThd = NULL;
if (EAI_MEMORY == PerformAsyncIPv6Query(pAsyncQuery)) {
if (pAsyncQuery->hThd) {
CloseHandle(pAsyncQuery->hThd);
pAsyncQuery->hThd = NULL;
}
pType = &Ipv6Guid;
Err = QueryName((char **)&pResults,
DEFAULT_QUERY_SIZE, pwszNodename, pType,
LUP_RETURN_ADDR | LUP_RETURN_NAME, NULL,
ppSvcInstName);
if (! Err) {
Err = ConvertToSockAddrList(pResults, PF_INET6, &pSAL);
if (! Err) {
ASSERT(pSAL);
SortV6Addrs(pSAL);
//ppOrigAI = ppRes;
Err = ConvertCSAddress(pSAL, PF_INET6,
SockType, Proto, ServicePort, &ppRes);
LocalFree(pSAL);
if ((AI_CANONNAME & Flags) && *ppSvcInstName) {
ASSERT(*ppSvcInstName = pSvcInstName);
CanonizeName(*ppOrigAI, pSvcInstName);
// only do this once to match XP even tho
// v4 and v6 queries may return differently
Flags &= ~AI_CANONNAME;
}
}
} else {
}
if (ppSvcInstName && *ppSvcInstName) {
LocalFree(*ppSvcInstName);
*ppSvcInstName = NULL;
}
}
}
ProtFamily = PF_INET;
pType = &InetHostName;
} else if ((PF_INET6 == ProtFamily) && fIPv6) {
pType = &Ipv6Guid;
ProtFamily = PF_INET6;
} else if (PF_INET == ProtFamily) {
// we only support these two Protocol families
ProtFamily = PF_INET;
pType = &InetHostName;
} else {
Err = EAI_FAMILY;
goto Exit;
}
memset(pResults, 0, DEFAULT_QUERY_SIZE);
Err = QueryName((char **)&pResults, DEFAULT_QUERY_SIZE,
pwszNodename, pType, LUP_RETURN_ADDR | LUP_RETURN_NAME, NULL,
ppSvcInstName);
if (pAsyncQuery && pAsyncQuery->bRunning) {
// Wait for IPv6 search thread before processing IPv4 results
if (pAsyncQuery->hThd) {
WaitForSingleObject(pAsyncQuery->hThd, INFINITE);
CloseHandle(pAsyncQuery->hThd);
if (! pAsyncQuery->Err) {
pAsyncQuery->Err = ConvertToSockAddrList(
pAsyncQuery->pResults, PF_INET6, &pSAL);
if (! pAsyncQuery->Err) {
ASSERT(pSAL);
SortV6Addrs(pSAL);
// ppOrigAI = ppRes;
pAsyncQuery->Err = ConvertCSAddress(pSAL, PF_INET6,
SockType, Proto, ServicePort, &ppRes);
LocalFree(pSAL);
if ((AI_CANONNAME & Flags) &&
pAsyncQuery->pwszSvcInstName) {
CanonizeName(*ppOrigAI, pAsyncQuery->pwszSvcInstName);
// only do this once to match XP even tho
// v4 and v6 queries may return differently
Flags &= ~AI_CANONNAME;
}
}
} else {
}
if (pAsyncQuery->pwszSvcInstName) {
LocalFree(pAsyncQuery->pwszSvcInstName);
pAsyncQuery->pwszSvcInstName = NULL;
}
}
if (pAsyncQuery->pResults) {
LocalFree(pAsyncQuery->pResults);
}
}
if (! Err) {
Err = ConvertToSockAddrList(pResults, ProtFamily, &pSAL);
if (! Err) {
ASSERT(pSAL);
if (fIPv6 && (PF_INET6 == ProtFamily))
SortV6Addrs(pSAL);
//ppOrigAI = ppRes;
Err = ConvertCSAddress(pSAL, ProtFamily,
SockType, Proto, ServicePort, &ppRes);
LocalFree(pSAL);
if ((AI_CANONNAME & Flags) && *ppSvcInstName) {
ASSERT(*ppSvcInstName = pSvcInstName);
CanonizeName(*ppOrigAI, pSvcInstName);
}
}
} else {
}
if (ppSvcInstName && *ppSvcInstName) {
LocalFree(*ppSvcInstName);
*ppSvcInstName = NULL;
}
} else { // if (pResults = LocalAlloc...)
Err = EAI_MEMORY;
}
}// else if (! pNodename)
Exit:
if (pwszNodename) {
LocalFree(pwszNodename);
}
// Return success if either query succeeded
if (((!pAsyncQuery || (FALSE == pAsyncQuery->bRunning)) && Err) ||
(pAsyncQuery && (TRUE == pAsyncQuery->bRunning) && Err && pAsyncQuery->Err)) {
if (ppRes) {
if (*ppRes) {
freeaddrinfo(*ppRes);
*ppRes = NULL;
}
}
// should we set last error?
SetLastError(Err);
} else {
Err = 0; // One of the protocols succeeded.
}
#if DEBUG
if (ppSvcInstName)
ASSERT(! (*ppSvcInstName));
#endif
if (pAsyncQuery) {
LocalFree(pAsyncQuery);
}
if (pResults) {
LocalFree(pResults);
}
return Err;
} // getaddrinfo()
int WSAAPI getnameinfo(
IN const struct sockaddr *pSAddr,
IN socklen_t cSAddr,
OUT char *pHost,
IN DWORD cHost,
OUT char *pServ,
IN DWORD cServ,
IN int Flags) {
int Err;
ushort Family, ServicePort;
WSAQUERYSETW *pResults;
WCHAR awszAddress[INET6_ADDRSTRLEN+2], *pwszAddr, *p;
DWORD cAddr;
pResults = NULL;
if (!pSAddr || (cSAddr < sizeof(*pSAddr))) {
// unfortunately the getnameinfo spec doesn't define this error code
// however XP is returning WSAEFAULT, so we will do the same
Err = WSAEFAULT;
} else if ((AF_INET != (Family = pSAddr->sa_family)) &&
AF_INET6 != pSAddr->sa_family) {
Err = EAI_FAMILY;
// no need to check AF_INET since it is same size as SOCKADDR
} else if (AF_INET6 == Family && cSAddr < sizeof(SOCKADDR_IN6)) {
// again no good error code defined in getnameinfo spec for this
Err = WSAEFAULT;
} else {
Err = 0;
ServicePort = ((SOCKADDR_IN *)pSAddr)->sin_port;
if (pServ) {
if (NI_NUMERICSERV & Flags) {
Err = MyShortToStr(htons(ServicePort), pServ, cServ);
} else {
// CE doesn't support the getservbyname functionality
Err = EAI_NODATA;
}
}
if ((! Err) && pHost) {
pwszAddr = awszAddress;
cAddr = sizeof(awszAddress);
// sin_port and sin6_port are in the same place
if (AF_INET == pSAddr->sa_family || AF_INET6 == pSAddr->sa_family)
((SOCKADDR_IN *)pSAddr)->sin_port = 0;
Err = WSAAddressToString((SOCKADDR *)pSAddr, cSAddr, NULL,
pwszAddr, &cAddr);
((SOCKADDR_IN *)pSAddr)->sin_port = ServicePort;
if (Err) {
Err = EAI_FAIL;
} else if (! (NI_NUMERICHOST & Flags)) {
// we don't yet do reverse ipv6 queries--our servers also
// just redirect it anyway...
if (AF_INET6 == pSAddr->sa_family) {
if (IN6ADDR_ISLOOPBACK((struct sockaddr_in6 *)pSAddr)) {
if (cHost < 10) {
Err = EAI_MEMORY;
} else {
memcpy(pHost, "localhost", cHost);
}
} else {
Err = EAI_NODATA;
}
goto Exit;
}
if (pResults = (WSAQUERYSETW *)
LocalAlloc(LPTR, DEFAULT_QUERY_SIZE)) {
if (Err = QueryName((char **)&pResults, DEFAULT_QUERY_SIZE,
pwszAddr, &AddressGuid, LUP_RETURN_NAME, NULL, NULL)) {
if (NI_NAMEREQD & Flags) {
DEBUGMSG(ZONE_WARN,
(TEXT("getnameinfo: NameQuery failed Err = %d\r\n"),
Err));
Err = EAI_FAIL;
}
// otherwise we fall on thru to numeric case.
} else {
pwszAddr = pResults->lpszServiceInstanceName;
// fall thru...
}
} else { // if (pResults = LocalAlloc...)
Err = EAI_MEMORY;
}
}
// we're almost done
if (! Err) {
if ((NI_NOFQDN & Flags) && !(NI_NUMERICHOST & Flags)) {
p = pwszAddr;
while (TEXT('\0') != *p) {
if (TEXT('.') == *p)
*p = TEXT('\0');
else
p++;
}
}
if (! WideCharToMultiByte(CP_UTF8, 0, pwszAddr, -1, pHost, cHost, NULL, NULL)) {
if (! WideCharToMultiByte(CP_ACP, 0, pwszAddr, -1, pHost, cHost, NULL, NULL)) {
DEBUGMSG(ZONE_WARN,
(TEXT("getnameinfo: WideCharToMB failed = %d\r\n"),
GetLastError()));
Err = EAI_MEMORY;
}
}
}
if (pResults)
LocalFree(pResults);
} // if (pHost)
}
Exit:
if (Err) {
SetLastError(Err);
}
return Err;
} // getnameinfo()
void WSAAPI freeaddrinfo(
IN struct addrinfo *pAi) {
struct addrinfo *pDel;
while (pDel = pAi) {
pAi = pAi->ai_next;
if (pDel->ai_addr)
LocalFree(pDel->ai_addr);
if (pDel->ai_canonname)
LocalFree(pDel->ai_canonname);
LocalFree(pDel);
}
} // freeaddrinfo()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -