The DNS Service is now used for hostname resolution...

This commit is contained in:
rpotts%netscape.com 1999-09-12 05:29:27 +00:00
Родитель 15a7c62d99
Коммит 0e5b738fa2
5 изменённых файлов: 197 добавлений и 89 удалений

Просмотреть файл

@ -37,6 +37,7 @@
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kSocketProviderService, NS_SOCKETPROVIDERSERVICE_CID);
static NS_DEFINE_CID(kDNSService, NS_DNSSERVICE_CID);
//
@ -144,11 +145,13 @@ nsSocketTransport::nsSocketTransport()
mService = nsnull;
mLoadAttributes = LOAD_NORMAL;
mStatus = NS_OK;
//
// Set up Internet defaults...
//
memset(&mNetAddress, 0, sizeof(mNetAddress));
PR_InitializeNetAddr(PR_IpAddrNull, 0, &mNetAddress);
PR_InitializeNetAddr(PR_IpAddrNull, 0, &mNetAddress);
//
// Initialize the global connect timeout value if necessary...
@ -203,7 +206,14 @@ nsSocketTransport::~nsSocketTransport()
mWritePipeIn = null_nsCOMPtr();
mWritePipeOut = null_nsCOMPtr();
#endif
//
// Cancel any pending DNS request...
//
if (mDNSRequest) {
mDNSRequest->Cancel();
}
mDNSRequest = null_nsCOMPtr();
NS_IF_RELEASE(mService);
if (mHostName) {
@ -277,7 +287,6 @@ nsresult nsSocketTransport::Init(nsSocketTransportService* aService,
nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
{
nsresult rv = NS_OK;
PRBool done = PR_FALSE;
//
@ -299,8 +308,7 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
PR_LOG(gSocketLog, PR_LOG_ERROR,
("Operation failed via PR_POLL_EXCEPT. [this=%x].\n", this));
// An error has occurred, so cancel the read and/or write operation...
mCurrentState = eSocketState_Error;
rv = NS_BINDING_FAILED;
mStatus = NS_BINDING_FAILED;
}
while (!done)
@ -314,7 +322,7 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
("Transport [this=%x] is suspended.\n", this));
done = PR_TRUE;
rv = NS_OK;
mStatus = NS_OK;
continue;
}
@ -322,12 +330,15 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
PR_LOG(gSocketLog, PR_LOG_DEBUG,
("Transport [this=%x] has been cancelled.\n", this));
// Cancel any read and/or write requests...
SetFlag(eSocketRead_Done);
SetFlag(eSocketWrite_Done);
mCurrentState = eSocketState_Done;
mCancelOperation = PR_FALSE;
mStatus = NS_BINDING_ABORTED;
}
rv = NS_BINDING_ABORTED;
//
// If an error has occurred then move into the error state...
//
if (NS_FAILED(mStatus) && (NS_BASE_STREAM_WOULD_BLOCK != mStatus)) {
mCurrentState = eSocketState_Error;
}
switch (mCurrentState) {
@ -364,6 +375,12 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
PR_LOG(gSocketLog, PR_LOG_DEBUG,
("Transport [this=%x] is in error state.\n", this));
// Cancel any DNS requests...
if (mDNSRequest) {
mDNSRequest->Cancel();
mDNSRequest = null_nsCOMPtr();
}
// Cancel any read and/or write requests...
SetFlag(eSocketRead_Done);
SetFlag(eSocketWrite_Done);
@ -379,7 +396,7 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
if (GetFlag(eSocketRead_Done)) {
// Fire a notification that the read has finished...
if (mReadListener) {
mReadListener->OnStopRequest(this, mReadContext, rv, nsnull);
mReadListener->OnStopRequest(this, mReadContext, mStatus, nsnull);
mReadListener = null_nsCOMPtr();
mReadContext = null_nsCOMPtr();
}
@ -398,7 +415,7 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
if (GetFlag(eSocketWrite_Done)) {
// Fire a notification that the write has finished...
if (mWriteObserver) {
mWriteObserver->OnStopRequest(this, mWriteContext, rv, nsnull);
mWriteObserver->OnStopRequest(this, mWriteContext, mStatus, nsnull);
mWriteObserver = null_nsCOMPtr();
mWriteContext = null_nsCOMPtr();
}
@ -421,6 +438,7 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
{
mCurrentState = gStateTable[mOperation][mCurrentState];
mOperation = eSocketOperation_None;
mStatus = NS_OK;
done = PR_TRUE;
} else {
// Still reading or writing...
@ -429,27 +447,27 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
continue;
case eSocketState_WaitDNS:
rv = doResolveHost();
mStatus = doResolveHost();
break;
case eSocketState_WaitConnect:
rv = doConnection(aSelectFlags);
mStatus = doConnection(aSelectFlags);
break;
case eSocketState_WaitReadWrite:
// Process the read request...
if (GetReadType() != eSocketRead_None) {
rv = doRead(aSelectFlags);
if (NS_OK == rv) {
mStatus = doRead(aSelectFlags);
if (NS_OK == mStatus) {
SetFlag(eSocketRead_Done);
break;
}
}
// Process the write request...
if ((NS_SUCCEEDED(rv) || rv == NS_BASE_STREAM_WOULD_BLOCK)
if ((NS_SUCCEEDED(mStatus) || mStatus == NS_BASE_STREAM_WOULD_BLOCK)
&& (GetWriteType() != eSocketWrite_None)) {
rv = doWrite(aSelectFlags);
if (NS_OK == rv) {
mStatus = doWrite(aSelectFlags);
if (NS_OK == mStatus) {
SetFlag(eSocketWrite_Done);
break;
}
@ -458,27 +476,25 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
case eSocketState_Timeout:
NS_ASSERTION(0, "Unexpected state...");
rv = NS_ERROR_FAILURE;
mStatus = NS_ERROR_FAILURE;
break;
default:
NS_ASSERTION(0, "Unexpected state...");
rv = NS_ERROR_FAILURE;
mStatus = NS_ERROR_FAILURE;
break;
}
//
// If the current state has successfully completed, then move to the
// next state for the current operation...
//
if (NS_OK == rv) {
if (NS_OK == mStatus) {
mCurrentState = gStateTable[mOperation][mCurrentState];
}
else if (NS_BASE_STREAM_WOULD_BLOCK == rv) {
else if (NS_BASE_STREAM_WOULD_BLOCK == mStatus) {
done = PR_TRUE;
}
else if (NS_FAILED(rv)) {
mCurrentState = eSocketState_Error;
}
//
// Any select flags are *only* valid the first time through the loop...
//
@ -486,12 +502,12 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
}
PR_LOG(gSocketLog, PR_LOG_DEBUG,
("--- Leaving nsSocketTransport::Process() [this=%x]. rv = %x.\t"
("--- Leaving nsSocketTransport::Process() [this=%x]. mStatus = %x.\t"
"CurrentState = %d\n\n",
this, rv, mCurrentState));
this, mStatus, mCurrentState));
PR_Unlock(mLock);
return rv;
return mStatus;
}
@ -510,7 +526,6 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
//-----
nsresult nsSocketTransport::doResolveHost(void)
{
PRStatus status;
nsresult rv = NS_OK;
NS_ASSERTION(eSocketState_WaitDNS == mCurrentState, "Wrong state.");
@ -520,57 +535,32 @@ nsresult nsSocketTransport::doResolveHost(void)
this));
//
// Initialize the port used for the connection...
// The hostname has not been resolved yet...
//
// XXX: The list of ports must be restricted - see net_bad_ports_table[] in
// mozilla/network/main/mkconect.c
//
mNetAddress.inet.port = PR_htons(mPort);
if (! mNetAddress.inet.ip) {
//
// Initialize the port used for the connection...
//
// XXX: The list of ports must be restricted - see net_bad_ports_table[] in
// mozilla/network/main/mkconect.c
//
mNetAddress.inet.port = PR_htons(mPort);
//
// Resolve the address of the given host...
//
char dbbuf[PR_NETDB_BUF_SIZE];
PRHostEnt hostEnt;
PRBool numeric = PR_TRUE;
for (char *hostCheck = mHostName; *hostCheck; hostCheck++) {
if (!nsString2::IsDigit(*hostCheck) && (*hostCheck != '.') ) {
numeric = PR_FALSE;
break;
}
}
if (numeric) {
PRNetAddr *netAddr = (PRNetAddr*)nsAllocator::Alloc(sizeof(PRNetAddr));
status = PR_StringToNetAddr(mHostName, netAddr);
if (PR_SUCCESS != status) {
rv = NS_ERROR_UNKNOWN_HOST; // check this!
}
status = PR_GetHostByAddr(netAddr, dbbuf, sizeof(dbbuf), &hostEnt);
nsAllocator::Free(netAddr);
} else {
status = PR_GetHostByName(mHostName, dbbuf, sizeof(dbbuf), &hostEnt);
}
if (PR_SUCCESS == status) {
if (hostEnt.h_addr_list) {
memcpy(&mNetAddress.inet.ip, hostEnt.h_addr_list[0],
sizeof(mNetAddress.inet.ip));
} else {
// XXX: What should happen here? The GetHostByName(...) succeeded but
// there are *no* A records...
NS_WITH_SERVICE(nsIDNSService,
pDNSService,
kDNSService,
&rv);
if (NS_FAILED(rv)) return rv;
rv = pDNSService->Lookup(nsnull, mHostName, this,
getter_AddRefs(mDNSRequest));
//
// The DNS lookup is being processed... Mark the transport as waiting
// until the result is available...
//
// XXX: What should this result code be??
if (NS_BASE_STREAM_WOULD_BLOCK == rv) {
SetFlag(eSocketDNS_Wait);
}
PR_LOG(gSocketLog, PR_LOG_DEBUG,
("Host name resolved [this=%x]. Name is %s\n", this, mHostName));
}
// DNS lookup failed...
else {
PR_LOG(gSocketLog, PR_LOG_ERROR,
("Host name resolution FAILURE [this=%x].\n", this));
rv = NS_ERROR_UNKNOWN_HOST;
}
PR_LOG(gSocketLog, PR_LOG_DEBUG,
@ -1158,6 +1148,11 @@ nsSocketTransport::QueryInterface(const nsIID& aIID, void* *aInstancePtr)
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIDNSListener))) {
*aInstancePtr = NS_STATIC_CAST(nsIDNSListener*, this);
NS_ADDREF_THIS();
return NS_OK;
}
#ifndef NSPIPE2
if (aIID.Equals(NS_GET_IID(nsIBufferObserver))) {
*aInstancePtr = NS_STATIC_CAST(nsIBufferObserver*, this);
@ -1397,6 +1392,72 @@ nsSocketTransport::OnEmpty(nsIPipe* aPipe)
}
//
// --------------------------------------------------------------------------
// nsIDNSListener implementation...
// --------------------------------------------------------------------------
//
NS_IMETHODIMP
nsSocketTransport::OnStartLookup(nsISupports *aContext, const char *aHostName)
{
PR_LOG(gSocketLog, PR_LOG_DEBUG,
("nsSocketTransport::OnStartLookup(...) [this=%x]. Host is %s\n",
this, aHostName));
return NS_OK;
}
NS_IMETHODIMP
nsSocketTransport::OnFound(nsISupports *aContext,
const char* aHostName,
nsHostEnt *aHostEnt)
{
PR_LOG(gSocketLog, PR_LOG_DEBUG,
("nsSocketTransport::OnFound(...) [this=%x]."
" DNS lookup for %s succeeded.\n",
this, aHostName));
//
// XXX: What thread are we on??
//
if (aHostEnt->hostEnt.h_addr_list) {
memcpy(&mNetAddress.inet.ip, aHostEnt->hostEnt.h_addr_list[0],
sizeof(mNetAddress.inet.ip));
} else {
// XXX: What should happen here? The GetHostByName(...) succeeded but
// there are *no* A records...
}
return NS_OK;
}
NS_IMETHODIMP
nsSocketTransport::OnStopLookup(nsISupports *aContext,
const char *aHostName,
nsresult aStatus)
{
PR_LOG(gSocketLog, PR_LOG_DEBUG,
("nsSocketTransport::OnStopLookup(...) [this=%x]. Status = %x Host is %s\n",
this, aStatus, aHostName));
//
// XXX: What thread are we on??
//
// Release our reference to the DNS Request...
mDNSRequest = null_nsCOMPtr();
if (GetFlag(eSocketDNS_Wait)) {
// Enter the socket transport lock...
nsAutoLock aLock(mLock);
ClearFlag(eSocketDNS_Wait);
mStatus = aStatus;
mService->AddToWorkQ(this);
}
return NS_OK;
}
//
// --------------------------------------------------------------------------
// nsIChannel implementation...

Просмотреть файл

@ -32,6 +32,7 @@
#include "nsIBufferOutputStream.h"
#include "nsIEventQueueService.h"
#include "nsIStreamListener.h"
#include "nsIDNSListener.h"
#ifndef NSPIPE2
#include "nsIBuffer.h"
#else
@ -105,13 +106,16 @@ enum nsSocketReadWriteInfo {
eSocketWrite_Done = 0x1000,
eSocketWrite_Wait = 0x2000,
eSocketWrite_Type_Mask = 0x0F00,
eSocketWrite_Flag_Mask = 0xF000
eSocketWrite_Flag_Mask = 0xF000,
eSocketDNS_Wait = 0x2020
};
// Forward declarations...
class nsSocketTransportService;
class nsSocketTransport : public nsIChannel,
public nsIDNSListener,
#ifndef NSPIPE2
public nsIBufferObserver
#else
@ -138,6 +142,9 @@ public:
NS_DECL_NSIPIPEOBSERVER
#endif
// nsIDNSListener methods:
NS_DECL_NSIDNSLISTENER
// nsSocketTransport methods:
nsSocketTransport();
virtual ~nsSocketTransport();
@ -237,6 +244,9 @@ protected:
nsSocketTransportService* mService;
PRUint32 mLoadAttributes;
nsCOMPtr<nsIRequest> mDNSRequest;
nsresult mStatus;
nsCOMPtr<nsISupports> mOwner;
};

Просмотреть файл

@ -226,6 +226,11 @@ nsresult nsSocketTransportService::ProcessWorkQ(void)
transport = nsSocketTransport::GetInstance(qp);
PR_REMOVE_AND_INIT_LINK(qp);
//
// Make sure that the transport is not already on the select list.
// It will be added (if necessary) after Process() is called...
//
RemoveFromSelectList(transport);
// Try to perform the operation...
//

Просмотреть файл

@ -47,6 +47,6 @@ interface nsIDNSListener : nsISupports
/**
* Notify the listener that we the lookup has completed.
*/
void OnStopLookup(in nsISupports ctxt, in string hostname);
void OnStopLookup(in nsISupports ctxt, in string hostname, in nsresult status);
};

Просмотреть файл

@ -21,6 +21,7 @@
#include "nsIRequest.h"
#include "prnetdb.h"
#include "nsString2.h"
////////////////////////////////////////////////////////////////////////////////
@ -111,7 +112,7 @@ nsDNSService::Lookup(nsISupports* ctxt,
nsIDNSListener* listener,
nsIRequest* *DNSRequest)
{
nsresult rv;
nsresult rv, result;
PRStatus status;
nsHostEnt* hostentry;
/*
@ -137,21 +138,52 @@ nsDNSService::Lookup(nsISupports* ctxt,
*/
// temporary SYNC version
result = NS_OK;
hostentry = new nsHostEnt;
if (!hostentry)
return NS_ERROR_OUT_OF_MEMORY;
rv = listener->OnStartLookup(ctxt, hostname);
status = PR_GetHostByName(hostname, hostentry->buffer, PR_NETDB_BUF_SIZE, &hostentry->hostEnt);
PRBool numeric = PR_TRUE;
for (char *hostCheck = mHostName; *hostCheck; hostCheck++) {
if (!nsString2::IsDigit(*hostCheck) && (*hostCheck != '.') ) {
numeric = PR_FALSE;
break;
}
}
if (numeric) {
PRNetAddr *netAddr = (PRNetAddr*)nsAllocator::Alloc(sizeof(PRNetAddr));
status = PR_StringToNetAddr(hostname, netAddr);
if (PR_SUCCESS != status) {
result = NS_ERROR_UNKNOWN_HOST; // check this!
}
status = PR_GetHostByAddr(netAddr,
hostentry->buffer,
PR_NETDB_BUF_SIZE,
&hostentry->hostEnt);
nsAllocator::Free(netAddr);
} else {
status = PR_GetHostByName(hostname,
hostentry->buffer,
PR_NETDB_BUF_SIZE,
&hostentry->hostEnt);
}
if (PR_SUCCESS == status)
rv = listener->OnFound(ctxt, hostname, hostentry); // turn ownership of hostentry over to listener?
else
delete hostentry;
if (PR_SUCCESS == status) {
rv = listener->OnFound(ctxt, hostname, hostentry);
result = NS_OK;
}
else {
result = NS_ERROR_UNKNOWN_HOST;
}
// XXX: The hostentry should really be reference counted so the
// listener does not need to copy it...
delete hostentry;
rv = listener->OnStopLookup(ctxt, hostname);
rv = listener->OnStopLookup(ctxt, hostname, result);
return NS_OK;
}