зеркало из https://github.com/mozilla/gecko-dev.git
Bug 992772 - Use mms specific network interface to do DNS lookup. r=echen, r=btseng, r=mrbkap
--HG-- extra : histedit_source : 670d2124210bc3769a460022214baaee6b305639
This commit is contained in:
Родитель
c723673526
Коммит
f9c56cb2da
|
@ -167,6 +167,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService",
|
|||
"@mozilla.org/mobileconnection/mobileconnectionservice;1",
|
||||
"nsIMobileConnectionService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
|
||||
"@mozilla.org/network/service;1",
|
||||
"nsINetworkService");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "MMS", function() {
|
||||
let MMS = {};
|
||||
Cu.import("resource://gre/modules/MmsPduHelper.jsm", MMS);
|
||||
|
@ -706,33 +710,38 @@ XPCOMUtils.defineLazyGetter(this, "gMmsTransactionHelper", function() {
|
|||
url = mmsConnection.mmsc;
|
||||
}
|
||||
|
||||
let startTransaction = () => {
|
||||
let startTransaction = netId => {
|
||||
if (DEBUG) debug("sendRequest: register proxy filter to " + url);
|
||||
let proxyFilter = new MmsProxyFilter(mmsConnection, url);
|
||||
gpps.registerFilter(proxyFilter, 0);
|
||||
|
||||
cancellable.xhr =
|
||||
this.sendHttpRequest(mmsConnection, method,
|
||||
url, istream, proxyFilter,
|
||||
url, istream, proxyFilter, netId,
|
||||
(aHttpStatus, aData) =>
|
||||
cancellable.done(aHttpStatus, aData));
|
||||
};
|
||||
|
||||
mmsConnection.ensureRouting(url)
|
||||
.then(() => startTransaction(),
|
||||
(aError) => {
|
||||
debug("Failed to ensureRouting: " + aError);
|
||||
let onRejected = aReason => {
|
||||
debug(aReason);
|
||||
mmsConnection.release();
|
||||
cancellable.done(_HTTP_STATUS_FAILED_TO_ROUTE, null);
|
||||
};
|
||||
|
||||
mmsConnection.release();
|
||||
cancellable.done(_HTTP_STATUS_FAILED_TO_ROUTE, null);
|
||||
});
|
||||
// TODO: |getNetId| will be implemented as a sync call in nsINetworkManager
|
||||
// once Bug 1141903 is landed.
|
||||
mmsConnection.ensureRouting(url)
|
||||
.then(() => gNetworkService.getNetId(mmsConnection.networkInterface.name),
|
||||
(aReason) => onRejected('Failed to ensureRouting: ' + aReason))
|
||||
.then((netId) => startTransaction(netId),
|
||||
(aReason) => onRejected('Failed to getNetId: ' + aReason));
|
||||
});
|
||||
|
||||
return cancellable;
|
||||
},
|
||||
|
||||
sendHttpRequest: function(mmsConnection, method, url, istream, proxyFilter,
|
||||
callback) {
|
||||
netId, callback) {
|
||||
let releaseMmsConnectionAndCallback = (httpStatus, data) => {
|
||||
gpps.unregisterFilter(proxyFilter);
|
||||
// Always release the MMS network connection before callback.
|
||||
|
@ -745,6 +754,7 @@ XPCOMUtils.defineLazyGetter(this, "gMmsTransactionHelper", function() {
|
|||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
|
||||
// Basic setups
|
||||
xhr.networkInterfaceId = netId;
|
||||
xhr.open(method, url, true);
|
||||
xhr.responseType = "arraybuffer";
|
||||
if (istream) {
|
||||
|
|
|
@ -277,48 +277,53 @@ NetworkManager.prototype = {
|
|||
switch (network.state) {
|
||||
case Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED:
|
||||
gNetworkService.createNetwork(network.name, () => {
|
||||
// Add host route for data calls
|
||||
if (this.isNetworkTypeMobile(network.type)) {
|
||||
let currentInterfaceLinks = this.networkInterfaceLinks[networkId];
|
||||
let newLinkRoutes = network.getDnses().concat(network.httpProxyHost);
|
||||
// If gateways have changed, remove all old routes first.
|
||||
this._handleGateways(networkId, network.getGateways())
|
||||
.then(() => this._updateRoutes(currentInterfaceLinks.linkRoutes,
|
||||
newLinkRoutes,
|
||||
network.getGateways(), network.name))
|
||||
.then(() => currentInterfaceLinks.setLinks(newLinkRoutes,
|
||||
network.getGateways(),
|
||||
network.name));
|
||||
}
|
||||
|
||||
// Remove pre-created default route and let setAndConfigureActive()
|
||||
// to set default route only on preferred network
|
||||
gNetworkService.removeDefaultRoute(network);
|
||||
|
||||
// Dun type is a special case where we add the default route to a
|
||||
// secondary table.
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
|
||||
this.setSecondaryDefaultRoute(network);
|
||||
}
|
||||
|
||||
this._addSubnetRoutes(network);
|
||||
this.setAndConfigureActive();
|
||||
|
||||
// Update data connection when Wifi connected/disconnected
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI && this.mRil) {
|
||||
for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
|
||||
this.mRil.getRadioInterface(i).updateRILNetworkInterface();
|
||||
// Set DNS server as early as possible to prevent from
|
||||
// premature domain name lookup.
|
||||
gNetworkService.setDNS(network, () => {
|
||||
// Add host route for data calls
|
||||
if (this.isNetworkTypeMobile(network.type)) {
|
||||
let currentInterfaceLinks = this.networkInterfaceLinks[networkId];
|
||||
let newLinkRoutes = network.getDnses().concat(network.httpProxyHost);
|
||||
// If gateways have changed, remove all old routes first.
|
||||
this._handleGateways(networkId, network.getGateways())
|
||||
.then(() => this._updateRoutes(currentInterfaceLinks.linkRoutes,
|
||||
newLinkRoutes,
|
||||
network.getGateways(), network.name))
|
||||
.then(() => currentInterfaceLinks.setLinks(newLinkRoutes,
|
||||
network.getGateways(),
|
||||
network.name));
|
||||
}
|
||||
}
|
||||
|
||||
// Probing the public network accessibility after routing table is ready
|
||||
CaptivePortalDetectionHelper
|
||||
.notify(CaptivePortalDetectionHelper.EVENT_CONNECT, this.active);
|
||||
// Dun type is a special case where we add the default route to a
|
||||
// secondary table.
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
|
||||
this.setSecondaryDefaultRoute(network);
|
||||
}
|
||||
|
||||
// Notify outer modules like MmsService to start the transaction after
|
||||
// the configuration of the network interface is done.
|
||||
Services.obs.notifyObservers(network, TOPIC_CONNECTION_STATE_CHANGED,
|
||||
this.convertConnectionType(network));
|
||||
this._addSubnetRoutes(network);
|
||||
this.setAndConfigureActive();
|
||||
|
||||
// Update data connection when Wifi connected/disconnected
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI && this.mRil) {
|
||||
for (let i = 0; i < this.mRil.numRadioInterfaces; i++) {
|
||||
this.mRil.getRadioInterface(i).updateRILNetworkInterface();
|
||||
}
|
||||
}
|
||||
|
||||
// Probing the public network accessibility after routing table is ready
|
||||
CaptivePortalDetectionHelper
|
||||
.notify(CaptivePortalDetectionHelper.EVENT_CONNECT, this.active);
|
||||
|
||||
// Notify outer modules like MmsService to start the transaction after
|
||||
// the configuration of the network interface is done.
|
||||
Services.obs.notifyObservers(network, TOPIC_CONNECTION_STATE_CHANGED,
|
||||
this.convertConnectionType(network));
|
||||
});
|
||||
});
|
||||
|
||||
break;
|
||||
|
@ -641,7 +646,7 @@ NetworkManager.prototype = {
|
|||
// The override was just set, so reconfigure the network.
|
||||
if (this.active != this._overriddenActive) {
|
||||
this.active = this._overriddenActive;
|
||||
this._setDefaultRouteAndDNS(this.active, oldActive);
|
||||
this._setDefaultRouteAndProxy(this.active, oldActive);
|
||||
Services.obs.notifyObservers(this.active, TOPIC_ACTIVE_CHANGED, null);
|
||||
}
|
||||
return;
|
||||
|
@ -652,7 +657,7 @@ NetworkManager.prototype = {
|
|||
this.active.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED &&
|
||||
this.active.type == this._preferredNetworkType) {
|
||||
debug("Active network is already our preferred type.");
|
||||
this._setDefaultRouteAndDNS(this.active, oldActive);
|
||||
this._setDefaultRouteAndProxy(this.active, oldActive);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -686,10 +691,8 @@ NetworkManager.prototype = {
|
|||
this.active = defaultDataNetwork;
|
||||
}
|
||||
// Don't set default route on secondary APN
|
||||
if (this.isNetworkTypeSecondaryMobile(this.active.type)) {
|
||||
gNetworkService.setDNS(this.active, function() {});
|
||||
} else {
|
||||
this._setDefaultRouteAndDNS(this.active, oldActive);
|
||||
if (!this.isNetworkTypeSecondaryMobile(this.active.type)) {
|
||||
this._setDefaultRouteAndProxy(this.active, oldActive);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -713,44 +716,48 @@ NetworkManager.prototype = {
|
|||
return Promise.resolve([hostname]);
|
||||
}
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let onLookupComplete = (aRequest, aRecord, aStatus) => {
|
||||
if (!Components.isSuccessCode(aStatus)) {
|
||||
deferred.reject(new Error(
|
||||
"Failed to resolve '" + hostname + "', with status: " + aStatus));
|
||||
return;
|
||||
}
|
||||
// Wrap gDNSService.asyncResolveExtended to a promise, which
|
||||
// resolves with an array of ip addresses or rejects with
|
||||
// the reason otherwise.
|
||||
let hostResolveWrapper = aNetId => {
|
||||
return new Promise((aResolve, aReject) => {
|
||||
// Callback for gDNSService.asyncResolveExtended.
|
||||
let onLookupComplete = (aRequest, aRecord, aStatus) => {
|
||||
if (!Components.isSuccessCode(aStatus)) {
|
||||
aReject(new Error("Failed to resolve '" + hostname +
|
||||
"', with status: " + aStatus));
|
||||
return;
|
||||
}
|
||||
|
||||
let retval = [];
|
||||
while (aRecord.hasMore()) {
|
||||
retval.push(aRecord.getNextAddrAsString());
|
||||
}
|
||||
let retval = [];
|
||||
while (aRecord.hasMore()) {
|
||||
retval.push(aRecord.getNextAddrAsString());
|
||||
}
|
||||
|
||||
if (!retval.length) {
|
||||
deferred.reject(new Error("No valid address after DNS lookup!"));
|
||||
return;
|
||||
}
|
||||
if (!retval.length) {
|
||||
aReject(new Error("No valid address after DNS lookup!"));
|
||||
return;
|
||||
}
|
||||
|
||||
debug("hostname is resolved: " + hostname);
|
||||
debug("Addresses: " + JSON.stringify(retval));
|
||||
debug("hostname is resolved: " + hostname);
|
||||
debug("Addresses: " + JSON.stringify(retval));
|
||||
|
||||
deferred.resolve(retval);
|
||||
aResolve(retval);
|
||||
};
|
||||
|
||||
debug('Calling gDNSService.asyncResolveExtended: ' + aNetId + ', ' + hostname);
|
||||
gDNSService.asyncResolveExtended(hostname,
|
||||
0,
|
||||
aNetId,
|
||||
onLookupComplete,
|
||||
Services.tm.mainThread);
|
||||
});
|
||||
};
|
||||
|
||||
// Bug 1058282 - Explicitly request ipv4 to get around 8.8.8.8 probe at
|
||||
// http://androidxref.com/4.3_r2.1/xref/bionic/libc/netbsd/net/getaddrinfo.c#1923
|
||||
//
|
||||
// Whenever MMS connection is the only network interface, there is no
|
||||
// default route so that any ip probe will fail.
|
||||
let flags = 0;
|
||||
if (network.type === Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS) {
|
||||
flags |= Ci.nsIDNSService.RESOLVE_DISABLE_IPV6;
|
||||
}
|
||||
|
||||
// TODO: Bug 992772 - Resolve the hostname with specified networkInterface.
|
||||
gDNSService.asyncResolve(hostname, flags, onLookupComplete, Services.tm.mainThread);
|
||||
|
||||
return deferred.promise;
|
||||
// TODO: |getNetId| will be implemented as a sync call in nsINetworkManager
|
||||
// once Bug 1141903 is landed.
|
||||
return gNetworkService.getNetId(network.name)
|
||||
.then(aNetId => hostResolveWrapper(aNetId));
|
||||
},
|
||||
|
||||
convertConnectionType: function(network) {
|
||||
|
@ -774,15 +781,13 @@ NetworkManager.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
_setDefaultRouteAndDNS: function(network, oldInterface) {
|
||||
_setDefaultRouteAndProxy: function(network, oldInterface) {
|
||||
gNetworkService.setDefaultRoute(network, oldInterface, function(success) {
|
||||
if (!success) {
|
||||
gNetworkService.destroyNetwork(network, function() {});
|
||||
return;
|
||||
}
|
||||
gNetworkService.setDNS(network, function(result) {
|
||||
gNetworkService.setNetworkProxy(network);
|
||||
});
|
||||
gNetworkService.setNetworkProxy(network);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
|
@ -391,7 +391,8 @@ NetworkService.prototype = {
|
|||
cmd: "setDNS",
|
||||
ifname: networkInterface.name,
|
||||
domain: "mozilla." + networkInterface.name + ".doman",
|
||||
dnses: dnses
|
||||
dnses: dnses,
|
||||
gateways: networkInterface.getGateways()
|
||||
};
|
||||
this.controlMessage(options, function(result) {
|
||||
callback.setDnsResult(result.success ? null : result.reason);
|
||||
|
@ -762,6 +763,23 @@ NetworkService.prototype = {
|
|||
callback.nativeCommandResult(!result.error);
|
||||
});
|
||||
},
|
||||
|
||||
getNetId: function(interfaceName) {
|
||||
let params = {
|
||||
cmd: "getNetId",
|
||||
ifname: interfaceName
|
||||
};
|
||||
|
||||
return new Promise((aResolve, aReject) => {
|
||||
this.controlMessage(params, result => {
|
||||
if (result.error) {
|
||||
aReject(result.reason);
|
||||
return;
|
||||
}
|
||||
aResolve(result.netId);
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkService]);
|
||||
|
|
|
@ -440,7 +440,6 @@ CommandResult::CommandResult(int32_t aResultCode)
|
|||
strerror_r(abs(aResultCode), strerrorBuf, STRERROR_R_BUF_SIZE);
|
||||
mResult.mReason = NS_ConvertUTF8toUTF16(strerrorBuf);
|
||||
}
|
||||
mResult.mRet = true;
|
||||
}
|
||||
|
||||
CommandResult::CommandResult(const mozilla::dom::NetworkResultOptions& aResult)
|
||||
|
@ -1535,6 +1534,7 @@ void NetworkUtils::ExecuteCommand(NetworkParams aOptions)
|
|||
BUILD_ENTRY(resetConnections),
|
||||
BUILD_ENTRY(createNetwork),
|
||||
BUILD_ENTRY(destroyNetwork),
|
||||
BUILD_ENTRY(getNetId),
|
||||
|
||||
#undef BUILD_ENTRY
|
||||
};
|
||||
|
@ -1704,6 +1704,7 @@ CommandResult NetworkUtils::setDNS(NetworkParams& aOptions)
|
|||
// Lollipop.
|
||||
static CommandFunc COMMAND_CHAIN[] = {
|
||||
setInterfaceDns,
|
||||
addDefaultRouteToNetwork,
|
||||
defaultAsyncSuccessHandler
|
||||
};
|
||||
NetIdManager::NetIdInfo netIdInfo;
|
||||
|
@ -1717,7 +1718,12 @@ CommandResult NetworkUtils::setDNS(NetworkParams& aOptions)
|
|||
if (SDK_VERSION >= 18) {
|
||||
// JB, KK.
|
||||
static CommandFunc COMMAND_CHAIN[] = {
|
||||
#if ANDROID_VERSION == 18
|
||||
// Since we don't use per-interface DNS lookup feature on JB,
|
||||
// we need to set the default DNS interface whenever setting the
|
||||
// DNS name server.
|
||||
setDefaultInterface,
|
||||
#endif
|
||||
setInterfaceDns,
|
||||
defaultAsyncSuccessHandler
|
||||
};
|
||||
|
@ -1898,6 +1904,17 @@ CommandResult NetworkUtils::setDefaultRouteLegacy(NetworkParams& aOptions)
|
|||
}
|
||||
}
|
||||
|
||||
// Set the default DNS interface.
|
||||
if (SDK_VERSION >= 18) {
|
||||
// For JB, KK only.
|
||||
static CommandFunc COMMAND_CHAIN[] = {
|
||||
setDefaultInterface,
|
||||
defaultAsyncSuccessHandler
|
||||
};
|
||||
runChain(aOptions, COMMAND_CHAIN, setDnsFail);
|
||||
return CommandResult::Pending();
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2516,6 +2533,27 @@ CommandResult NetworkUtils::destroyNetwork(NetworkParams& aOptions)
|
|||
return CommandResult::Pending();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the netId associated with the given network interface name.
|
||||
*/
|
||||
CommandResult NetworkUtils::getNetId(NetworkParams& aOptions)
|
||||
{
|
||||
NetworkResultOptions result;
|
||||
|
||||
if (SDK_VERSION < 20) {
|
||||
// For pre-Lollipop, use the interface name as the fallback.
|
||||
result.mNetId = GET_FIELD(mIfname);
|
||||
return result;
|
||||
}
|
||||
|
||||
NetIdManager::NetIdInfo netIdInfo;
|
||||
if (-1 == mNetIdManager.lookup(GET_FIELD(mIfname), &netIdInfo)) {
|
||||
return ESRCH;
|
||||
}
|
||||
result.mNetId.AppendInt(netIdInfo.mNetId, 10);
|
||||
return result;
|
||||
}
|
||||
|
||||
void NetworkUtils::sendBroadcastMessage(uint32_t code, char* reason)
|
||||
{
|
||||
NetworkResultOptions result;
|
||||
|
|
|
@ -309,6 +309,7 @@ private:
|
|||
CommandResult updateUpStream(NetworkParams& aOptions);
|
||||
CommandResult createNetwork(NetworkParams& aOptions);
|
||||
CommandResult destroyNetwork(NetworkParams& aOptions);
|
||||
CommandResult getNetId(NetworkParams& aOptions);
|
||||
|
||||
CommandResult addHostRouteLegacy(NetworkParams& aOptions);
|
||||
CommandResult removeHostRouteLegacy(NetworkParams& aOptions);
|
||||
|
|
|
@ -159,7 +159,7 @@ interface nsIDhcpRequestCallback : nsISupports
|
|||
/**
|
||||
* Provide network services.
|
||||
*/
|
||||
[scriptable, uuid(e40dd966-cb04-4dc7-ac4b-6382769c00b9)]
|
||||
[scriptable, uuid(a0f29630-c25c-11e4-8830-0800200c9a66)]
|
||||
interface nsINetworkService : nsISupports
|
||||
{
|
||||
const long MODIFY_ROUTE_ADD = 0;
|
||||
|
@ -486,4 +486,17 @@ interface nsINetworkService : nsISupports
|
|||
*/
|
||||
void destroyNetwork(in DOMString interfaceName,
|
||||
in nsINativeCommandCallback callback);
|
||||
|
||||
/**
|
||||
* Query the netId associated with given network interface name.
|
||||
*
|
||||
* @param interfaceName
|
||||
* The network interface name which we want to query.
|
||||
*
|
||||
* @return A deferred promise that resolves with a string to indicate.
|
||||
* the queried netId on success and rejects if the interface name
|
||||
* is invalid.
|
||||
*
|
||||
*/
|
||||
jsval getNetId(in DOMString interfaceName);
|
||||
};
|
||||
|
|
|
@ -96,4 +96,6 @@ dictionary NetworkResultOptions
|
|||
long dns1 = 0;
|
||||
long dns2 = 0;
|
||||
long server = 0;
|
||||
|
||||
DOMString netId = ""; // for "getNetId".
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче