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(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kSocketProviderService, NS_SOCKETPROVIDERSERVICE_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; mService = nsnull;
mLoadAttributes = LOAD_NORMAL; mLoadAttributes = LOAD_NORMAL;
mStatus = NS_OK;
// //
// Set up Internet defaults... // Set up Internet defaults...
// //
memset(&mNetAddress, 0, sizeof(mNetAddress)); 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... // Initialize the global connect timeout value if necessary...
@ -203,7 +206,14 @@ nsSocketTransport::~nsSocketTransport()
mWritePipeIn = null_nsCOMPtr(); mWritePipeIn = null_nsCOMPtr();
mWritePipeOut = null_nsCOMPtr(); mWritePipeOut = null_nsCOMPtr();
#endif #endif
//
// Cancel any pending DNS request...
//
if (mDNSRequest) {
mDNSRequest->Cancel();
}
mDNSRequest = null_nsCOMPtr();
NS_IF_RELEASE(mService); NS_IF_RELEASE(mService);
if (mHostName) { if (mHostName) {
@ -277,7 +287,6 @@ nsresult nsSocketTransport::Init(nsSocketTransportService* aService,
nsresult nsSocketTransport::Process(PRInt16 aSelectFlags) nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
{ {
nsresult rv = NS_OK;
PRBool done = PR_FALSE; PRBool done = PR_FALSE;
// //
@ -299,8 +308,7 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
PR_LOG(gSocketLog, PR_LOG_ERROR, PR_LOG(gSocketLog, PR_LOG_ERROR,
("Operation failed via PR_POLL_EXCEPT. [this=%x].\n", this)); ("Operation failed via PR_POLL_EXCEPT. [this=%x].\n", this));
// An error has occurred, so cancel the read and/or write operation... // An error has occurred, so cancel the read and/or write operation...
mCurrentState = eSocketState_Error; mStatus = NS_BINDING_FAILED;
rv = NS_BINDING_FAILED;
} }
while (!done) while (!done)
@ -314,7 +322,7 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
("Transport [this=%x] is suspended.\n", this)); ("Transport [this=%x] is suspended.\n", this));
done = PR_TRUE; done = PR_TRUE;
rv = NS_OK; mStatus = NS_OK;
continue; continue;
} }
@ -322,12 +330,15 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
PR_LOG(gSocketLog, PR_LOG_DEBUG, PR_LOG(gSocketLog, PR_LOG_DEBUG,
("Transport [this=%x] has been cancelled.\n", this)); ("Transport [this=%x] has been cancelled.\n", this));
// Cancel any read and/or write requests... mCancelOperation = PR_FALSE;
SetFlag(eSocketRead_Done); mStatus = NS_BINDING_ABORTED;
SetFlag(eSocketWrite_Done); }
mCurrentState = eSocketState_Done;
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) { switch (mCurrentState) {
@ -364,6 +375,12 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
PR_LOG(gSocketLog, PR_LOG_DEBUG, PR_LOG(gSocketLog, PR_LOG_DEBUG,
("Transport [this=%x] is in error state.\n", this)); ("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... // Cancel any read and/or write requests...
SetFlag(eSocketRead_Done); SetFlag(eSocketRead_Done);
SetFlag(eSocketWrite_Done); SetFlag(eSocketWrite_Done);
@ -379,7 +396,7 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
if (GetFlag(eSocketRead_Done)) { if (GetFlag(eSocketRead_Done)) {
// Fire a notification that the read has finished... // Fire a notification that the read has finished...
if (mReadListener) { if (mReadListener) {
mReadListener->OnStopRequest(this, mReadContext, rv, nsnull); mReadListener->OnStopRequest(this, mReadContext, mStatus, nsnull);
mReadListener = null_nsCOMPtr(); mReadListener = null_nsCOMPtr();
mReadContext = null_nsCOMPtr(); mReadContext = null_nsCOMPtr();
} }
@ -398,7 +415,7 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
if (GetFlag(eSocketWrite_Done)) { if (GetFlag(eSocketWrite_Done)) {
// Fire a notification that the write has finished... // Fire a notification that the write has finished...
if (mWriteObserver) { if (mWriteObserver) {
mWriteObserver->OnStopRequest(this, mWriteContext, rv, nsnull); mWriteObserver->OnStopRequest(this, mWriteContext, mStatus, nsnull);
mWriteObserver = null_nsCOMPtr(); mWriteObserver = null_nsCOMPtr();
mWriteContext = null_nsCOMPtr(); mWriteContext = null_nsCOMPtr();
} }
@ -421,6 +438,7 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
{ {
mCurrentState = gStateTable[mOperation][mCurrentState]; mCurrentState = gStateTable[mOperation][mCurrentState];
mOperation = eSocketOperation_None; mOperation = eSocketOperation_None;
mStatus = NS_OK;
done = PR_TRUE; done = PR_TRUE;
} else { } else {
// Still reading or writing... // Still reading or writing...
@ -429,27 +447,27 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
continue; continue;
case eSocketState_WaitDNS: case eSocketState_WaitDNS:
rv = doResolveHost(); mStatus = doResolveHost();
break; break;
case eSocketState_WaitConnect: case eSocketState_WaitConnect:
rv = doConnection(aSelectFlags); mStatus = doConnection(aSelectFlags);
break; break;
case eSocketState_WaitReadWrite: case eSocketState_WaitReadWrite:
// Process the read request... // Process the read request...
if (GetReadType() != eSocketRead_None) { if (GetReadType() != eSocketRead_None) {
rv = doRead(aSelectFlags); mStatus = doRead(aSelectFlags);
if (NS_OK == rv) { if (NS_OK == mStatus) {
SetFlag(eSocketRead_Done); SetFlag(eSocketRead_Done);
break; break;
} }
} }
// Process the write request... // 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)) { && (GetWriteType() != eSocketWrite_None)) {
rv = doWrite(aSelectFlags); mStatus = doWrite(aSelectFlags);
if (NS_OK == rv) { if (NS_OK == mStatus) {
SetFlag(eSocketWrite_Done); SetFlag(eSocketWrite_Done);
break; break;
} }
@ -458,27 +476,25 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
case eSocketState_Timeout: case eSocketState_Timeout:
NS_ASSERTION(0, "Unexpected state..."); NS_ASSERTION(0, "Unexpected state...");
rv = NS_ERROR_FAILURE; mStatus = NS_ERROR_FAILURE;
break; break;
default: default:
NS_ASSERTION(0, "Unexpected state..."); NS_ASSERTION(0, "Unexpected state...");
rv = NS_ERROR_FAILURE; mStatus = NS_ERROR_FAILURE;
break; break;
} }
// //
// If the current state has successfully completed, then move to the // If the current state has successfully completed, then move to the
// next state for the current operation... // next state for the current operation...
// //
if (NS_OK == rv) { if (NS_OK == mStatus) {
mCurrentState = gStateTable[mOperation][mCurrentState]; mCurrentState = gStateTable[mOperation][mCurrentState];
} }
else if (NS_BASE_STREAM_WOULD_BLOCK == rv) { else if (NS_BASE_STREAM_WOULD_BLOCK == mStatus) {
done = PR_TRUE; done = PR_TRUE;
} }
else if (NS_FAILED(rv)) {
mCurrentState = eSocketState_Error;
}
// //
// Any select flags are *only* valid the first time through the loop... // 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, 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", "CurrentState = %d\n\n",
this, rv, mCurrentState)); this, mStatus, mCurrentState));
PR_Unlock(mLock); PR_Unlock(mLock);
return rv; return mStatus;
} }
@ -510,7 +526,6 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
//----- //-----
nsresult nsSocketTransport::doResolveHost(void) nsresult nsSocketTransport::doResolveHost(void)
{ {
PRStatus status;
nsresult rv = NS_OK; nsresult rv = NS_OK;
NS_ASSERTION(eSocketState_WaitDNS == mCurrentState, "Wrong state."); NS_ASSERTION(eSocketState_WaitDNS == mCurrentState, "Wrong state.");
@ -520,57 +535,32 @@ nsresult nsSocketTransport::doResolveHost(void)
this)); 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 if (! mNetAddress.inet.ip) {
// mozilla/network/main/mkconect.c //
// // Initialize the port used for the connection...
mNetAddress.inet.port = PR_htons(mPort); //
// 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);
// NS_WITH_SERVICE(nsIDNSService,
// Resolve the address of the given host... pDNSService,
// kDNSService,
char dbbuf[PR_NETDB_BUF_SIZE]; &rv);
PRHostEnt hostEnt; if (NS_FAILED(rv)) return rv;
rv = pDNSService->Lookup(nsnull, mHostName, this,
PRBool numeric = PR_TRUE; getter_AddRefs(mDNSRequest));
for (char *hostCheck = mHostName; *hostCheck; hostCheck++) { //
if (!nsString2::IsDigit(*hostCheck) && (*hostCheck != '.') ) { // The DNS lookup is being processed... Mark the transport as waiting
numeric = PR_FALSE; // until the result is available...
break; //
} // XXX: What should this result code be??
} if (NS_BASE_STREAM_WOULD_BLOCK == rv) {
SetFlag(eSocketDNS_Wait);
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...
} }
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, PR_LOG(gSocketLog, PR_LOG_DEBUG,
@ -1158,6 +1148,11 @@ nsSocketTransport::QueryInterface(const nsIID& aIID, void* *aInstancePtr)
NS_ADDREF_THIS(); NS_ADDREF_THIS();
return NS_OK; return NS_OK;
} }
if (aIID.Equals(NS_GET_IID(nsIDNSListener))) {
*aInstancePtr = NS_STATIC_CAST(nsIDNSListener*, this);
NS_ADDREF_THIS();
return NS_OK;
}
#ifndef NSPIPE2 #ifndef NSPIPE2
if (aIID.Equals(NS_GET_IID(nsIBufferObserver))) { if (aIID.Equals(NS_GET_IID(nsIBufferObserver))) {
*aInstancePtr = NS_STATIC_CAST(nsIBufferObserver*, this); *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... // nsIChannel implementation...

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

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

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

@ -226,6 +226,11 @@ nsresult nsSocketTransportService::ProcessWorkQ(void)
transport = nsSocketTransport::GetInstance(qp); transport = nsSocketTransport::GetInstance(qp);
PR_REMOVE_AND_INIT_LINK(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... // Try to perform the operation...
// //

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

@ -47,6 +47,6 @@ interface nsIDNSListener : nsISupports
/** /**
* Notify the listener that we the lookup has completed. * 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 "nsIRequest.h"
#include "prnetdb.h" #include "prnetdb.h"
#include "nsString2.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -111,7 +112,7 @@ nsDNSService::Lookup(nsISupports* ctxt,
nsIDNSListener* listener, nsIDNSListener* listener,
nsIRequest* *DNSRequest) nsIRequest* *DNSRequest)
{ {
nsresult rv; nsresult rv, result;
PRStatus status; PRStatus status;
nsHostEnt* hostentry; nsHostEnt* hostentry;
/* /*
@ -137,21 +138,52 @@ nsDNSService::Lookup(nsISupports* ctxt,
*/ */
// temporary SYNC version // temporary SYNC version
result = NS_OK;
hostentry = new nsHostEnt; hostentry = new nsHostEnt;
if (!hostentry) if (!hostentry)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
rv = listener->OnStartLookup(ctxt, hostname); rv = listener->OnStartLookup(ctxt, hostname);
PRBool numeric = PR_TRUE;
status = PR_GetHostByName(hostname, hostentry->buffer, PR_NETDB_BUF_SIZE, &hostentry->hostEnt); 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) if (PR_SUCCESS == status) {
rv = listener->OnFound(ctxt, hostname, hostentry); // turn ownership of hostentry over to listener? rv = listener->OnFound(ctxt, hostname, hostentry);
else result = NS_OK;
delete hostentry; }
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; return NS_OK;
} }