mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
253 lines
5.9 KiB
253 lines
5.9 KiB
/*
|
|
Enhanced NCSA Mosaic from Spyglass
|
|
"Guitar"
|
|
|
|
Copyright 1994 Spyglass, Inc.
|
|
All Rights Reserved
|
|
|
|
Author(s):
|
|
Jim Seidman [email protected]
|
|
|
|
*/
|
|
|
|
#include "all.h"
|
|
|
|
PRIVATE char *hostname = "localhost"; /* The name of this host */
|
|
|
|
#define HOST_CACHE_SIZE 10
|
|
/* Cache for keeping track of the last few hosts */
|
|
static struct {
|
|
char hostname[128 + 1];
|
|
struct MultiAddress address;
|
|
time_t lastused;
|
|
} cache[HOST_CACHE_SIZE];
|
|
static BOOL bNetCacheInit = FALSE;
|
|
|
|
/* Report Internet Error
|
|
** ---------------------
|
|
*/
|
|
PUBLIC int HTInetStatus(char *where)
|
|
{
|
|
#ifdef WIN32
|
|
strerror(errno);
|
|
XX_DMsg(DBG_LOAD, ("errno = %d (WinSock: %d) after call to %s failed.\n%s\n", errno, WS_WSAGETLASTERROR(), where, strerror(errno)));
|
|
#endif
|
|
|
|
return -errno;
|
|
}
|
|
|
|
|
|
PUBLIC const char *HTHostName(void)
|
|
{
|
|
return hostname;
|
|
}
|
|
|
|
#define STATE_PARSE_DIDLOOKUP (STATE_OTHER)
|
|
int Net_MultiParse_Async(struct Mwin *tw, int nState, void **ppInfo)
|
|
{
|
|
struct Params_MultiParseInet *pParams;
|
|
int n;
|
|
struct MultiAddress *pAddress;
|
|
char buf[1024];
|
|
char *port;
|
|
struct Params_MultiGetHostByName *pghbn;
|
|
unsigned long addr;
|
|
|
|
pParams = *ppInfo;
|
|
|
|
switch (nState)
|
|
{
|
|
case STATE_INIT:
|
|
pParams->request = HTRequest_validate(pParams->request);
|
|
if (!pParams->str || !pParams->str[0])
|
|
{
|
|
*pParams->pStatus = -1;
|
|
return STATE_DONE;
|
|
}
|
|
|
|
strncpy(pParams->host, pParams->str, sizeof(pParams->host)); /* Take a copy we can mutilate */
|
|
|
|
/* Parse port number if present */
|
|
if ((port = strchr(pParams->host, ':')))
|
|
{
|
|
*port++ = 0; /* Chop off port */
|
|
if (port[0] >= '0' && port[0] <= '9')
|
|
{
|
|
*pParams->pPort = (unsigned short) WS_HTONS((unsigned short) strtol(port, (char **) 0, 10));
|
|
}
|
|
}
|
|
|
|
addr = WS_INET_ADDR(pParams->host);
|
|
if (addr != 0xffffffff)
|
|
{
|
|
/* Numeric node address: */
|
|
pParams->pAddress->aAddrs[0] = addr;
|
|
pParams->pAddress->nCount = 1;
|
|
pParams->pAddress->nLastUsed = 0;
|
|
*pParams->pStatus = 0;
|
|
return STATE_DONE;
|
|
}
|
|
else
|
|
{
|
|
pAddress = NULL;
|
|
|
|
#ifdef FEATURE_NO_DNS_CACHE
|
|
if (gPrefs.bUseDNSCache)
|
|
{
|
|
#endif
|
|
/* Alphanumeric node name: */
|
|
if (!bNetCacheInit)
|
|
{
|
|
memset(cache, 0, sizeof(cache));
|
|
bNetCacheInit = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* See if this host is present in the cache */
|
|
for (n = 0; n < HOST_CACHE_SIZE; n++)
|
|
{
|
|
if (!GTR_strcmpi(cache[n].hostname, pParams->host))
|
|
{
|
|
pAddress = &cache[n].address;
|
|
cache[n].lastused = time(NULL);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (pAddress)
|
|
{
|
|
memcpy(pParams->pAddress, &cache[n].address, sizeof(struct MultiAddress));
|
|
*pParams->pStatus = 0;
|
|
return STATE_DONE;
|
|
}
|
|
#ifdef FEATURE_NO_DNS_CACHE
|
|
}
|
|
#endif
|
|
/* If we got here, we actually have to go out on the network
|
|
to retrieve the address */
|
|
pghbn = GTR_MALLOC(sizeof(*pghbn));
|
|
|
|
GTR_formatmsg(RES_STRING_FINDADDR,buf,sizeof(buf),pParams->host);
|
|
WAIT_Push(tw, waitSameInteract, buf);
|
|
WAIT_SetStatusBarIcon( tw, SBI_FindingIcon );
|
|
|
|
pghbn->szHost = pParams->host;
|
|
pghbn->pDest = pParams->pAddress;
|
|
pghbn->pStatus = pParams->pStatus;
|
|
Async_DoCall(Net_MultiGetHostByName_Async, pghbn);
|
|
return STATE_PARSE_DIDLOOKUP;
|
|
}
|
|
|
|
case STATE_PARSE_DIDLOOKUP:
|
|
WAIT_Pop(tw);
|
|
if (*pParams->pStatus < 0)
|
|
{
|
|
/* The lookup failed */
|
|
ERR_InternalReportError(tw, errHostNotFound, pParams->host, NULL, pParams->request,NULL,NULL);
|
|
return STATE_DONE;
|
|
}
|
|
else if (*pParams->pStatus == HT_REDIRECTION_DCACHE_TIMEOUT)
|
|
{
|
|
PSTR psz;
|
|
|
|
/* Don't put up an error if request is in dcache */
|
|
if (!(psz = PszGetDCachePath(pParams->request->destination->szActualURL, NULL, NULL)))
|
|
{
|
|
/* request not in cache, error out */
|
|
*pParams->pStatus = -1;
|
|
ERR_InternalReportError(tw, errHostNotFound, pParams->host, NULL, pParams->request,NULL,NULL);
|
|
}
|
|
else
|
|
GTR_FREE(psz);
|
|
return STATE_DONE;
|
|
}
|
|
else
|
|
{
|
|
int oldest;
|
|
time_t date;
|
|
|
|
#ifdef FEATURE_NO_DNS_CACHE
|
|
if (gPrefs.bUseDNSCache)
|
|
{
|
|
#endif
|
|
/* Store it in the cache for later */
|
|
date = cache[0].lastused;
|
|
oldest = 0;
|
|
for (n = 1; n < HOST_CACHE_SIZE; n++)
|
|
{
|
|
if (cache[n].lastused < date)
|
|
{
|
|
date = cache[n].lastused;
|
|
oldest = n;
|
|
}
|
|
}
|
|
memcpy(&cache[oldest].address, pParams->pAddress, sizeof(struct MultiAddress));
|
|
strcpy(cache[oldest].hostname, pParams->host);
|
|
cache[oldest].lastused = time(NULL);
|
|
#ifdef FEATURE_NO_DNS_CACHE
|
|
}
|
|
#endif
|
|
return STATE_DONE;
|
|
}
|
|
|
|
case STATE_ABORT:
|
|
pParams->request = HTRequest_validate(pParams->request);
|
|
if (tw) WAIT_Pop(tw);
|
|
*pParams->pStatus = -1;
|
|
return STATE_DONE;
|
|
}
|
|
XX_Assert((0), ("Function called with illegal state: %d", nState));
|
|
return STATE_DONE;
|
|
}
|
|
|
|
void Net_UpdateCache(struct MultiAddress *pAddress)
|
|
{
|
|
int n;
|
|
unsigned long sample;
|
|
|
|
#ifdef FEATURE_NO_DNS_CACHE
|
|
if (gPrefs.bUseDNSCache)
|
|
{
|
|
#endif
|
|
XX_Assert((bNetCacheInit), ("Address cache not initialized!"));
|
|
|
|
/* To find this entry in the cache we just take a sample from
|
|
the address and search for that. We can't assume that the
|
|
values will be in the same order as they are in the cache,
|
|
since this item may have fallen out of the cache and then
|
|
back in. */
|
|
sample = pAddress->aAddrs[0];
|
|
for (n = 0; n < HOST_CACHE_SIZE; n++)
|
|
{
|
|
if (Net_CompareAddresses(sample, &cache[n].address))
|
|
{
|
|
/* We need to copy over the whole thing instead of just
|
|
copying nLastUsed since the items might be in a
|
|
different order */
|
|
memcpy(&cache[n].address, pAddress, sizeof(*pAddress));
|
|
cache[n].lastused = time(NULL);
|
|
break;
|
|
}
|
|
}
|
|
#ifdef FEATURE_NO_DNS_CACHE
|
|
}
|
|
#endif
|
|
}
|
|
|
|
BOOL Net_CompareAddresses(unsigned long single, struct MultiAddress *pMulti)
|
|
{
|
|
int n;
|
|
BOOL bResult;
|
|
|
|
bResult = FALSE;
|
|
|
|
for (n = 0; n < pMulti->nCount; n++)
|
|
{
|
|
if (pMulti->aAddrs[n] == single)
|
|
{
|
|
bResult = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
return bResult;
|
|
}
|