зеркало из https://github.com/mozilla/gecko-dev.git
landing patch for bug 205726 "DNS rewrite" r=dougt sr=bryner
This commit is contained in:
Родитель
ce762d3244
Коммит
f4a8778d0b
|
@ -49,7 +49,8 @@
|
|||
#include "nsIDNSService.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
#include "nsIProxyObjectManager.h"
|
||||
#include "netCore.h"
|
||||
#include "nsEventQueueUtils.h"
|
||||
#include "nsNetError.h"
|
||||
|
||||
const char kConsoleServiceContractId[] = "@mozilla.org/consoleservice;1";
|
||||
const char kDNSServiceContractId[] = "@mozilla.org/network/dns-service;1";
|
||||
|
@ -62,8 +63,7 @@ nsLDAPConnection::nsLDAPConnection()
|
|||
mPendingOperations(0),
|
||||
mRunnable(0),
|
||||
mSSL(PR_FALSE),
|
||||
mDNSRequest(0),
|
||||
mDNSFinished(PR_FALSE)
|
||||
mDNSRequest(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ nsLDAPConnection::~nsLDAPConnection()
|
|||
// Init listener (if still there).
|
||||
//
|
||||
if (mDNSRequest) {
|
||||
mDNSRequest->Cancel(NS_BINDING_ABORTED);
|
||||
mDNSRequest->Cancel();
|
||||
mDNSRequest = 0;
|
||||
}
|
||||
mInitListener = 0;
|
||||
|
@ -209,20 +209,11 @@ nsLDAPConnection::Init(const char *aHost, PRInt16 aPort, PRBool aSSL,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Get a proxy object so the callback happens on the current thread.
|
||||
// This is now a Synchronous proxy, due to the fact that the DNS
|
||||
// service hands out data which it later deallocates, and the async
|
||||
// proxy makes this unreliable. See bug 102227 for more details.
|
||||
//
|
||||
rv = NS_GetProxyForObject(NS_CURRENT_EVENTQ,
|
||||
NS_GET_IID(nsIDNSListener),
|
||||
NS_STATIC_CAST(nsIDNSListener*, this),
|
||||
PROXY_SYNC | PROXY_ALWAYS,
|
||||
getter_AddRefs(selfProxy));
|
||||
|
||||
nsCOMPtr<nsIEventQueue> curEventQ;
|
||||
rv = NS_GetCurrentEventQ(getter_AddRefs(curEventQ));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("nsLDAPConnection::Init(): couldn't "
|
||||
"create proxy to this object for callback");
|
||||
"get current event queue");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -242,10 +233,10 @@ nsLDAPConnection::Init(const char *aHost, PRInt16 aPort, PRBool aSSL,
|
|||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
rv = pDNSService->Lookup(aHost,
|
||||
selfProxy,
|
||||
nsnull,
|
||||
getter_AddRefs(mDNSRequest));
|
||||
mDNSHost = aHost;
|
||||
rv = pDNSService->AsyncResolve(mDNSHost,
|
||||
PR_FALSE, this, curEventQ,
|
||||
getter_AddRefs(mDNSRequest));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
switch (rv) {
|
||||
|
@ -253,24 +244,14 @@ nsLDAPConnection::Init(const char *aHost, PRInt16 aPort, PRBool aSSL,
|
|||
case NS_ERROR_UNKNOWN_HOST:
|
||||
case NS_ERROR_FAILURE:
|
||||
case NS_ERROR_OFFLINE:
|
||||
return rv;
|
||||
break;
|
||||
|
||||
default:
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
mDNSHost.Truncate();
|
||||
}
|
||||
|
||||
// The DNS service can actually call the listeners even before the
|
||||
// Lookup() function has returned. If that happens, we can still hold
|
||||
// a reference to the DNS request, even after the DNS lookup is done.
|
||||
// If this happens, lets just get rid of the DNS request, since we won't
|
||||
// need it any more.
|
||||
//
|
||||
if (mDNSFinished && mDNSRequest) {
|
||||
mDNSRequest = 0;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -823,102 +804,50 @@ nsLDAPConnectionLoop::Run(void)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// nsIDNSListener implementation, for asynchronous DNS. Once the lookup
|
||||
// has finished, we will initialize the LDAP connection properly.
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsLDAPConnection::OnStartLookup(nsISupports *aContext, const char *aHostName)
|
||||
{
|
||||
// Initialize some members which will be used in the other callbacks.
|
||||
//
|
||||
mDNSStatus = NS_OK;
|
||||
mResolvedIP = "";
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPConnection::OnFound(nsISupports *aContext,
|
||||
const char* aHostName,
|
||||
nsHostEnt *aHostEnt)
|
||||
{
|
||||
PRUint32 index = 0;
|
||||
PRNetAddr netAddress;
|
||||
char addrbuf[64];
|
||||
|
||||
// Do we have a proper host entry? If not, set the internal DNS
|
||||
// status to indicate that host lookup failed.
|
||||
//
|
||||
if (!aHostEnt->hostEnt.h_addr_list || !aHostEnt->hostEnt.h_addr_list[0]) {
|
||||
mDNSStatus = NS_ERROR_UNKNOWN_HOST;
|
||||
|
||||
return NS_ERROR_UNKNOWN_HOST;
|
||||
}
|
||||
|
||||
// Make sure our address structure is initialized properly
|
||||
//
|
||||
memset(&netAddress, 0, sizeof(netAddress));
|
||||
PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &netAddress);
|
||||
|
||||
// Loop through the addresses, and add them to our IP string.
|
||||
//
|
||||
while (aHostEnt->hostEnt.h_addr_list[index]) {
|
||||
if (aHostEnt->hostEnt.h_addrtype == PR_AF_INET6) {
|
||||
memcpy(&netAddress.ipv6.ip, aHostEnt->hostEnt.h_addr_list[index],
|
||||
sizeof(netAddress.ipv6.ip));
|
||||
} else {
|
||||
// Can this ever happen? Not sure, cause everything seems to be
|
||||
// IPv6 internally, even in the DNS service.
|
||||
//
|
||||
PR_ConvertIPv4AddrToIPv6(*(PRUint32*)aHostEnt->hostEnt.h_addr_list[0],
|
||||
&netAddress.ipv6.ip);
|
||||
}
|
||||
if (PR_IsNetAddrType(&netAddress, PR_IpAddrV4Mapped)) {
|
||||
// If there are more IPs in the list, we separate them with
|
||||
// a space, as supported/used by the LDAP C-SDK.
|
||||
//
|
||||
if (index)
|
||||
mResolvedIP.Append(' ');
|
||||
|
||||
// Convert the IPv4 address to a string, and append it to our
|
||||
// list of IPs.
|
||||
//
|
||||
PR_NetAddrToString(&netAddress, addrbuf, sizeof(addrbuf));
|
||||
if ((addrbuf[0] == ':') && (strlen(addrbuf) > 7))
|
||||
mResolvedIP.Append(addrbuf+7);
|
||||
else
|
||||
mResolvedIP.Append(addrbuf);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLDAPConnection::OnStopLookup(nsISupports *aContext,
|
||||
const char *aHostName,
|
||||
nsresult aStatus)
|
||||
{
|
||||
nsCOMPtr<nsILDAPMessageListener> selfProxy;
|
||||
nsLDAPConnection::OnLookupComplete(nsIDNSRequest *aRequest,
|
||||
nsIDNSRecord *aRecord,
|
||||
nsresult aStatus)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (NS_FAILED(mDNSStatus)) {
|
||||
// We failed previously in the OnFound() callback
|
||||
if (aRecord) {
|
||||
// Build mResolvedIP list
|
||||
//
|
||||
switch (mDNSStatus) {
|
||||
case NS_ERROR_UNKNOWN_HOST:
|
||||
case NS_ERROR_FAILURE:
|
||||
rv = mDNSStatus;
|
||||
break;
|
||||
mResolvedIP.Truncate();
|
||||
|
||||
default:
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
break;
|
||||
PRInt32 index = 0;
|
||||
char addrbuf[64];
|
||||
PRNetAddr addr;
|
||||
|
||||
while (NS_SUCCEEDED(aRecord->GetNextAddr(0, &addr))) {
|
||||
// We can only use v4 addresses
|
||||
//
|
||||
PRBool v4mapped = PR_FALSE;
|
||||
if (addr.raw.family == PR_AF_INET6)
|
||||
v4mapped = PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped);
|
||||
if (addr.raw.family == PR_AF_INET || v4mapped) {
|
||||
// If there are more IPs in the list, we separate them with
|
||||
// a space, as supported/used by the LDAP C-SDK.
|
||||
//
|
||||
if (index++)
|
||||
mResolvedIP.Append(' ');
|
||||
|
||||
// Convert the IPv4 address to a string, and append it to our
|
||||
// list of IPs. Strip leading '::FFFF:' (the IPv4-mapped-IPv6
|
||||
// indicator) if present.
|
||||
//
|
||||
PR_NetAddrToString(&addr, addrbuf, sizeof(addrbuf));
|
||||
if ((addrbuf[0] == ':') && (strlen(addrbuf) > 7))
|
||||
mResolvedIP.Append(addrbuf+7);
|
||||
else
|
||||
mResolvedIP.Append(addrbuf);
|
||||
}
|
||||
}
|
||||
} else if (NS_FAILED(aStatus)) {
|
||||
// The DNS service failed , lets pass something reasonable
|
||||
}
|
||||
|
||||
if (NS_FAILED(aStatus)) {
|
||||
// The DNS service failed, lets pass something reasonable
|
||||
// back to the listener.
|
||||
//
|
||||
switch (aStatus) {
|
||||
|
@ -977,7 +906,7 @@ nsLDAPConnection::OnStopLookup(nsISupports *aContext,
|
|||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
rv = nsLDAPInstallSSL(mConnectionHandle, aHostName);
|
||||
rv = nsLDAPInstallSSL(mConnectionHandle, mDNSHost.get());
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("nsLDAPConnection::OnStopLookup(): Error installing"
|
||||
" secure LDAP routines for connection");
|
||||
|
@ -1023,7 +952,7 @@ nsLDAPConnection::OnStopLookup(nsISupports *aContext,
|
|||
// indicating that DNS has finished.
|
||||
//
|
||||
mDNSRequest = 0;
|
||||
mDNSFinished = PR_TRUE;
|
||||
mDNSHost.Truncate();
|
||||
|
||||
// Call the listener, and then we can release our reference to it.
|
||||
//
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include "nspr.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsIDNSListener.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsIRequest.h"
|
||||
|
||||
// 0d871e30-1dd2-11b2-8ea9-831778c78e93
|
||||
|
@ -124,10 +124,9 @@ class nsLDAPConnection : public nsILDAPConnection,
|
|||
|
||||
nsCString mResolvedIP; // Preresolved list of host IPs
|
||||
nsCOMPtr<nsILDAPMessageListener> mInitListener; // Init callback
|
||||
nsCOMPtr<nsIRequest> mDNSRequest; // The "active" DNS request
|
||||
nsCOMPtr<nsIDNSRequest> mDNSRequest; // The "active" DNS request
|
||||
nsCString mDNSHost; // The hostname being resolved
|
||||
nsCOMPtr<nsISupports> mClosure; // private parameter (anything caller desires)
|
||||
nsresult mDNSStatus; // The status of DNS lookup (rv cache)
|
||||
PRBool mDNSFinished; // Flag if DNS lookup has finished
|
||||
};
|
||||
|
||||
// This class implements the nsIRunnable interface, in this case just a
|
||||
|
|
|
@ -193,7 +193,8 @@ nsLDAPSSLConnect(const char *hostlist, int defport, int timeout,
|
|||
// clear, and I suspect it may depend on the format of the name in
|
||||
// the certificate. Need to investigate.
|
||||
//
|
||||
rv = tlsSocketProvider->AddToSocket(sessionClosure->hostname, defport,
|
||||
rv = tlsSocketProvider->AddToSocket(PR_AF_INET,
|
||||
sessionClosure->hostname, defport,
|
||||
nsnull, 0, socketInfo.soinfo_prfd,
|
||||
getter_AddRefs(securityInfo));
|
||||
if (NS_FAILED(rv)) {
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "nsIRequest.h"
|
||||
#include "nsEventQueueUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsNetCID.h"
|
||||
|
||||
static const char kSecurityProperties[] =
|
||||
"chrome://communicator/locale/webservices/security.properties";
|
||||
|
@ -230,14 +231,14 @@ nsWSAUtils::GetOfficialHostName(nsIURI* aServiceURI,
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsXPIDLCString host;
|
||||
nsCAutoString host;
|
||||
aServiceURI->GetHost(host);
|
||||
|
||||
nsRefPtr<nsDNSListener> listener = new nsDNSListener();
|
||||
NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsCOMPtr<nsIRequest> dummy;
|
||||
rv = dns->Lookup(host, listener, nsnull, getter_AddRefs(dummy));
|
||||
nsCOMPtr<nsIDNSRequest> dummy;
|
||||
rv = dns->AsyncResolve(host, PR_FALSE, listener, nsnull, getter_AddRefs(dummy));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
@ -292,26 +293,13 @@ nsDNSListener::~nsDNSListener()
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSListener::OnStartLookup(nsISupports* aContext, const char* aHost)
|
||||
nsDNSListener::OnLookupComplete(nsIDNSRequest* aRequest,
|
||||
nsIDNSRecord* aRecord,
|
||||
nsresult aStatus)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
if (aRecord)
|
||||
aRecord->GetCanonicalName(mOfficialHostName);
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSListener::OnFound(nsISupports* aContext,
|
||||
const char* aHost,
|
||||
nsHostEnt* aHostEnt)
|
||||
{
|
||||
if (aHostEnt)
|
||||
mOfficialHostName.Assign(aHostEnt->hostEnt.h_name);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSListener::OnStopLookup(nsISupports* aContext,
|
||||
const char* aHost,
|
||||
nsresult aStatus)
|
||||
{
|
||||
// Post an event to the UI thread's event queue to cause
|
||||
// ProcessPendingEvents to run.
|
||||
nsCOMPtr<nsIEventQueue> uiEventQ;
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "nsXPCOM.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsNetError.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsAbLDAPAutoCompFormatter,
|
||||
nsILDAPAutoCompFormatter,
|
||||
|
|
|
@ -40,11 +40,7 @@
|
|||
interface nsIInterfaceRequestor;
|
||||
interface nsISocketEventSink;
|
||||
|
||||
%{C++
|
||||
#include "prio.h"
|
||||
%}
|
||||
|
||||
[ptr] native PRNetAddrStar(PRNetAddr);
|
||||
[ptr] native PRNetAddrStar(union PRNetAddr);
|
||||
|
||||
/**
|
||||
* nsISocketTransport
|
||||
|
@ -64,10 +60,11 @@ interface nsISocketTransport : nsITransport
|
|||
*/
|
||||
readonly attribute long port;
|
||||
|
||||
/**
|
||||
* Get the PRNetAddr for the underlying socket connection.
|
||||
/**
|
||||
* Returns the IP address for the underlying socket connection. This
|
||||
* attribute is only defined once a connection has been established.
|
||||
*/
|
||||
[noscript] void getAddress(in PRNetAddrStar addr);
|
||||
[noscript] void getAddress(in PRNetAddrStar netAddr);
|
||||
|
||||
/**
|
||||
* Security info object returned from the PSM socket provider. This object
|
||||
|
|
|
@ -254,6 +254,23 @@
|
|||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 42)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Socket specific error codes:
|
||||
*/
|
||||
|
||||
/**
|
||||
* The specified socket type does not exist.
|
||||
*/
|
||||
#define NS_ERROR_UNKNOWN_SOCKET_TYPE \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 51)
|
||||
|
||||
/**
|
||||
* The specified socket type could not be created.
|
||||
*/
|
||||
#define NS_ERROR_SOCKET_CREATE_FAILED \
|
||||
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 52)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Cache specific error codes:
|
||||
*
|
||||
|
|
|
@ -121,7 +121,7 @@ nsProxyAutoConfig.prototype = {
|
|||
// evaluate loded js file
|
||||
evalInSandbox(mypac, ProxySandBox, pacURL);
|
||||
try {
|
||||
ProxySandBox.myIP = dns.myIPAddress;
|
||||
ProxySandBox.myIP = dns.resolve(dns.myHostName, false).getNextAddrAsString();
|
||||
} catch (e) {
|
||||
// Well, theres nothing better.
|
||||
// see bugs 80363 and 92516.
|
||||
|
@ -149,7 +149,7 @@ function dnsResolve(host) {
|
|||
return dnsResolveCachedIp;
|
||||
}
|
||||
try {
|
||||
dnsResolveCachedIp = dns.resolve(host);
|
||||
dnsResolveCachedIp = dns.resolve(host, false).getNextAddrAsString();
|
||||
dnsResolveCachedHost = host;
|
||||
}
|
||||
catch (e) {
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "prmem.h"
|
||||
#include "pratom.h"
|
||||
#include "plstr.h"
|
||||
#include "prnetdb.h"
|
||||
#include "prerror.h"
|
||||
#include "prerr.h"
|
||||
|
||||
|
@ -58,7 +59,6 @@
|
|||
#include "nsISocketProviderService.h"
|
||||
#include "nsISocketProvider.h"
|
||||
#include "nsISSLSocketControl.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsIProxyInfo.h"
|
||||
#include "nsIPipe.h"
|
||||
|
||||
|
@ -91,7 +91,7 @@ static PRErrorCode RandomizeConnectError(PRErrorCode code)
|
|||
errors[] = {
|
||||
//
|
||||
// These errors should be recoverable provided there is another
|
||||
// IP address in mNetAddrList.
|
||||
// IP address in mDNSRecord.
|
||||
//
|
||||
{ PR_CONNECT_REFUSED_ERROR, "PR_CONNECT_REFUSED_ERROR" },
|
||||
{ PR_CONNECT_TIMEOUT_ERROR, "PR_CONNECT_TIMEOUT_ERROR" },
|
||||
|
@ -612,7 +612,6 @@ nsSocketTransport::nsSocketTransport()
|
|||
, mFDconnected(PR_FALSE)
|
||||
, mInput(this)
|
||||
, mOutput(this)
|
||||
, mNetAddr(nsnull)
|
||||
{
|
||||
LOG(("creating nsSocketTransport @%x\n", this));
|
||||
|
||||
|
@ -735,36 +734,12 @@ nsSocketTransport::ResolveHost()
|
|||
|
||||
nsresult rv;
|
||||
|
||||
PRIPv6Addr addr;
|
||||
rv = gSocketTransportService->LookupHost(SocketHost(), SocketPort(), &addr);
|
||||
nsCOMPtr<nsIDNSService> dns = do_GetService(kDNSServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = dns->AsyncResolve(SocketHost(), PR_FALSE, this, nsnull,
|
||||
getter_AddRefs(mDNSRequest));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// found address!
|
||||
mNetAddrList.Init(1);
|
||||
mNetAddr = mNetAddrList.GetNext(nsnull);
|
||||
PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, SocketPort(), mNetAddr);
|
||||
memcpy(&mNetAddr->ipv6.ip, &addr, sizeof(addr));
|
||||
#ifdef PR_LOGGING
|
||||
if (LOG_ENABLED()) {
|
||||
char buf[128];
|
||||
PR_NetAddrToString(mNetAddr, buf, sizeof(buf));
|
||||
LOG((" -> using cached ip address [%s]\n", buf));
|
||||
}
|
||||
#endif
|
||||
// suppress resolving status message since we are bypassing that step.
|
||||
mState = STATE_RESOLVING;
|
||||
rv = gSocketTransportService->PostEvent(this,
|
||||
MSG_DNS_LOOKUP_COMPLETE,
|
||||
NS_OK, nsnull);
|
||||
}
|
||||
else {
|
||||
const char *host = SocketHost().get();
|
||||
|
||||
nsCOMPtr<nsIDNSService> dns = do_GetService(kDNSServiceCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = dns->Lookup(host, this, nsnull, getter_AddRefs(mDNSRequest));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
LOG((" advancing to STATE_RESOLVING\n"));
|
||||
mState = STATE_RESOLVING;
|
||||
SendStatus(STATUS_RESOLVING);
|
||||
|
@ -783,7 +758,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool
|
|||
usingSSL = PR_FALSE;
|
||||
|
||||
if (mTypeCount == 0) {
|
||||
fd = PR_OpenTCPSocket(PR_AF_INET6);
|
||||
fd = PR_OpenTCPSocket(mNetAddr.raw.family);
|
||||
rv = fd ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
|
@ -812,7 +787,8 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool
|
|||
if (i == 0) {
|
||||
// if this is the first type, we'll want the
|
||||
// service to allocate a new socket
|
||||
rv = provider->NewSocket(host, port, proxyHost, proxyPort,
|
||||
rv = provider->NewSocket(mNetAddr.raw.family,
|
||||
host, port, proxyHost, proxyPort,
|
||||
&fd, getter_AddRefs(secinfo));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !fd) {
|
||||
|
@ -824,7 +800,8 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool
|
|||
// the socket has already been allocated,
|
||||
// so we just want the service to add itself
|
||||
// to the stack (such as pushing an io layer)
|
||||
rv = provider->AddToSocket(host, port, proxyHost, proxyPort,
|
||||
rv = provider->AddToSocket(mNetAddr.raw.family,
|
||||
host, port, proxyHost, proxyPort,
|
||||
fd, getter_AddRefs(secinfo));
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
|
@ -931,10 +908,18 @@ nsSocketTransport::InitiateSocket()
|
|||
mState = STATE_CONNECTING;
|
||||
SendStatus(STATUS_CONNECTING_TO);
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
if (LOG_ENABLED()) {
|
||||
char buf[64];
|
||||
PR_NetAddrToString(&mNetAddr, buf, sizeof(buf));
|
||||
LOG((" trying address: %s\n", buf));
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Initiate the connect() to the host...
|
||||
//
|
||||
status = PR_Connect(fd, mNetAddr, NS_SOCKET_CONNECT_TIMEOUT);
|
||||
status = PR_Connect(fd, &mNetAddr, NS_SOCKET_CONNECT_TIMEOUT);
|
||||
if (status == PR_SUCCESS) {
|
||||
//
|
||||
// we are connected!
|
||||
|
@ -1017,17 +1002,10 @@ nsSocketTransport::RecoverFromError()
|
|||
PRBool tryAgain = PR_FALSE;
|
||||
|
||||
// try next ip address only if past the resolver stage...
|
||||
if (mState == STATE_CONNECTING) {
|
||||
PRNetAddr *nextAddr = mNetAddrList.GetNext(mNetAddr);
|
||||
if (nextAddr) {
|
||||
mNetAddr = nextAddr;
|
||||
#if defined(PR_LOGGING)
|
||||
if (LOG_ENABLED()) {
|
||||
char buf[64];
|
||||
PR_NetAddrToString(mNetAddr, buf, sizeof(buf));
|
||||
LOG((" ...trying next address: %s\n", buf));
|
||||
}
|
||||
#endif
|
||||
if (mState == STATE_CONNECTING && mDNSRecord) {
|
||||
nsresult rv = mDNSRecord->GetNextAddr(SocketPort(), &mNetAddr);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
LOG((" trying again with next ip address\n"));
|
||||
tryAgain = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -1123,9 +1101,6 @@ nsSocketTransport::OnSocketConnected()
|
|||
NS_ASSERTION(mFDref == 1, "wrong socket ref count");
|
||||
mFDconnected = PR_TRUE;
|
||||
}
|
||||
|
||||
gSocketTransportService->RememberHost(SocketHost(), SocketPort(),
|
||||
&mNetAddr->ipv6.ip);
|
||||
}
|
||||
|
||||
PRFileDesc *
|
||||
|
@ -1189,6 +1164,12 @@ nsSocketTransport::OnSocketEvent(PRUint32 type, PRUint32 uparam, void *vparam)
|
|||
case MSG_DNS_LOOKUP_COMPLETE:
|
||||
LOG((" MSG_DNS_LOOKUP_COMPLETE\n"));
|
||||
mDNSRequest = 0;
|
||||
if (vparam) {
|
||||
nsIDNSRecord *rec = NS_REINTERPRET_CAST(nsIDNSRecord *, vparam);
|
||||
mDNSRecord = rec;
|
||||
NS_RELEASE(rec);
|
||||
mDNSRecord->GetNextAddr(SocketPort(), &mNetAddr);
|
||||
}
|
||||
// uparam contains DNS lookup status
|
||||
if (NS_FAILED(uparam)) {
|
||||
// fixup error code if proxy was not found
|
||||
|
@ -1323,7 +1304,7 @@ nsSocketTransport::OnSocketDetached(PRFileDesc *fd)
|
|||
|
||||
// make sure there isn't any pending DNS request
|
||||
if (mDNSRequest) {
|
||||
mDNSRequest->Cancel(mCondition);
|
||||
mDNSRequest->Cancel();
|
||||
mDNSRequest = 0;
|
||||
}
|
||||
|
||||
|
@ -1559,128 +1540,37 @@ nsSocketTransport::GetPort(PRInt32 *port)
|
|||
NS_IMETHODIMP
|
||||
nsSocketTransport::GetAddress(PRNetAddr *addr)
|
||||
{
|
||||
//
|
||||
// NOTE: mNetAddr is assigned on either the socket thread or the DNS thread.
|
||||
// assuming pointer assignment is atomic, this code does not need any
|
||||
// locks to maintain thread safety.
|
||||
//
|
||||
// once we are in the connected state, mNetAddr will not change.
|
||||
// so if we can verify that we are in the connected state, then
|
||||
// we can freely access mNetAddr from any thread without being
|
||||
// inside a critical section.
|
||||
|
||||
if (!mNetAddr)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
memcpy(addr, mNetAddr, sizeof(PRNetAddr));
|
||||
NS_ENSURE_TRUE(mState == STATE_TRANSFERRING, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
memcpy(addr, &mNetAddr, sizeof(mNetAddr));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransport::OnStartLookup(nsISupports *ctx, const char *host)
|
||||
nsSocketTransport::OnLookupComplete(nsIDNSRequest *request,
|
||||
nsIDNSRecord *rec,
|
||||
nsresult status)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransport::OnFound(nsISupports *ctx,
|
||||
const char *host,
|
||||
nsHostEnt *hostEnt)
|
||||
{
|
||||
// no locking should be required... yes, we are running on the DNS
|
||||
// thread, but our state variables we're going to touch will not be
|
||||
// touched by anyone else until we post a MSG_DNS_LOOKUP_COMPLETE
|
||||
// event, or until the socket transports destructor runs.
|
||||
|
||||
char **addrList = hostEnt->hostEnt.h_addr_list;
|
||||
|
||||
if (addrList && addrList[0]) {
|
||||
PRUint32 len = 0;
|
||||
PRUint16 port = SocketPort();
|
||||
|
||||
LOG(("nsSocketTransport::OnFound [%s:%hu this=%x] lookup succeeded [FQDN=%s]\n",
|
||||
host, port, this, hostEnt->hostEnt.h_name));
|
||||
|
||||
// determine the number of address in the list
|
||||
for (; *addrList; ++addrList)
|
||||
++len;
|
||||
addrList -= len;
|
||||
|
||||
// allocate space for the addresses
|
||||
mNetAddrList.Init(len);
|
||||
|
||||
// populate the address list
|
||||
PRNetAddr *addr = nsnull;
|
||||
while ((addr = mNetAddrList.GetNext(addr)) != nsnull) {
|
||||
PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, port, addr);
|
||||
if (hostEnt->hostEnt.h_addrtype == PR_AF_INET6)
|
||||
memcpy(&addr->ipv6.ip, *addrList, sizeof(addr->ipv6.ip));
|
||||
else
|
||||
PR_ConvertIPv4AddrToIPv6(*(PRUint32 *)(*addrList), &addr->ipv6.ip);
|
||||
++addrList;
|
||||
#if defined(PR_LOGGING)
|
||||
if (LOG_ENABLED()) {
|
||||
char buf[50];
|
||||
PR_NetAddrToString(addr, buf, sizeof(buf));
|
||||
LOG((" => %s\n", buf));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// start with first address in list
|
||||
mNetAddr = mNetAddrList.GetNext(nsnull);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransport::OnStopLookup(nsISupports *ctx, const char *host,
|
||||
nsresult status)
|
||||
{
|
||||
LOG(("nsSocketTransport::OnStopLookup [this=%x status=%x]\n",
|
||||
this, status));
|
||||
|
||||
// keep the DNS service honest...
|
||||
if (NS_SUCCEEDED(status) && (mNetAddr == nsnull)) {
|
||||
NS_ERROR("success without a result");
|
||||
status = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
// event handler will release this reference.
|
||||
NS_IF_ADDREF(rec);
|
||||
|
||||
nsresult rv = gSocketTransportService->PostEvent(this,
|
||||
MSG_DNS_LOOKUP_COMPLETE,
|
||||
status, nsnull);
|
||||
status, rec);
|
||||
|
||||
// if posting a message fails, then we should assume that the socket
|
||||
// transport has been shutdown. this should never happen! if it does
|
||||
// it means that the socket transport service was shutdown before the
|
||||
// DNS service.
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("unable to post DNS lookup complete message");
|
||||
NS_IF_RELEASE(rec);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsSocketTransport::NetAddrList
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
nsSocketTransport::NetAddrList::Init(PRUint32 len)
|
||||
{
|
||||
NS_ASSERTION(!mList, "already initialized");
|
||||
mList = new PRNetAddr[len];
|
||||
if (!mList)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
mLen = len;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRNetAddr *
|
||||
nsSocketTransport::NetAddrList::GetNext(PRNetAddr *addr)
|
||||
{
|
||||
if (!addr)
|
||||
return mList;
|
||||
|
||||
PRUint32 offset = addr - mList;
|
||||
NS_ASSERTION(offset < mLen, "invalid address");
|
||||
if (offset + 1 < mLen)
|
||||
return addr + 1;
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
|
|
@ -46,8 +46,7 @@
|
|||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsIAsyncOutputStream.h"
|
||||
#include "nsIDNSListener.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsIDNSService.h"
|
||||
|
||||
class nsSocketTransport;
|
||||
|
||||
|
@ -164,24 +163,6 @@ private:
|
|||
STATE_TRANSFERRING
|
||||
};
|
||||
|
||||
class NetAddrList {
|
||||
public:
|
||||
NetAddrList() : mList(nsnull), mLen(0) {}
|
||||
~NetAddrList() { delete[] mList; }
|
||||
|
||||
// allocate space for the address list
|
||||
nsresult Init(PRUint32 len);
|
||||
|
||||
// given a net addr in the list, return the next addr.
|
||||
// if given NULL, then return the first addr in the list.
|
||||
// returns NULL if given addr is the last addr.
|
||||
PRNetAddr *GetNext(PRNetAddr *currentAddr);
|
||||
|
||||
private:
|
||||
PRNetAddr *mList;
|
||||
PRUint32 mLen;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// these members are "set" at initialization time and are never modified
|
||||
// afterwards. this allows them to be safely accessed from any thread.
|
||||
|
@ -210,7 +191,9 @@ private:
|
|||
PRPackedBool mInputClosed;
|
||||
PRPackedBool mOutputClosed;
|
||||
|
||||
nsCOMPtr<nsIRequest> mDNSRequest;
|
||||
nsCOMPtr<nsIDNSRequest> mDNSRequest;
|
||||
nsCOMPtr<nsIDNSRecord> mDNSRecord;
|
||||
PRNetAddr mNetAddr;
|
||||
|
||||
// socket methods (these can only be called on the socket thread):
|
||||
|
||||
|
@ -296,14 +279,6 @@ private:
|
|||
else
|
||||
gSocketTransportService->PostEvent(this, MSG_OUTPUT_PENDING, 0, nsnull);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// we have to be careful with these. they are modified on the DNS thread,
|
||||
// while we are in the resolving state. once we've received the event
|
||||
// MSG_DNS_LOOKUP_COMPLETE, these can only be accessed on the socket thread.
|
||||
//
|
||||
NetAddrList mNetAddrList;
|
||||
PRNetAddr *mNetAddr;
|
||||
};
|
||||
|
||||
#endif // !nsSocketTransport_h__
|
||||
|
|
|
@ -41,10 +41,10 @@
|
|||
|
||||
#include "nsSocketTransportService2.h"
|
||||
#include "nsSocketTransport2.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsNetError.h"
|
||||
#include "prnetdb.h"
|
||||
#include "prlock.h"
|
||||
#include "prerror.h"
|
||||
#include "plstr.h"
|
||||
|
@ -354,70 +354,6 @@ nsSocketTransportService::ServiceEventQ()
|
|||
return keepGoing;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// host:port -> ipaddr cache
|
||||
|
||||
PLDHashTableOps nsSocketTransportService::ops =
|
||||
{
|
||||
PL_DHashAllocTable,
|
||||
PL_DHashFreeTable,
|
||||
PL_DHashGetKeyStub,
|
||||
PL_DHashStringKey,
|
||||
PL_DHashMatchStringKey,
|
||||
PL_DHashMoveEntryStub,
|
||||
PL_DHashFreeStringKey,
|
||||
PL_DHashFinalizeStub,
|
||||
nsnull
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsSocketTransportService::LookupHost(const nsACString &host, PRUint16 port, PRIPv6Addr *addr)
|
||||
{
|
||||
NS_ASSERTION(!host.IsEmpty(), "empty host");
|
||||
NS_ASSERTION(addr, "null addr");
|
||||
|
||||
PLDHashEntryHdr *hdr;
|
||||
nsCAutoString hostport(host + nsPrintfCString(":%d", port));
|
||||
|
||||
hdr = PL_DHashTableOperate(&mHostDB, hostport.get(), PL_DHASH_LOOKUP);
|
||||
if (PL_DHASH_ENTRY_IS_BUSY(hdr)) {
|
||||
// found match
|
||||
nsHostEntry *ent = NS_REINTERPRET_CAST(nsHostEntry *, hdr);
|
||||
memcpy(addr, &ent->addr, sizeof(ent->addr));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_UNKNOWN_HOST;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSocketTransportService::RememberHost(const nsACString &host, PRUint16 port, PRIPv6Addr *addr)
|
||||
{
|
||||
// remember hostname
|
||||
|
||||
PLDHashEntryHdr *hdr;
|
||||
nsCAutoString hostport(host + nsPrintfCString(":%d", port));
|
||||
|
||||
hdr = PL_DHashTableOperate(&mHostDB, hostport.get(), PL_DHASH_ADD);
|
||||
if (!hdr)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ASSERTION(PL_DHASH_ENTRY_IS_BUSY(hdr), "entry not busy");
|
||||
|
||||
nsHostEntry *ent = NS_REINTERPRET_CAST(nsHostEntry *, hdr);
|
||||
if (ent->key == nsnull) {
|
||||
ent->key = (const void *) ToNewCString(hostport);
|
||||
memcpy(&ent->addr, addr, sizeof(ent->addr));
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
// verify that the existing entry is in fact a perfect match
|
||||
NS_ASSERTION(PL_strcmp(ent->hostport(), hostport.get()) == 0, "bad match");
|
||||
NS_ASSERTION(memcmp(&ent->addr, addr, sizeof(ent->addr)) == 0, "bad match");
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// xpcom api
|
||||
|
@ -534,11 +470,6 @@ nsSocketTransportService::Run()
|
|||
|
||||
gSocketThread = PR_GetCurrentThread();
|
||||
|
||||
//
|
||||
// Initialize hostname database
|
||||
//
|
||||
PL_DHashTableInit(&mHostDB, &ops, nsnull, sizeof(nsHostEntry), 0);
|
||||
|
||||
//
|
||||
// add thread event to poll list (mThreadEvent may be NULL)
|
||||
//
|
||||
|
@ -650,9 +581,6 @@ nsSocketTransportService::Run()
|
|||
for (i=mIdleCount-1; i>=0; --i)
|
||||
DetachSocket(&mIdleList[i]);
|
||||
|
||||
// clear the hostname database
|
||||
PL_DHashTableFinish(&mHostDB);
|
||||
|
||||
gSocketThread = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -144,20 +144,6 @@ public:
|
|||
//
|
||||
nsresult AttachSocket(PRFileDesc *fd, nsASocketHandler *);
|
||||
|
||||
//
|
||||
// LookupHost checks to see if we've previously resolved the hostname
|
||||
// during this session. We remember all successful connections to prevent
|
||||
// ip-address spoofing. See bug 149943.
|
||||
//
|
||||
// Returns TRUE if found, and sets |addr| to the cached value.
|
||||
//
|
||||
nsresult LookupHost(const nsACString &host, PRUint16 port, PRIPv6Addr *addr);
|
||||
|
||||
//
|
||||
// Remember host:port -> IP address mapping.
|
||||
//
|
||||
nsresult RememberHost(const nsACString &host, PRUint16 port, PRIPv6Addr *addr);
|
||||
|
||||
private:
|
||||
|
||||
virtual ~nsSocketTransportService();
|
||||
|
@ -261,23 +247,6 @@ private:
|
|||
};
|
||||
PendingSocket *mPendingQHead;
|
||||
PendingSocket *mPendingQTail;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// mHostDB maps host:port -> nsHostEntry
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
struct nsHostEntry : PLDHashEntryStub
|
||||
{
|
||||
PRIPv6Addr addr;
|
||||
const char *hostport() const { return (const char *) key; }
|
||||
};
|
||||
|
||||
static PLDHashTableOps ops;
|
||||
|
||||
static PRBool PR_CALLBACK MatchEntry(PLDHashTable *, const PLDHashEntryHdr *, const void *);
|
||||
static void PR_CALLBACK ClearEntry(PLDHashTable *, PLDHashEntryHdr *);
|
||||
|
||||
PLDHashTable mHostDB;
|
||||
};
|
||||
|
||||
extern nsSocketTransportService *gSocketTransportService;
|
||||
|
|
|
@ -557,6 +557,18 @@
|
|||
* netwerk/dns/ classes
|
||||
*/
|
||||
|
||||
#define NS_DNSSERVICE_CLASSNAME \
|
||||
"nsDNSService"
|
||||
#define NS_DNSSERVICE_CONTRACTID \
|
||||
"@mozilla.org/network/dns-service;1"
|
||||
#define NS_DNSSERVICE_CID \
|
||||
{ /* b0ff4572-dae4-4bef-a092-83c1b88f6be9 */ \
|
||||
0xb0ff4572, \
|
||||
0xdae4, \
|
||||
0x4bef, \
|
||||
{0xa0, 0x92, 0x83, 0xc1, 0xb8, 0x8f, 0x6b, 0xe9} \
|
||||
}
|
||||
|
||||
#define NS_IDNSERVICE_CLASSNAME \
|
||||
"nsIDNService"
|
||||
/* ContractID of the XPCOM package that implements nsIIDNService */
|
||||
|
@ -586,4 +598,37 @@
|
|||
|
||||
#define NS_MIMEHEADERPARAM_CONTRACTID "@mozilla.org/network/mime-hdrparam;1"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* netwerk/socket classes
|
||||
*/
|
||||
|
||||
#define NS_SOCKETPROVIDERSERVICE_CLASSNAME \
|
||||
"nsSocketProviderService"
|
||||
#define NS_SOCKETPROVIDERSERVICE_CONTRACTID \
|
||||
"@mozilla.org/network/socket-provider-service;1"
|
||||
#define NS_SOCKETPROVIDERSERVICE_CID \
|
||||
{ /* ed394ba0-5472-11d3-bbc8-0000861d1237 */ \
|
||||
0xed394ba0, \
|
||||
0x5472, \
|
||||
0x11d3, \
|
||||
{ 0xbb, 0xc8, 0x00, 0x00, 0x86, 0x1d, 0x12, 0x37 } \
|
||||
}
|
||||
|
||||
#define NS_SOCKSSOCKETPROVIDER_CID \
|
||||
{ /* 8dbe7246-1dd2-11b2-9b8f-b9a849e4403a */ \
|
||||
0x8dbe7246, \
|
||||
0x1dd2, \
|
||||
0x11b2, \
|
||||
{ 0x9b, 0x8f, 0xb9, 0xa8, 0x49, 0xe4, 0x40, 0x3a } \
|
||||
}
|
||||
|
||||
#define NS_SOCKS4SOCKETPROVIDER_CID \
|
||||
{ /* F7C9F5F4-4451-41c3-A28A-5BA2447FBACE */ \
|
||||
0xf7c9f5f4, \
|
||||
0x4451, \
|
||||
0x41c3, \
|
||||
{ 0xa2, 0x8a, 0x5b, 0xa2, 0x44, 0x7f, 0xba, 0xce } \
|
||||
}
|
||||
|
||||
#endif // nsNetCID_h__
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include "nsSocketProviderService.h"
|
||||
#include "nscore.h"
|
||||
#include "nsSimpleURI.h"
|
||||
#include "nsDnsService.h"
|
||||
#include "nsLoadGroup.h"
|
||||
#include "nsStreamLoader.h"
|
||||
#include "nsUnicharStreamLoader.h"
|
||||
|
@ -56,7 +55,6 @@
|
|||
#include "nsBufferedStreams.h"
|
||||
#include "nsMIMEInputStream.h"
|
||||
#include "nsSOCKSSocketProvider.h"
|
||||
#include "nsSOCKS4SocketProvider.h"
|
||||
#include "nsCacheService.h"
|
||||
|
||||
#include "nsNetCID.h"
|
||||
|
@ -73,6 +71,9 @@
|
|||
|
||||
#include "nsIOService.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsIOService, Init)
|
||||
|
||||
#include "nsDNSService2.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDNSService, Init)
|
||||
|
||||
#include "nsProtocolProxyService.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsProtocolProxyService, Init)
|
||||
|
@ -575,14 +576,14 @@ static const nsModuleComponentInfo gNetModuleInfo[] = {
|
|||
NS_SOCKETTRANSPORTSERVICE_CID,
|
||||
NS_SOCKETTRANSPORTSERVICE_CONTRACTID,
|
||||
nsSocketTransportServiceConstructor },
|
||||
{ "Socket Provider Service",
|
||||
{ NS_SOCKETPROVIDERSERVICE_CLASSNAME,
|
||||
NS_SOCKETPROVIDERSERVICE_CID,
|
||||
"@mozilla.org/network/socket-provider-service;1",
|
||||
NS_SOCKETPROVIDERSERVICE_CONTRACTID,
|
||||
nsSocketProviderService::Create },
|
||||
{ "DNS Service",
|
||||
{ NS_DNSSERVICE_CLASSNAME,
|
||||
NS_DNSSERVICE_CID,
|
||||
"@mozilla.org/network/dns-service;1",
|
||||
nsDNSService::Create },
|
||||
NS_DNSSERVICE_CONTRACTID,
|
||||
nsDNSServiceConstructor },
|
||||
{ NS_IDNSERVICE_CLASSNAME,
|
||||
NS_IDNSERVICE_CID,
|
||||
NS_IDNSERVICE_CONTRACTID,
|
||||
|
@ -968,16 +969,16 @@ static const nsModuleComponentInfo gNetModuleInfo[] = {
|
|||
},
|
||||
#endif
|
||||
|
||||
{ NS_ISOCKSSOCKETPROVIDER_CLASSNAME,
|
||||
{ "nsSOCKSSocketProvider",
|
||||
NS_SOCKSSOCKETPROVIDER_CID,
|
||||
NS_ISOCKSSOCKETPROVIDER_CONTRACTID,
|
||||
nsSOCKSSocketProvider::Create
|
||||
NS_NETWORK_SOCKET_CONTRACTID_PREFIX "socks",
|
||||
nsSOCKSSocketProvider::CreateV5
|
||||
},
|
||||
|
||||
{ NS_ISOCKS4SOCKETPROVIDER_CLASSNAME,
|
||||
{ "nsSOCKS4SocketProvider",
|
||||
NS_SOCKS4SOCKETPROVIDER_CID,
|
||||
NS_ISOCKS4SOCKETPROVIDER_CONTRACTID,
|
||||
nsSOCKS4SocketProvider::Create
|
||||
NS_NETWORK_SOCKET_CONTRACTID_PREFIX "socks4",
|
||||
nsSOCKSSocketProvider::CreateV4
|
||||
},
|
||||
|
||||
{ NS_CACHESERVICE_CLASSNAME,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# vim: noexpandtab ts=8 sw=8
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
|
@ -31,10 +32,11 @@ XPIDL_MODULE = necko_dns
|
|||
GRE_MODULE = 1
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIDNSListener.idl \
|
||||
nsIDNSService.idl \
|
||||
nsIDNSListener.idl \
|
||||
nsIDNSRequest.idl \
|
||||
nsIDNSRecord.idl \
|
||||
nsIIDNService.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
|
|
@ -1,73 +1,62 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
* The Initial Developer of the Original Code is IBM Corporation.
|
||||
* Portions created by IBM Corporation are Copyright (C) 2003
|
||||
* IBM Corporation. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* IBM Corp.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
%{C++
|
||||
#include "prnetdb.h"
|
||||
interface nsIDNSRequest;
|
||||
interface nsIDNSRecord;
|
||||
|
||||
typedef struct nsHostEnt
|
||||
{
|
||||
PRHostEnt hostEnt;
|
||||
char buffer[PR_NETDB_BUF_SIZE];
|
||||
PRIntn bufLen;
|
||||
char * bufPtr;
|
||||
} nsHostEnt;
|
||||
%}
|
||||
|
||||
[ptr] native nsHostEntStar(nsHostEnt);
|
||||
|
||||
[scriptable, uuid(7686cef0-206e-11d3-9348-00104ba0fd40)]
|
||||
/**
|
||||
* nsIDNSListener
|
||||
*/
|
||||
[scriptable, uuid(36413eba-3a2a-444d-b88e-df9b6d306b73)]
|
||||
interface nsIDNSListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Notify the listener that we are about to lookup the requested hostname.
|
||||
* called when an asynchronous host lookup completes.
|
||||
*
|
||||
* @param aRequest
|
||||
* the value returned from asyncResolve.
|
||||
* @param aRecord
|
||||
* the DNS record corresponding to the hostname that was resolved.
|
||||
* this parameter is null if there was an error.
|
||||
* @param aStatus
|
||||
* if the lookup failed, this parameter gives the reason.
|
||||
*/
|
||||
void OnStartLookup(in nsISupports ctxt, in string hostname);
|
||||
|
||||
/**
|
||||
* Notify the listener that we have found one or more addresses for the hostname.
|
||||
*/
|
||||
[noscript] void OnFound(in nsISupports ctxt, in string hostname,
|
||||
in nsHostEntStar entry);
|
||||
|
||||
/**
|
||||
* Notify the listener that the lookup has completed.
|
||||
*/
|
||||
void OnStopLookup(in nsISupports ctxt, in string hostname, in nsresult status);
|
||||
void onLookupComplete(in nsIDNSRequest aRequest,
|
||||
in nsIDNSRecord aRecord,
|
||||
in nsresult aStatus);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is IBM Corporation.
|
||||
* Portions created by IBM Corporation are Copyright (C) 2003
|
||||
* IBM Corporation. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* IBM Corp.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[ptr] native PRNetAddrStar(union PRNetAddr);
|
||||
|
||||
/**
|
||||
* nsIDNSRecord
|
||||
*
|
||||
* this interface represents the result of a DNS lookup. since a DNS
|
||||
* query may return more than one resolved IP address, the record acts
|
||||
* like an enumerator, allowing the caller to easily step through the
|
||||
* list of IP addresses.
|
||||
*/
|
||||
[scriptable, uuid(31c9c52e-1100-457d-abac-d2729e43f506)]
|
||||
interface nsIDNSRecord : nsISupports
|
||||
{
|
||||
/**
|
||||
* @return the canonical hostname for this record.
|
||||
*
|
||||
* e.g., www.mozilla.org --> gila.mozilla.org
|
||||
*/
|
||||
readonly attribute ACString canonicalName;
|
||||
|
||||
/**
|
||||
* this function copies the value of the next IP address into the
|
||||
* given PRNetAddr struct and increments the internal address iterator.
|
||||
*
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if there is not another IP address in
|
||||
* the record.
|
||||
*/
|
||||
[noscript] void getNextAddr(in PRUint16 port, in PRNetAddrStar addr);
|
||||
|
||||
/**
|
||||
* this function returns the value of the next IP address as a
|
||||
* string and increments the internal address iterator.
|
||||
*
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if there is not another IP address in
|
||||
* the record.
|
||||
*/
|
||||
ACString getNextAddrAsString();
|
||||
|
||||
/**
|
||||
* this function returns true if there is another address in the record.
|
||||
*/
|
||||
boolean hasMore();
|
||||
|
||||
/**
|
||||
* this function resets the internal address iterator to the first
|
||||
* address in the record.
|
||||
*/
|
||||
void rewind();
|
||||
};
|
|
@ -0,0 +1,51 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is IBM Corporation.
|
||||
* Portions created by IBM Corporation are Copyright (C) 2003
|
||||
* IBM Corporation. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* IBM Corp.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* nsIDNSRequest
|
||||
*/
|
||||
[scriptable, uuid(3e538aea-d84b-4bf4-bae1-55f9969fe50e)]
|
||||
interface nsIDNSRequest : nsISupports
|
||||
{
|
||||
/**
|
||||
* called to cancel a pending asynchronous DNS request. the listener will
|
||||
* passed to asyncResolve will be notified immediately with a status code
|
||||
* of NS_ERROR_ABORT.
|
||||
*/
|
||||
void cancel();
|
||||
};
|
|
@ -1,83 +1,106 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999
|
||||
* Portions created by the Initial Developer are Copyright (C) 2003
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Gordon Sheridan <gordon@netscape.com>
|
||||
* IBM Corp.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIDNSRecord.idl"
|
||||
#include "nsIDNSRequest.idl"
|
||||
#include "nsIDNSListener.idl"
|
||||
|
||||
%{C++
|
||||
#include "nsNetError.h"
|
||||
interface nsIEventQueue;
|
||||
|
||||
#define NS_DNSSERVICE_CID \
|
||||
{ /* 718e7c81-f8b8-11d2-b951-c80918051d3c */ \
|
||||
0x718e7c81, \
|
||||
0xf8b8, \
|
||||
0x11d2, \
|
||||
{ 0xb9, 0x51, 0xc8, 0x09, 0x18, 0x05, 0x1d, 0x3c } \
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
interface nsIRequest;
|
||||
interface nsIDNSListener;
|
||||
|
||||
[scriptable, uuid(598f2f80-206f-11d3-9348-00104ba0fd40)]
|
||||
/**
|
||||
* nsIDNSService
|
||||
*/
|
||||
[scriptable, uuid(98519315-f139-405e-9182-3339907c29fd)]
|
||||
interface nsIDNSService : nsISupports
|
||||
{
|
||||
nsIRequest lookup(in string hostname,
|
||||
in nsIDNSListener listener,
|
||||
in nsISupports ctxt);
|
||||
|
||||
/**
|
||||
* Synchronously resolve the hostname to its IP address.
|
||||
*/
|
||||
string resolve(in string hostname);
|
||||
|
||||
/**
|
||||
* returns our own IP address
|
||||
*/
|
||||
readonly attribute string myIPAddress;
|
||||
|
||||
/**
|
||||
* Check if the specified address is in the network of the pattern
|
||||
* using the specified mask. This function would probably go away
|
||||
* once an implementation for it in JS exists for nsProxyAutoConfig.
|
||||
* See http://www.mozilla.org/docs/netlib/pac.html for more info.
|
||||
*/
|
||||
boolean isInNet(in string ipaddr, in string pattern, in string mask);
|
||||
|
||||
* called to initialize the DNS service.
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* called to shutdown the DNS service. any pending asynchronous
|
||||
* requests will be canceled, and the local cache of DNS records
|
||||
* will be cleared. NOTE: the operating system may still have
|
||||
* its own cache of DNS records, which would be unaffected by
|
||||
* this method.
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
/**
|
||||
* kicks off an asynchronous host lookup.
|
||||
*
|
||||
* @param aHostName
|
||||
* the hostname or IP-address-literal to resolve.
|
||||
* @param aBypassCache
|
||||
* if true, the internal DNS lookup cache will be bypassed.
|
||||
* @param aListener
|
||||
* the listener to be notified when the result is available.
|
||||
* @param aListenerEventQ
|
||||
* optional parameter (may be null). if non-null, this parameter
|
||||
* specifies the nsIEventQueue of the thread on which the listener's
|
||||
* onLookupComplete should be called. however, if this parameter is
|
||||
* null, then onLookupComplete will be called on an unspecified
|
||||
* thread (possibly recursively).
|
||||
*
|
||||
* @return DNS request instance that can be used to cancel the host lookup.
|
||||
*/
|
||||
nsIDNSRequest asyncResolve(in AUTF8String aHostName,
|
||||
in boolean aBypassCache,
|
||||
in nsIDNSListener aListener,
|
||||
in nsIEventQueue aListenerEventQ);
|
||||
|
||||
/**
|
||||
* called to synchronously resolve a hostname.
|
||||
*
|
||||
* @param aHostName
|
||||
* the hostname or IP-address-literal to resolve.
|
||||
* @param aBypassCache
|
||||
* if true, the internal DNS lookup cache will be bypassed.
|
||||
*
|
||||
* @return DNS record corresponding to the given hostname.
|
||||
* @throws NS_ERROR_UNKNOWN_HOST if host could not be resolved.
|
||||
*/
|
||||
nsIDNSRecord resolve(in AUTF8String aHostName,
|
||||
in boolean aBypassCache);
|
||||
|
||||
/**
|
||||
* @return the hostname of the operating system.
|
||||
*/
|
||||
readonly attribute AUTF8String myHostName;
|
||||
};
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# vim: noexpandtab ts=8 sw=8
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
|
@ -34,16 +35,18 @@ REQUIRES = xpcom \
|
|||
unicharutil \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = nsDnsService.cpp \
|
||||
nsIDNService.cpp
|
||||
CPPSRCS = nsIDNService.cpp \
|
||||
nsDNSService2.cpp \
|
||||
nsHostResolver.cpp \
|
||||
$(NULL)
|
||||
|
||||
CSRCS = race.c \
|
||||
nameprep.c \
|
||||
punycode.c
|
||||
CSRCS = race.c \
|
||||
nameprep.c \
|
||||
punycode.c \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a
|
||||
# static lib.
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
|
|
@ -0,0 +1,456 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is IBM Corporation.
|
||||
* Portions created by IBM Corporation are Copyright (C) 2003
|
||||
* IBM Corporation. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* IBM Corp.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsDNSService2.h"
|
||||
#include "nsIProxyObjectManager.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIPrefBranch.h"
|
||||
#include "nsIPrefBranchInternal.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetError.h"
|
||||
#include "prsystem.h"
|
||||
#include "prnetdb.h"
|
||||
#include "prmon.h"
|
||||
#include "prio.h"
|
||||
|
||||
static const char kPrefDnsCacheEntries[] = "network.dnsCacheEntries";
|
||||
static const char kPrefDnsCacheExpiration[] = "network.dnsCacheExpiration";
|
||||
static const char kPrefEnableIDN[] = "network.enableIDN";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class nsDNSRecord : public nsIDNSRecord
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDNSRECORD
|
||||
|
||||
nsDNSRecord(nsAddrInfo *ai)
|
||||
: mAddrInfo(ai)
|
||||
, mIter(nsnull)
|
||||
, mDone(PR_FALSE) {}
|
||||
|
||||
private:
|
||||
virtual ~nsDNSRecord() {}
|
||||
|
||||
nsRefPtr<nsAddrInfo> mAddrInfo;
|
||||
void *mIter;
|
||||
PRBool mDone;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDNSRecord, nsIDNSRecord)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSRecord::GetCanonicalName(nsACString &result)
|
||||
{
|
||||
NS_ENSURE_TRUE(mAddrInfo, NS_ERROR_NOT_AVAILABLE);
|
||||
result.Assign(PR_GetCanonNameFromAddrInfo(mAddrInfo->get()));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSRecord::GetNextAddr(PRUint16 port, PRNetAddr *addr)
|
||||
{
|
||||
NS_ENSURE_TRUE(mAddrInfo, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
// not a programming error to poke the DNS record when it has
|
||||
// no more entries. just silently fail. this enables consumers
|
||||
// to enumerate the DNS record without calling HasMore.
|
||||
if (mDone)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
mIter = PR_EnumerateAddrInfo(mIter, mAddrInfo->get(), port, addr);
|
||||
mDone = !mIter;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSRecord::GetNextAddrAsString(nsACString &result)
|
||||
{
|
||||
PRNetAddr addr;
|
||||
nsresult rv = GetNextAddr(0, &addr);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
char buf[64];
|
||||
if (PR_NetAddrToString(&addr, buf, sizeof(buf)) == PR_SUCCESS) {
|
||||
result.Assign(buf);
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ERROR("PR_NetAddrToString failed unexpectedly");
|
||||
return NS_ERROR_FAILURE; // conversion failed for some reason
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSRecord::HasMore(PRBool *result)
|
||||
{
|
||||
*result = !mDone;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSRecord::Rewind()
|
||||
{
|
||||
mIter = nsnull;
|
||||
mDone = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class nsDNSAsyncRequest : public nsResolveHostCB
|
||||
, public nsIDNSRequest
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDNSREQUEST
|
||||
|
||||
nsDNSAsyncRequest(nsHostResolver *res,
|
||||
const nsACString &host,
|
||||
nsIDNSListener *listener)
|
||||
: mResolver(res)
|
||||
, mHost(host)
|
||||
, mListener(listener) {}
|
||||
virtual ~nsDNSAsyncRequest() {}
|
||||
|
||||
void OnLookupComplete(nsHostResolver *, const char *, nsresult, nsAddrInfo *);
|
||||
|
||||
nsRefPtr<nsHostResolver> mResolver;
|
||||
nsCString mHost; // hostname we're resolving
|
||||
nsCOMPtr<nsIDNSListener> mListener;
|
||||
};
|
||||
|
||||
void
|
||||
nsDNSAsyncRequest::OnLookupComplete(nsHostResolver *resolver,
|
||||
const char *host,
|
||||
nsresult status,
|
||||
nsAddrInfo *ai)
|
||||
{
|
||||
nsDNSRecord *rec;
|
||||
if (!ai)
|
||||
rec = nsnull;
|
||||
else {
|
||||
rec = new nsDNSRecord(ai);
|
||||
if (!rec)
|
||||
status = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
mListener->OnLookupComplete(this, rec, status);
|
||||
mListener = nsnull;
|
||||
|
||||
// release the reference to ourselves that was added before we were
|
||||
// handed off to the host resolver.
|
||||
NS_RELEASE_THIS();
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDNSAsyncRequest, nsIDNSRequest)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSAsyncRequest::Cancel()
|
||||
{
|
||||
mResolver->DetachCallback(mHost.get(), this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class nsDNSSyncRequest : public nsResolveHostCB
|
||||
{
|
||||
public:
|
||||
nsDNSSyncRequest(PRMonitor *mon)
|
||||
: mDone(PR_FALSE)
|
||||
, mStatus(NS_OK)
|
||||
, mMonitor(mon) {}
|
||||
virtual ~nsDNSSyncRequest() {}
|
||||
|
||||
void OnLookupComplete(nsHostResolver *, const char *, nsresult, nsAddrInfo *);
|
||||
|
||||
PRBool mDone;
|
||||
nsresult mStatus;
|
||||
nsRefPtr<nsAddrInfo> mAddrInfo;
|
||||
|
||||
private:
|
||||
PRMonitor *mMonitor;
|
||||
};
|
||||
|
||||
void
|
||||
nsDNSSyncRequest::OnLookupComplete(nsHostResolver *resolver,
|
||||
const char *host,
|
||||
nsresult status,
|
||||
nsAddrInfo *ai)
|
||||
{
|
||||
// store results, and wake up nsDNSService::Resolve to process results.
|
||||
PR_EnterMonitor(mMonitor);
|
||||
mDone = PR_TRUE;
|
||||
mStatus = status;
|
||||
mAddrInfo = ai;
|
||||
PR_Notify(mMonitor);
|
||||
PR_ExitMonitor(mMonitor);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
nsDNSService::nsDNSService()
|
||||
: mLock(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
nsDNSService::~nsDNSService()
|
||||
{
|
||||
if (mLock)
|
||||
PR_DestroyLock(mLock);
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsDNSService, nsIDNSService, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSService::Init()
|
||||
{
|
||||
NS_ENSURE_TRUE(!mResolver, NS_ERROR_ALREADY_INITIALIZED);
|
||||
|
||||
PRBool firstTime = (mLock == nsnull);
|
||||
|
||||
// prefs
|
||||
PRUint32 maxCacheEntries = 20;
|
||||
PRUint32 maxCacheLifetime = 5; // minutes
|
||||
PRBool enableIDN = PR_TRUE;
|
||||
|
||||
// read prefs
|
||||
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
if (prefs) {
|
||||
PRInt32 val;
|
||||
if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheEntries, &val)))
|
||||
maxCacheEntries = val;
|
||||
if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheExpiration, &val)))
|
||||
maxCacheLifetime = (val / 60); // convert from seconds to minutes
|
||||
if (NS_SUCCEEDED(prefs->GetBoolPref(kPrefEnableIDN, (PRBool*)&val)))
|
||||
enableIDN = (PRBool) val;
|
||||
}
|
||||
|
||||
// we have to null out mIDN since we might be getting re-initialized
|
||||
// as a result of a pref change.
|
||||
if (enableIDN)
|
||||
mIDN = do_GetService(NS_IDNSERVICE_CONTRACTID);
|
||||
else
|
||||
mIDN = nsnull;
|
||||
|
||||
if (firstTime) {
|
||||
mLock = PR_NewLock();
|
||||
if (!mLock)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// register as prefs observer
|
||||
nsCOMPtr<nsIPrefBranchInternal> prefsInt = do_QueryInterface(prefs);
|
||||
if (prefsInt) {
|
||||
prefsInt->AddObserver(kPrefDnsCacheEntries, this, PR_FALSE);
|
||||
prefsInt->AddObserver(kPrefDnsCacheExpiration, this, PR_FALSE);
|
||||
prefsInt->AddObserver(kPrefEnableIDN, this, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return nsHostResolver::Create(maxCacheEntries,
|
||||
maxCacheLifetime,
|
||||
getter_AddRefs(mResolver));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSService::Shutdown()
|
||||
{
|
||||
nsRefPtr<nsHostResolver> res;
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
res = mResolver;
|
||||
mResolver = nsnull;
|
||||
}
|
||||
if (res)
|
||||
res->Shutdown();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSService::AsyncResolve(const nsACString &hostname,
|
||||
PRBool bypassCache,
|
||||
nsIDNSListener *listener,
|
||||
nsIEventQueue *eventQ,
|
||||
nsIDNSRequest **result)
|
||||
{
|
||||
// grab reference to global host resolver and IDN service. beware
|
||||
// simultaneous shutdown!!
|
||||
nsRefPtr<nsHostResolver> res;
|
||||
nsCOMPtr<nsIIDNService> idn;
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
res = mResolver;
|
||||
idn = mIDN;
|
||||
}
|
||||
NS_ENSURE_TRUE(res, NS_ERROR_OFFLINE);
|
||||
|
||||
const nsACString *hostPtr = &hostname;
|
||||
|
||||
nsresult rv;
|
||||
nsCAutoString hostBuf;
|
||||
if (idn && !IsASCII(hostname)) {
|
||||
rv = idn->ConvertUTF8toACE(hostname, hostBuf);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
hostPtr = &hostBuf;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDNSListener> listenerProxy;
|
||||
if (eventQ) {
|
||||
rv = NS_GetProxyForObject(eventQ,
|
||||
NS_GET_IID(nsIDNSListener),
|
||||
listener,
|
||||
PROXY_ASYNC | PROXY_ALWAYS,
|
||||
getter_AddRefs(listenerProxy));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
listener = listenerProxy;
|
||||
}
|
||||
|
||||
nsDNSAsyncRequest *req = new nsDNSAsyncRequest(res, *hostPtr, listener);
|
||||
if (!req)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(*result = req);
|
||||
|
||||
// addref for resolver; will be released when OnLookupComplete is called.
|
||||
NS_ADDREF(req);
|
||||
rv = res->ResolveHost(req->mHost.get(), bypassCache, req);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(req);
|
||||
NS_RELEASE(*result);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSService::Resolve(const nsACString &hostname,
|
||||
PRBool bypassCache,
|
||||
nsIDNSRecord **result)
|
||||
{
|
||||
// grab reference to global host resolver and IDN service. beware
|
||||
// simultaneous shutdown!!
|
||||
nsRefPtr<nsHostResolver> res;
|
||||
nsCOMPtr<nsIIDNService> idn;
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
res = mResolver;
|
||||
idn = mIDN;
|
||||
}
|
||||
NS_ENSURE_TRUE(res, NS_ERROR_OFFLINE);
|
||||
|
||||
const nsACString *hostPtr = &hostname;
|
||||
|
||||
nsresult rv;
|
||||
nsCAutoString hostBuf;
|
||||
if (idn && !IsASCII(hostname)) {
|
||||
rv = idn->ConvertUTF8toACE(hostname, hostBuf);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
hostPtr = &hostBuf;
|
||||
}
|
||||
|
||||
//
|
||||
// sync resolve: since the host resolver only works asynchronously, we need
|
||||
// to use a mutex and a condvar to wait for the result. however, since the
|
||||
// result may be in the resolvers cache, we might get called back recursively
|
||||
// on the same thread. so, our mutex needs to be re-entrant. inotherwords,
|
||||
// we need to use a monitor! ;-)
|
||||
//
|
||||
|
||||
PRMonitor *mon = PR_NewMonitor();
|
||||
if (!mon)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
PR_EnterMonitor(mon);
|
||||
nsDNSSyncRequest syncReq(mon);
|
||||
|
||||
rv = res->ResolveHost(PromiseFlatCString(*hostPtr).get(), bypassCache, &syncReq);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// wait for result
|
||||
while (!syncReq.mDone)
|
||||
PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
|
||||
|
||||
if (NS_FAILED(syncReq.mStatus))
|
||||
rv = syncReq.mStatus;
|
||||
else {
|
||||
nsDNSRecord *rec = new nsDNSRecord(syncReq.mAddrInfo);
|
||||
if (!rec)
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
else
|
||||
NS_ADDREF(*result = rec);
|
||||
}
|
||||
}
|
||||
|
||||
PR_ExitMonitor(mon);
|
||||
PR_DestroyMonitor(mon);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSService::GetMyHostName(nsACString &result)
|
||||
{
|
||||
char name[100];
|
||||
if (PR_GetSystemInfo(PR_SI_HOSTNAME, name, sizeof(name)) == PR_SUCCESS) {
|
||||
result = name;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSService::Observe(nsISupports *subject, const char *topic, const PRUnichar *data)
|
||||
{
|
||||
// we are only getting called if a preference has changed.
|
||||
NS_ASSERTION(strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0,
|
||||
"unexpected observe call");
|
||||
|
||||
//
|
||||
// Shutdown and this function are both only called on the UI thread, so we don't
|
||||
// have to worry about mResolver being cleared out from under us.
|
||||
//
|
||||
// NOTE Shutting down and reinitializing the service like this is obviously
|
||||
// suboptimal if Observe gets called several times in a row, but we don't
|
||||
// expect that to be the case.
|
||||
//
|
||||
|
||||
if (mResolver) {
|
||||
Shutdown();
|
||||
Init();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is IBM Corporation.
|
||||
* Portions created by IBM Corporation are Copyright (C) 2003
|
||||
* IBM Corporation. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* IBM Corp.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsIIDNService.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsHostResolver.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "prlock.h"
|
||||
|
||||
class nsDNSService : public nsIDNSService
|
||||
, public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDNSSERVICE
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
nsDNSService();
|
||||
virtual ~nsDNSService();
|
||||
|
||||
private:
|
||||
nsRefPtr<nsHostResolver> mResolver;
|
||||
nsCOMPtr<nsIIDNService> mIDN;
|
||||
PRLock *mLock;
|
||||
|
||||
// mLock protects access to mResolver
|
||||
};
|
|
@ -0,0 +1,602 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is IBM Corporation.
|
||||
* Portions created by IBM Corporation are Copyright (C) 2003
|
||||
* IBM Corporation. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* IBM Corp.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#if defined(HAVE_RES_NINIT)
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
#define RES_RETRY_ON_FAILURE
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "nsHostResolver.h"
|
||||
#include "nsNetError.h"
|
||||
#include "nsISupportsBase.h"
|
||||
#include "nsISupportsUtils.h"
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "pratom.h"
|
||||
#include "prthread.h"
|
||||
#include "prerror.h"
|
||||
#include "prcvar.h"
|
||||
#include "prtime.h"
|
||||
#include "prlong.h"
|
||||
#include "pldhash.h"
|
||||
#include "plstr.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#define MAX_THREADS 8
|
||||
#define THREAD_IDLE_TIMEOUT PR_SecondsToInterval(5)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//#define DEBUG_HOST_RESOLVER
|
||||
#ifdef DEBUG_HOST_RESOLVER
|
||||
#define LOG(args) printf args
|
||||
#else
|
||||
#define LOG(args)
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static inline void
|
||||
MoveCList(PRCList &from, PRCList &to)
|
||||
{
|
||||
if (!PR_CLIST_IS_EMPTY(&from)) {
|
||||
to.next = from.next;
|
||||
to.prev = from.prev;
|
||||
to.next->prev = &to;
|
||||
to.prev->next = &to;
|
||||
PR_INIT_CLIST(&from);
|
||||
}
|
||||
}
|
||||
|
||||
static PRUint32
|
||||
NowInMinutes()
|
||||
{
|
||||
PRTime now = PR_Now(), minutes, factor;
|
||||
LL_I2L(factor, 60 * PR_USEC_PER_SEC);
|
||||
LL_DIV(minutes, now, factor);
|
||||
PRUint32 result;
|
||||
LL_L2UI(result, minutes);
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if defined(RES_RETRY_ON_FAILURE)
|
||||
|
||||
// this class represents the resolver state for a given thread. if we
|
||||
// encounter a lookup failure, then we can invoke the Reset method on an
|
||||
// instance of this class to reset the resolver (in case /etc/resolv.conf
|
||||
// for example changed). this is mainly an issue on GNU systems since glibc
|
||||
// only reads in /etc/resolv.conf once per thread. it may be an issue on
|
||||
// other systems as well.
|
||||
|
||||
class nsResState
|
||||
{
|
||||
public:
|
||||
nsResState()
|
||||
// initialize mLastReset to the time when this object
|
||||
// is created. this means that a reset will not occur
|
||||
// if a thread is too young. the alternative would be
|
||||
// to initialize this to the beginning of time, so that
|
||||
// the first failure would cause a reset, but since the
|
||||
// thread would have just started up, it likely would
|
||||
// already have current /etc/resolv.conf info.
|
||||
: mLastReset(PR_IntervalNow())
|
||||
{
|
||||
}
|
||||
|
||||
PRBool Reset()
|
||||
{
|
||||
// reset no more than once per second
|
||||
if (PR_IntervalToSeconds(PR_IntervalNow() - mLastReset) < 1)
|
||||
return PR_FALSE;
|
||||
|
||||
LOG(("calling res_ninit\n"));
|
||||
|
||||
mLastReset = PR_IntervalNow();
|
||||
return (res_ninit(&_res) == 0);
|
||||
}
|
||||
|
||||
private:
|
||||
PRIntervalTime mLastReset;
|
||||
};
|
||||
|
||||
#endif // RES_RETRY_ON_FAILURE
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class nsHostRecord : public PRCList
|
||||
{
|
||||
public:
|
||||
NET_DECL_REFCOUNTED_THREADSAFE
|
||||
|
||||
nsHostRecord(const char *h)
|
||||
: host(PL_strdup(h))
|
||||
, expireTime(NowInMinutes())
|
||||
, mRefCount(0)
|
||||
{
|
||||
PR_INIT_CLIST(this);
|
||||
PR_INIT_CLIST(&callbacks);
|
||||
}
|
||||
~nsHostRecord()
|
||||
{
|
||||
PL_strfree(host);
|
||||
}
|
||||
|
||||
char *host;
|
||||
nsRefPtr<nsAddrInfo> addr;
|
||||
PRUint32 expireTime; // minutes since epoch
|
||||
PRCList callbacks;
|
||||
|
||||
private:
|
||||
PRInt32 mRefCount;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
struct nsHostDBEnt : PLDHashEntryHdr
|
||||
{
|
||||
nsHostRecord *rec;
|
||||
};
|
||||
|
||||
static const void * PR_CALLBACK
|
||||
HostDB_GetKey(PLDHashTable *table, PLDHashEntryHdr *entry)
|
||||
{
|
||||
nsHostDBEnt *he = NS_STATIC_CAST(nsHostDBEnt *, entry);
|
||||
return he->rec->host;
|
||||
}
|
||||
|
||||
static PRBool PR_CALLBACK
|
||||
HostDB_MatchEntry(PLDHashTable *table,
|
||||
const PLDHashEntryHdr *entry,
|
||||
const void *key)
|
||||
{
|
||||
const nsHostDBEnt *he = NS_STATIC_CAST(const nsHostDBEnt *, entry);
|
||||
return !strcmp(he->rec->host, (const char *) key);
|
||||
}
|
||||
|
||||
static void PR_CALLBACK
|
||||
HostDB_MoveEntry(PLDHashTable *table,
|
||||
const PLDHashEntryHdr *from,
|
||||
PLDHashEntryHdr *to)
|
||||
{
|
||||
NS_STATIC_CAST(nsHostDBEnt *, to)->rec =
|
||||
NS_STATIC_CAST(const nsHostDBEnt *, from)->rec;
|
||||
}
|
||||
|
||||
static void PR_CALLBACK
|
||||
HostDB_ClearEntry(PLDHashTable *table,
|
||||
PLDHashEntryHdr *entry)
|
||||
{
|
||||
nsHostDBEnt *he = NS_STATIC_CAST(nsHostDBEnt *, entry);
|
||||
#ifdef DEBUG_HOST_RESOLVER
|
||||
if (!he->rec->addr)
|
||||
LOG(("%s: => null\n", he->rec->host));
|
||||
else {
|
||||
PRInt32 now = (PRInt32) NowInMinutes();
|
||||
PRInt32 diff = (PRInt32) he->rec->expireTime - now;
|
||||
LOG(("%s: exp=%d => %s\n",
|
||||
he->rec->host, diff,
|
||||
PR_GetCanonNameFromAddrInfo(he->rec->addr->get())));
|
||||
void *iter = nsnull;
|
||||
PRNetAddr addr;
|
||||
char buf[64];
|
||||
do {
|
||||
iter = PR_EnumerateAddrInfo(iter, he->rec->addr->get(), 0, &addr);
|
||||
PR_NetAddrToString(&addr, buf, sizeof(buf));
|
||||
LOG((" %s\n", buf));
|
||||
} while (iter);
|
||||
}
|
||||
#endif
|
||||
NS_RELEASE(he->rec);
|
||||
}
|
||||
|
||||
static PRBool PR_CALLBACK
|
||||
HostDB_InitEntry(PLDHashTable *table,
|
||||
PLDHashEntryHdr *entry,
|
||||
const void *key)
|
||||
{
|
||||
nsHostDBEnt *he = NS_STATIC_CAST(nsHostDBEnt *, entry);
|
||||
he->rec = new nsHostRecord(NS_REINTERPRET_CAST(const char *, key));
|
||||
// addref result if initialized correctly; otherwise, leave record
|
||||
// null so caller can detect and propagate error.
|
||||
if (he->rec) {
|
||||
if (he->rec->host)
|
||||
NS_ADDREF(he->rec);
|
||||
else {
|
||||
delete he->rec;
|
||||
he->rec = nsnull;
|
||||
}
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PLDHashTableOps gHostDB_ops =
|
||||
{
|
||||
PL_DHashAllocTable,
|
||||
PL_DHashFreeTable,
|
||||
HostDB_GetKey,
|
||||
PL_DHashStringKey,
|
||||
HostDB_MatchEntry,
|
||||
HostDB_MoveEntry,
|
||||
HostDB_ClearEntry,
|
||||
PL_DHashFinalizeStub,
|
||||
HostDB_InitEntry,
|
||||
};
|
||||
|
||||
static PLDHashOperator PR_CALLBACK
|
||||
HostDB_RemoveEntry(PLDHashTable *table,
|
||||
PLDHashEntryHdr *hdr,
|
||||
PRUint32 number,
|
||||
void *arg)
|
||||
{
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
nsHostResolver::nsHostResolver(PRUint32 maxCacheEntries,
|
||||
PRUint32 maxCacheLifetime)
|
||||
: mRefCount(0)
|
||||
, mMaxCacheEntries(maxCacheEntries)
|
||||
, mMaxCacheLifetime(maxCacheLifetime)
|
||||
, mLock(nsnull)
|
||||
, mIdleThreadCV(nsnull)
|
||||
, mHaveIdleThread(PR_FALSE)
|
||||
, mThreadCount(0)
|
||||
, mEvictionQSize(0)
|
||||
, mShutdown(PR_TRUE)
|
||||
{
|
||||
mCreationTime = PR_Now();
|
||||
PR_INIT_CLIST(&mPendingQ);
|
||||
PR_INIT_CLIST(&mEvictionQ);
|
||||
}
|
||||
|
||||
nsHostResolver::~nsHostResolver()
|
||||
{
|
||||
if (mIdleThreadCV)
|
||||
PR_DestroyCondVar(mIdleThreadCV);
|
||||
|
||||
if (mLock)
|
||||
PR_DestroyLock(mLock);
|
||||
|
||||
PL_DHashTableFinish(&mDB);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHostResolver::Init()
|
||||
{
|
||||
mLock = PR_NewLock();
|
||||
if (!mLock)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mIdleThreadCV = PR_NewCondVar(mLock);
|
||||
if (!mIdleThreadCV)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
PL_DHashTableInit(&mDB, &gHostDB_ops, nsnull, sizeof(nsHostDBEnt), 0);
|
||||
|
||||
mShutdown = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsHostResolver::Shutdown()
|
||||
{
|
||||
LOG(("nsHostResolver::Shutdown\n"));
|
||||
|
||||
PRCList pendingQ;
|
||||
PR_INIT_CLIST(&pendingQ);
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
mShutdown = PR_TRUE;
|
||||
|
||||
MoveCList(mPendingQ, pendingQ);
|
||||
|
||||
if (mHaveIdleThread)
|
||||
PR_NotifyCondVar(mIdleThreadCV);
|
||||
|
||||
// empty host database
|
||||
PL_DHashTableEnumerate(&mDB, HostDB_RemoveEntry, nsnull);
|
||||
}
|
||||
|
||||
// loop through pending queue, erroring out pending lookups.
|
||||
if (!PR_CLIST_IS_EMPTY(&pendingQ)) {
|
||||
PRCList *node = pendingQ.next;
|
||||
while (node != &pendingQ) {
|
||||
nsHostRecord *rec = NS_STATIC_CAST(nsHostRecord *, node);
|
||||
node = node->next;
|
||||
OnLookupComplete(rec, NS_ERROR_ABORT, nsnull);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHostResolver::ResolveHost(const char *host,
|
||||
PRBool bypassCache,
|
||||
nsResolveHostCB *callback)
|
||||
{
|
||||
NS_ENSURE_TRUE(host && *host, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
if (mShutdown)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
// check to see if there is already an entry for this |host|
|
||||
// in the hash table. if so, then check to see if we can't
|
||||
// just reuse the lookup result. otherwise, if there are
|
||||
// any pending callbacks, then add to pending callbacks queue,
|
||||
// and return. otherwise, add ourselves as first pending
|
||||
// callback, and proceed to do the lookup.
|
||||
|
||||
PLDHashEntryHdr *hdr;
|
||||
|
||||
hdr = PL_DHashTableOperate(&mDB, host, PL_DHASH_ADD);
|
||||
if (!hdr)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsHostDBEnt *he = NS_STATIC_CAST(nsHostDBEnt *, hdr);
|
||||
if (!he->rec)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
else if (!bypassCache &&
|
||||
he->rec->addr && NowInMinutes() <= he->rec->expireTime) {
|
||||
// ok, we can reuse this result. but, since we are
|
||||
// making a callback, we must only do so outside the
|
||||
// lock, and that requires holding an owning reference
|
||||
// to the addrinfo structure.
|
||||
nsRefPtr<nsAddrInfo> ai = he->rec->addr;
|
||||
lock.unlock();
|
||||
callback->OnLookupComplete(this, host, NS_OK, ai);
|
||||
lock.lock();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool doLookup = PR_CLIST_IS_EMPTY(&he->rec->callbacks);
|
||||
|
||||
// add callback to the list of pending callbacks
|
||||
PR_APPEND_LINK(callback, &he->rec->callbacks);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (doLookup) {
|
||||
rv = IssueLookup(he->rec);
|
||||
if (NS_FAILED(rv))
|
||||
PR_REMOVE_AND_INIT_LINK(callback);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsHostResolver::DetachCallback(const char *host,
|
||||
nsResolveHostCB *callback)
|
||||
{
|
||||
PRBool doCallback = PR_FALSE;
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
nsHostDBEnt *he = NS_STATIC_CAST(nsHostDBEnt *,
|
||||
PL_DHashTableOperate(&mDB, host, PL_DHASH_LOOKUP));
|
||||
if (he && he->rec) {
|
||||
// walk list looking for |callback|... we cannot assume
|
||||
// that it will be there!
|
||||
PRCList *node = he->rec->callbacks.next;
|
||||
while (node != &he->rec->callbacks) {
|
||||
if (NS_STATIC_CAST(nsResolveHostCB *, node) == callback) {
|
||||
PR_REMOVE_LINK(callback);
|
||||
doCallback = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doCallback)
|
||||
callback->OnLookupComplete(this, host, NS_ERROR_ABORT, nsnull);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHostResolver::IssueLookup(nsHostRecord *rec)
|
||||
{
|
||||
// add rec to mPendingQ, possibly removing it from mEvictionQ.
|
||||
// if rec is on mEvictionQ, then we can just move the owning
|
||||
// reference over to mPendingQ.
|
||||
if (rec->next == rec)
|
||||
NS_ADDREF(rec);
|
||||
else {
|
||||
PR_REMOVE_LINK(rec);
|
||||
mEvictionQSize--;
|
||||
}
|
||||
PR_APPEND_LINK(rec, &mPendingQ);
|
||||
|
||||
if (mHaveIdleThread) {
|
||||
// wake up idle thread to process this lookup
|
||||
PR_NotifyCondVar(mIdleThreadCV);
|
||||
}
|
||||
else if (mThreadCount < MAX_THREADS) {
|
||||
// dispatch new worker thread
|
||||
NS_ADDREF_THIS(); // owning reference passed to thread
|
||||
mThreadCount++;
|
||||
PRThread *thr = PR_CreateThread(PR_SYSTEM_THREAD,
|
||||
ThreadFunc,
|
||||
this,
|
||||
PR_PRIORITY_NORMAL,
|
||||
PR_GLOBAL_THREAD,
|
||||
PR_UNJOINABLE_THREAD,
|
||||
0);
|
||||
if (!thr) {
|
||||
mThreadCount--;
|
||||
NS_RELEASE_THIS();
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHostResolver::GetHostToLookup(nsHostRecord **result)
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
while (PR_CLIST_IS_EMPTY(&mPendingQ) && !mHaveIdleThread && !mShutdown) {
|
||||
// become the idle thread and wait for a lookup
|
||||
mHaveIdleThread = PR_TRUE;
|
||||
PR_WaitCondVar(mIdleThreadCV, THREAD_IDLE_TIMEOUT);
|
||||
mHaveIdleThread = PR_FALSE;
|
||||
}
|
||||
|
||||
if (!PR_CLIST_IS_EMPTY(&mPendingQ)) {
|
||||
// remove next record from mPendingQ; hand over owning reference.
|
||||
*result = NS_STATIC_CAST(nsHostRecord *, mPendingQ.next);
|
||||
PR_REMOVE_AND_INIT_LINK(*result);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
// tell thread to exit...
|
||||
mThreadCount--;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsHostResolver::OnLookupComplete(nsHostRecord *rec, nsresult status, PRAddrInfo *result)
|
||||
{
|
||||
nsAddrInfo *ai;
|
||||
if (!result)
|
||||
ai = nsnull;
|
||||
else {
|
||||
ai = new nsAddrInfo(result);
|
||||
if (!ai) {
|
||||
status = NS_ERROR_OUT_OF_MEMORY;
|
||||
PR_FreeAddrInfo(result);
|
||||
}
|
||||
}
|
||||
|
||||
// get the list of pending callbacks for this lookup, and notify
|
||||
// them that the lookup is complete.
|
||||
PRCList cbs;
|
||||
PR_INIT_CLIST(&cbs);
|
||||
{
|
||||
nsAutoLock lock(mLock);
|
||||
|
||||
MoveCList(rec->callbacks, cbs);
|
||||
rec->addr = ai;
|
||||
rec->expireTime = NowInMinutes() + mMaxCacheLifetime;
|
||||
|
||||
if (rec->addr) {
|
||||
// add to mEvictionQ
|
||||
PR_APPEND_LINK(rec, &mEvictionQ);
|
||||
NS_ADDREF(rec);
|
||||
if (mEvictionQSize < mMaxCacheEntries)
|
||||
mEvictionQSize++;
|
||||
else {
|
||||
// remove last element on mEvictionQ
|
||||
nsHostRecord *tail =
|
||||
NS_STATIC_CAST(nsHostRecord *, PR_LIST_TAIL(&mEvictionQ));
|
||||
PR_REMOVE_AND_INIT_LINK(tail);
|
||||
PL_DHashTableOperate(&mDB, tail->host, PL_DHASH_REMOVE);
|
||||
// release reference to rec owned by mEvictionQ
|
||||
NS_RELEASE(tail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!PR_CLIST_IS_EMPTY(&cbs)) {
|
||||
PRCList *node = cbs.next;
|
||||
while (node != &cbs) {
|
||||
nsResolveHostCB *callback = NS_STATIC_CAST(nsResolveHostCB *, node);
|
||||
node = node->next;
|
||||
callback->OnLookupComplete(this, rec->host, status, ai);
|
||||
// NOTE: callback must not be dereferenced after this point!!
|
||||
}
|
||||
}
|
||||
|
||||
NS_RELEASE(rec);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void PR_CALLBACK
|
||||
nsHostResolver::ThreadFunc(void *arg)
|
||||
{
|
||||
#if defined(RES_RETRY_ON_FAILURE)
|
||||
nsResState rs;
|
||||
#endif
|
||||
|
||||
nsHostResolver *resolver = (nsHostResolver *) arg;
|
||||
nsHostRecord *rec;
|
||||
PRAddrInfo *ai;
|
||||
while (resolver->GetHostToLookup(&rec)) {
|
||||
LOG(("[%p] resolving %s ...\n", (void*)PR_GetCurrentThread(), rec->host));
|
||||
ai = PR_GetAddrInfoByName(rec->host, PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
|
||||
#if defined(RES_RETRY_ON_FAILURE)
|
||||
if (!ai && rs.Reset())
|
||||
ai = PR_GetAddrInfoByName(rec->host, PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
|
||||
#endif
|
||||
// convert error code to nsresult.
|
||||
nsresult status = ai ? NS_OK : NS_ERROR_UNKNOWN_HOST;
|
||||
resolver->OnLookupComplete(rec, status, ai);
|
||||
}
|
||||
NS_RELEASE(resolver);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
nsHostResolver::Create(PRUint32 maxCacheEntries,
|
||||
PRUint32 maxCacheLifetime,
|
||||
nsHostResolver **result)
|
||||
{
|
||||
nsHostResolver *res = new nsHostResolver(maxCacheEntries,
|
||||
maxCacheLifetime);
|
||||
if (!res)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(res);
|
||||
|
||||
nsresult rv = res->Init();
|
||||
if (NS_FAILED(rv))
|
||||
NS_RELEASE(res);
|
||||
|
||||
*result = res;
|
||||
return rv;
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is IBM Corporation.
|
||||
* Portions created by IBM Corporation are Copyright (C) 2003
|
||||
* IBM Corporation. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* IBM Corp.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsHostResolver_h__
|
||||
#define nsHostResolver_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "pratom.h"
|
||||
#include "prcvar.h"
|
||||
#include "prclist.h"
|
||||
#include "prnetdb.h"
|
||||
#include "pldhash.h"
|
||||
|
||||
class nsHostResolver;
|
||||
class nsHostRecord;
|
||||
class nsResolveHostCB;
|
||||
class nsAddrInfo;
|
||||
|
||||
/* XXX move this someplace more generic */
|
||||
#define NET_DECL_REFCOUNTED_THREADSAFE \
|
||||
PRInt32 AddRef() { \
|
||||
return PR_AtomicIncrement(&mRefCount); \
|
||||
} \
|
||||
PRInt32 Release() { \
|
||||
PRInt32 n = PR_AtomicDecrement(&mRefCount); \
|
||||
if (n == 0) \
|
||||
delete this; \
|
||||
return n; \
|
||||
}
|
||||
|
||||
/**
|
||||
* reference counted wrapper around PRAddrInfo. these are stored in
|
||||
* the DNS cache.
|
||||
*/
|
||||
class nsAddrInfo
|
||||
{
|
||||
public:
|
||||
NET_DECL_REFCOUNTED_THREADSAFE
|
||||
|
||||
nsAddrInfo(PRAddrInfo *data)
|
||||
: mRefCount(0)
|
||||
, mData(data) {}
|
||||
|
||||
const PRAddrInfo *get() const { return mData; }
|
||||
|
||||
private:
|
||||
nsAddrInfo(); // never called
|
||||
~nsAddrInfo() { if (mData) PR_FreeAddrInfo(mData); }
|
||||
|
||||
PRInt32 mRefCount;
|
||||
PRAddrInfo *mData;
|
||||
};
|
||||
|
||||
/**
|
||||
* ResolveHost callback object. It's PRCList members are used by
|
||||
* the nsHostResolver and should not be used by anything else.
|
||||
*/
|
||||
class nsResolveHostCB : public PRCList
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* LookupComplete
|
||||
*
|
||||
* Runs on an unspecified background thread.
|
||||
*
|
||||
* @param resolver
|
||||
* nsHostResolver object associated with this result
|
||||
* @param host
|
||||
* hostname that was resolved
|
||||
* @param status
|
||||
* if successful, |result| will be non-null
|
||||
* @param result
|
||||
* resulting nsAddrInfo object
|
||||
*/
|
||||
virtual void OnLookupComplete(nsHostResolver *resolver,
|
||||
const char *host,
|
||||
nsresult status,
|
||||
nsAddrInfo *result) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~nsResolveHostCB() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* nsHostResolver: an asynchronous hostname resolver.
|
||||
*/
|
||||
class nsHostResolver
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* creates an addref'd instance of a nsHostResolver object.
|
||||
*/
|
||||
static nsresult Create(PRUint32 maxCacheEntries, // zero disables cache
|
||||
PRUint32 maxCacheLifetime, // minutes
|
||||
nsHostResolver **resolver);
|
||||
|
||||
/**
|
||||
* puts the resolver in the shutdown state, which will cause any pending
|
||||
* callbacks to be detached. any future calls to ResolveHost will fail.
|
||||
*/
|
||||
void Shutdown();
|
||||
|
||||
/**
|
||||
* host resolver instances are reference counted.
|
||||
*/
|
||||
NET_DECL_REFCOUNTED_THREADSAFE
|
||||
|
||||
/**
|
||||
* resolve the given hostname asynchronously. the caller can synthesize
|
||||
* a synchronous host lookup using a lock and a cvar. as noted above
|
||||
* the callback will occur re-entrantly from an unspecified thread. the
|
||||
* host lookup cannot be canceled (cancelation can be layered above this
|
||||
* by having the callback implementation return without doing anything).
|
||||
*/
|
||||
nsresult ResolveHost(const char *hostname,
|
||||
PRBool bypassCache,
|
||||
nsResolveHostCB *callback);
|
||||
|
||||
/**
|
||||
* removes the specified callback from the nsHostRecord for the given
|
||||
* hostname. this function executes the callback if the callback is
|
||||
* still pending with the status failure code NS_ERROR_ABORT.
|
||||
*/
|
||||
void DetachCallback(const char *hostname,
|
||||
nsResolveHostCB *callback);
|
||||
|
||||
private:
|
||||
nsHostResolver(PRUint32 maxCacheEntries=50, PRUint32 maxCacheLifetime=1);
|
||||
~nsHostResolver();
|
||||
|
||||
nsresult Init();
|
||||
nsresult IssueLookup(nsHostRecord *);
|
||||
PRBool GetHostToLookup(nsHostRecord **);
|
||||
void OnLookupComplete(nsHostRecord *, nsresult, PRAddrInfo *);
|
||||
|
||||
static void PR_CALLBACK ThreadFunc(void *);
|
||||
|
||||
PRInt32 mRefCount;
|
||||
PRUint32 mMaxCacheEntries;
|
||||
PRUint32 mMaxCacheLifetime;
|
||||
PRLock *mLock;
|
||||
PRCondVar *mIdleThreadCV; // non-null if idle thread
|
||||
PRBool mHaveIdleThread;
|
||||
PRUint32 mThreadCount;
|
||||
PLDHashTable mDB;
|
||||
PRCList mPendingQ;
|
||||
PRCList mEvictionQ;
|
||||
PRUint32 mEvictionQSize;
|
||||
PRTime mCreationTime;
|
||||
PRBool mShutdown;
|
||||
};
|
||||
|
||||
#endif // nsHostResolver_h__
|
|
@ -1,3 +1,4 @@
|
|||
# vim: noexpandtab ts=4 sw=4
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
|
@ -33,19 +34,20 @@ REQUIRES = xpcom \
|
|||
string \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = nsSocketProviderService.cpp nsSOCKSSocketProvider.cpp nsSOCKS4SocketProvider.cpp nsSOCKSIOLayer.cpp
|
||||
CPPSRCS = \
|
||||
nsSocketProviderService.cpp \
|
||||
nsSOCKSSocketProvider.cpp \
|
||||
nsSOCKSIOLayer.cpp \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsISocketProvider.idl \
|
||||
nsISocketProviderService.idl \
|
||||
nsISOCKSSocketProvider.idl \
|
||||
nsISOCKSSocketInfo.idl \
|
||||
nsISOCKS4SocketProvider.idl \
|
||||
nsISOCKS4SocketInfo.idl \
|
||||
nsISSLSocketProvider.idl \
|
||||
nsITransportSecurityInfo.idl \
|
||||
nsISSLSocketControl.idl \
|
||||
$(NULL)
|
||||
nsISSLSocketProvider.idl \
|
||||
nsISSLSocketControl.idl \
|
||||
$(NULL)
|
||||
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
NO_GEN_XPT=1
|
||||
|
|
|
@ -37,36 +37,64 @@
|
|||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
%{C++
|
||||
#include "prio.h"
|
||||
%}
|
||||
[ptr] native nsFileDescStar(struct PRFileDesc);
|
||||
|
||||
[ptr] native nsFileDescStar(PRFileDesc);
|
||||
|
||||
[noscript, uuid(0906de00-5414-11d3-bbc8-0000861d1237)]
|
||||
interface nsISocketProvider : nsISupports {
|
||||
|
||||
void NewSocket(in string host,
|
||||
in long port,
|
||||
in string proxyHost,
|
||||
in long proxyPort,
|
||||
out nsFileDescStar fileDesc,
|
||||
out nsISupports securityInfo );
|
||||
|
||||
void AddToSocket(in string host,
|
||||
in long port,
|
||||
in string proxyHost,
|
||||
in long proxyPort,
|
||||
in nsFileDescStar fileDesc,
|
||||
out nsISupports securityInfo );
|
||||
/**
|
||||
* nsISocketProvider
|
||||
*/
|
||||
[noscript, uuid(4c29772e-cf73-414a-98d9-661761a4511a)]
|
||||
interface nsISocketProvider : nsISupports
|
||||
{
|
||||
/**
|
||||
* newSocket
|
||||
*
|
||||
* @param aFamily
|
||||
* The address family for this socket (PR_AF_INET or PR_AF_INET6).
|
||||
* @param aHost
|
||||
* The hostname for this connection.
|
||||
* @param aPort
|
||||
* The port for this connection.
|
||||
* @param aProxyHost
|
||||
* If non-null, the proxy hostname for this connection.
|
||||
* @param aProxyPort
|
||||
* The proxy port for this connection.
|
||||
* @param aFileDesc
|
||||
* The resulting PRFileDesc.
|
||||
* @param aSecurityInfo
|
||||
* Any security info that should be associated with aFileDesc. This
|
||||
* object typically implements nsITransportSecurityInfo.
|
||||
*/
|
||||
void newSocket(in long aFamily,
|
||||
in string aHost,
|
||||
in long aPort,
|
||||
in string aProxyHost,
|
||||
in long aProxyPort,
|
||||
out nsFileDescStar aFileDesc,
|
||||
out nsISupports aSecurityInfo);
|
||||
|
||||
/**
|
||||
* addToSocket
|
||||
*
|
||||
* This function is called to allow the socket provider to layer a PRFileDesc
|
||||
* on top of another PRFileDesc. For example, SSL via a SOCKS proxy.
|
||||
*
|
||||
* Parameters are the same as newSocket with the exception of aFileDesc, which
|
||||
* is an in-param instead.
|
||||
*/
|
||||
void addToSocket(in long aFamily,
|
||||
in string aHost,
|
||||
in long aPort,
|
||||
in string aProxyHost,
|
||||
in long aProxyPort,
|
||||
in nsFileDescStar aFileDesc,
|
||||
out nsISupports aSecurityInfo);
|
||||
};
|
||||
|
||||
%{C++
|
||||
#define NS_NETWORK_SOCKET_CONTRACTID "@mozilla.org/network/socket;1"
|
||||
#define NS_NETWORK_SOCKET_CONTRACTID_PREFIX NS_NETWORK_SOCKET_CONTRACTID "?type="
|
||||
#define NS_NETWORK_SOCKET_CONTRACTID_PREFIX_LENGTH 41 // strlen(NS_NETWORK_SOCKET_CONTRACTID_PREFIX)
|
||||
|
||||
#define NS_ERROR_UNKNOWN_SOCKET_TYPE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 51)
|
||||
#define NS_ERROR_SOCKET_CREATE_FAILED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 52)
|
||||
/**
|
||||
* nsISocketProvider implementations should be registered with XPCOM under a
|
||||
* contract ID of the form: "@mozilla.org/network/socket;2?type=foo"
|
||||
*/
|
||||
#define NS_NETWORK_SOCKET_CONTRACTID_PREFIX \
|
||||
"@mozilla.org/network/socket;2?type="
|
||||
%}
|
||||
|
|
|
@ -39,21 +39,14 @@
|
|||
|
||||
interface nsISocketProvider;
|
||||
|
||||
/**
|
||||
* nsISocketProviderService
|
||||
*
|
||||
* Provides a mapping between a socket type and its associated socket provider
|
||||
* instance. One could also use the service manager directly.
|
||||
*/
|
||||
[noscript, uuid(8f8a23d0-5472-11d3-bbc8-0000861d1237)]
|
||||
interface nsISocketProviderService : nsISupports
|
||||
{
|
||||
nsISocketProvider GetSocketProvider(in string socketType);
|
||||
nsISocketProvider getSocketProvider(in string socketType);
|
||||
};
|
||||
|
||||
|
||||
%{C++
|
||||
|
||||
#define NS_SOCKETPROVIDERSERVICE_CID \
|
||||
{ /* ed394ba0-5472-11d3-bbc8-0000861d1237 */ \
|
||||
0xed394ba0, \
|
||||
0x5472, \
|
||||
0x11d3, \
|
||||
{0xbb, 0xc8, 0x00, 0x00, 0x86, 0x1d, 0x12, 0x37} \
|
||||
}
|
||||
|
||||
%}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Justin Bradford <jab@atdot.org>
|
||||
* Bradley Baetz <bbaetz@acm.org>
|
||||
* Darin Fisher <darin@meer.net>
|
||||
*/
|
||||
|
||||
#include "nspr.h"
|
||||
|
@ -26,7 +28,10 @@
|
|||
#include "nsCRT.h"
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsISOCKSSocketInfo.h"
|
||||
#include "nsSOCKSIOLayer.h"
|
||||
#include "nsNetCID.h"
|
||||
|
||||
static PRDescIdentity nsSOCKSIOLayerIdentity;
|
||||
static PRIOMethods nsSOCKSIOLayerMethods;
|
||||
|
@ -46,145 +51,45 @@ class nsSOCKSSocketInfo : public nsISOCKSSocketInfo
|
|||
{
|
||||
public:
|
||||
nsSOCKSSocketInfo();
|
||||
virtual ~nsSOCKSSocketInfo();
|
||||
virtual ~nsSOCKSSocketInfo() {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISOCKSSOCKETINFO
|
||||
|
||||
NS_IMETHOD GetProxyHost(char * *aProxyHost);
|
||||
NS_IMETHOD SetProxyHost(const char * aProxyHost);
|
||||
NS_IMETHOD GetProxyPort(PRInt32 *aProxyPort);
|
||||
NS_IMETHOD SetProxyPort(PRInt32 aProxyPort);
|
||||
NS_IMETHOD GetProxyType(char * *aProxyType);
|
||||
NS_IMETHOD SetProxyType(const char * aProxyType);
|
||||
NS_IMETHOD GetSOCKSVersion(PRInt32 *aVersion);
|
||||
NS_IMETHOD SetSOCKSVersion(PRInt32 aVersion);
|
||||
|
||||
protected:
|
||||
void Init(PRInt32 version, const char *proxyHost, PRInt32 proxyPort);
|
||||
|
||||
char* mProxyHost;
|
||||
PRInt32 mProxyPort;
|
||||
char* mProxyType;
|
||||
PRInt32 mSOCKSVersion; // SOCKS version 4 or 5 (default is 5)
|
||||
|
||||
// nsISOCKSSocketInfo
|
||||
PRNetAddr mInternalProxyAddr;
|
||||
PRNetAddr mExternalProxyAddr;
|
||||
PRNetAddr mDestinationAddr;
|
||||
const nsCString &ProxyHost() { return mProxyHost; }
|
||||
PRInt32 ProxyPort() { return mProxyPort; }
|
||||
PRInt32 Version() { return mVersion; }
|
||||
|
||||
private:
|
||||
nsCString mProxyHost;
|
||||
PRInt32 mProxyPort;
|
||||
PRInt32 mVersion; // SOCKS version 4 or 5
|
||||
PRNetAddr mInternalProxyAddr;
|
||||
PRNetAddr mExternalProxyAddr;
|
||||
PRNetAddr mDestinationAddr;
|
||||
};
|
||||
|
||||
nsSOCKSSocketInfo::nsSOCKSSocketInfo()
|
||||
: mSOCKSVersion(-1)
|
||||
: mProxyPort(-1)
|
||||
, mVersion(-1)
|
||||
{
|
||||
mProxyHost = nsnull;
|
||||
mProxyPort = -1;
|
||||
mProxyType = nsnull;
|
||||
|
||||
PR_InitializeNetAddr(PR_IpAddrAny, 0, &mInternalProxyAddr);
|
||||
PR_InitializeNetAddr(PR_IpAddrAny, 0, &mExternalProxyAddr);
|
||||
PR_InitializeNetAddr(PR_IpAddrAny, 0, &mDestinationAddr);
|
||||
}
|
||||
|
||||
nsSOCKSSocketInfo::~nsSOCKSSocketInfo()
|
||||
void
|
||||
nsSOCKSSocketInfo::Init(PRInt32 version, const char *proxyHost, PRInt32 proxyPort)
|
||||
{
|
||||
PR_FREEIF(mProxyHost);
|
||||
mVersion = version;
|
||||
mProxyHost = proxyHost;
|
||||
mProxyPort = proxyPort;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsSOCKSSocketInfo, nsISOCKSSocketInfo)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSOCKSSocketInfo::GetProxyHost(char * *aProxyHost)
|
||||
{
|
||||
if (!aProxyHost) return NS_ERROR_NULL_POINTER;
|
||||
if (mProxyHost)
|
||||
{
|
||||
*aProxyHost = nsCRT::strdup(mProxyHost);
|
||||
return (*aProxyHost == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
*aProxyHost = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSOCKSSocketInfo::SetProxyHost(const char * aProxyHost)
|
||||
{
|
||||
PR_FREEIF(mProxyHost);
|
||||
if (aProxyHost)
|
||||
{
|
||||
mProxyHost = nsCRT::strdup(aProxyHost);
|
||||
return (mProxyHost == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
mProxyHost = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSOCKSSocketInfo::GetProxyPort(PRInt32 *aProxyPort)
|
||||
{
|
||||
*aProxyPort = mProxyPort;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSOCKSSocketInfo::SetProxyPort(PRInt32 aProxyPort)
|
||||
{
|
||||
mProxyPort = aProxyPort;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSOCKSSocketInfo::GetProxyType(char * *aProxyType)
|
||||
{
|
||||
if (!aProxyType) return NS_ERROR_NULL_POINTER;
|
||||
if (mProxyType)
|
||||
{
|
||||
*aProxyType = nsCRT::strdup(mProxyType);
|
||||
return (*aProxyType == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
*aProxyType = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSOCKSSocketInfo::SetProxyType(const char * aProxyType)
|
||||
{
|
||||
PR_FREEIF(mProxyType);
|
||||
if (aProxyType)
|
||||
{
|
||||
mProxyType = nsCRT::strdup(aProxyType);
|
||||
return (mProxyType == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
mProxyType = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSOCKSSocketInfo::GetSOCKSVersion(PRInt32 *aVersion)
|
||||
{
|
||||
*aVersion = mSOCKSVersion;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSOCKSSocketInfo::SetSOCKSVersion(PRInt32 aVersion)
|
||||
{
|
||||
mSOCKSVersion = aVersion;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSOCKSSocketInfo::GetExternalProxyAddr(PRNetAddr * *aExternalProxyAddr)
|
||||
{
|
||||
|
@ -561,44 +466,35 @@ nsSOCKSIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime /*ti
|
|||
if (info == NULL) return PR_FAILURE;
|
||||
|
||||
// First, we need to look up our proxy...
|
||||
char scratch[PR_NETDB_BUF_SIZE];
|
||||
PRHostEnt hostentry;
|
||||
nsXPIDLCString proxyHost;
|
||||
const nsCString &proxyHost = info->ProxyHost();
|
||||
|
||||
nsresult rv = info->GetProxyHost(getter_Copies(proxyHost));
|
||||
|
||||
if (NS_FAILED(rv) || proxyHost.IsEmpty()) {
|
||||
if (proxyHost.IsEmpty())
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
PRInt32 socksVersion = -1;
|
||||
rv = info->GetSOCKSVersion(&socksVersion);
|
||||
if (NS_FAILED(rv)) {
|
||||
|
||||
return PR_FAILURE;
|
||||
}
|
||||
PRInt32 socksVersion = info->Version();
|
||||
|
||||
LOGDEBUG(("nsSOCKSIOLayerConnect SOCKS %u; proxyHost: %s.", socksVersion, proxyHost.get()));
|
||||
|
||||
status = PR_GetHostByName(proxyHost, scratch, PR_NETDB_BUF_SIZE, &hostentry);
|
||||
|
||||
if (PR_SUCCESS != status) {
|
||||
LOGERROR(("PR_GetHostByName() failed. proxyHost = %s, status = %x.",proxyHost.get(), status));
|
||||
return status;
|
||||
}
|
||||
|
||||
// Extract the proxy addr
|
||||
PRIntn entEnum = 0;
|
||||
// Sync resolve the proxy hostname.
|
||||
PRNetAddr proxyAddr;
|
||||
PRInt32 proxyPort;
|
||||
info->GetProxyPort(&proxyPort);
|
||||
entEnum = PR_EnumerateHostEnt(entEnum, &hostentry, proxyPort, &proxyAddr);
|
||||
|
||||
if (entEnum <= 0) {
|
||||
LOGERROR(("PR_EnumerateHostEnt() failed. proxyPort = %u, entEnum = %u.", proxyPort, entEnum));
|
||||
return PR_FAILURE;
|
||||
{
|
||||
nsCOMPtr<nsIDNSService> dns;
|
||||
nsCOMPtr<nsIDNSRecord> rec;
|
||||
nsresult rv;
|
||||
|
||||
dns = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return PR_FAILURE;
|
||||
|
||||
rv = dns->Resolve(proxyHost, PR_FALSE, getter_AddRefs(rec));
|
||||
if (NS_FAILED(rv))
|
||||
return PR_FAILURE;
|
||||
|
||||
rv = rec->GetNextAddr(info->ProxyPort(), &proxyAddr);
|
||||
if (NS_FAILED(rv))
|
||||
return PR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
info->SetInternalProxyAddr(&proxyAddr);
|
||||
|
||||
// For now, we'll do this as a blocking connect,
|
||||
|
@ -663,6 +559,8 @@ nsSOCKSIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime /*ti
|
|||
|
||||
NS_ASSERTION((socksVersion == 4) || (socksVersion == 5), "SOCKS Version must be selected");
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Try to connect via SOCKS 5.
|
||||
if (socksVersion == 5) {
|
||||
rv = ConnectSOCKS5(fd, addr, &extAddr, connectWait);
|
||||
|
@ -767,101 +665,10 @@ nsSOCKSIOLayerListen(PRFileDesc *fd, PRIntn backlog)
|
|||
return fd->lower->methods->listen(fd->lower, backlog);
|
||||
}
|
||||
|
||||
|
||||
// create a new socket with a SOCKS IO layer
|
||||
nsresult
|
||||
nsSOCKSIOLayerNewSocket(const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
PRInt32 socksVersion,
|
||||
PRFileDesc **fd,
|
||||
nsISupports** info)
|
||||
{
|
||||
NS_ENSURE_TRUE((socksVersion == 4) || (socksVersion == 5), NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
|
||||
if (firstTime)
|
||||
{
|
||||
nsSOCKSIOLayerIdentity = PR_GetUniqueIdentity("SOCKS layer");
|
||||
nsSOCKSIOLayerMethods = *PR_GetDefaultIOMethods();
|
||||
|
||||
nsSOCKSIOLayerMethods.connect = nsSOCKSIOLayerConnect;
|
||||
nsSOCKSIOLayerMethods.bind = nsSOCKSIOLayerBind;
|
||||
nsSOCKSIOLayerMethods.acceptread = nsSOCKSIOLayerAcceptRead;
|
||||
nsSOCKSIOLayerMethods.getsockname = nsSOCKSIOLayerGetName;
|
||||
nsSOCKSIOLayerMethods.getpeername = nsSOCKSIOLayerGetPeerName;
|
||||
nsSOCKSIOLayerMethods.accept = nsSOCKSIOLayerAccept;
|
||||
nsSOCKSIOLayerMethods.listen = nsSOCKSIOLayerListen;
|
||||
nsSOCKSIOLayerMethods.close = nsSOCKSIOLayerClose;
|
||||
|
||||
firstTime = PR_FALSE;
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
gSOCKSLog = PR_NewLogModule("SOCKS");
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
LOGDEBUG(("Entering nsSOCKSIOLayerNewSocket()."));
|
||||
|
||||
PRFileDesc * sock;
|
||||
PRFileDesc * layer;
|
||||
PRStatus rv;
|
||||
|
||||
/* Get a normal NSPR socket */
|
||||
sock = PR_NewTCPSocket();
|
||||
if (! sock)
|
||||
{
|
||||
LOGERROR(("PR_NewTCPSocket() failed"));
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
layer = PR_CreateIOLayerStub(nsSOCKSIOLayerIdentity, &nsSOCKSIOLayerMethods);
|
||||
if (! layer)
|
||||
{
|
||||
LOGERROR(("PR_CreateIOLayerStub() failed."));
|
||||
PR_Close(sock);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsSOCKSSocketInfo * infoObject = new nsSOCKSSocketInfo();
|
||||
if (!infoObject)
|
||||
{
|
||||
LOGERROR(("Failed to create nsSOCKSSocketInfo()."));
|
||||
PR_Close(sock);
|
||||
// clean up IOLayerStub
|
||||
PR_DELETE(layer);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_ADDREF(infoObject);
|
||||
infoObject->SetProxyHost(proxyHost);
|
||||
infoObject->SetProxyPort(proxyPort);
|
||||
infoObject->SetSOCKSVersion(socksVersion);
|
||||
layer->secret = (PRFilePrivate*) infoObject;
|
||||
rv = PR_PushIOLayer(sock, PR_GetLayersIdentity(sock), layer);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
LOGERROR(("PR_PushIOLayer() failed. rv = %x.", rv));
|
||||
PR_Close(sock);
|
||||
NS_RELEASE(infoObject);
|
||||
PR_DELETE(layer);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*fd = sock;
|
||||
*info = infoObject;
|
||||
NS_ADDREF(*info);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// add SOCKS IO layer to an existing socket
|
||||
nsresult
|
||||
nsSOCKSIOLayerAddToSocket(const char *host,
|
||||
nsSOCKSIOLayerAddToSocket(PRInt32 family,
|
||||
const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
|
@ -916,9 +723,7 @@ nsSOCKSIOLayerAddToSocket(const char *host,
|
|||
}
|
||||
|
||||
NS_ADDREF(infoObject);
|
||||
infoObject->SetProxyHost(proxyHost);
|
||||
infoObject->SetProxyPort(proxyPort);
|
||||
infoObject->SetSOCKSVersion(socksVersion);
|
||||
infoObject->Init(socksVersion, proxyHost, proxyPort);
|
||||
layer->secret = (PRFilePrivate*) infoObject;
|
||||
rv = PR_PushIOLayer(fd, PR_GetLayersIdentity(fd), layer);
|
||||
|
||||
|
@ -934,5 +739,3 @@ nsSOCKSIOLayerAddToSocket(const char *host,
|
|||
NS_ADDREF(*info);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,22 +21,15 @@
|
|||
* Justin Bradford <jab@atdot.org>
|
||||
*/
|
||||
|
||||
#ifndef _NSSOCKSIOLAYER_H_
|
||||
#define _NSSOCKSIOLAYER_H_
|
||||
#ifndef nsSOCKSIOLayer_h__
|
||||
#define NSSOCKSIOLayer_h__
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "prio.h"
|
||||
#include "nsISOCKSSocketInfo.h"
|
||||
#include "nscore.h"
|
||||
|
||||
nsresult nsSOCKSIOLayerNewSocket(const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
PRInt32 socksVersion,
|
||||
PRFileDesc **fd,
|
||||
nsISupports **info);
|
||||
|
||||
nsresult nsSOCKSIOLayerAddToSocket(const char *host,
|
||||
nsresult nsSOCKSIOLayerAddToSocket(PRInt32 family,
|
||||
const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
|
@ -44,4 +37,4 @@ nsresult nsSOCKSIOLayerAddToSocket(const char *host,
|
|||
PRFileDesc *fd,
|
||||
nsISupports **info);
|
||||
|
||||
#endif /* _NSSOCKSIOLAYER_H_ */
|
||||
#endif /* nsSOCKSIOLayer_h__ */
|
||||
|
|
|
@ -19,95 +19,95 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Justin Bradford <jab@atdot.org>
|
||||
* Darin Fisher <darin@meer.net>
|
||||
*/
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsSOCKSSocketProvider.h"
|
||||
#include "nsSOCKSIOLayer.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsNetError.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsSOCKSSocketProvider::nsSOCKSSocketProvider()
|
||||
{
|
||||
}
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(nsSOCKSSocketProvider, nsISocketProvider)
|
||||
|
||||
nsresult
|
||||
nsSOCKSSocketProvider::Init()
|
||||
NS_METHOD
|
||||
nsSOCKSSocketProvider::CreateV4(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISocketProvider> inst =
|
||||
new nsSOCKSSocketProvider(NS_SOCKS_VERSION_4);
|
||||
if (!inst)
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
else
|
||||
rv = inst->QueryInterface(aIID, aResult);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsSOCKSSocketProvider::~nsSOCKSSocketProvider()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsSOCKSSocketProvider, nsISocketProvider, nsISOCKSSocketProvider)
|
||||
|
||||
NS_METHOD
|
||||
nsSOCKSSocketProvider::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
nsSOCKSSocketProvider::CreateV5(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsSOCKSSocketProvider * inst;
|
||||
|
||||
if (NULL == aResult) {
|
||||
rv = NS_ERROR_NULL_POINTER;
|
||||
return rv;
|
||||
}
|
||||
*aResult = NULL;
|
||||
if (NULL != aOuter) {
|
||||
rv = NS_ERROR_NO_AGGREGATION;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_NEWXPCOM(inst, nsSOCKSSocketProvider);
|
||||
if (NULL == inst) {
|
||||
nsCOMPtr<nsISocketProvider> inst =
|
||||
new nsSOCKSSocketProvider(NS_SOCKS_VERSION_5);
|
||||
if (!inst)
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
return rv;
|
||||
}
|
||||
NS_ADDREF(inst);
|
||||
rv = inst->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(inst);
|
||||
|
||||
else
|
||||
rv = inst->QueryInterface(aIID, aResult);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSOCKSSocketProvider::NewSocket(const char *host,
|
||||
nsSOCKSSocketProvider::NewSocket(PRInt32 family,
|
||||
const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
PRFileDesc **_result,
|
||||
PRFileDesc **result,
|
||||
nsISupports **socksInfo)
|
||||
{
|
||||
nsresult rv = nsSOCKSIOLayerNewSocket(host,
|
||||
port,
|
||||
proxyHost,
|
||||
proxyPort,
|
||||
5, // SOCKS 5
|
||||
_result,
|
||||
socksInfo);
|
||||
PRFileDesc *sock;
|
||||
|
||||
return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK;
|
||||
}
|
||||
sock = PR_OpenTCPSocket(family);
|
||||
if (!sock)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSOCKSSocketProvider::AddToSocket(const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
PRFileDesc *socket,
|
||||
nsISupports **socksInfo)
|
||||
{
|
||||
nsresult rv = nsSOCKSIOLayerAddToSocket(host,
|
||||
nsresult rv = nsSOCKSIOLayerAddToSocket(family,
|
||||
host,
|
||||
port,
|
||||
proxyHost,
|
||||
proxyPort,
|
||||
5, // SOCKS 5
|
||||
socket,
|
||||
mVersion,
|
||||
sock,
|
||||
socksInfo);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*result = sock;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_SOCKET_CREATE_FAILED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSOCKSSocketProvider::AddToSocket(PRInt32 family,
|
||||
const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
PRFileDesc *sock,
|
||||
nsISupports **socksInfo)
|
||||
{
|
||||
nsresult rv = nsSOCKSIOLayerAddToSocket(family,
|
||||
host,
|
||||
port,
|
||||
proxyHost,
|
||||
proxyPort,
|
||||
mVersion,
|
||||
sock,
|
||||
socksInfo);
|
||||
|
||||
return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK;
|
||||
if (NS_FAILED(rv))
|
||||
rv = NS_ERROR_SOCKET_CREATE_FAILED;
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -19,34 +19,34 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Justin Bradford <jab@atdot.org>
|
||||
* Darin Fisher <darin@meer.net>
|
||||
*/
|
||||
|
||||
#ifndef _NSSOCKSSOCKETPROVIDER_H_
|
||||
#define _NSSOCKSSOCKETPROVIDER_H_
|
||||
#ifndef nsSOCKSSocketProvider_h__
|
||||
#define nsSOCKSSocketProvider_h__
|
||||
|
||||
#include "nsISOCKSSocketProvider.h"
|
||||
#include "nsISocketProvider.h"
|
||||
|
||||
// values for ctor's |version| argument
|
||||
enum {
|
||||
NS_SOCKS_VERSION_4 = 4,
|
||||
NS_SOCKS_VERSION_5 = 5
|
||||
};
|
||||
|
||||
/* 8dbe7246-1dd2-11b2-9b8f-b9a849e4403a */
|
||||
#define NS_SOCKSSOCKETPROVIDER_CID { 0x8dbe7246, 0x1dd2, 0x11b2, {0x9b, 0x8f, 0xb9, 0xa8, 0x49, 0xe4, 0x40, 0x3a}}
|
||||
|
||||
class nsSOCKSSocketProvider : public nsISOCKSSocketProvider
|
||||
class nsSOCKSSocketProvider : public nsISocketProvider
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISOCKETPROVIDER
|
||||
NS_DECL_NSISOCKSSOCKETPROVIDER
|
||||
|
||||
// nsSOCKSSocketProvider methods:
|
||||
nsSOCKSSocketProvider();
|
||||
virtual ~nsSOCKSSocketProvider();
|
||||
nsSOCKSSocketProvider(PRUint32 version) : mVersion(version) {}
|
||||
virtual ~nsSOCKSSocketProvider() {}
|
||||
|
||||
static NS_METHOD
|
||||
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
static NS_METHOD CreateV4(nsISupports *, REFNSIID aIID, void **aResult);
|
||||
static NS_METHOD CreateV5(nsISupports *, REFNSIID aIID, void **aResult);
|
||||
|
||||
nsresult Init();
|
||||
|
||||
protected:
|
||||
private:
|
||||
PRUint32 mVersion; // NS_SOCKS_VERSION_4 or 5
|
||||
};
|
||||
|
||||
#endif /* _NSSOCKSSOCKETPROVIDER_H_ */
|
||||
#endif /* nsSOCKSSocketProvider_h__ */
|
||||
|
|
|
@ -37,48 +37,21 @@
|
|||
|
||||
#include "nsString.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "nsSocketProviderService.h"
|
||||
#include "nsISocketProvider.h"
|
||||
#include "nsSocketProviderService.h"
|
||||
#include "nsNetError.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsSocketProviderService::nsSocketProviderService()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSocketProviderService::Init()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsSocketProviderService::~nsSocketProviderService()
|
||||
{
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsSocketProviderService::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
nsSocketProviderService* pSockProvServ = new nsSocketProviderService();
|
||||
if (pSockProvServ == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(pSockProvServ);
|
||||
rv = pSockProvServ->Init();
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
delete pSockProvServ;
|
||||
return rv;
|
||||
}
|
||||
rv = pSockProvServ->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(pSockProvServ);
|
||||
|
||||
nsCOMPtr<nsISocketProviderService> inst = new nsSocketProviderService();
|
||||
if (!inst)
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
else
|
||||
rv = inst->QueryInterface(aIID, aResult);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -87,19 +60,18 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsSocketProviderService, nsISocketProviderService)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSocketProviderService::GetSocketProvider(const char *aSocketType, nsISocketProvider **_result)
|
||||
nsSocketProviderService::GetSocketProvider(const char *type,
|
||||
nsISocketProvider **result)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCAutoString contractID(
|
||||
nsDependentCString(NS_NETWORK_SOCKET_CONTRACTID_PREFIX) +
|
||||
nsDependentCString(aSocketType));
|
||||
NS_LITERAL_CSTRING(NS_NETWORK_SOCKET_CONTRACTID_PREFIX) +
|
||||
nsDependentCString(type));
|
||||
|
||||
rv = CallGetService(contractID.get(), _result);
|
||||
rv = CallGetService(contractID.get(), result);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_UNKNOWN_SOCKET_TYPE;
|
||||
|
||||
return NS_OK;
|
||||
rv = NS_ERROR_UNKNOWN_SOCKET_TYPE;
|
||||
return rv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef _NSSOCKETPROVIDERSERVICE_H_
|
||||
#define _NSSOCKETPROVIDERSERVICE_H_
|
||||
#ifndef nsSocketProviderService_h__
|
||||
#define nsSocketProviderService_h__
|
||||
|
||||
#include "nsISocketProviderService.h"
|
||||
|
||||
|
@ -44,19 +44,12 @@ class nsSocketProviderService : public nsISocketProviderService
|
|||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSISOCKETPROVIDERSERVICE
|
||||
|
||||
// nsISocketProviderService methods:
|
||||
nsSocketProviderService();
|
||||
virtual ~nsSocketProviderService();
|
||||
nsSocketProviderService() {}
|
||||
virtual ~nsSocketProviderService() {}
|
||||
|
||||
static NS_METHOD
|
||||
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
nsresult Init();
|
||||
|
||||
protected:
|
||||
static NS_METHOD Create(nsISupports *, REFNSIID aIID, void **aResult);
|
||||
};
|
||||
|
||||
#endif /* _NSSOCKETPROVIDERSERVICE_H */
|
||||
#endif /* nsSocketProviderService_h__ */
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# vim: noexpandtab ts=8 sw=8
|
||||
#
|
||||
# The contents of this file are subject to the Netscape Public
|
||||
# License Version 1.1 (the "License"); you may not use this file
|
||||
|
@ -33,55 +34,43 @@ REQUIRES = xpcom \
|
|||
util \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
PropertiesTest.cpp \
|
||||
urltest.cpp \
|
||||
TestCallbacks.cpp \
|
||||
TestPageLoad.cpp \
|
||||
TestPerf.cpp \
|
||||
TestIDN.cpp \
|
||||
TestURLParser.cpp \
|
||||
TestStandardURL.cpp \
|
||||
TestSocketTransport.cpp \
|
||||
TestUpload.cpp \
|
||||
TestStreamTransport.cpp \
|
||||
TestStreamChannel.cpp \
|
||||
TestStreamPump.cpp \
|
||||
TestProtocols.cpp \
|
||||
TestBlockingSocket.cpp \
|
||||
$(NULL)
|
||||
|
||||
# TestHttp.cpp \
|
||||
# TestFileInput.cpp \
|
||||
# TestFileInput2.cpp \
|
||||
# TestMCTransport.cpp \
|
||||
# TestSocketIO.cpp \
|
||||
# TestSocketInput.cpp \
|
||||
# TestSocketTransport.cpp \
|
||||
# TestFileTransport.cpp
|
||||
CPPSRCS = PropertiesTest.cpp \
|
||||
urltest.cpp \
|
||||
TestCallbacks.cpp \
|
||||
TestPageLoad.cpp \
|
||||
TestPerf.cpp \
|
||||
TestIDN.cpp \
|
||||
TestURLParser.cpp \
|
||||
TestStandardURL.cpp \
|
||||
TestSocketTransport.cpp \
|
||||
TestUpload.cpp \
|
||||
TestStreamTransport.cpp \
|
||||
TestStreamChannel.cpp \
|
||||
TestStreamPump.cpp \
|
||||
TestProtocols.cpp \
|
||||
TestBlockingSocket.cpp \
|
||||
TestDNS.cpp \
|
||||
$(NULL)
|
||||
|
||||
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
LIBS = \
|
||||
$(EXTRA_DSO_LIBS) \
|
||||
$(MOZ_JS_LIBS) \
|
||||
$(XPCOM_LIBS) \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
LIBS = $(EXTRA_DSO_LIBS) \
|
||||
$(MOZ_JS_LIBS) \
|
||||
$(XPCOM_LIBS) \
|
||||
$(NSPR_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_RES_FILES = \
|
||||
urlparse.dat \
|
||||
urlparse_unx.dat \
|
||||
jarlist.dat \
|
||||
$(NULL)
|
||||
_RES_FILES = urlparse.dat \
|
||||
urlparse_unx.dat \
|
||||
jarlist.dat \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_RES_FILES)
|
||||
$(INSTALL) $^ $(DIST)/bin/res
|
||||
|
||||
install:: $(_RES_FILES)
|
||||
$(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/res
|
||||
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is IBM Corporation.
|
||||
* Portions created by IBM Corporation are Copyright (C) 2003
|
||||
* IBM Corporation. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* IBM Corp.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDNSService.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "prinrval.h"
|
||||
#include "prthread.h"
|
||||
#include "prnetdb.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
class myDNSListener : public nsIDNSListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
myDNSListener(const char *host, PRInt32 index)
|
||||
: mHost(host)
|
||||
, mIndex(index) {}
|
||||
virtual ~myDNSListener() {}
|
||||
|
||||
NS_IMETHOD OnLookupComplete(nsIDNSRequest *request,
|
||||
nsIDNSRecord *rec,
|
||||
nsresult status)
|
||||
{
|
||||
printf("%d: OnLookupComplete called [host=%s status=%x ai=%p]\n",
|
||||
mIndex, mHost.get(), status, (void*)rec);
|
||||
|
||||
if (NS_SUCCEEDED(status)) {
|
||||
nsCAutoString buf;
|
||||
|
||||
rec->GetCanonicalName(buf);
|
||||
printf("%d: canonname=%s\n", mIndex, buf.get());
|
||||
|
||||
while (NS_SUCCEEDED(rec->GetNextAddrAsString(buf)))
|
||||
printf("%d: => %s\n", mIndex, buf.get());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCString mHost;
|
||||
PRInt32 mIndex;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(myDNSListener, nsIDNSListener)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int sleepLen = 10; // default: 10 seconds
|
||||
|
||||
if (argc == 1) {
|
||||
printf("usage: TestDNS [-N] hostname1 [hostname2 ...]\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
|
||||
if (!dns)
|
||||
return -1;
|
||||
|
||||
if (argv[1][0] == '-') {
|
||||
sleepLen = atoi(argv[1]+1);
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
for (int j=0; j<2; ++j) {
|
||||
for (int i=1; i<argc; ++i) {
|
||||
// assume non-ASCII input is given in the native charset
|
||||
nsCAutoString hostBuf;
|
||||
if (nsCRT::IsAscii(argv[i]))
|
||||
hostBuf.Assign(argv[i]);
|
||||
else
|
||||
hostBuf = NS_ConvertUCS2toUTF8(NS_ConvertASCIItoUCS2(argv[i]));
|
||||
|
||||
nsCOMPtr<nsIDNSListener> listener = new myDNSListener(argv[i], i);
|
||||
nsCOMPtr<nsIDNSRequest> req;
|
||||
dns->AsyncResolve(hostBuf, PR_FALSE, listener, nsnull, getter_AddRefs(req));
|
||||
}
|
||||
|
||||
printf("main thread sleeping for %d seconds...\n", sleepLen);
|
||||
PR_Sleep(PR_SecondsToInterval(sleepLen));
|
||||
}
|
||||
|
||||
printf("shutting down main thread...\n");
|
||||
dns->Shutdown();
|
||||
return 0;
|
||||
}
|
|
@ -1199,7 +1199,8 @@ static void InitNSSMethods()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsSSLIOLayerNewSocket(const char *host,
|
||||
nsSSLIOLayerNewSocket(PRInt32 family,
|
||||
const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
|
@ -1217,10 +1218,10 @@ nsSSLIOLayerNewSocket(const char *host,
|
|||
firstTime = PR_FALSE;
|
||||
}
|
||||
|
||||
PRFileDesc* sock = PR_OpenTCPSocket(PR_AF_INET6);
|
||||
PRFileDesc* sock = PR_OpenTCPSocket(family);
|
||||
if (!sock) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsresult rv = nsSSLIOLayerAddToSocket(host, port, proxyHost, proxyPort,
|
||||
nsresult rv = nsSSLIOLayerAddToSocket(family, host, port, proxyHost, proxyPort,
|
||||
sock, info, forSTARTTLS);
|
||||
if (NS_FAILED(rv)) {
|
||||
PR_Close(sock);
|
||||
|
@ -2326,7 +2327,8 @@ nsSSLIOLayerSetOptions(PRFileDesc *fd, PRBool forSTARTTLS,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsSSLIOLayerAddToSocket(const char* host,
|
||||
nsSSLIOLayerAddToSocket(PRInt32 family,
|
||||
const char* host,
|
||||
PRInt32 port,
|
||||
const char* proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
|
|
|
@ -111,7 +111,8 @@ private:
|
|||
void destructorSafeDestroyNSSReference();
|
||||
};
|
||||
|
||||
nsresult nsSSLIOLayerNewSocket(const char *host,
|
||||
nsresult nsSSLIOLayerNewSocket(PRInt32 family,
|
||||
const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
|
@ -119,7 +120,8 @@ nsresult nsSSLIOLayerNewSocket(const char *host,
|
|||
nsISupports **securityInfo,
|
||||
PRBool forSTARTTLS);
|
||||
|
||||
nsresult nsSSLIOLayerAddToSocket(const char *host,
|
||||
nsresult nsSSLIOLayerAddToSocket(PRInt32 family,
|
||||
const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "nsSSLSocketProvider.h"
|
||||
#include "nsNSSIOLayer.h"
|
||||
#include "nsNetError.h"
|
||||
|
||||
nsSSLSocketProvider::nsSSLSocketProvider()
|
||||
{
|
||||
|
@ -36,14 +37,16 @@ NS_IMPL_THREADSAFE_ISUPPORTS2(nsSSLSocketProvider, nsISocketProvider,
|
|||
nsISSLSocketProvider)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSSLSocketProvider::NewSocket(const char *host,
|
||||
nsSSLSocketProvider::NewSocket(PRInt32 family,
|
||||
const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
PRFileDesc **_result,
|
||||
nsISupports **securityInfo)
|
||||
{
|
||||
nsresult rv = nsSSLIOLayerNewSocket(host,
|
||||
nsresult rv = nsSSLIOLayerNewSocket(family,
|
||||
host,
|
||||
port,
|
||||
proxyHost,
|
||||
proxyPort,
|
||||
|
@ -55,14 +58,16 @@ nsSSLSocketProvider::NewSocket(const char *host,
|
|||
|
||||
// Add the SSL IO layer to an existing socket
|
||||
NS_IMETHODIMP
|
||||
nsSSLSocketProvider::AddToSocket(const char *host,
|
||||
nsSSLSocketProvider::AddToSocket(PRInt32 family,
|
||||
const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
PRFileDesc *aSocket,
|
||||
nsISupports **securityInfo)
|
||||
{
|
||||
nsresult rv = nsSSLIOLayerAddToSocket(host,
|
||||
nsresult rv = nsSSLIOLayerAddToSocket(family,
|
||||
host,
|
||||
port,
|
||||
proxyHost,
|
||||
proxyPort,
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "nsTLSSocketProvider.h"
|
||||
#include "nsNSSIOLayer.h"
|
||||
#include "nsNetError.h"
|
||||
|
||||
nsTLSSocketProvider::nsTLSSocketProvider()
|
||||
{
|
||||
|
@ -36,14 +37,16 @@ NS_IMPL_THREADSAFE_ISUPPORTS2(nsTLSSocketProvider, nsISocketProvider,
|
|||
nsISSLSocketProvider)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTLSSocketProvider::NewSocket(const char *host,
|
||||
nsTLSSocketProvider::NewSocket(PRInt32 family,
|
||||
const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
PRFileDesc **_result,
|
||||
nsISupports **securityInfo)
|
||||
{
|
||||
nsresult rv = nsSSLIOLayerNewSocket(host,
|
||||
nsresult rv = nsSSLIOLayerNewSocket(family,
|
||||
host,
|
||||
port,
|
||||
proxyHost,
|
||||
proxyPort,
|
||||
|
@ -56,14 +59,16 @@ nsTLSSocketProvider::NewSocket(const char *host,
|
|||
|
||||
// Add the SSL IO layer to an existing socket
|
||||
NS_IMETHODIMP
|
||||
nsTLSSocketProvider::AddToSocket(const char *host,
|
||||
nsTLSSocketProvider::AddToSocket(PRInt32 family,
|
||||
const char *host,
|
||||
PRInt32 port,
|
||||
const char *proxyHost,
|
||||
PRInt32 proxyPort,
|
||||
PRFileDesc *aSocket,
|
||||
nsISupports **securityInfo)
|
||||
{
|
||||
nsresult rv = nsSSLIOLayerAddToSocket(host,
|
||||
nsresult rv = nsSSLIOLayerAddToSocket(family,
|
||||
host,
|
||||
port,
|
||||
proxyHost,
|
||||
proxyPort,
|
||||
|
|
Загрузка…
Ссылка в новой задаче