landing patch for bug 205726 "DNS rewrite" r=dougt sr=bryner

This commit is contained in:
darin%meer.net 2003-09-11 20:32:33 +00:00
Родитель ce762d3244
Коммит f4a8778d0b
39 изменённых файлов: 2170 добавлений и 1057 удалений

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

@ -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

126
netwerk/test/TestDNS.cpp Normal file
Просмотреть файл

@ -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,