From 1c2e79e90f7bb5ae99950a6c155bfeaeaf1847c0 Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Tue, 23 Jun 2015 13:21:33 -0400 Subject: [PATCH 01/13] stash changes --- src/generic_core/remote-connection.ts | 1 + src/generic_core/remote-instance.ts | 5 ++++- src/generic_core/remote-user.ts | 4 ++++ src/interfaces/uproxy_core_api.ts | 8 +++++++- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/generic_core/remote-connection.ts b/src/generic_core/remote-connection.ts index 76403d0702..685a164dd1 100644 --- a/src/generic_core/remote-connection.ts +++ b/src/generic_core/remote-connection.ts @@ -53,6 +53,7 @@ import tcp = require('../../../third_party/uproxy-lib/net/tcp'); this.resetSharerCreated(); } +// TREV: generate ID on first message. private createSender_ = (type :social.PeerMessageType) => { return (signal :bridge.SignallingMessage) => { this.sendUpdate_(uproxy_core_api.Update.SIGNALLING_MESSAGE, { diff --git a/src/generic_core/remote-instance.ts b/src/generic_core/remote-instance.ts index 228db81917..f76308bb22 100644 --- a/src/generic_core/remote-instance.ts +++ b/src/generic_core/remote-instance.ts @@ -120,9 +120,10 @@ export var remoteProxyInstance :RemoteInstance = null; } private handleConnectionUpdate_ = (update :uproxy_core_api.Update, data?:any) => { - log.debug('connection update: %1', uproxy_core_api.Update[update]); + log.debug('connection update %1: %2', uproxy_core_api.Update[update], data); switch (update) { case uproxy_core_api.Update.SIGNALLING_MESSAGE: + case uproxy_core_api.Update.PROXYING_SESSION_ID: var clientId = this.user.instanceToClient(this.instanceId); if (!clientId) { log.error('Could not find clientId for instance', this); @@ -188,6 +189,8 @@ export var remoteProxyInstance :RemoteInstance = null; return Promise.resolve(); } +// TREV: need to check for session id? + // Create a new RtcToNet instance each time a new round of client peer // messages begins. The type field check is so pre-bridge, // MESSAGE_VERSION = 1, clients can initiate. diff --git a/src/generic_core/remote-user.ts b/src/generic_core/remote-user.ts index 8df4ce4fb9..19a214af51 100644 --- a/src/generic_core/remote-user.ts +++ b/src/generic_core/remote-user.ts @@ -212,6 +212,10 @@ var log :logging.Log = new logging.Log('remote-user'); msg.version); return; + case social.PeerMessageType. + + return; + case social.PeerMessageType.INSTANCE_REQUEST: log.debug('received instance request', clientId); this.sendInstanceHandshake(clientId); diff --git a/src/interfaces/uproxy_core_api.ts b/src/interfaces/uproxy_core_api.ts index d671674b11..b6ee257964 100644 --- a/src/interfaces/uproxy_core_api.ts +++ b/src/interfaces/uproxy_core_api.ts @@ -111,7 +111,13 @@ export enum Update { STATE = 2019, FRIEND_FAILED_TO_GET = 2020, POST_TO_CLOUDFRONT = 2021, - COPYPASTE_MESSAGE = 2022 + COPYPASTE_MESSAGE = 2022, + + // Specfies the unique ID associated with this proxying session. + // The ID is used for feedback purposes. This also signifies a + // new a attempt to proxying or, in other words, delimits proxying + // attempts. + PROXYING_SESSION_ID = 2023 } // Action taken by the user. These values are not on the wire. They are passed From 081a0d9c984aac5163bb7fbab6c06b6f07667717 Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Tue, 23 Jun 2015 18:57:17 -0400 Subject: [PATCH 02/13] less of a mess now --- src/generic_core/remote-connection.ts | 1 - src/generic_core/remote-instance.ts | 64 +++++++++++++++++---------- src/generic_core/remote-user.ts | 7 +-- src/generic_ui/scripts/ui.ts | 9 ++-- src/interfaces/social.ts | 11 +++++ src/interfaces/uproxy_core_api.ts | 14 +++--- 6 files changed, 66 insertions(+), 40 deletions(-) diff --git a/src/generic_core/remote-connection.ts b/src/generic_core/remote-connection.ts index 685a164dd1..76403d0702 100644 --- a/src/generic_core/remote-connection.ts +++ b/src/generic_core/remote-connection.ts @@ -53,7 +53,6 @@ import tcp = require('../../../third_party/uproxy-lib/net/tcp'); this.resetSharerCreated(); } -// TREV: generate ID on first message. private createSender_ = (type :social.PeerMessageType) => { return (signal :bridge.SignallingMessage) => { this.sendUpdate_(uproxy_core_api.Update.SIGNALLING_MESSAGE, { diff --git a/src/generic_core/remote-instance.ts b/src/generic_core/remote-instance.ts index f76308bb22..ad1fa1edb8 100644 --- a/src/generic_core/remote-instance.ts +++ b/src/generic_core/remote-instance.ts @@ -93,6 +93,9 @@ export var remoteProxyInstance :RemoteInstance = null; private connection_ :remote_connection.RemoteConnection = null; + // Unique ID of the most recent proxying attempt with this instance. + private proxyingId_: string; + /** * Construct a Remote Instance as the result of receiving an instance * handshake, or loadig from storage. Typically, instances are initialized @@ -123,7 +126,6 @@ export var remoteProxyInstance :RemoteInstance = null; log.debug('connection update %1: %2', uproxy_core_api.Update[update], data); switch (update) { case uproxy_core_api.Update.SIGNALLING_MESSAGE: - case uproxy_core_api.Update.PROXYING_SESSION_ID: var clientId = this.user.instanceToClient(this.instanceId); if (!clientId) { log.error('Could not find clientId for instance', this); @@ -172,16 +174,39 @@ export var remoteProxyInstance :RemoteInstance = null; return this.localSharingWithRemote === social.SharingState.SHARING_ACCESS; } - /** - * Handle signals sent along the signalling channel from the remote - * instance, and pass it along to the relevant socks-rtc module. - * TODO: spec - * TODO: assuming that signal is valid, should we remove signal? - * TODO: return a boolean on success/failure - */ - public handleSignal = (type:social.PeerMessageType, - signalFromRemote:bridge.SignallingMessage, - messageVersion:number) :Promise => { + public handleSignal = ( + type:social.PeerMessageType, + message:Object, + messageVersion:number) + :Promise => { + // TODO: forward messages from pre-bridge clients + if ((message).signals !== undefined) { + return this.forwardSignal_(type, message, messageVersion); + } else { + return this.handleMetadataSignal_(message); + } + } + + private handleMetadataSignal_ = ( + message:social.SignallingMetadata) : Promise => { + if (message.first) { + log.info('remote side has initiated a new proxying session'); + this.connection_.resetSharerCreated(); + this.startShare_(); + } + if (message.proxyingId) { + log.info('unique ID for proxying session is %1', message.proxyingId); + this.proxyingId_ = message.proxyingId; + } + return Promise.resolve(); + } + + // Forwards a signalling message to the RemoteConnection. + private forwardSignal_ = ( + type:social.PeerMessageType, + signalFromRemote: Object, + messageVersion: number) + :Promise => { if (social.PeerMessageType.SIGNAL_FROM_CLIENT_PEER === type) { // If the remote peer sent signal as the client, we act as server. if (!this.user.consent.localGrantsAccessToRemote) { @@ -189,17 +214,7 @@ export var remoteProxyInstance :RemoteInstance = null; return Promise.resolve(); } -// TREV: need to check for session id? - - // Create a new RtcToNet instance each time a new round of client peer - // messages begins. The type field check is so pre-bridge, - // MESSAGE_VERSION = 1, clients can initiate. - // TODO: remove the OFFER check once ancient clients are deprecated - if (signalFromRemote.first || - ((signalFromRemote).type === signals.Type.OFFER)) { - this.connection_.resetSharerCreated(); - this.startShare_(); - } + // TODO: handle old clients // Wait for the new rtcToNet instance to be created before you handle // additional messages from a client peer. @@ -253,7 +268,10 @@ export var remoteProxyInstance :RemoteInstance = null; // assumption that our peer failed to start getting access. this.startRtcToNetTimeout_ = setTimeout(() => { log.warn('Timing out rtcToNet_ connection'); - ui.update(uproxy_core_api.Update.FRIEND_FAILED_TO_GET, this.user.name); + ui.update(uproxy_core_api.Update.FRIEND_FAILED_TO_GET, { + name: this.user.name, + proxyingId: this.proxyingId_ + }); this.stopShare(); }, this.RTC_TO_NET_TIMEOUT); diff --git a/src/generic_core/remote-user.ts b/src/generic_core/remote-user.ts index 19a214af51..915f69c0b4 100644 --- a/src/generic_core/remote-user.ts +++ b/src/generic_core/remote-user.ts @@ -208,12 +208,7 @@ var log :logging.Log = new logging.Log('remote-user'); log.error('failed to get instance', clientId); return; } - instance.handleSignal(msg.type, msg.data, - msg.version); - return; - - case social.PeerMessageType. - + instance.handleSignal(msg.type, msg.data, msg.version); return; case social.PeerMessageType.INSTANCE_REQUEST: diff --git a/src/generic_ui/scripts/ui.ts b/src/generic_ui/scripts/ui.ts index 5f7222f644..f6ad3ff5c0 100644 --- a/src/generic_ui/scripts/ui.ts +++ b/src/generic_ui/scripts/ui.ts @@ -341,11 +341,14 @@ export class UserInterface implements ui_constants.UiApi { this.updateSharingStatusBar_(); }); - core.onUpdate(uproxy_core_api.Update.FRIEND_FAILED_TO_GET, (nameOfFriend :string) => { + // TODO: grab logs now, lest they be lost in time...like tears in rain + core.onUpdate(uproxy_core_api.Update.FRIEND_FAILED_TO_GET, (info:uproxy_core_api.FriendFailedToGet) => { + console.log('proxying attempt ' + info.proxyingId + ' failed!!!'); // Setting this variable will toggle a paper-toast (in root.html) // to open. - this.toastMessage = - this.i18n_t('unableToShareWith', { name: nameOfFriend }); + this.toastMessage = this.i18n_t('unableToShareWith', { + name: info.name + }); this.unableToShare = true; }); diff --git a/src/interfaces/social.ts b/src/interfaces/social.ts index 166c7e6c93..656fa83794 100644 --- a/src/interfaces/social.ts +++ b/src/interfaces/social.ts @@ -199,6 +199,17 @@ export interface UserState { consent :ConsentState; } +// One possible payload of SIGNAL_FROM_CLIENT_PEER and SIGNAL_FROM_SERVER_PEER +// messages. Multiple fields may be present. +export interface SignallingMetadata { + // If present, indicates a new batch of signalling messages. + first ?:boolean; + + // Random ID associated with this proxying attempt. + // USed for logging purposes. + proxyingId ?:string; +} + /** * */ diff --git a/src/interfaces/uproxy_core_api.ts b/src/interfaces/uproxy_core_api.ts index b6ee257964..70dff414ff 100644 --- a/src/interfaces/uproxy_core_api.ts +++ b/src/interfaces/uproxy_core_api.ts @@ -111,13 +111,7 @@ export enum Update { STATE = 2019, FRIEND_FAILED_TO_GET = 2020, POST_TO_CLOUDFRONT = 2021, - COPYPASTE_MESSAGE = 2022, - - // Specfies the unique ID associated with this proxying session. - // The ID is used for feedback purposes. This also signifies a - // new a attempt to proxying or, in other words, delimits proxying - // attempts. - PROXYING_SESSION_ID = 2023 + COPYPASTE_MESSAGE = 2022 } // Action taken by the user. These values are not on the wire. They are passed @@ -130,6 +124,12 @@ export enum ConsentUserAction { OFFER = 5100, CANCEL_OFFER, IGNORE_REQUEST, UNIGNORE_REQUEST, } +// Payload of FRIEND_FAILED_TO_GET messages. +export interface FriendFailedToGet { + name: string; + proxyingId: string; +} + /** * ConsentCommands are sent from the UI to the Core, to modify the consent of * a :RemoteInstance in the local client. (This is not sent on the wire to From ef9d12e974e136f75b39be55685eb0d75b19620a Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Wed, 24 Jun 2015 11:58:50 -0400 Subject: [PATCH 03/13] this is roughly it --- src/generic_core/remote-instance.ts | 21 ++++++++++++++++++--- src/generic_core/uproxy_core.ts | 11 ++++++----- src/generic_ui/polymer/instance.ts | 4 +++- src/generic_ui/scripts/core_connector.ts | 7 ++++--- src/generic_ui/scripts/ui.ts | 14 +++++++++++--- src/interfaces/social.ts | 2 +- src/interfaces/uproxy_core_api.ts | 9 ++++++++- 7 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/generic_core/remote-instance.ts b/src/generic_core/remote-instance.ts index ad1fa1edb8..61f7cb6381 100644 --- a/src/generic_core/remote-instance.ts +++ b/src/generic_core/remote-instance.ts @@ -81,11 +81,11 @@ export var remoteProxyInstance :RemoteInstance = null; private isUIUpdatePending = false; // Number of milliseconds before timing out socksToRtc_.start - public SOCKS_TO_RTC_TIMEOUT :number = 30000; + public SOCKS_TO_RTC_TIMEOUT :number = 5000; // Ensure RtcToNet is only closed after SocksToRtc times out (i.e. finishes // trying to connect) by timing out rtcToNet_.start 15 seconds later than // socksToRtc_.start - public RTC_TO_NET_TIMEOUT :number = this.SOCKS_TO_RTC_TIMEOUT + 15000; + public RTC_TO_NET_TIMEOUT :number = this.SOCKS_TO_RTC_TIMEOUT + 5000; // Timeouts for when to abort starting up SocksToRtc and RtcToNet. // TODO: why are these not in remote-connection? private startSocksToRtcTimeout_ :number = null; @@ -94,6 +94,8 @@ export var remoteProxyInstance :RemoteInstance = null; private connection_ :remote_connection.RemoteConnection = null; // Unique ID of the most recent proxying attempt with this instance. + // Generated by the UI when getting, comes in on the social network when + // giving. private proxyingId_: string; /** @@ -268,6 +270,7 @@ export var remoteProxyInstance :RemoteInstance = null; // assumption that our peer failed to start getting access. this.startRtcToNetTimeout_ = setTimeout(() => { log.warn('Timing out rtcToNet_ connection'); + // Tell the UI that sharing failed. It will show a toast. ui.update(uproxy_core_api.Update.FRIEND_FAILED_TO_GET, { name: this.user.name, proxyingId: this.proxyingId_ @@ -300,12 +303,24 @@ export var remoteProxyInstance :RemoteInstance = null; * Begin to use this remote instance as a proxy server, if permission is * currently granted. */ - public start = () :Promise => { + public start = (proxyingId:string) :Promise => { if (!this.wireConsentFromRemote.isOffering) { log.warn('Lacking permission to proxy'); return Promise.reject(Error('Lacking permission to proxy')); } + this.proxyingId_ = proxyingId; + + // Tell the remote peer to get ready...we want access. + var signal :social.SignallingMetadata = { + first: true, + proxyingId: proxyingId + } + this.handleConnectionUpdate_(uproxy_core_api.Update.SIGNALLING_MESSAGE, { + type: social.PeerMessageType.SIGNAL_FROM_CLIENT_PEER, + data: signal + }); + // Cancel socksToRtc_ connection if start hasn't completed in 30 seconds. this.startSocksToRtcTimeout_ = setTimeout(() => { log.warn('Timing out socksToRtc_ connection'); diff --git a/src/generic_core/uproxy_core.ts b/src/generic_core/uproxy_core.ts index 03deb6f568..6c651205b9 100644 --- a/src/generic_core/uproxy_core.ts +++ b/src/generic_core/uproxy_core.ts @@ -266,7 +266,7 @@ export class uProxyCore implements uproxy_core_api.CoreApi { * Starts SDP negotiations with a remote peer. Assumes |path| to the * RemoteInstance exists. */ - public start = (path :social.InstancePath) : Promise => { + public start = (command:uproxy_core_api.StartCommand) : Promise => { // Disable any previous proxying session. var stoppedGetting :Promise[] = []; if (remoteProxyInstance) { @@ -286,15 +286,16 @@ export class uProxyCore implements uproxy_core_api.CoreApi { // connect with the new one, do not propogate this error log.error('Could not clean up old connections', e); }).then(() => { - var remote = this.getInstance(path); + var remote = this.getInstance(command.instancePath); if (!remote) { - log.error('Instance does not exist for proxying', path.instanceId); - return Promise.reject(new Error('Instance does not exist for proxying (' + path.instanceId + ')')); + log.error('Instance does not exist for proxying', command.instancePath.instanceId); + return Promise.reject(new Error('Instance does not exist for proxying (' + + command.instancePath.instanceId + ')')); } // Remember this instance as our proxy. Set this before start fulfills // in case the user decides to cancel the proxy before it begins. remoteProxyInstance = remote; - return remote.start(); + return remote.start(command.proxyingId); }).catch((e) => { remoteProxyInstance = null; // make sure to clean up any state log.error('Could not start remote proxying session', e.stack); diff --git a/src/generic_ui/polymer/instance.ts b/src/generic_ui/polymer/instance.ts index 9d215e71cf..aa7394e5cf 100644 --- a/src/generic_ui/polymer/instance.ts +++ b/src/generic_ui/polymer/instance.ts @@ -24,7 +24,9 @@ Polymer({ return; } - ui.startGettingFromInstance(this.instance.instanceId); + ui.startGettingFromInstance(this.instance.instanceId).catch((e: Error) => { + console.error('TREV: could not proxy'); + }); }, stop: function() { ui.stopGettingFromInstance(this.instance.instanceId); diff --git a/src/generic_ui/scripts/core_connector.ts b/src/generic_ui/scripts/core_connector.ts index f241c5f67f..f48657d015 100644 --- a/src/generic_ui/scripts/core_connector.ts +++ b/src/generic_ui/scripts/core_connector.ts @@ -171,9 +171,10 @@ class CoreConnector implements uproxy_core_api.CoreApi { this.sendCommand(uproxy_core_api.Command.COPYPASTE_SIGNALLING_MESSAGE, signal); } - start = (path :social.InstancePath) : Promise => { - console.log('Starting to proxy through ' + path); - return this.promiseCommand(uproxy_core_api.Command.START_PROXYING, path); + start = (command:uproxy_core_api.StartCommand) : Promise => { + console.log('Starting proxying session ' + command.proxyingId + + ' through ' + command.instancePath); + return this.promiseCommand(uproxy_core_api.Command.START_PROXYING, command); } stop = () => { diff --git a/src/generic_ui/scripts/ui.ts b/src/generic_ui/scripts/ui.ts index 2676ccc8a0..e75dc0ef00 100644 --- a/src/generic_ui/scripts/ui.ts +++ b/src/generic_ui/scripts/ui.ts @@ -341,9 +341,8 @@ export class UserInterface implements ui_constants.UiApi { this.updateSharingStatusBar_(); }); - // TODO: grab logs now, lest they be lost in time...like tears in rain core.onUpdate(uproxy_core_api.Update.FRIEND_FAILED_TO_GET, (info:uproxy_core_api.FriendFailedToGet) => { - console.log('proxying attempt ' + info.proxyingId + ' failed!!!'); + // TODO: grab logs now or they may be lost in time...like tears in rain // Setting this variable will toggle a paper-toast (in root.html) // to open. this.toastMessage = this.i18n_t('unableToShareWith', { @@ -569,7 +568,13 @@ export class UserInterface implements ui_constants.UiApi { this.instanceTryingToGetAccessFrom = instanceId; - return this.core.start(path).then((endpoint :net.Endpoint) => { + // TODO: generate a random ID + var proxyingId = 'abc123'; + + return this.core.start({ + instancePath: path, + proxyingId: proxyingId + }).then((endpoint :net.Endpoint) => { this.instanceTryingToGetAccessFrom = null; this.startGettingInUiAndConfig(instanceId, endpoint); @@ -580,6 +585,9 @@ export class UserInterface implements ui_constants.UiApi { return; } + // TODO: fetch logs now + console.log('proxying attempt ' + proxyingId + ' failed (getting)'); + this.toastMessage = this.i18n_t('unableToGetFrom', { name: user.name }); this.instanceTryingToGetAccessFrom = null; this.unableToGet = true; diff --git a/src/interfaces/social.ts b/src/interfaces/social.ts index 656fa83794..f2a1073e85 100644 --- a/src/interfaces/social.ts +++ b/src/interfaces/social.ts @@ -219,7 +219,7 @@ export interface LocalUserInstance extends BaseInstance { } export interface RemoteUserInstance extends BaseInstance { - start() :Promise; + start(proxyingId:string) :Promise; stop() :Promise; } diff --git a/src/interfaces/uproxy_core_api.ts b/src/interfaces/uproxy_core_api.ts index 2464a6b697..d28f0dfdf4 100644 --- a/src/interfaces/uproxy_core_api.ts +++ b/src/interfaces/uproxy_core_api.ts @@ -114,6 +114,7 @@ export enum Update { START_GIVING = 2017, STOP_GIVING = 2018, STATE = 2019, + // TODO: rename to FAILED_TO_SHARE FRIEND_FAILED_TO_GET = 2020, POST_TO_CLOUDFRONT = 2021, COPYPASTE_MESSAGE = 2022 @@ -156,6 +157,12 @@ export interface LoginArgs { reconnect :boolean; } +// Start getting access from a friend. +export interface StartCommand { + instancePath: social.InstancePath; + proxyingId: string; +} + /** * The primary interface to the uProxy Core. * @@ -198,7 +205,7 @@ export interface CoreApi { sendCopyPasteSignal(signal :social.PeerMessage) :void; // Using peer as a proxy. - start(instancePath :social.InstancePath) : Promise; + start(command:StartCommand) : Promise; stop () : void; updateGlobalSettings(newSettings :GlobalSettings) :void; From f04c64c230be480d2c03688dee83cf61226fc16c Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Wed, 24 Jun 2015 12:21:00 -0400 Subject: [PATCH 04/13] tidy up --- src/generic_core/remote-instance.ts | 21 +++++++++------------ src/generic_core/uproxy_core.ts | 3 ++- src/generic_ui/polymer/instance.ts | 2 +- src/generic_ui/scripts/core_connector.ts | 5 +++-- src/generic_ui/scripts/ui.ts | 9 +++++---- src/interfaces/social.ts | 9 +++------ 6 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/generic_core/remote-instance.ts b/src/generic_core/remote-instance.ts index 61f7cb6381..0dff758e3c 100644 --- a/src/generic_core/remote-instance.ts +++ b/src/generic_core/remote-instance.ts @@ -81,11 +81,11 @@ export var remoteProxyInstance :RemoteInstance = null; private isUIUpdatePending = false; // Number of milliseconds before timing out socksToRtc_.start - public SOCKS_TO_RTC_TIMEOUT :number = 5000; + public SOCKS_TO_RTC_TIMEOUT :number = 30000; // Ensure RtcToNet is only closed after SocksToRtc times out (i.e. finishes // trying to connect) by timing out rtcToNet_.start 15 seconds later than // socksToRtc_.start - public RTC_TO_NET_TIMEOUT :number = this.SOCKS_TO_RTC_TIMEOUT + 5000; + public RTC_TO_NET_TIMEOUT :number = this.SOCKS_TO_RTC_TIMEOUT + 15000; // Timeouts for when to abort starting up SocksToRtc and RtcToNet. // TODO: why are these not in remote-connection? private startSocksToRtcTimeout_ :number = null; @@ -125,7 +125,7 @@ export var remoteProxyInstance :RemoteInstance = null; } private handleConnectionUpdate_ = (update :uproxy_core_api.Update, data?:any) => { - log.debug('connection update %1: %2', uproxy_core_api.Update[update], data); + log.debug('connection update: %1', uproxy_core_api.Update[update]); switch (update) { case uproxy_core_api.Update.SIGNALLING_MESSAGE: var clientId = this.user.instanceToClient(this.instanceId); @@ -176,6 +176,7 @@ export var remoteProxyInstance :RemoteInstance = null; return this.localSharingWithRemote === social.SharingState.SHARING_ACCESS; } + // Handles signals received on the signalling channel from the remote peer. public handleSignal = ( type:social.PeerMessageType, message:Object, @@ -190,14 +191,9 @@ export var remoteProxyInstance :RemoteInstance = null; } private handleMetadataSignal_ = ( - message:social.SignallingMetadata) : Promise => { - if (message.first) { - log.info('remote side has initiated a new proxying session'); - this.connection_.resetSharerCreated(); - this.startShare_(); - } + message:social.SignallingMetadata) :Promise => { if (message.proxyingId) { - log.info('unique ID for proxying session is %1', message.proxyingId); + log.info('proxying session %1 initiated by remote peer', message.proxyingId); this.proxyingId_ = message.proxyingId; } return Promise.resolve(); @@ -206,7 +202,7 @@ export var remoteProxyInstance :RemoteInstance = null; // Forwards a signalling message to the RemoteConnection. private forwardSignal_ = ( type:social.PeerMessageType, - signalFromRemote: Object, + signalFromRemote:Object, messageVersion: number) :Promise => { if (social.PeerMessageType.SIGNAL_FROM_CLIENT_PEER === type) { @@ -216,7 +212,7 @@ export var remoteProxyInstance :RemoteInstance = null; return Promise.resolve(); } - // TODO: handle old clients + // TODO: handle old clients that don't send signalling metadata // Wait for the new rtcToNet instance to be created before you handle // additional messages from a client peer. @@ -304,6 +300,7 @@ export var remoteProxyInstance :RemoteInstance = null; * currently granted. */ public start = (proxyingId:string) :Promise => { + log.info('proxying session %1 initiated by this user', proxyingId); if (!this.wireConsentFromRemote.isOffering) { log.warn('Lacking permission to proxy'); return Promise.reject(Error('Lacking permission to proxy')); diff --git a/src/generic_core/uproxy_core.ts b/src/generic_core/uproxy_core.ts index 6c651205b9..db6b56ddbc 100644 --- a/src/generic_core/uproxy_core.ts +++ b/src/generic_core/uproxy_core.ts @@ -288,7 +288,8 @@ export class uProxyCore implements uproxy_core_api.CoreApi { }).then(() => { var remote = this.getInstance(command.instancePath); if (!remote) { - log.error('Instance does not exist for proxying', command.instancePath.instanceId); + log.error('Instance does not exist for proxying', + command.instancePath.instanceId); return Promise.reject(new Error('Instance does not exist for proxying (' + command.instancePath.instanceId + ')')); } diff --git a/src/generic_ui/polymer/instance.ts b/src/generic_ui/polymer/instance.ts index aa7394e5cf..bc791ad71f 100644 --- a/src/generic_ui/polymer/instance.ts +++ b/src/generic_ui/polymer/instance.ts @@ -25,7 +25,7 @@ Polymer({ } ui.startGettingFromInstance(this.instance.instanceId).catch((e: Error) => { - console.error('TREV: could not proxy'); + console.error('could not get access: ' + e.message); }); }, stop: function() { diff --git a/src/generic_ui/scripts/core_connector.ts b/src/generic_ui/scripts/core_connector.ts index f48657d015..bfd6253fb1 100644 --- a/src/generic_ui/scripts/core_connector.ts +++ b/src/generic_ui/scripts/core_connector.ts @@ -173,8 +173,9 @@ class CoreConnector implements uproxy_core_api.CoreApi { start = (command:uproxy_core_api.StartCommand) : Promise => { console.log('Starting proxying session ' + command.proxyingId + - ' through ' + command.instancePath); - return this.promiseCommand(uproxy_core_api.Command.START_PROXYING, command); + ', getting access from ' + command.instancePath.instanceId); + return this.promiseCommand(uproxy_core_api.Command.START_PROXYING, + command); } stop = () => { diff --git a/src/generic_ui/scripts/ui.ts b/src/generic_ui/scripts/ui.ts index e75dc0ef00..edb150318d 100644 --- a/src/generic_ui/scripts/ui.ts +++ b/src/generic_ui/scripts/ui.ts @@ -341,10 +341,11 @@ export class UserInterface implements ui_constants.UiApi { this.updateSharingStatusBar_(); }); - core.onUpdate(uproxy_core_api.Update.FRIEND_FAILED_TO_GET, (info:uproxy_core_api.FriendFailedToGet) => { + core.onUpdate(uproxy_core_api.Update.FRIEND_FAILED_TO_GET, + (info:uproxy_core_api.FriendFailedToGet) => { // TODO: grab logs now or they may be lost in time...like tears in rain - // Setting this variable will toggle a paper-toast (in root.html) - // to open. + console.error('proxying attempt ' + info.proxyingId + ' failed (giving)'); + this.toastMessage = this.i18n_t('unableToShareWith', { name: info.name }); @@ -586,7 +587,7 @@ export class UserInterface implements ui_constants.UiApi { } // TODO: fetch logs now - console.log('proxying attempt ' + proxyingId + ' failed (getting)'); + console.error('proxying attempt ' + proxyingId + ' failed (getting)'); this.toastMessage = this.i18n_t('unableToGetFrom', { name: user.name }); this.instanceTryingToGetAccessFrom = null; diff --git a/src/interfaces/social.ts b/src/interfaces/social.ts index f2a1073e85..e86d2d4d62 100644 --- a/src/interfaces/social.ts +++ b/src/interfaces/social.ts @@ -199,14 +199,11 @@ export interface UserState { consent :ConsentState; } -// One possible payload of SIGNAL_FROM_CLIENT_PEER and SIGNAL_FROM_SERVER_PEER -// messages. Multiple fields may be present. +// Payload for SIGNAL_FROM_CLIENT_PEER and SIGNAL_FROM_SERVER_PEER messages. +// Other payload types exist, e.g. bridging peerconnection signals. export interface SignallingMetadata { - // If present, indicates a new batch of signalling messages. - first ?:boolean; - // Random ID associated with this proxying attempt. - // USed for logging purposes. + // Used for logging purposes and implicitly delimits proxying attempts. proxyingId ?:string; } From 13d2af6d719025c7b02e0fa6a7d26957b0aa194e Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Wed, 24 Jun 2015 12:30:52 -0400 Subject: [PATCH 05/13] handle older clients --- src/generic_core/globals.ts | 3 ++- src/generic_core/remote-instance.ts | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/generic_core/globals.ts b/src/generic_core/globals.ts index dc94d18fca..7b950f0c08 100644 --- a/src/generic_core/globals.ts +++ b/src/generic_core/globals.ts @@ -15,7 +15,8 @@ export var STORAGE_VERSION = 1; // 1: initial release // 2: uproxy-lib v27, move to bridge but no obfuscation yet // 3: offer basicObfuscation -export var MESSAGE_VERSION = 3; +// 4: introduce proxying session IDs +export var MESSAGE_VERSION = 4; export var DEFAULT_STUN_SERVERS = [ {urls: ['stun:stun.l.google.com:19302']}, diff --git a/src/generic_core/remote-instance.ts b/src/generic_core/remote-instance.ts index 0dff758e3c..19e4ab7f96 100644 --- a/src/generic_core/remote-instance.ts +++ b/src/generic_core/remote-instance.ts @@ -14,7 +14,6 @@ import logging = require('../../../third_party/uproxy-lib/logging/logging'); import net = require('../../../third_party/uproxy-lib/net/net.types'); import remote_connection = require('./remote-connection'); import remote_user = require('./remote-user'); -import bridge = require('../../../third_party/uproxy-lib/bridge/bridge'); import signals = require('../../../third_party/uproxy-lib/webrtc/signals'); import social = require('../interfaces/social'); import ui_connector = require('./ui_connector'); @@ -212,7 +211,17 @@ export var remoteProxyInstance :RemoteInstance = null; return Promise.resolve(); } - // TODO: handle old clients that don't send signalling metadata + // Handle old, pre-signalling metadata clients: + // - the bridge adds a field named "first" (do this for + // MESSAGE_VERSIONs 2 and 3) + // - for ancient clients (MESSAGE_VERSION 1), we need to inspect + // the SDP (!) + if (messageVersion < 4) { + if ((signalFromRemote).first || + ((signalFromRemote).type === signals.Type.OFFER)) { + this.startShare_(); + } + } // Wait for the new rtcToNet instance to be created before you handle // additional messages from a client peer. @@ -248,6 +257,8 @@ export var remoteProxyInstance :RemoteInstance = null; * we should try to start sharing. */ private startShare_ = () : void => { + this.connection_.resetSharerCreated(); + var sharingStopped :Promise; if (this.localSharingWithRemote === social.SharingState.NONE) { // Stop any existing sharing attempts with this instance. From d70f323c42910f881206ce11c12ab74d07086c85 Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Wed, 24 Jun 2015 14:35:17 -0400 Subject: [PATCH 06/13] generate random proxying session IDs --- src/generic_ui/scripts/ui.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/generic_ui/scripts/ui.ts b/src/generic_ui/scripts/ui.ts index edb150318d..db4ef1fdfa 100644 --- a/src/generic_ui/scripts/ui.ts +++ b/src/generic_ui/scripts/ui.ts @@ -134,6 +134,25 @@ export interface NotificationData { unique ?:string; } +var PROXYING_SESSION_ID_LENGTH = 16; + +// Generates a string of random letters suitable for use a proxying session ID. +var generateProxyingSessionId_ = (): string => { + // Generates a random number between 97 and 122 inclusive, corresponding + // to lowercase a and z: + // http://unicode.org/charts/PDF/U0000.pdf + var a = 97, b = 122; + var randomCharCode = (): number => { + // TODO: vulcanize, though that requires crpyto from third_party + return a + (Math.floor(Math.random() * (b - a))); + }; + var letters: string[] = []; + for (var i = 0; i < PROXYING_SESSION_ID_LENGTH; i++) { + letters.push(String.fromCharCode(randomCharCode())); + } + return letters.join(''); +} + /** * The User Interface class. * @@ -570,7 +589,7 @@ export class UserInterface implements ui_constants.UiApi { this.instanceTryingToGetAccessFrom = instanceId; // TODO: generate a random ID - var proxyingId = 'abc123'; + var proxyingId = generateProxyingSessionId_(); return this.core.start({ instancePath: path, From 93caa38fe92c67d43381c6d86e91b7e2d7090888 Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Wed, 24 Jun 2015 14:59:59 -0400 Subject: [PATCH 07/13] fix vulcanize-related comment --- src/generic_ui/scripts/ui.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generic_ui/scripts/ui.ts b/src/generic_ui/scripts/ui.ts index db4ef1fdfa..93d4298749 100644 --- a/src/generic_ui/scripts/ui.ts +++ b/src/generic_ui/scripts/ui.ts @@ -143,7 +143,7 @@ var generateProxyingSessionId_ = (): string => { // http://unicode.org/charts/PDF/U0000.pdf var a = 97, b = 122; var randomCharCode = (): number => { - // TODO: vulcanize, though that requires crpyto from third_party + // TODO: use crypto, but that requires vulcanize to play with third_party return a + (Math.floor(Math.random() * (b - a))); }; var letters: string[] = []; From fc5c11a57d34e0e5b66008e14713ba45ca5ef551 Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Wed, 24 Jun 2015 15:00:06 -0400 Subject: [PATCH 08/13] remove non-existant field --- src/generic_core/remote-instance.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/generic_core/remote-instance.ts b/src/generic_core/remote-instance.ts index 19e4ab7f96..17b0c20195 100644 --- a/src/generic_core/remote-instance.ts +++ b/src/generic_core/remote-instance.ts @@ -321,7 +321,6 @@ export var remoteProxyInstance :RemoteInstance = null; // Tell the remote peer to get ready...we want access. var signal :social.SignallingMetadata = { - first: true, proxyingId: proxyingId } this.handleConnectionUpdate_(uproxy_core_api.Update.SIGNALLING_MESSAGE, { From 2e2084a16e76ae9a769d644c7c6319908f7ddb74 Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Wed, 24 Jun 2015 15:23:10 -0400 Subject: [PATCH 09/13] oops, typo, we need to create rtctonet when we see signalling metadata --- src/generic_core/remote-instance.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/generic_core/remote-instance.ts b/src/generic_core/remote-instance.ts index 17b0c20195..cdbce28eee 100644 --- a/src/generic_core/remote-instance.ts +++ b/src/generic_core/remote-instance.ts @@ -194,6 +194,7 @@ export var remoteProxyInstance :RemoteInstance = null; if (message.proxyingId) { log.info('proxying session %1 initiated by remote peer', message.proxyingId); this.proxyingId_ = message.proxyingId; + this.startShare_(); } return Promise.resolve(); } From 8d513496cf8a43d9fc737f964b091cc296c9eba7 Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Wed, 24 Jun 2015 18:05:18 -0400 Subject: [PATCH 10/13] proxying session IDs should be generated by RemoteConnection --- src/generic_core/globals.ts | 3 +- src/generic_core/remote-connection.ts | 74 +++++++++++++++++++-- src/generic_core/remote-instance.ts | 83 +++++++----------------- src/generic_core/uproxy_core.ts | 12 ++-- src/generic_ui/scripts/core_connector.ts | 8 +-- src/generic_ui/scripts/ui.ts | 30 +-------- src/interfaces/social.ts | 2 +- src/interfaces/uproxy_core_api.ts | 8 +-- 8 files changed, 101 insertions(+), 119 deletions(-) diff --git a/src/generic_core/globals.ts b/src/generic_core/globals.ts index 7b950f0c08..dc94d18fca 100644 --- a/src/generic_core/globals.ts +++ b/src/generic_core/globals.ts @@ -15,8 +15,7 @@ export var STORAGE_VERSION = 1; // 1: initial release // 2: uproxy-lib v27, move to bridge but no obfuscation yet // 3: offer basicObfuscation -// 4: introduce proxying session IDs -export var MESSAGE_VERSION = 4; +export var MESSAGE_VERSION = 3; export var DEFAULT_STUN_SERVERS = [ {urls: ['stun:stun.l.google.com:19302']}, diff --git a/src/generic_core/remote-connection.ts b/src/generic_core/remote-connection.ts index 76403d0702..956154b8a2 100644 --- a/src/generic_core/remote-connection.ts +++ b/src/generic_core/remote-connection.ts @@ -16,6 +16,25 @@ import uproxy_core_api = require('../interfaces/uproxy_core_api'); import peerconnection = require('../../../third_party/uproxy-lib/webrtc/peerconnection'); import tcp = require('../../../third_party/uproxy-lib/net/tcp'); +var PROXYING_SESSION_ID_LENGTH = 16; + +// Generates a string of random letters suitable for use a proxying session ID. +var generateProxyingSessionId_ = (): string => { + // Generates a random number between 97 and 122 inclusive, corresponding + // to lowercase a and z: + // http://unicode.org/charts/PDF/U0000.pdf + var a = 97, b = 122; + var randomCharCode = (): number => { + // TODO: use crypto, but that requires vulcanize to play with third_party + return a + (Math.floor(Math.random() * (b - a))); + }; + var letters: string[] = []; + for (var i = 0; i < PROXYING_SESSION_ID_LENGTH; i++) { + letters.push(String.fromCharCode(randomCharCode())); + } + return letters.join(''); +} + // module Core { var log :logging.Log = new logging.Log('remote-connection'); @@ -46,6 +65,9 @@ import tcp = require('../../../third_party/uproxy-lib/net/tcp'); public activeEndpoint :net.Endpoint = null; + // Unique ID of the most recent proxying attempt. + private proxyingId_: string; + constructor( sendUpdate :(x :uproxy_core_api.Update, data?:Object) => void ) { @@ -62,16 +84,39 @@ import tcp = require('../../../third_party/uproxy-lib/net/tcp'); } } - // TODO: should probably either return something or throw errors - public handleSignal = (message :social.PeerMessage) => { - if (social.PeerMessageType.SIGNAL_FROM_CLIENT_PEER === message.type + // Handles signals received on the signalling channel from the remote peer. + public handleSignal = (message:social.PeerMessage) :Promise => { + // TODO: forward messages from pre-bridge clients + if ((message.data).signals !== undefined) { + return this.forwardSignal_(message.type, message.data); + } else { + return this.handleMetadataSignal_( + message.data); + } + } + + private handleMetadataSignal_ = ( + message:social.SignallingMetadata) :Promise => { + if (message.proxyingId) { + log.info('proxying session %1 initiated by remote peer', message.proxyingId); + this.proxyingId_ = message.proxyingId; + } + return Promise.resolve(); + } + + // Forwards a signalling message to the RemoteConnection. + private forwardSignal_ = ( + type:social.PeerMessageType, + signal:Object) + :Promise => { + if (social.PeerMessageType.SIGNAL_FROM_CLIENT_PEER === type && this.rtcToNet_) { - this.rtcToNet_.handleSignalFromPeer(message.data); - } else if (social.PeerMessageType.SIGNAL_FROM_SERVER_PEER === message.type + this.rtcToNet_.handleSignalFromPeer(signal); + } else if (social.PeerMessageType.SIGNAL_FROM_SERVER_PEER === type && this.socksToRtc_) { - this.socksToRtc_.handleSignalFromPeer(message.data); + this.socksToRtc_.handleSignalFromPeer(signal); } else { - log.warn('Invalid signal: ', social.PeerMessageType[message.type]); + log.warn('Invalid signal: ', social.PeerMessageType[type]); return; } }; @@ -168,6 +213,17 @@ import tcp = require('../../../third_party/uproxy-lib/net/tcp'); throw new Error('socksToRtc_ already exists'); } + this.proxyingId_ = generateProxyingSessionId_(); + + // Send the proxying session ID to the remote peer. + var signal :social.SignallingMetadata = { + proxyingId: this.proxyingId_ + } + this.sendUpdate_(uproxy_core_api.Update.SIGNALLING_MESSAGE, { + type: social.PeerMessageType.SIGNAL_FROM_CLIENT_PEER, + data: signal + }); + this.socksToRtc_ = new socks_to_rtc.SocksToRtc(); // set up basic handlers @@ -294,5 +350,9 @@ import tcp = require('../../../third_party/uproxy-lib/net/tcp'); localSharingWithRemote: this.localSharingWithRemote }; } + + public getProxyingId = () : string => { + return this.proxyingId_; + } } // } diff --git a/src/generic_core/remote-instance.ts b/src/generic_core/remote-instance.ts index cdbce28eee..3815cd9476 100644 --- a/src/generic_core/remote-instance.ts +++ b/src/generic_core/remote-instance.ts @@ -14,6 +14,7 @@ import logging = require('../../../third_party/uproxy-lib/logging/logging'); import net = require('../../../third_party/uproxy-lib/net/net.types'); import remote_connection = require('./remote-connection'); import remote_user = require('./remote-user'); +import bridge = require('../../../third_party/uproxy-lib/bridge/bridge'); import signals = require('../../../third_party/uproxy-lib/webrtc/signals'); import social = require('../interfaces/social'); import ui_connector = require('./ui_connector'); @@ -92,11 +93,6 @@ export var remoteProxyInstance :RemoteInstance = null; private connection_ :remote_connection.RemoteConnection = null; - // Unique ID of the most recent proxying attempt with this instance. - // Generated by the UI when getting, comes in on the social network when - // giving. - private proxyingId_: string; - /** * Construct a Remote Instance as the result of receiving an instance * handshake, or loadig from storage. Typically, instances are initialized @@ -175,36 +171,16 @@ export var remoteProxyInstance :RemoteInstance = null; return this.localSharingWithRemote === social.SharingState.SHARING_ACCESS; } - // Handles signals received on the signalling channel from the remote peer. - public handleSignal = ( - type:social.PeerMessageType, - message:Object, - messageVersion:number) - :Promise => { - // TODO: forward messages from pre-bridge clients - if ((message).signals !== undefined) { - return this.forwardSignal_(type, message, messageVersion); - } else { - return this.handleMetadataSignal_(message); - } - } - - private handleMetadataSignal_ = ( - message:social.SignallingMetadata) :Promise => { - if (message.proxyingId) { - log.info('proxying session %1 initiated by remote peer', message.proxyingId); - this.proxyingId_ = message.proxyingId; - this.startShare_(); - } - return Promise.resolve(); - } - - // Forwards a signalling message to the RemoteConnection. - private forwardSignal_ = ( - type:social.PeerMessageType, - signalFromRemote:Object, - messageVersion: number) - :Promise => { + /** + * Handle signals sent along the signalling channel from the remote + * instance, and pass it along to the relevant socks-rtc module. + * TODO: spec + * TODO: assuming that signal is valid, should we remove signal? + * TODO: return a boolean on success/failure + */ + public handleSignal = (type:social.PeerMessageType, + signalFromRemote:bridge.SignallingMessage, + messageVersion:number) :Promise => { if (social.PeerMessageType.SIGNAL_FROM_CLIENT_PEER === type) { // If the remote peer sent signal as the client, we act as server. if (!this.user.consent.localGrantsAccessToRemote) { @@ -212,16 +188,14 @@ export var remoteProxyInstance :RemoteInstance = null; return Promise.resolve(); } - // Handle old, pre-signalling metadata clients: - // - the bridge adds a field named "first" (do this for - // MESSAGE_VERSIONs 2 and 3) - // - for ancient clients (MESSAGE_VERSION 1), we need to inspect - // the SDP (!) - if (messageVersion < 4) { - if ((signalFromRemote).first || - ((signalFromRemote).type === signals.Type.OFFER)) { - this.startShare_(); - } + // Create a new RtcToNet instance each time a new round of client peer + // messages begins. The type field check is so pre-bridge, + // MESSAGE_VERSION = 1, clients can initiate. + // TODO: have RemoteConnection do this, based on SignallingMetadata + if (signalFromRemote.first || + ((signalFromRemote).type === signals.Type.OFFER)) { + this.connection_.resetSharerCreated(); + this.startShare_(); } // Wait for the new rtcToNet instance to be created before you handle @@ -258,8 +232,6 @@ export var remoteProxyInstance :RemoteInstance = null; * we should try to start sharing. */ private startShare_ = () : void => { - this.connection_.resetSharerCreated(); - var sharingStopped :Promise; if (this.localSharingWithRemote === social.SharingState.NONE) { // Stop any existing sharing attempts with this instance. @@ -279,9 +251,10 @@ export var remoteProxyInstance :RemoteInstance = null; this.startRtcToNetTimeout_ = setTimeout(() => { log.warn('Timing out rtcToNet_ connection'); // Tell the UI that sharing failed. It will show a toast. + // TODO: have RemoteConnection do this ui.update(uproxy_core_api.Update.FRIEND_FAILED_TO_GET, { name: this.user.name, - proxyingId: this.proxyingId_ + proxyingId: this.connection_.getProxyingId(); }); this.stopShare(); }, this.RTC_TO_NET_TIMEOUT); @@ -311,24 +284,12 @@ export var remoteProxyInstance :RemoteInstance = null; * Begin to use this remote instance as a proxy server, if permission is * currently granted. */ - public start = (proxyingId:string) :Promise => { - log.info('proxying session %1 initiated by this user', proxyingId); + public start = () :Promise => { if (!this.wireConsentFromRemote.isOffering) { log.warn('Lacking permission to proxy'); return Promise.reject(Error('Lacking permission to proxy')); } - this.proxyingId_ = proxyingId; - - // Tell the remote peer to get ready...we want access. - var signal :social.SignallingMetadata = { - proxyingId: proxyingId - } - this.handleConnectionUpdate_(uproxy_core_api.Update.SIGNALLING_MESSAGE, { - type: social.PeerMessageType.SIGNAL_FROM_CLIENT_PEER, - data: signal - }); - // Cancel socksToRtc_ connection if start hasn't completed in 30 seconds. this.startSocksToRtcTimeout_ = setTimeout(() => { log.warn('Timing out socksToRtc_ connection'); diff --git a/src/generic_core/uproxy_core.ts b/src/generic_core/uproxy_core.ts index db6b56ddbc..03deb6f568 100644 --- a/src/generic_core/uproxy_core.ts +++ b/src/generic_core/uproxy_core.ts @@ -266,7 +266,7 @@ export class uProxyCore implements uproxy_core_api.CoreApi { * Starts SDP negotiations with a remote peer. Assumes |path| to the * RemoteInstance exists. */ - public start = (command:uproxy_core_api.StartCommand) : Promise => { + public start = (path :social.InstancePath) : Promise => { // Disable any previous proxying session. var stoppedGetting :Promise[] = []; if (remoteProxyInstance) { @@ -286,17 +286,15 @@ export class uProxyCore implements uproxy_core_api.CoreApi { // connect with the new one, do not propogate this error log.error('Could not clean up old connections', e); }).then(() => { - var remote = this.getInstance(command.instancePath); + var remote = this.getInstance(path); if (!remote) { - log.error('Instance does not exist for proxying', - command.instancePath.instanceId); - return Promise.reject(new Error('Instance does not exist for proxying (' + - command.instancePath.instanceId + ')')); + log.error('Instance does not exist for proxying', path.instanceId); + return Promise.reject(new Error('Instance does not exist for proxying (' + path.instanceId + ')')); } // Remember this instance as our proxy. Set this before start fulfills // in case the user decides to cancel the proxy before it begins. remoteProxyInstance = remote; - return remote.start(command.proxyingId); + return remote.start(); }).catch((e) => { remoteProxyInstance = null; // make sure to clean up any state log.error('Could not start remote proxying session', e.stack); diff --git a/src/generic_ui/scripts/core_connector.ts b/src/generic_ui/scripts/core_connector.ts index bfd6253fb1..f241c5f67f 100644 --- a/src/generic_ui/scripts/core_connector.ts +++ b/src/generic_ui/scripts/core_connector.ts @@ -171,11 +171,9 @@ class CoreConnector implements uproxy_core_api.CoreApi { this.sendCommand(uproxy_core_api.Command.COPYPASTE_SIGNALLING_MESSAGE, signal); } - start = (command:uproxy_core_api.StartCommand) : Promise => { - console.log('Starting proxying session ' + command.proxyingId + - ', getting access from ' + command.instancePath.instanceId); - return this.promiseCommand(uproxy_core_api.Command.START_PROXYING, - command); + start = (path :social.InstancePath) : Promise => { + console.log('Starting to proxy through ' + path); + return this.promiseCommand(uproxy_core_api.Command.START_PROXYING, path); } stop = () => { diff --git a/src/generic_ui/scripts/ui.ts b/src/generic_ui/scripts/ui.ts index 93d4298749..0b882a9e74 100644 --- a/src/generic_ui/scripts/ui.ts +++ b/src/generic_ui/scripts/ui.ts @@ -134,25 +134,6 @@ export interface NotificationData { unique ?:string; } -var PROXYING_SESSION_ID_LENGTH = 16; - -// Generates a string of random letters suitable for use a proxying session ID. -var generateProxyingSessionId_ = (): string => { - // Generates a random number between 97 and 122 inclusive, corresponding - // to lowercase a and z: - // http://unicode.org/charts/PDF/U0000.pdf - var a = 97, b = 122; - var randomCharCode = (): number => { - // TODO: use crypto, but that requires vulcanize to play with third_party - return a + (Math.floor(Math.random() * (b - a))); - }; - var letters: string[] = []; - for (var i = 0; i < PROXYING_SESSION_ID_LENGTH; i++) { - letters.push(String.fromCharCode(randomCharCode())); - } - return letters.join(''); -} - /** * The User Interface class. * @@ -588,13 +569,7 @@ export class UserInterface implements ui_constants.UiApi { this.instanceTryingToGetAccessFrom = instanceId; - // TODO: generate a random ID - var proxyingId = generateProxyingSessionId_(); - - return this.core.start({ - instancePath: path, - proxyingId: proxyingId - }).then((endpoint :net.Endpoint) => { + return this.core.start(path).then((endpoint :net.Endpoint) => { this.instanceTryingToGetAccessFrom = null; this.startGettingInUiAndConfig(instanceId, endpoint); @@ -605,9 +580,6 @@ export class UserInterface implements ui_constants.UiApi { return; } - // TODO: fetch logs now - console.error('proxying attempt ' + proxyingId + ' failed (getting)'); - this.toastMessage = this.i18n_t('unableToGetFrom', { name: user.name }); this.instanceTryingToGetAccessFrom = null; this.unableToGet = true; diff --git a/src/interfaces/social.ts b/src/interfaces/social.ts index e86d2d4d62..d23628e658 100644 --- a/src/interfaces/social.ts +++ b/src/interfaces/social.ts @@ -216,7 +216,7 @@ export interface LocalUserInstance extends BaseInstance { } export interface RemoteUserInstance extends BaseInstance { - start(proxyingId:string) :Promise; + start() :Promise; stop() :Promise; } diff --git a/src/interfaces/uproxy_core_api.ts b/src/interfaces/uproxy_core_api.ts index d28f0dfdf4..18e8663ccd 100644 --- a/src/interfaces/uproxy_core_api.ts +++ b/src/interfaces/uproxy_core_api.ts @@ -157,12 +157,6 @@ export interface LoginArgs { reconnect :boolean; } -// Start getting access from a friend. -export interface StartCommand { - instancePath: social.InstancePath; - proxyingId: string; -} - /** * The primary interface to the uProxy Core. * @@ -205,7 +199,7 @@ export interface CoreApi { sendCopyPasteSignal(signal :social.PeerMessage) :void; // Using peer as a proxy. - start(command:StartCommand) : Promise; + start(instancePath :social.InstancePath) : Promise; stop () : void; updateGlobalSettings(newSettings :GlobalSettings) :void; From b6c174ea35587a3b7336c57b0a4d182f35a25420 Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Thu, 25 Jun 2015 13:34:45 -0400 Subject: [PATCH 11/13] log the proxying session id when initiating --- src/generic_core/remote-connection.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/generic_core/remote-connection.ts b/src/generic_core/remote-connection.ts index 956154b8a2..d3fd453f05 100644 --- a/src/generic_core/remote-connection.ts +++ b/src/generic_core/remote-connection.ts @@ -214,6 +214,7 @@ var generateProxyingSessionId_ = (): string => { } this.proxyingId_ = generateProxyingSessionId_(); + log.info('initiating proxying session %1', this.proxyingId_); // Send the proxying session ID to the remote peer. var signal :social.SignallingMetadata = { From 2637ae3424b2639c8de172248ad7ded4b001d753 Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Thu, 25 Jun 2015 16:11:09 -0400 Subject: [PATCH 12/13] define a FAILED_TO_GET update which delivers the proxying session id to the FE --- src/generic_core/remote-instance.ts | 10 ++++++++-- src/generic_ui/scripts/ui.ts | 30 ++++++++++++++--------------- src/interfaces/uproxy_core_api.ts | 10 +++++----- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/generic_core/remote-instance.ts b/src/generic_core/remote-instance.ts index 3815cd9476..48db10687f 100644 --- a/src/generic_core/remote-instance.ts +++ b/src/generic_core/remote-instance.ts @@ -252,9 +252,9 @@ export var remoteProxyInstance :RemoteInstance = null; log.warn('Timing out rtcToNet_ connection'); // Tell the UI that sharing failed. It will show a toast. // TODO: have RemoteConnection do this - ui.update(uproxy_core_api.Update.FRIEND_FAILED_TO_GET, { + ui.update(uproxy_core_api.Update.FAILED_TO_GIVE, { name: this.user.name, - proxyingId: this.connection_.getProxyingId(); + proxyingId: this.connection_.getProxyingId() }); this.stopShare(); }, this.RTC_TO_NET_TIMEOUT); @@ -293,6 +293,12 @@ export var remoteProxyInstance :RemoteInstance = null; // Cancel socksToRtc_ connection if start hasn't completed in 30 seconds. this.startSocksToRtcTimeout_ = setTimeout(() => { log.warn('Timing out socksToRtc_ connection'); + // Tell the UI that sharing failed. It will show a toast. + // TODO: have RemoteConnection do this + ui.update(uproxy_core_api.Update.FAILED_TO_GET, { + name: this.user.name, + proxyingId: this.connection_.getProxyingId() + }); this.connection_.stopGet(); }, this.SOCKS_TO_RTC_TIMEOUT); diff --git a/src/generic_ui/scripts/ui.ts b/src/generic_ui/scripts/ui.ts index 0b882a9e74..60fc990606 100644 --- a/src/generic_ui/scripts/ui.ts +++ b/src/generic_ui/scripts/ui.ts @@ -341,9 +341,8 @@ export class UserInterface implements ui_constants.UiApi { this.updateSharingStatusBar_(); }); - core.onUpdate(uproxy_core_api.Update.FRIEND_FAILED_TO_GET, - (info:uproxy_core_api.FriendFailedToGet) => { - // TODO: grab logs now or they may be lost in time...like tears in rain + core.onUpdate(uproxy_core_api.Update.FAILED_TO_GIVE, + (info:uproxy_core_api.FailedToGetOrGive) => { console.error('proxying attempt ' + info.proxyingId + ' failed (giving)'); this.toastMessage = this.i18n_t('unableToShareWith', { @@ -352,6 +351,18 @@ export class UserInterface implements ui_constants.UiApi { this.unableToShare = true; }); + core.onUpdate(uproxy_core_api.Update.FAILED_TO_GET, + (info:uproxy_core_api.FailedToGetOrGive) => { + console.error('proxying attempt ' + info.proxyingId + ' failed (getting)'); + + this.toastMessage = this.i18n_t('unableToGetFrom', { + name: info.name + }); + this.instanceTryingToGetAccessFrom = null; + this.unableToGet = true; + this.bringUproxyToFront(); + }); + core.onUpdate( uproxy_core_api.Update.POST_TO_CLOUDFRONT, (data :uproxy_core_api.CloudfrontPostData) => { @@ -571,20 +582,7 @@ export class UserInterface implements ui_constants.UiApi { return this.core.start(path).then((endpoint :net.Endpoint) => { this.instanceTryingToGetAccessFrom = null; - this.startGettingInUiAndConfig(instanceId, endpoint); - }).catch((e :Error) => { - // this is only an error if we are still trying to get access from the - // instance - if (this.instanceTryingToGetAccessFrom !== instanceId) { - return; - } - - this.toastMessage = this.i18n_t('unableToGetFrom', { name: user.name }); - this.instanceTryingToGetAccessFrom = null; - this.unableToGet = true; - this.bringUproxyToFront(); - return Promise.reject(e); }); } diff --git a/src/interfaces/uproxy_core_api.ts b/src/interfaces/uproxy_core_api.ts index 18e8663ccd..c71b8add03 100644 --- a/src/interfaces/uproxy_core_api.ts +++ b/src/interfaces/uproxy_core_api.ts @@ -114,10 +114,10 @@ export enum Update { START_GIVING = 2017, STOP_GIVING = 2018, STATE = 2019, - // TODO: rename to FAILED_TO_SHARE - FRIEND_FAILED_TO_GET = 2020, + FAILED_TO_GIVE = 2020, POST_TO_CLOUDFRONT = 2021, - COPYPASTE_MESSAGE = 2022 + COPYPASTE_MESSAGE = 2022, + FAILED_TO_GET = 2023 } // Action taken by the user. These values are not on the wire. They are passed @@ -130,8 +130,8 @@ export enum ConsentUserAction { OFFER = 5100, CANCEL_OFFER, IGNORE_REQUEST, UNIGNORE_REQUEST, } -// Payload of FRIEND_FAILED_TO_GET messages. -export interface FriendFailedToGet { +// Payload of FAILED_TO_GET and FAILED_TO_GIVE messages. +export interface FailedToGetOrGive { name: string; proxyingId: string; } From 5a06ba19d92d38a7be0ac52b7036ac2297e7a3cb Mon Sep 17 00:00:00 2001 From: Trevor Johnston Date: Thu, 25 Jun 2015 16:25:59 -0400 Subject: [PATCH 13/13] fix fake type, which fixes tests --- src/generic_core/remote-instance.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/generic_core/remote-instance.spec.ts b/src/generic_core/remote-instance.spec.ts index dd5d04d465..b86773c8d2 100644 --- a/src/generic_core/remote-instance.spec.ts +++ b/src/generic_core/remote-instance.spec.ts @@ -243,8 +243,8 @@ describe('remote_instance.RemoteInstance', () => { 'start': () => {} }; var fakeSignallingMessage :bridge.SignallingMessage = { - providers: { - 'FAKE': {} + signals: { + 'FAKE': [] }, first: true };