diff --git a/bower.json b/bower.json
index 36ff7e909c..8d9d66245d 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "uProxy",
- "version": "0.8.13",
+ "version": "0.8.14",
"dependencies": {
"polymer": "^0.5.6",
"paper-elements": "Polymer/paper-elements#^0.5.6",
diff --git a/package.json b/package.json
index 7039d527b3..a7c79edaba 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "uProxy",
"description": "Share your pathway to the Internet",
- "version": "0.8.13",
+ "version": "0.8.14",
"repository": {
"type": "git",
"url": "https://github.com/uproxy/uproxy"
@@ -47,7 +47,7 @@
"lodash": "^3.7.0",
"regex2dfa": "^0.1.6",
"tsd": "^0.5.7",
- "uproxy-lib": "^27.2.5",
+ "uproxy-lib": "^28.0.0",
"utransformers": "^0.2.1",
"xregexp": "^2.0.0"
},
diff --git a/src/chrome/app/manifest.json b/src/chrome/app/manifest.json
index 8dae33101f..a240694985 100644
--- a/src/chrome/app/manifest.json
+++ b/src/chrome/app/manifest.json
@@ -3,7 +3,7 @@
"name": "__MSG_appName__",
"description": "__MSG_appDescription__",
"minimum_chrome_version": "41.0.2272.63",
- "version": "0.8.13",
+ "version": "0.8.14",
"default_locale": "en",
"icons": {
"128": "icons/128_online.png"
diff --git a/src/chrome/extension/manifest.json b/src/chrome/extension/manifest.json
index ca774d206d..297dddfaf7 100644
--- a/src/chrome/extension/manifest.json
+++ b/src/chrome/extension/manifest.json
@@ -1,6 +1,6 @@
{
"name": "__MSG_extName__",
- "version": "0.8.13",
+ "version": "0.8.14",
"manifest_version": 2,
"description": "__MSG_extDescription__",
"minimum_chrome_version": "41.0.2272.63",
diff --git a/src/chrome/extension/scripts/background.ts b/src/chrome/extension/scripts/background.ts
index af7d49a5f8..40a82980e8 100644
--- a/src/chrome/extension/scripts/background.ts
+++ b/src/chrome/extension/scripts/background.ts
@@ -15,12 +15,11 @@ import UiApi = require('../../../interfaces/ui');
import user_interface = require('../../../generic_ui/scripts/ui');
import CoreConnector = require('../../../generic_ui/scripts/core_connector');
import uproxy_core_api = require('../../../interfaces/uproxy_core_api');
+import Constants = require('../../../generic_ui/scripts/constants');
///
///
-export import model = user_interface.model;
-
// --------------------- Communicating with the App ----------------------------
export var browserConnector :ChromeCoreConnector; // way for ui to speak to a uProxy.CoreApi
export var core :CoreConnector; // way for ui to speak to a uProxy.CoreApi
@@ -63,6 +62,10 @@ chrome.runtime.onMessageExternal.addListener((request :any, sender :chrome.runti
* updates from the Chrome App side propogate to the UI.
*/
browserApi = new ChromeBrowserApi();
+browserConnector = new ChromeCoreConnector({ name: 'uproxy-extension-to-app-port' });
+browserConnector.onUpdate(uproxy_core_api.Update.LAUNCH_UPROXY,
+ browserApi.bringUproxyToFront);
+
// TODO (lucyhe): Make sure that the "install" event isn't missed if we
// are adding the listener after the event is fired.
chrome.runtime.onInstalled.addListener((details :chrome.runtime.InstalledDetails) => {
@@ -70,6 +73,14 @@ chrome.runtime.onInstalled.addListener((details :chrome.runtime.InstalledDetails
// we only want to launch the window on the first install
return;
}
+ browserConnector.onceConnected.then(() => {
+ chrome.browserAction.setIcon({
+ path: {
+ "19" : "icons/19_" + Constants.DEFAULT_ICON,
+ "38" : "icons/38_" + Constants.DEFAULT_ICON,
+ }
+ });
+ });
chrome.tabs.query({currentWindow: true, active: true}, function(tabs){
// Do not open the extension when it's installed if the user is
@@ -85,10 +96,6 @@ chrome.browserAction.onClicked.addListener((tab) => {
browserApi.bringUproxyToFront();
});
-browserConnector = new ChromeCoreConnector({ name: 'uproxy-extension-to-app-port' });
-browserConnector.onUpdate(uproxy_core_api.Update.LAUNCH_UPROXY,
- browserApi.bringUproxyToFront);
-
core = new CoreConnector(browserConnector);
var oAuth = new ChromeTabAuth();
browserConnector.onUpdate(uproxy_core_api.Update.GET_CREDENTIALS,
diff --git a/src/chrome/extension/scripts/chrome_browser_api.ts b/src/chrome/extension/scripts/chrome_browser_api.ts
index 00e3c9ffcf..df8c1e12a0 100644
--- a/src/chrome/extension/scripts/chrome_browser_api.ts
+++ b/src/chrome/extension/scripts/chrome_browser_api.ts
@@ -57,7 +57,7 @@ class ChromeBrowserApi implements BrowserAPI {
private popupState_ = PopupState.NOT_LAUNCHED;
- public fulfillLaunched : () => void;
+ public handlePopupLaunch :() => void;
private onceLaunched_ :Promise;
constructor() {
@@ -169,7 +169,7 @@ class ChromeBrowserApi implements BrowserAPI {
// after webstore installation), then allow the popup to open at a default
// location.
this.onceLaunched_ = new Promise((F, R) => {
- this.fulfillLaunched = F;
+ this.handlePopupLaunch = F;
});
chrome.windows.create({url: this.POPUP_URL,
type: "popup",
diff --git a/src/chrome/extension/scripts/chrome_core_connector.spec.ts b/src/chrome/extension/scripts/chrome_core_connector.spec.ts
index 9a61b6abef..b0f1984dbd 100644
--- a/src/chrome/extension/scripts/chrome_core_connector.spec.ts
+++ b/src/chrome/extension/scripts/chrome_core_connector.spec.ts
@@ -39,7 +39,8 @@ describe('core-connector', () => {
chromeBrowserApi = jasmine.createSpyObj('ChromeBrowserApi',
['bringUproxyToFront',
'showNotification',
- 'on']);
+ 'on',
+ 'handlePopupLaunch']);
diff --git a/src/chrome/extension/scripts/chrome_tab_auth.ts b/src/chrome/extension/scripts/chrome_tab_auth.ts
index 2aa63f791f..af49bb72c4 100644
--- a/src/chrome/extension/scripts/chrome_tab_auth.ts
+++ b/src/chrome/extension/scripts/chrome_tab_auth.ts
@@ -34,7 +34,7 @@ class ChromeTabAuth {
}
};
- var isActive = !user_interface.model.reconnecting;
+ var isActive = true; //TODO use actual value
chrome.tabs.create({url: url, active: isActive},
function(tab: chrome.tabs.Tab) {
if (isActive) {
diff --git a/src/chrome/extension/scripts/context.ts b/src/chrome/extension/scripts/context.ts
index 020261e3b5..bbe1ffdba6 100644
--- a/src/chrome/extension/scripts/context.ts
+++ b/src/chrome/extension/scripts/context.ts
@@ -13,7 +13,7 @@ export var browserConnector :browser_connector.CoreBrowserConnector = ui_context
export var ui :user_interface.UserInterface = new user_interface.UserInterface(core, ui_context.browserApi);
-export var model :user_interface.Model = user_interface.model;
+export var model :user_interface.Model = ui.model;
ui.browser = 'chrome';
console.log('Loaded dependencies for Chrome Extension.');
diff --git a/src/firefox/data/scripts/background.ts b/src/firefox/data/scripts/background.ts
index 0c2ebd18ab..75ef962dd7 100644
--- a/src/firefox/data/scripts/background.ts
+++ b/src/firefox/data/scripts/background.ts
@@ -3,10 +3,10 @@ import CoreConnector = require('../../../generic_ui/scripts/core_connector');
import FirefoxCoreConnector = require('./firefox_connector');
import FirefoxBrowserApi = require('./firefox_browser_api');
-export import model = user_interface.model;
export var ui :user_interface.UserInterface;
export var core :CoreConnector;
export var browserConnector: FirefoxCoreConnector;
+export var model :user_interface.Model;
function initUI() {
browserConnector = new FirefoxCoreConnector();
core = new CoreConnector(browserConnector);
@@ -17,6 +17,7 @@ function initUI() {
if (undefined === ui) {
ui = initUI();
+ model = ui.model;
}
ui.browser = 'firefox';
diff --git a/src/firefox/data/scripts/firefox_browser_api.ts b/src/firefox/data/scripts/firefox_browser_api.ts
index b4463d58be..97124a35e1 100644
--- a/src/firefox/data/scripts/firefox_browser_api.ts
+++ b/src/firefox/data/scripts/firefox_browser_api.ts
@@ -33,9 +33,8 @@ class FirefoxBrowserApi implements BrowserAPI {
port.on('emitRejected', this.handleEmitRejected_);
}
- // Firefox doesn't ever need to wait for popup to open,
- // We don't have onceLaunched promise, so fulfillLaunched is empty.
- public fulfillLaunched = () => {
+ // Firefox has no work to do on initial launch
+ public handlePopupLaunch = () => {
}
public setIcon = (iconFile :string) : void => {
diff --git a/src/firefox/package.json b/src/firefox/package.json
index 83c3bf04b4..81065d9ad1 100644
--- a/src/firefox/package.json
+++ b/src/firefox/package.json
@@ -5,7 +5,7 @@
"description": "This is the alpha version of uProxy.",
"author": "uProxy Team ",
"license": "Apache 2.0",
- "version": "0.8.13",
+ "version": "0.8.14",
"permissions": {
"private-browsing": true
}
diff --git a/src/generic_core/diagnose-nat.ts b/src/generic_core/diagnose-nat.ts
index abc91abc68..7c1b49af8d 100644
--- a/src/generic_core/diagnose-nat.ts
+++ b/src/generic_core/diagnose-nat.ts
@@ -613,13 +613,6 @@ export function doUdpTest() {
}
socket.bind('0.0.0.0', 0)
- .then((result :number) => {
- if (result != 0) {
- return Promise.reject(new Error('listen failed to bind :5758' +
- ' with result code ' + result));
- }
- return Promise.resolve(result);
- })
.then(socket.getInfo)
.then((socketInfo: freedom_UdpSocket.SocketInfo) => {
log.debug('listening on %1:%2',
@@ -694,13 +687,7 @@ function pingStunServer(serverAddr: string) {
var bytes = Turn.formatStunMessage(bindRequest);
socket.bind('0.0.0.0', 0)
- .then((result: number) => {
- if (result != 0) {
- return Promise.reject(new Error('listen failed to bind :5758' +
- ' with result code ' + result));
- }
- return Promise.resolve(result);
- }).then(() => {
+ .then(() => {
return socket.sendTo(bytes.buffer, parts[1], parseInt(parts[2]));
}).then((written: number) => {
log.debug('%1 bytes sent correctly', [written]);
@@ -769,12 +756,6 @@ export function doNatProvoking() :Promise {
socket.on('onData', onUdpData);
socket.bind('0.0.0.0', 0)
- .then((result: number) => {
- if (result != 0) {
- return Promise.reject(new Error('failed to bind to a port: err=' + result));
- }
- return Promise.resolve(result);
- })
.then(socket.getInfo)
.then((socketInfo: freedom_UdpSocket.SocketInfo) => {
log.debug('listening on %1:%2',
@@ -879,28 +860,24 @@ export function probePmpSupport(routerIp:string, privateIp:string) :Promise {
- if (result != 0) {
- R(new Error('Failed to bind to a port: Err= ' + result));
- }
-
- // Construct the NAT-PMP map request as an ArrayBuffer
- // Map internal port 55555 to external port 55555 w/ 120 sec lifetime
- var pmpBuffer = new ArrayBuffer(12);
- var pmpView = new DataView(pmpBuffer);
- // Version and OP fields (1 byte each)
- pmpView.setInt8(0, 0);
- pmpView.setInt8(1, 1);
- // Reserved, internal port, external port fields (2 bytes each)
- pmpView.setInt16(2, 0, false);
- pmpView.setInt16(4, 55555, false);
- pmpView.setInt16(6, 55555, false);
- // Mapping lifetime field (4 bytes)
- pmpView.setInt32(8, 120, false);
-
- socket.sendTo(pmpBuffer, routerIp, 5351);
- });
+ socket.bind('0.0.0.0', 0).
+ then(() => {
+ // Construct the NAT-PMP map request as an ArrayBuffer
+ // Map internal port 55555 to external port 55555 w/ 120 sec lifetime
+ var pmpBuffer = new ArrayBuffer(12);
+ var pmpView = new DataView(pmpBuffer);
+ // Version and OP fields (1 byte each)
+ pmpView.setInt8(0, 0);
+ pmpView.setInt8(1, 1);
+ // Reserved, internal port, external port fields (2 bytes each)
+ pmpView.setInt16(2, 0, false);
+ pmpView.setInt16(4, 55555, false);
+ pmpView.setInt16(6, 55555, false);
+ // Mapping lifetime field (4 bytes)
+ pmpView.setInt32(8, 120, false);
+
+ socket.sendTo(pmpBuffer, routerIp, 5351);
+ }).catch(R);
});
// Give _probePmpSupport 2 seconds before timing out
@@ -923,55 +900,51 @@ export function probePcpSupport(routerIp:string, privateIp:string) :Promise {
- if (result != 0) {
- R(new Error('Failed to bind to a port: Err= ' + result));
- }
-
- // Create the PCP MAP request as an ArrayBuffer
- // Map internal port 55556 to external port 55556 w/ 120 sec lifetime
- var pcpBuffer = new ArrayBuffer(60);
- var pcpView = new DataView(pcpBuffer);
- // Version field (1 byte)
- pcpView.setInt8(0, 0b00000010);
- // R and Opcode fields (1 bit + 7 bits)
- pcpView.setInt8(1, 0b00000001);
- // Reserved field (2 bytes)
- pcpView.setInt16(2, 0, false);
- // Requested lifetime (4 bytes)
- pcpView.setInt32(4, 120, false);
- // Client IP address (128 bytes; we use the IPv4 -> IPv6 mapping)
- pcpView.setInt32(8, 0, false);
- pcpView.setInt32(12, 0, false);
- pcpView.setInt16(16, 0, false);
- pcpView.setInt16(18, 0xffff, false);
- // Start of IPv4 octets of the client's private IP
- var ipOctets = ipaddr.IPv4.parse(privateIp).octets;
- pcpView.setInt8(20, ipOctets[0]);
- pcpView.setInt8(21, ipOctets[1]);
- pcpView.setInt8(22, ipOctets[2]);
- pcpView.setInt8(23, ipOctets[3]);
- // Mapping Nonce (12 bytes)
- pcpView.setInt32(24, randInt(0, 0xffffffff), false);
- pcpView.setInt32(28, randInt(0, 0xffffffff), false);
- pcpView.setInt32(32, randInt(0, 0xffffffff), false);
- // Protocol (1 byte)
- pcpView.setInt8(36, 17);
- // Reserved (3 bytes)
- pcpView.setInt16(37, 0, false);
- pcpView.setInt8(39, 0);
- // Internal and external ports
- pcpView.setInt16(40, 55556, false);
- pcpView.setInt16(42, 55556, false);
- // External IP address (128 bytes; we use the all-zero IPv4 -> IPv6 mapping)
- pcpView.setFloat64(44, 0, false);
- pcpView.setInt16(52, 0, false);
- pcpView.setInt16(54, 0xffff, false);
- pcpView.setInt32(56, 0, false);
-
- socket.sendTo(pcpBuffer, routerIp, 5351);
- });
+ socket.bind('0.0.0.0', 0).
+ then(() => {
+ // Create the PCP MAP request as an ArrayBuffer
+ // Map internal port 55556 to external port 55556 w/ 120 sec lifetime
+ var pcpBuffer = new ArrayBuffer(60);
+ var pcpView = new DataView(pcpBuffer);
+ // Version field (1 byte)
+ pcpView.setInt8(0, 0b00000010);
+ // R and Opcode fields (1 bit + 7 bits)
+ pcpView.setInt8(1, 0b00000001);
+ // Reserved field (2 bytes)
+ pcpView.setInt16(2, 0, false);
+ // Requested lifetime (4 bytes)
+ pcpView.setInt32(4, 120, false);
+ // Client IP address (128 bytes; we use the IPv4 -> IPv6 mapping)
+ pcpView.setInt32(8, 0, false);
+ pcpView.setInt32(12, 0, false);
+ pcpView.setInt16(16, 0, false);
+ pcpView.setInt16(18, 0xffff, false);
+ // Start of IPv4 octets of the client's private IP
+ var ipOctets = ipaddr.IPv4.parse(privateIp).octets;
+ pcpView.setInt8(20, ipOctets[0]);
+ pcpView.setInt8(21, ipOctets[1]);
+ pcpView.setInt8(22, ipOctets[2]);
+ pcpView.setInt8(23, ipOctets[3]);
+ // Mapping Nonce (12 bytes)
+ pcpView.setInt32(24, randInt(0, 0xffffffff), false);
+ pcpView.setInt32(28, randInt(0, 0xffffffff), false);
+ pcpView.setInt32(32, randInt(0, 0xffffffff), false);
+ // Protocol (1 byte)
+ pcpView.setInt8(36, 17);
+ // Reserved (3 bytes)
+ pcpView.setInt16(37, 0, false);
+ pcpView.setInt8(39, 0);
+ // Internal and external ports
+ pcpView.setInt16(40, 55556, false);
+ pcpView.setInt16(42, 55556, false);
+ // External IP address (128 bytes; we use the all-zero IPv4 -> IPv6 mapping)
+ pcpView.setFloat64(44, 0, false);
+ pcpView.setInt16(52, 0, false);
+ pcpView.setInt16(54, 0xffff, false);
+ pcpView.setInt32(56, 0, false);
+
+ socket.sendTo(pcpBuffer, routerIp, 5351);
+ }).catch(R);
});
// Give _probePcpSupport 2 seconds before timing out
@@ -1007,12 +980,8 @@ function sendSsdpRequest(privateIp:string) :Promise {
});
// Bind a socket and send the SSDP request
- socket.bind(privateIp, 0).
- then((result:number) => {
- if (result != 0) {
- R(new Error('Failed to bind to a port: Err= ' + result));
- }
-
+ socket.bind('0.0.0.0', 0).
+ then(() => {
// Construct and send a UPnP SSDP message
var ssdpStr = 'M-SEARCH * HTTP/1.1\r\n' +
'HOST: 239.255.255.250:1900\r\n' +
@@ -1021,7 +990,7 @@ function sendSsdpRequest(privateIp:string) :Promise {
'ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1';
var ssdpBuffer = arraybuffers.stringToArrayBuffer(ssdpStr);
socket.sendTo(ssdpBuffer, '239.255.255.250', 1900);
- });
+ }).catch(R);
});
// Give _sendSsdpRequest 1 second before timing out
diff --git a/src/generic_core/globals.ts b/src/generic_core/globals.ts
index 9d097c62e2..8d80abf46f 100644
--- a/src/generic_core/globals.ts
+++ b/src/generic_core/globals.ts
@@ -42,7 +42,8 @@ export var settings :uproxy_core_api.GlobalSettings = {
splashState: 0,
statsReportingEnabled: false,
consoleFilter: loggingTypes.Level.warn,
- language: 'en'
+ language: 'en',
+ force_message_version: 0 // zero means "don't override"
};
export var natType :string = '';
@@ -73,4 +74,10 @@ export var loadSettings :Promise =
log.info('No global settings loaded', e.message);
});
+// Client version to run as, which is globals.MESSAGE_VERSION unless
+// overridden in advanced settings.
+export var effectiveMessageVersion = () : number => {
+ return settings.force_message_version || MESSAGE_VERSION;
+}
+
export var metrics = new metrics_module.Metrics(storage);
diff --git a/src/generic_core/local-instance.ts b/src/generic_core/local-instance.ts
index 0dd1a480b2..9df617f356 100644
--- a/src/generic_core/local-instance.ts
+++ b/src/generic_core/local-instance.ts
@@ -109,7 +109,7 @@ import storage = globals.storage;
}
public saveToStorage = () :Promise => {
- return storage.save(this.getStorePath(), this.currentState())
+ return storage.save(this.getStorePath(), this.currentState())
.catch((e:Error) => {
log.error('Could not save new LocalInstance: ',
this.instanceId, e.toString());
diff --git a/src/generic_core/remote-connection.spec.ts b/src/generic_core/remote-connection.spec.ts
index fb6074243b..d1dfef43cc 100644
--- a/src/generic_core/remote-connection.spec.ts
+++ b/src/generic_core/remote-connection.spec.ts
@@ -51,7 +51,8 @@ describe('remote_connection.RemoteConnection', () => {
spyOn(rtc_to_net, 'RtcToNet').and.returnValue(rtcToNet);
updateSpy = jasmine.createSpy('updateSpy');
- connection = new remote_connection.RemoteConnection(updateSpy);
+ connection = new remote_connection.RemoteConnection(updateSpy,
+ 'the userId');
});
describe('client setup', () => {
diff --git a/src/generic_core/remote-connection.ts b/src/generic_core/remote-connection.ts
index 69f429d0d9..dc9dedf2d2 100644
--- a/src/generic_core/remote-connection.ts
+++ b/src/generic_core/remote-connection.ts
@@ -69,7 +69,8 @@ var generateProxyingSessionId_ = (): string => {
private proxyingId_: string;
constructor(
- sendUpdate :(x :uproxy_core_api.Update, data?:Object) => void
+ sendUpdate :(x :uproxy_core_api.Update, data?:Object) => void,
+ private userId_?:string
) {
this.sendUpdate_ = sendUpdate;
this.resetSharerCreated();
@@ -142,7 +143,7 @@ var generateProxyingSessionId_ = (): string => {
pc = bridge.best('rtctonet', config);
}
- this.rtcToNet_ = new rtc_to_net.RtcToNet();
+ this.rtcToNet_ = new rtc_to_net.RtcToNet(this.userId_);
this.rtcToNet_.start({
allowNonUnicast: globals.settings.allowNonUnicast
}, pc);
@@ -273,21 +274,30 @@ var generateProxyingSessionId_ = (): string => {
};
var pc: peerconnection.PeerConnection