Skip to content

Commit

Permalink
Merge pull request #1686 from uProxy/trevj-proxying-id
Browse files Browse the repository at this point in the history
generate a random, unique ID for each proxying attempt
  • Loading branch information
trevj committed Jun 29, 2015
2 parents 7541a95 + 9e97058 commit 3e7d3ed
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 34 deletions.
75 changes: 68 additions & 7 deletions src/generic_core/remote-connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -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
) {
Expand All @@ -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<void> => {
// TODO: forward messages from pre-bridge clients
if ((<any>message.data).signals !== undefined) {
return this.forwardSignal_(message.type, message.data);
} else {
return this.handleMetadataSignal_(
<social.SignallingMetadata>message.data);
}
}

private handleMetadataSignal_ = (
message:social.SignallingMetadata) :Promise<void> => {
if (message.proxyingId) {
log.info('proxying session %1 initiated by remote peer', message.proxyingId);
this.proxyingId_ = message.proxyingId;
}
return Promise.resolve<void>();
}

// Forwards a signalling message to the RemoteConnection.
private forwardSignal_ = (
type:social.PeerMessageType,
signal:Object)
:Promise<void> => {
if (social.PeerMessageType.SIGNAL_FROM_CLIENT_PEER === type
&& this.rtcToNet_) {
this.rtcToNet_.handleSignalFromPeer(<bridge.SignallingMessage>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(<bridge.SignallingMessage>message.data);
this.socksToRtc_.handleSignalFromPeer(signal);
} else {
log.warn('Invalid signal: ', social.PeerMessageType[message.type]);
log.warn('Invalid signal: ', social.PeerMessageType[type]);
return;
}
};
Expand Down Expand Up @@ -168,6 +213,18 @@ import tcp = require('../../../third_party/uproxy-lib/net/tcp');
throw new Error('socksToRtc_ already exists');
}

this.proxyingId_ = generateProxyingSessionId_();
log.info('initiating proxying session %1', this.proxyingId_);

// 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
Expand Down Expand Up @@ -297,5 +354,9 @@ import tcp = require('../../../third_party/uproxy-lib/net/tcp');
localSharingWithRemote: this.localSharingWithRemote
};
}

public getProxyingId = () : string => {
return this.proxyingId_;
}
}
// }
4 changes: 2 additions & 2 deletions src/generic_core/remote-instance.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ describe('remote_instance.RemoteInstance', () => {
'start': () => {}
};
var fakeSignallingMessage :bridge.SignallingMessage = {
providers: {
'FAKE': {}
signals: {
'FAKE': []
},
first: true
};
Expand Down
15 changes: 13 additions & 2 deletions src/generic_core/remote-instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export var remoteProxyInstance :RemoteInstance = null;
// 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
// TODO: have RemoteConnection do this, based on SignallingMetadata
if (signalFromRemote.first ||
((<signals.Message>signalFromRemote).type === signals.Type.OFFER)) {
this.connection_.resetSharerCreated();
Expand Down Expand Up @@ -250,7 +250,12 @@ 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);
// Tell the UI that sharing failed. It will show a toast.
// TODO: have RemoteConnection do this
ui.update(uproxy_core_api.Update.FAILED_TO_GIVE, {
name: this.user.name,
proxyingId: this.connection_.getProxyingId()
});
this.stopShare();
}, this.RTC_TO_NET_TIMEOUT);

Expand Down Expand Up @@ -288,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);

Expand Down
3 changes: 1 addition & 2 deletions src/generic_core/remote-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,7 @@ var log :logging.Log = new logging.Log('remote-user');
log.error('failed to get instance', clientId);
return;
}
instance.handleSignal(msg.type, <bridge.SignallingMessage>msg.data,
msg.version);
instance.handleSignal(msg.type, msg.data, msg.version);
return;

case social.PeerMessageType.INSTANCE_REQUEST:
Expand Down
4 changes: 3 additions & 1 deletion src/generic_ui/polymer/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ Polymer({
return;
}

ui.startGettingFromInstance(this.instance.instanceId);
ui.startGettingFromInstance(this.instance.instanceId).catch((e: Error) => {
console.error('could not get access: ' + e.message);
});
},
stop: function() {
ui.stopGettingFromInstance(this.instance.instanceId);
Expand Down
37 changes: 19 additions & 18 deletions src/generic_ui/scripts/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,14 +341,28 @@ export class UserInterface implements ui_constants.UiApi {
this.updateSharingStatusBar_();
});

core.onUpdate(uproxy_core_api.Update.FRIEND_FAILED_TO_GET, (nameOfFriend :string) => {
// Setting this variable will toggle a paper-toast (in root.html)
// to open.
this.toastMessage =
this.i18n_t('unableToShareWith', { name: nameOfFriend });
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', {
name: info.name
});
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) => {
Expand Down Expand Up @@ -568,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);
});
}

Expand Down
8 changes: 8 additions & 0 deletions src/interfaces/social.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,14 @@ export interface RemoteUserInstance {
stop() :Promise<void>;
}

// Payload for SIGNAL_FROM_CLIENT_PEER and SIGNAL_FROM_SERVER_PEER messages.
// Other payload types exist, e.g. bridging peerconnection signals.
export interface SignallingMetadata {
// Random ID associated with this proxying attempt.
// Used for logging purposes and implicitly delimits proxying attempts.
proxyingId ?:string;
}

/**
*
*/
Expand Down
11 changes: 9 additions & 2 deletions src/interfaces/uproxy_core_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,10 @@ export enum Update {
START_GIVING = 2017,
STOP_GIVING = 2018,
STATE = 2019,
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
Expand All @@ -129,6 +130,12 @@ export enum ConsentUserAction {
OFFER = 5100, CANCEL_OFFER, IGNORE_REQUEST, UNIGNORE_REQUEST,
}

// Payload of FAILED_TO_GET and FAILED_TO_GIVE messages.
export interface FailedToGetOrGive {
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
Expand Down

0 comments on commit 3e7d3ed

Please sign in to comment.