Fix Android Connection Swap Issue (Server Side)
Summary: - Take device id retrieved by matching CSR to the given CSR destination - Otherwise, use the previous way Note: - Backward compatibility will be fixed next diff Reviewed By: jknoxville Differential Revision: D17346422 fbshipit-source-id: 59b2fb9849373db1ba930dde702194c5fb201678
This commit is contained in:
committed by
Facebook Github Bot
parent
88197a7076
commit
2239ca65a5
@@ -112,7 +112,6 @@ export default class Client extends EventEmitter {
|
||||
lessPlugins: Plugins | undefined;
|
||||
showAllPlugins: boolean;
|
||||
connection: RSocketClientSocket<any, any> | null | undefined;
|
||||
responder: Partial<Responder<string, any>>;
|
||||
store: Store;
|
||||
activePlugins: Set<string>;
|
||||
device: Promise<BaseDevice>;
|
||||
@@ -121,6 +120,7 @@ export default class Client extends EventEmitter {
|
||||
logger: Logger;
|
||||
lastSeenDeviceList: Array<BaseDevice>;
|
||||
broadcastCallbacks: Map<string, Map<string, Set<Function>>>;
|
||||
rIC: any;
|
||||
|
||||
requestCallbacks: Map<
|
||||
number,
|
||||
@@ -162,19 +162,12 @@ export default class Client extends EventEmitter {
|
||||
|
||||
const client = this;
|
||||
// node.js doesn't support requestIdleCallback
|
||||
const rIC =
|
||||
this.rIC =
|
||||
typeof window === 'undefined'
|
||||
? (cb: Function, _: any) => {
|
||||
cb();
|
||||
}
|
||||
: window.requestIdleCallback;
|
||||
|
||||
this.responder = {
|
||||
fireAndForget: (payload: {data: string}) =>
|
||||
rIC(() => client.onMessage(payload.data), {
|
||||
timeout: 500,
|
||||
}),
|
||||
};
|
||||
: window.requestIdleCallback.bind(window);
|
||||
|
||||
if (conn) {
|
||||
conn.connectionStatus().subscribe({
|
||||
|
||||
@@ -28,6 +28,11 @@ type ClientInfo = {
|
||||
client: Client;
|
||||
};
|
||||
|
||||
type ClientCsrQuery = {
|
||||
csr?: string | undefined;
|
||||
csr_path?: string | undefined;
|
||||
};
|
||||
|
||||
declare interface Server {
|
||||
on(event: 'new-client', callback: (client: Client) => void): this;
|
||||
on(event: 'error', callback: (err: Error) => void): this;
|
||||
@@ -124,16 +129,24 @@ class Server extends EventEmitter {
|
||||
if (!payload.data) {
|
||||
return {};
|
||||
}
|
||||
const clientData: ClientQuery = JSON.parse(payload.data);
|
||||
const clientData: ClientQuery & ClientCsrQuery = JSON.parse(payload.data);
|
||||
this.connectionTracker.logConnectionAttempt(clientData);
|
||||
|
||||
const client = this.addConnection(socket, clientData);
|
||||
const {app, os, device, device_id, sdk_version, csr, csr_path} = clientData;
|
||||
|
||||
const client: Promise<Client> = this.addConnection(
|
||||
socket,
|
||||
{app, os, device, device_id, sdk_version},
|
||||
{csr, csr_path},
|
||||
);
|
||||
|
||||
socket.connectionStatus().subscribe({
|
||||
onNext(payload) {
|
||||
if (payload.kind == 'ERROR' || payload.kind == 'CLOSED') {
|
||||
client.then(client => {
|
||||
console.debug(`Device disconnected ${client.id}`, 'server');
|
||||
server.removeConnection(client.id);
|
||||
});
|
||||
}
|
||||
},
|
||||
onSubscribe(subscription) {
|
||||
@@ -141,7 +154,14 @@ class Server extends EventEmitter {
|
||||
},
|
||||
});
|
||||
|
||||
return client.responder;
|
||||
return {
|
||||
fireAndForget: (payload: {data: string}) =>
|
||||
client.then(client => {
|
||||
client.rIC(() => client.onMessage(payload.data), {
|
||||
timeout: 500,
|
||||
});
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
_untrustedRequestHandler = (
|
||||
@@ -272,13 +292,29 @@ class Server extends EventEmitter {
|
||||
return null;
|
||||
}
|
||||
|
||||
addConnection(
|
||||
async addConnection(
|
||||
conn: RSocketClientSocket<any, any>,
|
||||
query: ClientQuery,
|
||||
): Client {
|
||||
csrQuery: ClientCsrQuery,
|
||||
): Promise<Client> {
|
||||
invariant(query, 'expected query');
|
||||
|
||||
const id = `${query.app}#${query.os}#${query.device}#${query.device_id}`;
|
||||
// try to get id by comparing giving `csr` to file from `csr_path`
|
||||
// otherwise, use given device_id
|
||||
const {csr_path, csr} = csrQuery;
|
||||
return (csr_path && csr
|
||||
? this.certificateProvider.extractAppNameFromCSR(csr).then(appName => {
|
||||
return this.certificateProvider.getTargetDeviceId(
|
||||
query.os,
|
||||
appName,
|
||||
csr_path,
|
||||
csr,
|
||||
);
|
||||
})
|
||||
: Promise.resolve(query.device_id)
|
||||
).then(csrId => {
|
||||
query.device_id = csrId;
|
||||
const id = `${query.app}#${query.os}#${query.device}#${csrId}`;
|
||||
console.debug(`Device connected: ${id}`, 'server');
|
||||
|
||||
const client = new Client(id, query, conn, this.logger, this.store);
|
||||
@@ -315,6 +351,7 @@ class Server extends EventEmitter {
|
||||
});
|
||||
|
||||
return client;
|
||||
});
|
||||
}
|
||||
|
||||
attachFakeClient(client: Client) {
|
||||
|
||||
@@ -346,7 +346,12 @@ export default class CertificateProvider {
|
||||
return androidUtil
|
||||
.pull(deviceId, processName, directory + csrFileName)
|
||||
.then(deviceCsr => {
|
||||
return this.santitizeString(deviceCsr.toString()) === csr;
|
||||
// Santitize both of the string before comparation
|
||||
// The csr string extraction on client side return string in both way
|
||||
return (
|
||||
this.santitizeString(deviceCsr.toString()) ===
|
||||
this.santitizeString(csr)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user