You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			121 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			121 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			TypeScript
		
	
import { EnvelopePlus } from './types';
 | 
						|
import { SignalService } from '../protobuf';
 | 
						|
import * as libsession from './../session';
 | 
						|
import { toNumber } from 'lodash';
 | 
						|
import { PubKey } from '../session/types';
 | 
						|
import { SessionEstablishedMessage } from '../session/messages/outgoing';
 | 
						|
import { SessionProtocol } from '../session/protocols';
 | 
						|
 | 
						|
export async function handleEndSession(number: string): Promise<void> {
 | 
						|
  window.log.info('got end session');
 | 
						|
 | 
						|
  const { ConversationController } = window;
 | 
						|
 | 
						|
  try {
 | 
						|
    const conversation = ConversationController.get(number);
 | 
						|
    if (conversation) {
 | 
						|
      await conversation.onSessionResetReceived();
 | 
						|
    } else {
 | 
						|
      throw new Error();
 | 
						|
    }
 | 
						|
  } catch (e) {
 | 
						|
    window.log.error('Error getting conversation: ', number);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export async function handleSessionRequestMessage(
 | 
						|
  envelope: EnvelopePlus,
 | 
						|
  preKeyBundleMessage: SignalService.IPreKeyBundleMessage
 | 
						|
) {
 | 
						|
  const { libsignal, libloki, StringView, textsecure, dcodeIO, log } = window;
 | 
						|
 | 
						|
  window.console.log(
 | 
						|
    `Received SESSION_REQUEST from source: ${envelope.source}`
 | 
						|
  );
 | 
						|
 | 
						|
  if (!preKeyBundleMessage) {
 | 
						|
    log.warn('No pre-key bundle found in a session request');
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  const shouldProcessSessionRequest = await SessionProtocol.shouldProcessSessionRequest(
 | 
						|
    new PubKey(envelope.source),
 | 
						|
    toNumber(envelope.timestamp)
 | 
						|
  );
 | 
						|
 | 
						|
  if (!shouldProcessSessionRequest) {
 | 
						|
    log.debug('Ignoring a session request message');
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  try {
 | 
						|
    // device id are always 1 with Session
 | 
						|
    const deviceId = 1;
 | 
						|
    const pubkey = envelope.source;
 | 
						|
    const address = new libsignal.SignalProtocolAddress(
 | 
						|
      envelope.source,
 | 
						|
      deviceId
 | 
						|
    );
 | 
						|
    // we process the new prekeys and initiate a new session.
 | 
						|
    // The old sessions will get deleted once the correspondant
 | 
						|
    // has switch to the new session.
 | 
						|
    const [identityKey, preKey, signedKey, signature] = [
 | 
						|
      preKeyBundleMessage.identityKey,
 | 
						|
      preKeyBundleMessage.preKey,
 | 
						|
      preKeyBundleMessage.signedKey,
 | 
						|
      preKeyBundleMessage.signature,
 | 
						|
    ].map(k => dcodeIO.ByteBuffer.wrap(k).toArrayBuffer());
 | 
						|
    const { preKeyId, signedKeyId } = preKeyBundleMessage;
 | 
						|
 | 
						|
    if (pubkey !== StringView.arrayBufferToHex(identityKey)) {
 | 
						|
      throw new Error(
 | 
						|
        'Error in savePreKeyBundleMessage: envelope pubkey does not match pubkey in prekey bundle'
 | 
						|
      );
 | 
						|
    }
 | 
						|
    if (preKey === undefined || signedKey === undefined) {
 | 
						|
      window.console.warn(
 | 
						|
        "Couldn't process prekey bundle without preKey or signedKey"
 | 
						|
      );
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    const signedPreKey = {
 | 
						|
      keyId: signedKeyId,
 | 
						|
      publicKey: signedKey,
 | 
						|
      signature,
 | 
						|
    };
 | 
						|
 | 
						|
    const preKeyObject = {
 | 
						|
      publicKey: preKey,
 | 
						|
      keyId: preKeyId,
 | 
						|
    };
 | 
						|
 | 
						|
    const device = {
 | 
						|
      identityKey,
 | 
						|
      deviceId,
 | 
						|
      preKey: preKeyObject,
 | 
						|
      signedPreKey,
 | 
						|
      registrationId: 0,
 | 
						|
    };
 | 
						|
    const builder = new libsignal.SessionBuilder(
 | 
						|
      textsecure.storage.protocol,
 | 
						|
      address
 | 
						|
    );
 | 
						|
    await builder.processPreKey(device);
 | 
						|
 | 
						|
    await SessionProtocol.onSessionRequestProcessed(
 | 
						|
      new PubKey(envelope.source)
 | 
						|
    );
 | 
						|
    log.debug('sending session established to', envelope.source);
 | 
						|
    // We don't need to await the call below because we just want to send it off
 | 
						|
 | 
						|
    const user = new PubKey(envelope.source);
 | 
						|
 | 
						|
    const sessionEstablished = new SessionEstablishedMessage({
 | 
						|
      timestamp: Date.now(),
 | 
						|
    });
 | 
						|
    await libsession.getMessageQueue().send(user, sessionEstablished);
 | 
						|
  } catch (e) {
 | 
						|
    log.warn('Failed to process session request', e);
 | 
						|
    // TODO how to handle a failed session request?
 | 
						|
  }
 | 
						|
}
 |