UNPKG

@jsxc/jsxc

Version:

Real-time XMPP chat application with video calls, file transfer and encrypted communication

184 lines (142 loc) 5.59 kB
import { IConnection } from './Connection.interface'; import Account from '../Account'; import * as JSM from 'jingle'; import { createRegistry } from 'jxt'; import Log from '../util/Log'; import UUID from '../util/UUID'; import JID from '@src/JID'; import { IJID } from '../JID.interface'; import { VideoDialog } from '../ui/VideoDialog'; import JingleSessionFactory from '../JingleSessionFactory'; import JingleAbstractSession from '../JingleAbstractSession'; import JingleMediaSession from '@src/JingleMediaSession'; import { IOTalkJingleMediaSession } from '@vendor/Jingle.interface'; import IceServers, { ICEServer } from '@src/IceServers'; import Client from '@src/Client'; let jxt = createRegistry(); jxt.use(require('jxt-xmpp-types')); jxt.use(require('jxt-xmpp')); let IqStanza = jxt.getDefinition('iq', 'jabber:client'); interface IOfferOptions { offerToReceiveAudio?: boolean; offerToReceiveVideo?: boolean; } export default class JingleHandler { protected manager: JSM; protected static videoDialog: VideoDialog; protected static instances: JingleHandler[] = []; constructor(protected account: Account, protected connection: IConnection) { this.manager = new JSM({ // peerConnectionConstraints: this.getPeerConstraints(), jid: connection.getJID().full, selfID: connection.getJID().full, iceServers: Client.getOption('RTCPeerConfig').iceServers, }); this.manager.on('change:connectionState', function () { Log.info('change:connectionState', arguments); }); this.manager.on('log:*', function (level, msg) { Log.debug('[JINGLE][' + level + ']', msg); }); this.manager.on('send', data => { let iq = new IqStanza(data); let iqElement = $.parseXML(iq.toString()).getElementsByTagName('iq')[0]; iqElement.querySelectorAll('payload-type[name="telephone-event"]').forEach(el => el.remove()); if (!iqElement.getAttribute('id')) { iqElement.setAttribute('id', UUID.v4() + ':sendIQ'); } (<any>this.connection).send(iqElement); //@REVIEW }); this.manager.on('incoming', session => { this.onIncoming(session); }); IceServers.registerUpdateHook(iceServers => { this.setICEServers(iceServers); }); JingleHandler.instances.push(this); } public async initiate( peerJID: IJID, stream: MediaStream, offerOptions?: IOfferOptions, sessionId?: string ): Promise<JingleMediaSession> { let iceServers = await IceServers.get(); this.setICEServers(iceServers); let session: IOTalkJingleMediaSession = this.manager.createMediaSession(peerJID.full, sessionId, stream); return new Promise<JingleMediaSession>(resolve => { session.start(offerOptions, () => { let jingleSession = JingleSessionFactory.create(this.account, session); resolve(jingleSession); }); }); } public terminate(jid: IJID, reason?: string, silent?: boolean); public terminate(reason?: string, silent?: boolean); public terminate() { if (arguments[0] instanceof JID) { this.manager.endPeerSessions(arguments[0].full, arguments[1], arguments[2]); } else { this.manager.endAllSessions(arguments[0], arguments[1]); } } public addICEServer(server: ICEServer | string) { this.manager.addICEServer(server); } public setICEServers(servers: ICEServer[]) { this.manager.iceServers = servers; } public setPeerConstraints(constraints) { this.manager.config.peerConnectionConstraints = constraints; } public onJingle = (iq: Element) => { let req; try { req = jxt.parse(iq.outerHTML); } catch (err) { Log.error('Error while parsing jingle: ', err); return; } this.manager.process(req.toJSON()); return true; }; protected onIncoming(session: IOTalkJingleMediaSession): JingleAbstractSession { return JingleSessionFactory.create(this.account, session); } // private onIncomingFileTransfer(session: IOTalkJingleMediaSession) { // Log.debug('incoming file transfer from ' + session.peerID); // let peerJID = new JID(session.peerID); // let contact = this.account.getContact(peerJID); // if (!contact) { // Log.warn('Reject file transfer, because the contact is not in your contact list'); // return; // } // session.accept(); // // let chatWindow = contact.getChatWindow(); // // let message = new Message({ // // peer: contact.getJid(), // // direction: Message.DIRECTION.IN, // // attachment: new Attachment({ // // name: session.receiver.metadata.name, // // type: session.receiver.metadata.type || 'application/octet-stream' // // }) // // }); // // message.save(); // // chatWindow.receiveIncomingMessage(message); // // // // session.receiver.on('progress', function(sent, size) { // // message.updateProgress(sent, size); // // }); // } public static terminateAll(reason?: string) { JingleHandler.instances.forEach(instance => { instance.terminate(reason); }); } public static getVideoDialog(): VideoDialog { if (!JingleHandler.videoDialog || !JingleHandler.videoDialog.isReady()) { JingleHandler.videoDialog = new VideoDialog(); } return JingleHandler.videoDialog; } }