review changes

pull/1175/head
Vincent 5 years ago
parent affba056d2
commit 48e3ded9d2

@ -8,7 +8,7 @@ interface ClosedGroupMessageParams extends MessageParams {
} }
export abstract class ClosedGroupMessage extends DataMessage { export abstract class ClosedGroupMessage extends DataMessage {
protected readonly groupId: string; public readonly groupId: string;
constructor(params: ClosedGroupMessageParams) { constructor(params: ClosedGroupMessageParams) {
super({ super({

@ -1,31 +0,0 @@
import { SignalService } from '../../../../../protobuf';
import { MessageParams } from '../../Message';
import { SyncMessage } from '../';
import { PubKey } from '../../../../types';
import { DataMessage } from '../data';
interface ContactSyncMessageParams extends MessageParams {
// Send to our devices
contacts: Array<PubKey>;
dataMessage?: DataMessage;
}
export class ContactSyncMessage extends SyncMessage {
private readonly contacts: Array<PubKey>;
private readonly dataMessage?: DataMessage;
constructor(params: ContactSyncMessageParams) {
super(params);
// Stubbed for now
this.contacts = params.contacts;
this.dataMessage = params.dataMessage;
this.syncProto();
}
protected syncProto(): SignalService.SyncMessage {
return new SignalService.SyncMessage();
}
}

@ -1,4 +1,3 @@
import { SyncMessage } from './SyncMessage'; import { SyncMessage } from './SyncMessage';
import { ContactSyncMessage } from './ContactSyncMessage';
export { ContactSyncMessage, SyncMessage }; export { SyncMessage };

@ -1,5 +1,5 @@
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as Data from '../../../js/modules/data'; import { getPairedDevicesFor } from '../../../js/modules/data';
import { ConversationController } from '../../window'; import { ConversationController } from '../../window';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
@ -14,14 +14,11 @@ import {
SessionRequestMessage, SessionRequestMessage,
} from '../messages/outgoing'; } from '../messages/outgoing';
import { PendingMessageCache } from './PendingMessageCache'; import { PendingMessageCache } from './PendingMessageCache';
import { import { JobQueue, SyncMessageUtils, TypedEventEmitter } from '../utils';
JobQueue,
SyncMessageUtils,
TypedEventEmitter,
} from '../utils';
import { PubKey } from '../types'; import { PubKey } from '../types';
import { MessageSender } from '.'; import { MessageSender } from '.';
import { SessionProtocol } from '../protocols'; import { SessionProtocol } from '../protocols';
import * as UserUtils from '../../util/user';
export class MessageQueue implements MessageQueueInterface { export class MessageQueue implements MessageQueueInterface {
public readonly events: TypedEventEmitter<MessageQueueInterfaceEvents>; public readonly events: TypedEventEmitter<MessageQueueInterfaceEvents>;
@ -35,7 +32,7 @@ export class MessageQueue implements MessageQueueInterface {
} }
public async sendUsingMultiDevice(user: PubKey, message: ContentMessage) { public async sendUsingMultiDevice(user: PubKey, message: ContentMessage) {
const userLinked = await Data.getPairedDevicesFor(user.key); const userLinked = await getPairedDevicesFor(user.key);
const userDevices = userLinked.map(d => new PubKey(d)); const userDevices = userLinked.map(d => new PubKey(d));
await this.sendMessageToDevices(userDevices, message); await this.sendMessageToDevices(userDevices, message);
@ -53,23 +50,34 @@ export class MessageQueue implements MessageQueueInterface {
// Sync to our devices if syncable // Sync to our devices if syncable
if (SyncMessageUtils.canSync(message)) { if (SyncMessageUtils.canSync(message)) {
const currentDevice = await UserUtils.getCurrentDevicePubKey();
if (currentDevice) {
const otherDevices = await getPairedDevicesFor(currentDevice);
const ourDevices = await SyncMessageUtils.getOurPairedDevices(); const ourDevices = [currentDevice, ...otherDevices].map(
await this.sendSyncMessage(message, ourDevices); device => new PubKey(device)
);
await this.sendSyncMessage(message, ourDevices);
// Remove our devices from currentDevices // Remove our devices from currentDevices
const ourDeviceContacts = ourDevices.map(device => ConversationController.get(device.key)); const ourDeviceContacts = ourDevices.map(device =>
currentDevices = _.xor(currentDevices, ourDeviceContacts); ConversationController.get(device.key)
);
currentDevices = _.xor(currentDevices, ourDeviceContacts);
}
} }
const promises = currentDevices.map(async device => { const promises = currentDevices.map(async device => {
await this.queue(device, message); await this.process(device, message);
}); });
return Promise.all(promises); return Promise.all(promises);
} }
public async sendToGroup(message: OpenGroupMessage | ContentMessage): Promise<boolean> { public async sendToGroup(
message: OpenGroupMessage | ContentMessage
): Promise<boolean> {
if ( if (
!(message instanceof OpenGroupMessage) && !(message instanceof OpenGroupMessage) &&
!(message instanceof ClosedGroupMessage) !(message instanceof ClosedGroupMessage)
@ -102,15 +110,12 @@ export class MessageQueue implements MessageQueueInterface {
return false; return false;
} }
public async sendSyncMessage( public async sendSyncMessage(message: ContentMessage, sendTo: Array<PubKey>) {
message: ContentMessage,
sendTo: Array<PubKey>
) {
// Sync with our devices // Sync with our devices
const promises = sendTo.map(async device => { const promises = sendTo.map(async device => {
const syncMessage = await SyncMessageUtils.from(message, device); const syncMessage = await SyncMessageUtils.from(message);
return this.queue(device, syncMessage); return this.process(device, syncMessage);
}); });
return Promise.all(promises); return Promise.all(promises);
@ -130,17 +135,19 @@ export class MessageQueue implements MessageQueueInterface {
} }
const jobQueue = this.getJobQueue(device); const jobQueue = this.getJobQueue(device);
messages.forEach(message => { messages.forEach(async message => {
if (!jobQueue.has(message.identifier)) { const messageId = String(message.timestamp);
const promise = jobQueue.add(async () => MessageSender.send(message));
if (!jobQueue.has(messageId)) {
promise try {
.then(() => { await jobQueue.addWithId(messageId, async () =>
// Message sent; remove from cache MessageSender.send(message)
void this.pendingMessageCache.remove(message); );
}) void this.pendingMessageCache.remove(message);
// Message failed to send this.events.emit('success', message);
.catch(() => null); } catch (e) {
this.events.emit('fail', message, e);
}
} }
}); });
} }
@ -152,8 +159,8 @@ export class MessageQueue implements MessageQueueInterface {
return Promise.all(promises); return Promise.all(promises);
} }
private async queue(device: PubKey, message: ContentMessage) { private async process(device: PubKey, message?: ContentMessage) {
if (message instanceof SessionRequestMessage) { if (!message || message instanceof SessionRequestMessage) {
return; return;
} }
@ -170,5 +177,4 @@ export class MessageQueue implements MessageQueueInterface {
return queue; return queue;
} }
} }

@ -19,5 +19,8 @@ export interface MessageQueueInterface {
sendUsingMultiDevice(user: PubKey, message: ContentMessage): void; sendUsingMultiDevice(user: PubKey, message: ContentMessage): void;
send(device: PubKey, message: ContentMessage): void; send(device: PubKey, message: ContentMessage): void;
sendToGroup(message: GroupMessageType): void; sendToGroup(message: GroupMessageType): void;
sendSyncMessage(message: ContentMessage, sendTo: Array<PubKey>): Promise<Array<void>>; sendSyncMessage(
message: ContentMessage,
sendTo: Array<PubKey>
): Promise<Array<void>>;
} }

@ -1,7 +1,8 @@
export class PubKey { export class PubKey {
public static readonly PUBKEY_LEN = 66; public static readonly PUBKEY_LEN = 66;
private static readonly regex: RegExp = new RegExp(`^05[0-9a-fA-F]{${PubKey.PUBKEY_LEN - private static readonly regex: RegExp = new RegExp(
2}}$`); `^05[0-9a-fA-F]{${PubKey.PUBKEY_LEN - 2}}$`
);
public readonly key: string; public readonly key: string;
constructor(pubkeyString: string) { constructor(pubkeyString: string) {

@ -1,53 +1,54 @@
import {
ContactSyncMessage,
ContentMessage,
SyncMessageEnum,
} from '../messages/outgoing';
import { PubKey } from '../types';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as Data from '../../../js/modules/data'; import * as UserUtils from '../../util/user';
import { ConversationController, textsecure, Whisper } from '../../window'; import {
import { OpenGroup } from '../types/OpenGroup'; getAllConversations,
getPrimaryDeviceFor,
} from '../../../js/modules/data';
import { ConversationController, Whisper } from '../../window';
import { ContentMessage, SyncMessage } from '../messages/outgoing';
export async function from( export async function from(
message: ContentMessage, message: ContentMessage
sendTo: PubKey | OpenGroup, ): Promise<SyncMessage | undefined> {
syncType: SyncMessageEnum.CONTACTS | SyncMessageEnum.GROUPS = SyncMessageEnum.CONTACTS // const { timestamp, identifier } = message;
): Promise<ContactSyncMessage> {
const { timestamp, identifier } = message;
// Stubbed for now // Stubbed for now
return new ContactSyncMessage({ return undefined;
timestamp,
identifier,
contacts: [],
});
} }
export async function canSync(message: ContentMessage): Promise<boolean> { export async function canSync(message: ContentMessage): Promise<boolean> {
// This function should be agnostic to the device; it shouldn't need // This function should be agnostic to the device; it shouldn't need
// to know about the recipient // to know about the recipient
// return Boolean(from(message, device)); // return Boolean(from(message));
// Stubbed for now // Stubbed for now
return true; return true;
} }
export async function getSyncContacts(): Promise<Array<any>> { export async function getSyncContacts(): Promise<Array<any> | undefined> {
const thisDevice = textsecure.storage.user.getNumber(); const thisDevice = await UserUtils.getCurrentDevicePubKey();
const primaryDevice = await Data.getPrimaryDeviceFor(thisDevice);
const conversations = await Data.getAllConversations({ ConversationCollection: Whisper.ConversationCollection }); if (!thisDevice) {
return [];
}
const primaryDevice = await getPrimaryDeviceFor(thisDevice);
const conversations = await getAllConversations({
ConversationCollection: Whisper.ConversationCollection,
});
// We are building a set of all contacts // We are building a set of all contacts
const primaryContacts = conversations.filter(c => const primaryContacts =
c.isPrivate() && conversations.filter(
!c.isOurLocalDevice() && c =>
c.isFriend() && c.isPrivate() &&
!c.attributes.secondaryStatus !c.isOurLocalDevice() &&
) || []; c.isFriend() &&
!c.attributes.secondaryStatus
) || [];
const secondaryContactsPartial = conversations.filter(c => const secondaryContactsPartial = conversations.filter(
c =>
c.isPrivate() && c.isPrivate() &&
!c.isOurLocalDevice() && !c.isOurLocalDevice() &&
c.isFriend() && c.isFriend() &&
@ -66,15 +67,8 @@ export async function getSyncContacts(): Promise<Array<any>> {
.filter(c => c.id !== primaryDevice); .filter(c => c.id !== primaryDevice);
// Return unique contacts // Return unique contacts
return _.uniqBy([ return _.uniqBy(
...primaryContacts, [...primaryContacts, ...secondaryContacts],
...secondaryContacts, device => !!device
], device => !!device); );
}
export async function getOurPairedDevices(): Promise<Array<PubKey>> {
const ourPubKey = textsecure.storage.user.getNumber();
const ourDevices = await Data.getPairedDevicesFor(ourPubKey);
return ourDevices.map(device => new PubKey(device));
} }

@ -1,6 +1,6 @@
import { expect } from 'chai'; import { expect } from 'chai';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as MessageUtils from '../../../session/utils'; import { MessageUtils } from '../../../session/utils';
import { TestUtils } from '../../../test/test-utils'; import { TestUtils } from '../../../test/test-utils';
import { PendingMessageCache } from '../../../session/sending/PendingMessageCache'; import { PendingMessageCache } from '../../../session/sending/PendingMessageCache';
@ -53,7 +53,7 @@ describe('PendingMessageCache', () => {
it('can add to cache', async () => { it('can add to cache', async () => {
const device = TestUtils.generateFakePubkey(); const device = TestUtils.generateFakePubkey();
const message = TestUtils.generateUniqueChatMessage(); const message = TestUtils.generateChatMessage();
const rawMessage = MessageUtils.toRawMessage(device, message); const rawMessage = MessageUtils.toRawMessage(device, message);
await pendingMessageCacheStub.add(device, message); await pendingMessageCacheStub.add(device, message);
@ -70,7 +70,7 @@ describe('PendingMessageCache', () => {
it('can remove from cache', async () => { it('can remove from cache', async () => {
const device = TestUtils.generateFakePubkey(); const device = TestUtils.generateFakePubkey();
const message = TestUtils.generateUniqueChatMessage(); const message = TestUtils.generateChatMessage();
const rawMessage = MessageUtils.toRawMessage(device, message); const rawMessage = MessageUtils.toRawMessage(device, message);
await pendingMessageCacheStub.add(device, message); await pendingMessageCacheStub.add(device, message);
@ -91,15 +91,15 @@ describe('PendingMessageCache', () => {
const cacheItems = [ const cacheItems = [
{ {
device: TestUtils.generateFakePubkey(), device: TestUtils.generateFakePubkey(),
message: TestUtils.generateUniqueChatMessage(), message: TestUtils.generateChatMessage(),
}, },
{ {
device: TestUtils.generateFakePubkey(), device: TestUtils.generateFakePubkey(),
message: TestUtils.generateUniqueChatMessage(), message: TestUtils.generateChatMessage(),
}, },
{ {
device: TestUtils.generateFakePubkey(), device: TestUtils.generateFakePubkey(),
message: TestUtils.generateUniqueChatMessage(), message: TestUtils.generateChatMessage(),
}, },
]; ];
@ -123,11 +123,11 @@ describe('PendingMessageCache', () => {
const cacheItems = [ const cacheItems = [
{ {
device: TestUtils.generateFakePubkey(), device: TestUtils.generateFakePubkey(),
message: TestUtils.generateUniqueChatMessage(), message: TestUtils.generateChatMessage(),
}, },
{ {
device: TestUtils.generateFakePubkey(), device: TestUtils.generateFakePubkey(),
message: TestUtils.generateUniqueChatMessage(), message: TestUtils.generateChatMessage(),
}, },
]; ];
@ -150,7 +150,7 @@ describe('PendingMessageCache', () => {
it('can find nothing when empty', async () => { it('can find nothing when empty', async () => {
const device = TestUtils.generateFakePubkey(); const device = TestUtils.generateFakePubkey();
const message = TestUtils.generateUniqueChatMessage(); const message = TestUtils.generateChatMessage();
const rawMessage = MessageUtils.toRawMessage(device, message); const rawMessage = MessageUtils.toRawMessage(device, message);
const foundMessage = pendingMessageCacheStub.find(rawMessage); const foundMessage = pendingMessageCacheStub.find(rawMessage);
@ -159,7 +159,7 @@ describe('PendingMessageCache', () => {
it('can find message in cache', async () => { it('can find message in cache', async () => {
const device = TestUtils.generateFakePubkey(); const device = TestUtils.generateFakePubkey();
const message = TestUtils.generateUniqueChatMessage(); const message = TestUtils.generateChatMessage();
const rawMessage = MessageUtils.toRawMessage(device, message); const rawMessage = MessageUtils.toRawMessage(device, message);
await pendingMessageCacheStub.add(device, message); await pendingMessageCacheStub.add(device, message);
@ -176,15 +176,15 @@ describe('PendingMessageCache', () => {
const cacheItems = [ const cacheItems = [
{ {
device: TestUtils.generateFakePubkey(), device: TestUtils.generateFakePubkey(),
message: TestUtils.generateUniqueChatMessage(), message: TestUtils.generateChatMessage(),
}, },
{ {
device: TestUtils.generateFakePubkey(), device: TestUtils.generateFakePubkey(),
message: TestUtils.generateUniqueChatMessage(), message: TestUtils.generateChatMessage(),
}, },
{ {
device: TestUtils.generateFakePubkey(), device: TestUtils.generateFakePubkey(),
message: TestUtils.generateUniqueChatMessage(), message: TestUtils.generateChatMessage(),
}, },
]; ];
@ -206,15 +206,15 @@ describe('PendingMessageCache', () => {
const cacheItems = [ const cacheItems = [
{ {
device: TestUtils.generateFakePubkey(), device: TestUtils.generateFakePubkey(),
message: TestUtils.generateUniqueChatMessage(), message: TestUtils.generateChatMessage(),
}, },
{ {
device: TestUtils.generateFakePubkey(), device: TestUtils.generateFakePubkey(),
message: TestUtils.generateUniqueChatMessage(), message: TestUtils.generateChatMessage(),
}, },
{ {
device: TestUtils.generateFakePubkey(), device: TestUtils.generateFakePubkey(),
message: TestUtils.generateUniqueChatMessage(), message: TestUtils.generateChatMessage(),
}, },
]; ];

@ -55,7 +55,7 @@ export function generateFakePubkey(): PubKey {
return new PubKey(pubkeyString); return new PubKey(pubkeyString);
} }
export function generateUniqueChatMessage(): ChatMessage { export function generateChatMessage(): ChatMessage {
return new ChatMessage({ return new ChatMessage({
body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', body: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
identifier: uuid(), identifier: uuid(),

Loading…
Cancel
Save