93002: [distribution]Conn: Use dialup networking (.DUN) when launching
mozilla. r=dougt,sr=rpotts. Help Windows NT, 2000, and XP dialup a RAS connection when a network address is unreachable. (c/osmeredith) the controlling pref is "network.autodial-helper.enabled". git-svn-id: svn://10.0.0.236/trunk@124314 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
a5064d775f
commit
bbe078f6ae
@ -102,6 +102,12 @@ interface nsISocketTransportService : nsISupports
|
||||
* A number of nsSocketTransport objects connected (this may include keep-alive idle connections)
|
||||
*/
|
||||
readonly attribute unsigned long connectedTransportCount;
|
||||
|
||||
/**
|
||||
* Autodial helper is enabled via pref.
|
||||
*/
|
||||
attribute boolean autodialEnabled;
|
||||
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
||||
@ -77,6 +77,8 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
|
||||
else
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
|
||||
CPPSRCS += nsIOServiceWin.cpp
|
||||
CPPSRCS += nsNativeConnectionHelper.cpp
|
||||
CPPSRCS += nsAutodialWin.cpp
|
||||
else
|
||||
CPPSRCS += nsIOServiceUnix.cpp
|
||||
endif
|
||||
|
||||
@ -68,6 +68,8 @@ CPP_OBJS = \
|
||||
.\$(OBJDIR)\nsStorageTransport.obj \
|
||||
.\$(OBJDIR)\nsStreamListenerTee.obj \
|
||||
.\$(OBJDIR)\nsURIChecker.obj \
|
||||
.\$(OBJDIR)\nsNativeConnectionHelper.obj \
|
||||
.\$(OBJDIR)\nsAutodialWin.obj \
|
||||
$(NULL)
|
||||
|
||||
JSFILES = \
|
||||
|
||||
674
mozilla/netwerk/base/src/nsAutodialWin.cpp
Normal file
674
mozilla/netwerk/base/src/nsAutodialWin.cpp
Normal file
@ -0,0 +1,674 @@
|
||||
/* ***** 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
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Steve Meredith <smeredith@netscape.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
// This source is mostly a bunch of Windows API calls. It is only compiled for
|
||||
// Windows builds.
|
||||
#include <windows.h>
|
||||
#include <winsvc.h>
|
||||
#include "nsAutodialWin.h"
|
||||
#include "prlog.h"
|
||||
|
||||
//
|
||||
// Log module for autodial logging...
|
||||
//
|
||||
// To enable logging (see prlog.h for full details):
|
||||
//
|
||||
// set NSPR_LOG_MODULES=Autodial:5
|
||||
// set NSPR_LOG_FILE=nspr.log
|
||||
//
|
||||
// this enables PR_LOG_DEBUG level information and places all output in
|
||||
// the file nspr.log
|
||||
//
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* gLog = nsnull;
|
||||
#endif
|
||||
|
||||
#define LOGD(args) PR_LOG(gLog, PR_LOG_DEBUG, args)
|
||||
#define LOGE(args) PR_LOG(gLog, PR_LOG_ERROR, args)
|
||||
|
||||
// Don't try to dial again within a few seconds of when user pressed cancel.
|
||||
#define NO_RETRY_PERIOD_SEC 5
|
||||
PRIntervalTime nsRASAutodial::mDontRetryUntil = 0;
|
||||
|
||||
|
||||
tRASPHONEBOOKDLG nsRASAutodial::mpRasPhonebookDlg = nsnull;
|
||||
tRASENUMCONNECTIONS nsRASAutodial::mpRasEnumConnections = nsnull;
|
||||
tRASENUMENTRIES nsRASAutodial::mpRasEnumEntries = nsnull;
|
||||
tRASDIALDLG nsRASAutodial::mpRasDialDlg = nsnull;
|
||||
tRASSETAUTODIALADDRESS nsRASAutodial::mpRasSetAutodialAddress = nsnull;
|
||||
tRASGETAUTODIALADDRESS nsRASAutodial::mpRasGetAutodialAddress = nsnull;
|
||||
HINSTANCE nsRASAutodial::mhRASdlg = nsnull;
|
||||
HINSTANCE nsRASAutodial::mhRASapi32 = nsnull;
|
||||
|
||||
// ctor.
|
||||
nsRASAutodial::nsRASAutodial()
|
||||
: mAutodialBehavior(AUTODIAL_NEVER),
|
||||
mNumRASConnectionEntries(0)
|
||||
{
|
||||
mOSVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&mOSVerInfo);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (!gLog)
|
||||
gLog = PR_NewLogModule("Autodial");
|
||||
#endif
|
||||
|
||||
// We only need to dial on nt based systems. For all other platforms,
|
||||
// mAutodialBehavior will remain AUTODIAL_NEVER, and we can skip
|
||||
// these initializations.
|
||||
if ((mOSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
||||
&& (mOSVerInfo.dwMajorVersion >= 3))
|
||||
{
|
||||
if (!mhRASdlg)
|
||||
{
|
||||
mhRASdlg = ::LoadLibrary("rasdlg.dll");
|
||||
if ((UINT)mhRASdlg > 32)
|
||||
{
|
||||
// RasPhonebookDlg
|
||||
mpRasPhonebookDlg =
|
||||
(tRASPHONEBOOKDLG)::GetProcAddress(mhRASdlg, "RasPhonebookDlgA");
|
||||
|
||||
// RasDialDlg
|
||||
mpRasDialDlg =
|
||||
(tRASDIALDLG)::GetProcAddress(mhRASdlg, "RasDialDlgA");
|
||||
|
||||
}
|
||||
|
||||
if (!mhRASdlg || !mpRasPhonebookDlg || !mpRasDialDlg)
|
||||
{
|
||||
LOGE(("Autodial: Error loading RASDLG.DLL."));
|
||||
}
|
||||
}
|
||||
|
||||
if (!mhRASapi32)
|
||||
{
|
||||
mhRASapi32 = ::LoadLibrary("rasapi32.dll");
|
||||
if ((UINT)mhRASapi32 > 32)
|
||||
{
|
||||
// RasEnumConnections
|
||||
mpRasEnumConnections = (tRASENUMCONNECTIONS)
|
||||
::GetProcAddress(mhRASapi32, "RasEnumConnectionsA");
|
||||
|
||||
// RasEnumEntries
|
||||
mpRasEnumEntries = (tRASENUMENTRIES)
|
||||
::GetProcAddress(mhRASapi32, "RasEnumEntriesA");
|
||||
|
||||
// RasSetAutodialAddress
|
||||
mpRasSetAutodialAddress = (tRASSETAUTODIALADDRESS)
|
||||
::GetProcAddress(mhRASapi32, "RasSetAutodialAddressA");
|
||||
|
||||
// RasSetAutodialAddress
|
||||
mpRasGetAutodialAddress = (tRASGETAUTODIALADDRESS)
|
||||
::GetProcAddress(mhRASapi32, "RasGetAutodialAddressA");
|
||||
}
|
||||
|
||||
if (!mhRASapi32
|
||||
|| !mpRasEnumConnections
|
||||
|| !mpRasEnumEntries
|
||||
|| !mpRasSetAutodialAddress
|
||||
|| !mpRasGetAutodialAddress)
|
||||
{
|
||||
LOGE(("Autodial: Error loading RASAPI32.DLL."));
|
||||
}
|
||||
}
|
||||
|
||||
// Initializations that can be made again since RAS OS settings can
|
||||
// change.
|
||||
Init();
|
||||
}
|
||||
}
|
||||
|
||||
// dtor
|
||||
nsRASAutodial::~nsRASAutodial()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// Get settings from the OS. These are settings that might change during
|
||||
// the OS session. Call Init() again to pick up those changes if required.
|
||||
// Returns NS_ERROR_FAILURE if error or NS_OK if success.
|
||||
nsresult nsRASAutodial::Init()
|
||||
{
|
||||
mDefaultEntryName[0] = '\0';
|
||||
mNumRASConnectionEntries = 0;
|
||||
mAutodialBehavior = QueryAutodialBehavior();
|
||||
|
||||
// No need to continue in this case.
|
||||
if (mAutodialBehavior == AUTODIAL_NEVER)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get the number of dialup entries in the phonebook.
|
||||
mNumRASConnectionEntries = NumRASEntries();
|
||||
|
||||
// Get the name of the default entry.
|
||||
nsresult result = GetDefaultEntryName(mDefaultEntryName,
|
||||
RAS_MaxEntryName + 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Should we attempt to dial on a network error? Yes if the Internet Options
|
||||
// configured as such. Yes if the RAS autodial service is running (we'll
|
||||
// force it to dail in that case by adding the network address to its db.)
|
||||
PRBool nsRASAutodial::ShouldDialOnNetworkError()
|
||||
{
|
||||
// Don't try to dial again within a few seconds of when user pressed cancel.
|
||||
if (mDontRetryUntil)
|
||||
{
|
||||
PRIntervalTime intervalNow = PR_IntervalNow();
|
||||
if (intervalNow < mDontRetryUntil)
|
||||
{
|
||||
LOGD(("Autodial: Not dialing: too soon."));
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ((mAutodialBehavior == AUTODIAL_ALWAYS)
|
||||
|| (mAutodialBehavior == AUTODIAL_ON_NETWORKERROR)
|
||||
|| (mAutodialBehavior == AUTODIAL_USE_SERVICE));
|
||||
}
|
||||
|
||||
|
||||
// The autodial info is set in Control Panel | Internet Options | Connections.
|
||||
// The values are stored in the registry. This function gets those values from
|
||||
// the registry and determines if we should never dial, always dial, or dial
|
||||
// when there is no network found.
|
||||
int nsRASAutodial::QueryAutodialBehavior()
|
||||
{
|
||||
if (IsAutodialServiceRunning())
|
||||
return AUTODIAL_USE_SERVICE;
|
||||
|
||||
HKEY hKey = 0;
|
||||
LONG result = ::RegOpenKeyEx(
|
||||
HKEY_CURRENT_USER,
|
||||
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
return AUTODIAL_NEVER;
|
||||
}
|
||||
|
||||
DWORD entryType = 0;
|
||||
DWORD autodial = 0;
|
||||
DWORD onDemand = 0;
|
||||
DWORD paramSize = sizeof(DWORD);
|
||||
|
||||
result = ::RegQueryValueEx(hKey, "EnableAutodial", nsnull, &entryType, (LPBYTE)&autodial, ¶mSize);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
::RegCloseKey(hKey);
|
||||
return AUTODIAL_NEVER;
|
||||
}
|
||||
|
||||
result = ::RegQueryValueEx(hKey, "NoNetAutodial", nsnull, &entryType, (LPBYTE)&onDemand, ¶mSize);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
::RegCloseKey(hKey);
|
||||
return AUTODIAL_NEVER;
|
||||
}
|
||||
|
||||
::RegCloseKey(hKey);
|
||||
|
||||
if (!autodial)
|
||||
{
|
||||
return AUTODIAL_NEVER;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (onDemand)
|
||||
{
|
||||
return AUTODIAL_ON_NETWORKERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return AUTODIAL_ALWAYS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the RAS autodial service is running, use it. Otherwise, dial
|
||||
// the default RAS connection. There are two possible RAS dialogs:
|
||||
// one that dials a single entry, and one that lets the user choose which
|
||||
// to dial. If there is only one connection entry in the phone book, or
|
||||
// there are multiple entries but one is defined as the default, we'll use
|
||||
// the single entry dial dialog. If there are multiple connection entries,
|
||||
// and none is specified as default, we'll bring up the diallog which lets
|
||||
// the user select the connection entry to use.
|
||||
nsresult nsRASAutodial::DialDefault(const char* hostName)
|
||||
{
|
||||
mDontRetryUntil = 0;
|
||||
|
||||
if (mAutodialBehavior == AUTODIAL_NEVER)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// If already a RAS connection, bail.
|
||||
if (IsRASConnected())
|
||||
{
|
||||
LOGD(("Autodial: Not dialing: active connection."));
|
||||
return NS_OK; //NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// If no dialup connections configured, bail.
|
||||
if (mNumRASConnectionEntries <= 0)
|
||||
{
|
||||
LOGD(("Autodial: Not dialing: no entries."));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// If autodial service is running, let it dial. In order for it to dial
|
||||
// reliably, we have to add the target address to the autodial database.
|
||||
// This is the only way the autodial service dial if there is a network
|
||||
// adapter installed.
|
||||
// See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rras/ras4over_3dwl.asp
|
||||
if (mAutodialBehavior == AUTODIAL_USE_SERVICE)
|
||||
{
|
||||
if (!AddAddressToAutodialDirectory(hostName))
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Do the dialing ourselves.
|
||||
else
|
||||
{
|
||||
// If a default dial entry is configured, use it.
|
||||
if (mDefaultEntryName[0] != '\0')
|
||||
{
|
||||
LOGD(("Autodial: Dialing default: %s.",mDefaultEntryName));
|
||||
|
||||
RASDIALDLG rasDialDlg;
|
||||
memset(&rasDialDlg, 0, sizeof(RASDIALDLG));
|
||||
rasDialDlg.dwSize = sizeof(RASDIALDLG);
|
||||
|
||||
NS_ASSERTION(mpRasDialDlg != nsnull,
|
||||
"RAS DLLs only loaded for NT-based OSs.");
|
||||
|
||||
if (!mpRasDialDlg)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
PRBool dialed =
|
||||
(*mpRasDialDlg)(nsnull, mDefaultEntryName, nsnull, &rasDialDlg);
|
||||
if (!dialed)
|
||||
{
|
||||
if (rasDialDlg.dwError != 0)
|
||||
{
|
||||
LOGE(("Autodial ::RasDialDlg failed: Error: %d.",
|
||||
rasDialDlg.dwError));
|
||||
}
|
||||
else
|
||||
{
|
||||
mDontRetryUntil = PR_IntervalNow() + PR_SecondsToInterval(NO_RETRY_PERIOD_SEC);
|
||||
LOGD(("Autodial: User cancelled dial."));
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
LOGD(("Autodial: RAS dialup connection successful."));
|
||||
}
|
||||
|
||||
// If no default connection specified, open the dialup dialog that lets
|
||||
// the user specifiy which connection to dial.
|
||||
else
|
||||
{
|
||||
LOGD(("Autodial: Prompting for phonebook entry."));
|
||||
|
||||
RASPBDLG rasPBDlg;
|
||||
memset(&rasPBDlg, 0, sizeof(RASPBDLG));
|
||||
rasPBDlg.dwSize = sizeof(RASPBDLG);
|
||||
|
||||
NS_ASSERTION(mpRasPhonebookDlg != nsnull,
|
||||
"RAS DLLs only loaded for NT-based OSs.");
|
||||
|
||||
if (!mpRasPhonebookDlg)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
PRBool dialed = (*mpRasPhonebookDlg)(nsnull, nsnull, &rasPBDlg);
|
||||
|
||||
if (!dialed)
|
||||
{
|
||||
if (rasPBDlg.dwError != 0)
|
||||
{
|
||||
LOGE(("Autodial: ::RasPhonebookDlg failed: Error = %d.",
|
||||
rasPBDlg.dwError));
|
||||
}
|
||||
else
|
||||
{
|
||||
mDontRetryUntil = PR_IntervalNow() + PR_SecondsToInterval(NO_RETRY_PERIOD_SEC);
|
||||
LOGD(("Autodial: User cancelled dial."));
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
LOGD(("Autodial: RAS dialup connection successful."));
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
// Check to see if RAS is already connected.
|
||||
PRBool nsRASAutodial::IsRASConnected()
|
||||
{
|
||||
DWORD connections;
|
||||
RASCONN rasConn;
|
||||
rasConn.dwSize = sizeof(RASCONN);
|
||||
DWORD structSize = sizeof(RASCONN);
|
||||
|
||||
NS_ASSERTION(mpRasEnumConnections != nsnull,
|
||||
"RAS DLLs only loaded for NT-based OSs.");
|
||||
|
||||
if (!mpRasEnumConnections)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
DWORD result = (*mpRasEnumConnections)(&rasConn, &structSize, &connections);
|
||||
|
||||
// ERROR_BUFFER_TOO_SMALL is OK because we only need one struct.
|
||||
if (result == ERROR_SUCCESS || result == ERROR_BUFFER_TOO_SMALL)
|
||||
{
|
||||
return (connections > 0);
|
||||
}
|
||||
|
||||
LOGE(("Autodial: ::RasEnumConnections failed: Error = %d", result));
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Get the first RAS dial entry name from the phonebook.
|
||||
nsresult nsRASAutodial::GetFirstEntryName(char* entryName, int bufferSize)
|
||||
{
|
||||
RASENTRYNAME rasEntryName;
|
||||
rasEntryName.dwSize = sizeof(RASENTRYNAME);
|
||||
DWORD cb = sizeof(RASENTRYNAME);
|
||||
DWORD cEntries = 0;
|
||||
|
||||
NS_ASSERTION(mpRasEnumEntries != nsnull,
|
||||
"RAS DLLs only loaded for NT-based OSs.");
|
||||
|
||||
if (!mpRasEnumEntries)
|
||||
{
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
DWORD result =
|
||||
(*mpRasEnumEntries)(nsnull, nsnull, &rasEntryName, &cb, &cEntries);
|
||||
|
||||
// ERROR_BUFFER_TOO_SMALL is OK because we only need one struct.
|
||||
if (result == ERROR_SUCCESS || result == ERROR_BUFFER_TOO_SMALL)
|
||||
{
|
||||
strncpy(entryName, rasEntryName.szEntryName, bufferSize);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Get the number of RAS dial entries in the phonebook.
|
||||
int nsRASAutodial::NumRASEntries()
|
||||
{
|
||||
RASENTRYNAME rasEntryName;
|
||||
rasEntryName.dwSize = sizeof(RASENTRYNAME);
|
||||
DWORD cb = sizeof(RASENTRYNAME);
|
||||
DWORD cEntries = 0;
|
||||
|
||||
NS_ASSERTION(mpRasEnumEntries != nsnull,
|
||||
"RAS DLLs only loaded for NT-based OSs.");
|
||||
|
||||
if (!mpRasEnumEntries)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD result =
|
||||
(*mpRasEnumEntries)(nsnull, nsnull, &rasEntryName, &cb, &cEntries);
|
||||
|
||||
// ERROR_BUFFER_TOO_SMALL is OK because we only need one struct.
|
||||
if (result == ERROR_SUCCESS || result == ERROR_BUFFER_TOO_SMALL)
|
||||
{
|
||||
return (int)cEntries;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the name of the default dial entry.
|
||||
nsresult nsRASAutodial::GetDefaultEntryName(char* entryName, int bufferSize)
|
||||
{
|
||||
// No RAS dialup entries.
|
||||
if (mNumRASConnectionEntries <= 0)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Single RAS dialup entry. Use it as the default to autodail.
|
||||
if (mNumRASConnectionEntries == 1)
|
||||
{
|
||||
return GetFirstEntryName(entryName, bufferSize);
|
||||
}
|
||||
|
||||
// Multiple RAS dialup entries. If a default configured in the registry,
|
||||
// use it.
|
||||
//
|
||||
// For Windows XP: HKCU/Software/Microsoft/RAS Autodial/Default/DefaultInternet.
|
||||
// or HKLM/Software/Microsoft/RAS Autodial/Default/DefaultInternet.
|
||||
// For Windows 2K: HKCU/RemoteAccess/InternetProfile.
|
||||
|
||||
char* key = nsnull;
|
||||
char* val = nsnull;
|
||||
|
||||
HKEY hKey = 0;
|
||||
LONG result = 0;
|
||||
|
||||
// Windows NT and 2000
|
||||
if ((mOSVerInfo.dwMajorVersion == 4) // Windows NT
|
||||
|| ((mOSVerInfo.dwMajorVersion == 5) && (mOSVerInfo.dwMinorVersion == 0))) // Windows 2000
|
||||
{
|
||||
key = "RemoteAccess";
|
||||
val = "InternetProfile";
|
||||
|
||||
result = ::RegOpenKeyEx(
|
||||
HKEY_CURRENT_USER,
|
||||
key,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
else // Windows XP
|
||||
{
|
||||
key = "Software\\Microsoft\\RAS Autodial\\Default";
|
||||
val = "DefaultInternet";
|
||||
|
||||
|
||||
// Try HKCU first.
|
||||
result = ::RegOpenKeyEx(
|
||||
HKEY_CURRENT_USER,
|
||||
key,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
// If not present, try HKLM.
|
||||
result = ::RegOpenKeyEx(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
key,
|
||||
0,
|
||||
KEY_READ,
|
||||
&hKey);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DWORD entryType = 0;
|
||||
DWORD buffSize = bufferSize;
|
||||
|
||||
result = ::RegQueryValueEx(hKey,
|
||||
val,
|
||||
nsnull,
|
||||
&entryType,
|
||||
(LPBYTE)entryName,
|
||||
&buffSize);
|
||||
|
||||
::RegCloseKey(hKey);
|
||||
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
// Use first entry if none configured as default.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// Determine if the autodial service is running on this PC.
|
||||
PRBool nsRASAutodial::IsAutodialServiceRunning()
|
||||
{
|
||||
SC_HANDLE hSCManager =
|
||||
OpenSCManager(nsnull, SERVICES_ACTIVE_DATABASE, SERVICE_QUERY_STATUS);
|
||||
|
||||
if (hSCManager == nsnull)
|
||||
{
|
||||
LOGE(("Autodial: failed to open service control manager. Error %d.",
|
||||
::GetLastError()));
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
SC_HANDLE hService =
|
||||
OpenService(hSCManager, "RasAuto", SERVICE_QUERY_STATUS);
|
||||
|
||||
if (hSCManager == nsnull)
|
||||
{
|
||||
LOGE(("Autodial: failed to open RasAuto service."));
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
SERVICE_STATUS status;
|
||||
if (!QueryServiceStatus(hService, &status))
|
||||
{
|
||||
LOGE(("Autodial: ::QueryServiceStatus() failed. Error: %d",
|
||||
::GetLastError()));
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return (status.dwCurrentState == SERVICE_RUNNING);
|
||||
}
|
||||
|
||||
// Add the specified address to the autodial directory.
|
||||
PRBool nsRASAutodial::AddAddressToAutodialDirectory(const char* hostName)
|
||||
{
|
||||
NS_ASSERTION(mpRasGetAutodialAddress != nsnull,
|
||||
"RAS DLLs only loaded for NT-based OSs.");
|
||||
|
||||
NS_ASSERTION(mpRasSetAutodialAddress != nsnull,
|
||||
"RAS DLLs only loaded for NT-based OSs.");
|
||||
|
||||
if (!mpRasGetAutodialAddress || !mpRasSetAutodialAddress)
|
||||
{
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// First see if there is already a db entry for this address.
|
||||
DWORD size = 0;
|
||||
DWORD entries = 0;
|
||||
|
||||
DWORD result = (*mpRasGetAutodialAddress)(hostName,
|
||||
NULL,
|
||||
NULL,
|
||||
&size,
|
||||
&entries);
|
||||
|
||||
// If there is already an entry in db for this address, return.
|
||||
if (size != 0)
|
||||
{
|
||||
LOGD(("Autodial: Address %s already in autodial db.", hostName));
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
RASAUTODIALENTRY autodialEntry;
|
||||
autodialEntry.dwSize = sizeof(RASAUTODIALENTRY);
|
||||
autodialEntry.dwFlags = 0;
|
||||
autodialEntry.dwDialingLocation = 1;
|
||||
GetDefaultEntryName(autodialEntry.szEntry, RAS_MaxEntryName);
|
||||
|
||||
result = (*mpRasSetAutodialAddress)(hostName,
|
||||
0,
|
||||
&autodialEntry,
|
||||
sizeof(RASAUTODIALENTRY),
|
||||
1);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
LOGE(("Autodial ::RasSetAutodialAddress failed result %d.", result));
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
LOGD(("Autodial: Added address %s to RAS autodial db for entry %s.",
|
||||
hostName, autodialEntry.szEntry));
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
176
mozilla/netwerk/base/src/nsAutodialWin.h
Normal file
176
mozilla/netwerk/base/src/nsAutodialWin.h
Normal file
@ -0,0 +1,176 @@
|
||||
/* ***** 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
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Steve Meredith <smeredith@netscape.com>
|
||||
*
|
||||
* 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 nsAutodialWin_h__
|
||||
#define nsAutodialWin_h__
|
||||
|
||||
#include <windows.h>
|
||||
#include <ras.h>
|
||||
#include <rasdlg.h>
|
||||
#include <raserror.h>
|
||||
#include "nscore.h"
|
||||
#include "nspr.h"
|
||||
|
||||
#if (WINVER < 0x401)
|
||||
/* AutoDial address properties.
|
||||
*/
|
||||
typedef struct tagRASAUTODIALENTRYA {
|
||||
DWORD dwSize;
|
||||
DWORD dwFlags;
|
||||
DWORD dwDialingLocation;
|
||||
CHAR szEntry[RAS_MaxEntryName + 1];
|
||||
} RASAUTODIALENTRYA, *LPRASAUTODIALENTRYA;
|
||||
typedef RASAUTODIALENTRYA RASAUTODIALENTRY, *LPRASAUTODIALENTRY;
|
||||
#endif // WINVER
|
||||
|
||||
// Loading the RAS DLL dynamically.
|
||||
typedef DWORD (WINAPI* tRASPHONEBOOKDLG)(LPTSTR,LPTSTR,LPRASPBDLG);
|
||||
typedef DWORD (WINAPI* tRASDIALDLG)(LPTSTR,LPTSTR,LPTSTR,LPRASDIALDLG);
|
||||
typedef DWORD (WINAPI* tRASENUMCONNECTIONS)(LPRASCONN,LPDWORD,LPDWORD);
|
||||
typedef DWORD (WINAPI* tRASENUMENTRIES)(LPTSTR,LPTSTR,LPRASENTRYNAME,LPDWORD,LPDWORD);
|
||||
typedef DWORD (WINAPI* tRASSETAUTODIALADDRESS)(LPCTSTR,DWORD,LPRASAUTODIALENTRY,DWORD,DWORD);
|
||||
typedef DWORD (WINAPI* tRASGETAUTODIALADDRESS)(LPCTSTR,LPDWORD,LPRASAUTODIALENTRY,LPDWORD,LPDWORD);
|
||||
|
||||
// For Windows NT 4, 2000, and XP, we sometimes want to open the RAS dialup
|
||||
// window ourselves, since those versions aren't very nice about it.
|
||||
// See bug 93002. If the RAS autodial service is running, (Remote Access
|
||||
// Auto Connection Manager, aka RasAuto) we will force it to dial
|
||||
// on network error by adding the target address to the autodial
|
||||
// database. If the service is not running, we will open the RAS dialogs
|
||||
// instead.
|
||||
//
|
||||
// The OS can be configured to always dial, or dial when there is no
|
||||
// connection. We implement both by dialing when a network error occurs.
|
||||
//
|
||||
// An object of this class checks with the OS when it is constructed and
|
||||
// remembers those settings. If required, it can be resynced with
|
||||
// the OS at anytime with the Init() method. At the time of implementation,
|
||||
// the caller creates an object of this class each time a network error occurs.
|
||||
// In this case, the initialization overhead is not significant, and it will
|
||||
// guaranteed to be in sync with OS.
|
||||
//
|
||||
// To use, create an instance and call ShouldDialOnNetworkError() to determine
|
||||
// if you should dial or not. That function only return true for the
|
||||
// target OS's so the caller doesn't have to deal with OS version checking.
|
||||
//
|
||||
|
||||
class nsRASAutodial
|
||||
{
|
||||
private:
|
||||
|
||||
//
|
||||
// Some helper functions to query the OS for autodial configuration.
|
||||
//
|
||||
|
||||
// Determine if the autodial service is running on this PC.
|
||||
PRBool IsAutodialServiceRunning();
|
||||
|
||||
// Get the number of RAS connection entries configured from the OS.
|
||||
int NumRASEntries();
|
||||
|
||||
// Get the name of the default connection from the OS.
|
||||
nsresult GetDefaultEntryName(char* entryName, int bufferSize);
|
||||
|
||||
// Get the name of the first RAS dial entry from the OS.
|
||||
nsresult GetFirstEntryName(char* entryName, int bufferSize);
|
||||
|
||||
// Check to see if RAS already has a dialup connection going.
|
||||
PRBool IsRASConnected();
|
||||
|
||||
// Get the autodial behavior from the OS.
|
||||
int QueryAutodialBehavior();
|
||||
|
||||
// Add the specified address to the autodial directory.
|
||||
PRBool AddAddressToAutodialDirectory(const char* hostName);
|
||||
|
||||
//
|
||||
// Autodial behavior. This comes from the Windows registry, set in the ctor.
|
||||
// Object won't pick up changes to the registry automatically, but can be
|
||||
// refreshed at anytime by calling Init(). So if the user changed the
|
||||
// autodial settings, they wouldn't be noticed unless Init() is called.
|
||||
int mAutodialBehavior;
|
||||
|
||||
enum { AUTODIAL_NEVER = 1 }; // Never autodial.
|
||||
enum { AUTODIAL_ALWAYS = 2 }; // Always autodial as set in Internet Options.
|
||||
enum { AUTODIAL_ON_NETWORKERROR = 3 }; // Autodial when a connection error occurs as set in Internet Options.
|
||||
enum { AUTODIAL_USE_SERVICE = 4 }; // Use the RAS autodial service to dial.
|
||||
|
||||
// Number of RAS connection entries in the phonebook.
|
||||
int mNumRASConnectionEntries;
|
||||
|
||||
// Default connection entry name.
|
||||
char mDefaultEntryName[RAS_MaxEntryName + 1];
|
||||
|
||||
// Don't try to dial again within a few seconds of when user pressed cancel.
|
||||
static PRIntervalTime mDontRetryUntil;
|
||||
|
||||
// OS version info.
|
||||
OSVERSIONINFO mOSVerInfo;
|
||||
|
||||
// DLL instance handles.
|
||||
static HINSTANCE mhRASdlg;
|
||||
static HINSTANCE mhRASapi32;
|
||||
|
||||
// DLL function pointers.
|
||||
static tRASPHONEBOOKDLG mpRasPhonebookDlg;
|
||||
static tRASENUMCONNECTIONS mpRasEnumConnections;
|
||||
static tRASENUMENTRIES mpRasEnumEntries;
|
||||
static tRASDIALDLG mpRasDialDlg;
|
||||
static tRASSETAUTODIALADDRESS mpRasSetAutodialAddress;
|
||||
static tRASGETAUTODIALADDRESS mpRasGetAutodialAddress;
|
||||
|
||||
public:
|
||||
|
||||
// ctor
|
||||
nsRASAutodial();
|
||||
|
||||
// dtor
|
||||
virtual ~nsRASAutodial();
|
||||
|
||||
// Get the autodial info from the OS and init this obj with it. Call it any
|
||||
// time to refresh the object's settings from the OS.
|
||||
nsresult Init();
|
||||
|
||||
// Dial the default RAS dialup connection.
|
||||
nsresult DialDefault(const char* hostName);
|
||||
|
||||
// Should we try to dial on network error?
|
||||
PRBool ShouldDialOnNetworkError();
|
||||
};
|
||||
|
||||
#endif // !nsAutodialWin_h__
|
||||
|
||||
@ -68,6 +68,7 @@
|
||||
|
||||
#define PORT_PREF_PREFIX "network.security.ports."
|
||||
#define PORT_PREF(x) PORT_PREF_PREFIX x
|
||||
#define AUTODIAL_PREF "network.autodial-helper.enabled"
|
||||
|
||||
static NS_DEFINE_CID(kFileTransportService, NS_FILETRANSPORTSERVICE_CID);
|
||||
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
|
||||
@ -220,8 +221,10 @@ nsIOService::Init()
|
||||
GetPrefBranch(getter_AddRefs(prefBranch));
|
||||
if (prefBranch) {
|
||||
nsCOMPtr<nsIPrefBranchInternal> pbi = do_QueryInterface(prefBranch);
|
||||
if (pbi)
|
||||
if (pbi) {
|
||||
pbi->AddObserver(PORT_PREF_PREFIX, this, PR_TRUE);
|
||||
pbi->AddObserver(AUTODIAL_PREF, this, PR_TRUE);
|
||||
}
|
||||
PrefsChanged(prefBranch);
|
||||
}
|
||||
|
||||
@ -965,6 +968,16 @@ nsIOService::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
|
||||
// ...as well as previous blocks to remove.
|
||||
if (!pref || PL_strcmp(pref, PORT_PREF("banned.override")) == 0)
|
||||
ParsePortList(prefs, PORT_PREF("banned.override"), PR_TRUE);
|
||||
|
||||
if (!pref || PL_strcmp(pref, AUTODIAL_PREF) == 0) {
|
||||
PRBool enableAutodial = PR_FALSE;
|
||||
nsresult rv = prefs->GetBoolPref(AUTODIAL_PREF, &enableAutodial);
|
||||
// If pref not found, default to disabled.
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (mSocketTransportService)
|
||||
mSocketTransportService->SetAutodialEnabled(enableAutodial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
164
mozilla/netwerk/base/src/nsNativeConnectionHelper.cpp
Normal file
164
mozilla/netwerk/base/src/nsNativeConnectionHelper.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
/* ***** 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
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@netscape.com>
|
||||
* Steve Meredith <smeredith@netscape.com>
|
||||
*
|
||||
* 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 "nsNativeConnectionHelper.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutodialWin.h"
|
||||
#include "nsIPref.h"
|
||||
|
||||
static NS_DEFINE_IID(kPrefServiceCID, NS_PREF_CID);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsSyncEvent - implements a synchronous event that runs on the main thread.
|
||||
//
|
||||
// XXX move this class into xpcom/proxy
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class nsSyncEvent
|
||||
{
|
||||
public:
|
||||
nsSyncEvent() {}
|
||||
virtual ~nsSyncEvent() {}
|
||||
|
||||
nsresult Dispatch();
|
||||
|
||||
virtual void HandleEvent() = 0;
|
||||
|
||||
private:
|
||||
static void* PR_CALLBACK EventHandler (PLEvent *self);
|
||||
static void PR_CALLBACK EventDestructor (PLEvent *self);
|
||||
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsSyncEvent::Dispatch()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIEventQueueService> eqs(
|
||||
do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIEventQueue> eventQ;
|
||||
rv = eqs->GetSpecialEventQueue(nsIEventQueueService::UI_THREAD_EVENT_QUEUE,
|
||||
getter_AddRefs(eventQ));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRBool onCurrentThread = PR_FALSE;
|
||||
eventQ->IsQueueOnCurrentThread(&onCurrentThread);
|
||||
if (onCurrentThread) {
|
||||
HandleEvent();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Otherwise build up an event and post it to the main thread's event queue
|
||||
// and block before returning.
|
||||
|
||||
|
||||
PLEvent *ev = new PLEvent;
|
||||
if (!ev)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
PL_InitEvent(ev, (void *) this, EventHandler, EventDestructor);
|
||||
|
||||
// block until the event is answered
|
||||
eventQ->PostSynchronousEvent(ev, nsnull);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void* PR_CALLBACK
|
||||
nsSyncEvent::EventHandler(PLEvent *self)
|
||||
{
|
||||
nsSyncEvent *ev = (nsSyncEvent *) PL_GetEventOwner(self);
|
||||
if (ev)
|
||||
ev->HandleEvent();
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void PR_CALLBACK
|
||||
nsSyncEvent::EventDestructor(PLEvent *self)
|
||||
{
|
||||
delete self;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsOnConnectionFailedEvent
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class nsOnConnectionFailedEvent : public nsSyncEvent
|
||||
{
|
||||
private:
|
||||
nsRASAutodial mAutodial;
|
||||
const char* mHostName;
|
||||
|
||||
public:
|
||||
nsOnConnectionFailedEvent(const char* hostname) : mRetry(PR_FALSE), mHostName(hostname) { }
|
||||
|
||||
void HandleEvent();
|
||||
|
||||
PRBool mRetry;
|
||||
};
|
||||
|
||||
void nsOnConnectionFailedEvent::HandleEvent()
|
||||
{
|
||||
mRetry = PR_FALSE;
|
||||
if (mAutodial.ShouldDialOnNetworkError()) {
|
||||
mRetry = NS_SUCCEEDED(mAutodial.DialDefault(mHostName));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// API typically invoked on the socket transport thread
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
PRBool
|
||||
nsNativeConnectionHelper::OnConnectionFailed(const char* strHostName)
|
||||
{
|
||||
nsOnConnectionFailedEvent event(strHostName);
|
||||
if (NS_SUCCEEDED(event.Dispatch()))
|
||||
return event.mRetry;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
57
mozilla/netwerk/base/src/nsNativeConnectionHelper.h
Normal file
57
mozilla/netwerk/base/src/nsNativeConnectionHelper.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* ***** 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
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@netscape.com>
|
||||
*
|
||||
* 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 nsNativeConnectionHelper_h__
|
||||
#define nsNativeConnectionHelper_h__
|
||||
|
||||
#include "nscore.h"
|
||||
|
||||
class nsISocketTransport;
|
||||
|
||||
class nsNativeConnectionHelper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* OnConnectionFailed
|
||||
*
|
||||
* Return PR_TRUE if the connection should be re-attempted.
|
||||
*/
|
||||
static PRBool OnConnectionFailed(const char* strHostName);
|
||||
};
|
||||
|
||||
#endif // !nsNativeConnectionHelper_h__
|
||||
|
||||
@ -63,6 +63,10 @@
|
||||
#include "nsIProxyInfo.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include "nsNativeConnectionHelper.h"
|
||||
#endif
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
static PRLogModuleInfo *gSocketTransportLog = nsnull;
|
||||
#endif
|
||||
@ -536,7 +540,9 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
|
||||
// on connection failure, reuse next address if one exists
|
||||
if (mStatus == NS_ERROR_CONNECTION_REFUSED) {
|
||||
LOG(("connection failed [this=%x error=%x]\n", this, mStatus));
|
||||
if (TryNextAddress()) {
|
||||
|
||||
// Try again? OnConnectionFailed() may exit and re-enter the monitor.
|
||||
if (OnConnectionFailed(PR_TRUE)) {
|
||||
done = PR_TRUE;
|
||||
continue;
|
||||
}
|
||||
@ -563,7 +569,9 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
|
||||
firedOnStart = mReadRequest->IsInitialized();
|
||||
if (!firedOnStart && mWriteRequest)
|
||||
firedOnStart = mWriteRequest->IsInitialized();
|
||||
if (!firedOnStart && TryNextAddress()) {
|
||||
|
||||
// Try again? OnConnectionFailed() may exit and re-enter the monitor.
|
||||
if (!firedOnStart && OnConnectionFailed(PR_TRUE)) {
|
||||
// a little bit of hackery here so we'll end up in the
|
||||
// WaitConnect state...
|
||||
mCurrentState = eSocketState_WaitConnect;
|
||||
@ -619,27 +627,60 @@ nsSocketTransport::Cancel(nsresult status)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Try next address if param says to. Otherwise, try to use autodial. If a
|
||||
// connection is made, we try the network again. Otherwise, we don't.
|
||||
// Returns true to cause connection failures to try again.
|
||||
//
|
||||
PRBool
|
||||
nsSocketTransport::TryNextAddress()
|
||||
nsSocketTransport::OnConnectionFailed(PRBool tryNextAddress)
|
||||
{
|
||||
mNetAddress = mNetAddrList.GetNext(mNetAddress);
|
||||
if (mNetAddress) {
|
||||
LOG(("nsSocketTransport Entering OnConnectionFailed()"));
|
||||
|
||||
PRBool tryAgain = PR_FALSE;
|
||||
|
||||
// If required, retry using next address.
|
||||
if (tryNextAddress) {
|
||||
|
||||
PRNetAddr* nextNetAddress = mNetAddrList.GetNext(mNetAddress);
|
||||
|
||||
if (nextNetAddress) {
|
||||
mNetAddress = nextNetAddress;
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
char buf[64];
|
||||
PR_NetAddrToString(mNetAddress, buf, sizeof(buf));
|
||||
LOG((" ...trying next address: %s\n", buf));
|
||||
char buf[64];
|
||||
PR_NetAddrToString(mNetAddress, buf, sizeof(buf));
|
||||
LOG((" ...trying next address: %s\n", buf));
|
||||
#endif
|
||||
PR_Close(mSocketFD);
|
||||
tryAgain = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// If not trying next address, try to make a connection using dialup.
|
||||
// Retry if that connection is made.
|
||||
if (!tryAgain && mService->mAutodialEnabled) {
|
||||
|
||||
#if defined(XP_WIN)
|
||||
PR_ExitMonitor(mMonitor);
|
||||
tryAgain = nsNativeConnectionHelper::OnConnectionFailed(GetSocketHost());
|
||||
PR_EnterMonitor(mMonitor);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Prepare to try again.
|
||||
if (tryAgain)
|
||||
{
|
||||
if (mSocketFD)
|
||||
PR_Close(mSocketFD);
|
||||
mSocketFD = nsnull;
|
||||
|
||||
// mask error status so we'll return to this state
|
||||
mStatus = NS_OK;
|
||||
|
||||
// need to re-enter Process() asynchronously
|
||||
mService->AddToWorkQ(this);
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
|
||||
LOG(("nsSocketTransport Leaving OnConnectionFailed() tryAgain = %d",tryAgain));
|
||||
return tryAgain;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1629,11 +1670,21 @@ nsSocketTransport::OnStopLookup(nsISupports *aContext,
|
||||
// Release our reference to the DNS Request...
|
||||
mDNSRequest = 0;
|
||||
|
||||
// If the lookup failed, set the status...
|
||||
if (NS_FAILED(aStatus))
|
||||
mStatus = aStatus;
|
||||
else if (mNetAddress == nsnull)
|
||||
// If the lookup failed...
|
||||
if (NS_FAILED(aStatus)) {
|
||||
|
||||
// Retry? OnConnectionFailed() may exit and re-enter the monitor.
|
||||
// Don't want to set the tryNextAddress param because DNS lookup has
|
||||
// just failed so hostname has not been resolved yet.
|
||||
if (aStatus != NS_BASE_STREAM_WOULD_BLOCK && OnConnectionFailed(PR_FALSE))
|
||||
mStatus = NS_OK;
|
||||
else
|
||||
mStatus = aStatus;
|
||||
}
|
||||
else if (mNetAddress == nsnull) {
|
||||
mStatus = NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
|
||||
// Start processing the transport again - if necessary...
|
||||
if (GetFlag(eSocketDNS_Wait)) {
|
||||
|
||||
@ -208,7 +208,7 @@ protected:
|
||||
nsresult doReadWrite(PRInt16 aSelectFlags);
|
||||
nsresult doResolveHost();
|
||||
|
||||
PRBool TryNextAddress();
|
||||
PRBool OnConnectionFailed(PRBool tryNextAddress);
|
||||
|
||||
void CompleteAsyncRead();
|
||||
void CompleteAsyncWrite();
|
||||
|
||||
@ -69,7 +69,8 @@ static NS_DEFINE_CID(kDNSService, NS_DNSSERVICE_CID);
|
||||
|
||||
nsSocketTransportService::nsSocketTransportService () :
|
||||
mConnectedTransports (0),
|
||||
mTotalTransports (0)
|
||||
mTotalTransports (0),
|
||||
mAutodialEnabled(PR_FALSE)
|
||||
{
|
||||
#if defined(PR_LOGGING)
|
||||
if (!gSocketTransportServiceLog)
|
||||
@ -937,3 +938,18 @@ nsSocketTransportService::OnTransportConnected(const char *host, PRNetAddr *addr
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransportService::GetAutodialEnabled(PRBool *enabled)
|
||||
{
|
||||
*enabled = mAutodialEnabled;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransportService::SetAutodialEnabled(PRBool enabled)
|
||||
{
|
||||
mAutodialEnabled = enabled;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -115,6 +115,9 @@ public:
|
||||
nsIDNSService *GetCachedDNSService() { return mDNSService.get(); }
|
||||
nsIEventQueueService *GetCachedEventQueueService() { return mEventQService.get(); }
|
||||
|
||||
// Pref to enable autodial helper on windows.
|
||||
PRBool mAutodialEnabled;
|
||||
|
||||
protected:
|
||||
//
|
||||
// mHostDB maps hostname -> nsHostEntry
|
||||
|
||||
@ -1346,12 +1346,12 @@ nsDNSService::Run()
|
||||
// convert InetHostInfo to nsHostEnt
|
||||
lookup->ConvertHostEntry();
|
||||
}
|
||||
lookup->ProcessRequests();
|
||||
if (lookup->IsNotCacheable()) {
|
||||
EvictLookup(lookup);
|
||||
} else {
|
||||
AddToEvictionQ(lookup);
|
||||
}
|
||||
lookup->ProcessRequests();
|
||||
NS_RELEASE(lookup);
|
||||
}
|
||||
|
||||
@ -1376,12 +1376,12 @@ nsDNSService::Run()
|
||||
// Got a request!!
|
||||
NS_ADDREF(lookup); // keep the lookup while we process it
|
||||
lookup->DoSyncLookup();
|
||||
lookup->ProcessRequests();
|
||||
if (lookup->IsNotCacheable()) {
|
||||
EvictLookup(lookup);
|
||||
} else {
|
||||
AddToEvictionQ(lookup);
|
||||
}
|
||||
lookup->ProcessRequests();
|
||||
NS_RELEASE(lookup);
|
||||
} else {
|
||||
// Woken up without a request --> shutdown
|
||||
@ -1495,7 +1495,6 @@ nsDNSService::Lookup(const char* hostName,
|
||||
if (NS_FAILED(rv)) goto exit;
|
||||
|
||||
if (lookup->IsComplete()) {
|
||||
lookup->ProcessRequests(); // releases and re-acquires dns lock
|
||||
if (lookup->IsNotCacheable()) {
|
||||
// non-cacheable lookups are released here.
|
||||
EvictLookup(lookup);
|
||||
@ -1505,6 +1504,7 @@ nsDNSService::Lookup(const char* hostName,
|
||||
AddToEvictionQ(lookup);
|
||||
#endif
|
||||
}
|
||||
lookup->ProcessRequests(); // releases and re-acquires dns lock
|
||||
}
|
||||
|
||||
exit:
|
||||
@ -1639,8 +1639,10 @@ nsDNSService::AbortLookups()
|
||||
while(lookup != &mPendingQ) {
|
||||
PR_REMOVE_AND_INIT_LINK(lookup);
|
||||
lookup->MarkComplete(NS_BINDING_ABORTED);
|
||||
lookup->ProcessRequests();
|
||||
NS_ADDREF(lookup);
|
||||
EvictLookup(lookup);
|
||||
lookup->ProcessRequests();
|
||||
NS_RELEASE(lookup);
|
||||
lookup = (nsDNSLookup *)PR_LIST_HEAD(&mPendingQ);
|
||||
}
|
||||
|
||||
@ -1974,12 +1976,12 @@ nsDNSService::ProcessLookup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
FreeMsgID(lookup->mMsgID);
|
||||
|
||||
PR_REMOVE_AND_INIT_LINK(lookup);
|
||||
lookup->ProcessRequests();
|
||||
if (lookup->IsNotCacheable()) {
|
||||
EvictLookup(lookup);
|
||||
} else {
|
||||
AddToEvictionQ(lookup);
|
||||
}
|
||||
lookup->ProcessRequests();
|
||||
NS_RELEASE(lookup);
|
||||
|
||||
return error ? -1 : 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user