Telegram Web K with changes to work inside I2P
https://web.telegram.i2p/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
5.7 KiB
196 lines
5.7 KiB
/* |
|
* https://github.com/morethanwords/tweb |
|
* Copyright (C) 2019-2021 Eduard Kuzmenko |
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE |
|
* |
|
* Originally from: |
|
* https://github.com/evgeny-nadymov/telegram-react |
|
* Copyright (C) 2018 Evgeny Nadymov |
|
* https://github.com/evgeny-nadymov/telegram-react/blob/master/LICENSE |
|
*/ |
|
|
|
import indexOfAndSplice from '../../helpers/array/indexOfAndSplice'; |
|
import safeAssign from '../../helpers/object/safeAssign'; |
|
import {GroupCallParticipantVideoSourceGroup} from '../../layer'; |
|
import {fixMediaLineType, SDPBuilder, WebRTCLineType, WEBRTC_MEDIA_PORT} from './sdpBuilder'; |
|
import {AudioCodec, GroupCallConnectionTransport, Ssrc, UpdateGroupCallConnectionData, VideoCodec} from './types'; |
|
|
|
export class ConferenceEntry { |
|
public source: number; |
|
public sourceGroups: GroupCallParticipantVideoSourceGroup[]; |
|
public transceiver: RTCRtpTransceiver; |
|
public originalDirection: RTCRtpTransceiverDirection; |
|
public direction: RTCRtpTransceiverDirection; |
|
public port: string; |
|
public endpoint: string; |
|
public peerId: PeerId; |
|
|
|
public sendEntry: ConferenceEntry; |
|
public recvEntry: ConferenceEntry; |
|
|
|
constructor(public mid: string, public type: WebRTCLineType) { |
|
this.port = WEBRTC_MEDIA_PORT; |
|
} |
|
|
|
public setDirection(direction: RTCRtpTransceiverDirection) { |
|
if(!this.originalDirection) { |
|
this.originalDirection = direction; |
|
} |
|
|
|
return this.direction = direction; |
|
} |
|
|
|
public setPort(port: string) { |
|
return this.port = port; |
|
} |
|
|
|
public setEndpoint(endpoint: string) { |
|
return this.endpoint = endpoint; |
|
} |
|
|
|
public setPeerId(peerId: PeerId) { |
|
return this.peerId = peerId; |
|
} |
|
|
|
public createTransceiver(connection: RTCPeerConnection, init?: RTCRtpTransceiverInit) { |
|
if(init?.direction) { |
|
this.setDirection(init.direction); |
|
} |
|
|
|
return this.transceiver = connection.addTransceiver(fixMediaLineType(this.type), init); |
|
} |
|
|
|
public setSource(source: number | GroupCallParticipantVideoSourceGroup[]) { |
|
let sourceGroups: GroupCallParticipantVideoSourceGroup[]; |
|
if(Array.isArray(source)) { |
|
if(!source[0]) return; |
|
sourceGroups = source; |
|
source = sourceGroups[0].sources[0]; |
|
} |
|
|
|
this.sourceGroups = sourceGroups; |
|
return this.source = source; |
|
} |
|
|
|
public shouldBeSkipped(isAnswer?: boolean) { |
|
return isAnswer && this.direction === 'inactive'; |
|
} |
|
} |
|
|
|
export function generateSsrc(type: WebRTCLineType, source: number | GroupCallParticipantVideoSourceGroup[], endpoint?: string): Ssrc { |
|
let sourceGroups: GroupCallParticipantVideoSourceGroup[]; |
|
if(Array.isArray(source)) { |
|
if(!source[0]) return; |
|
sourceGroups = source; |
|
source = sourceGroups[0].sources[0]; |
|
} |
|
|
|
return { |
|
endpoint, |
|
type, |
|
source, |
|
sourceGroups |
|
}; |
|
} |
|
|
|
export default class LocalConferenceDescription implements UpdateGroupCallConnectionData { |
|
public readonly sessionId: string; |
|
// public ssrcs: Ssrc[]; |
|
public readonly transport: GroupCallConnectionTransport; |
|
public readonly audio?: AudioCodec; |
|
public readonly video: VideoCodec; |
|
public readonly screencast?: VideoCodec; |
|
|
|
private maxSeenId: number; |
|
public readonly entries: ConferenceEntry[]; |
|
private entriesByMid: Map<ConferenceEntry['mid'], ConferenceEntry>; |
|
private entriesBySource: Map<ConferenceEntry['source'], ConferenceEntry>; |
|
private entriesByPeerId: Map<ConferenceEntry['peerId'], Set<ConferenceEntry>>; |
|
|
|
constructor(public connection: RTCPeerConnection) { |
|
this.sessionId = '' + Date.now(); |
|
// this.ssrcs = []; |
|
this.maxSeenId = -1; |
|
this.entries = []; |
|
this.entriesByMid = new Map(); |
|
this.entriesBySource = new Map(); |
|
this.entriesByPeerId = new Map(); |
|
} |
|
|
|
public setData(data: UpdateGroupCallConnectionData) { |
|
return safeAssign(this, data); |
|
} |
|
|
|
public createEntry(type: WebRTCLineType) { |
|
const mid = '' + ++this.maxSeenId; |
|
const entry = new ConferenceEntry(mid, type); |
|
this.entries.push(entry); |
|
this.entriesByMid.set(mid, entry); |
|
return entry; |
|
} |
|
|
|
public deleteEntry(entry: ConferenceEntry) { |
|
indexOfAndSplice(this.entries, entry); |
|
this.entriesByMid.delete(entry.mid); |
|
this.entriesBySource.delete(entry.source); |
|
|
|
const set = this.entriesByPeerId.get(entry.peerId); |
|
if(set) { |
|
set.delete(entry); |
|
if(!set.size) { |
|
this.entriesByPeerId.delete(entry.peerId); |
|
} |
|
} |
|
} |
|
|
|
public setEntrySource(entry: ConferenceEntry, source: Parameters<ConferenceEntry['setSource']>[0]) { |
|
entry.setSource(source); |
|
this.entriesBySource.set(entry.source, entry); |
|
} |
|
|
|
public setEntryPeerId(entry: ConferenceEntry, peerId: ConferenceEntry['peerId']) { |
|
entry.setPeerId(peerId); |
|
let set = this.entriesByPeerId.get(peerId); |
|
if(!set) { |
|
this.entriesByPeerId.set(peerId, set = new Set()); |
|
} |
|
|
|
set.add(entry); |
|
} |
|
|
|
public findEntry(verify: Parameters<LocalConferenceDescription['entries']['find']>[0]) { |
|
return this.entries.find(verify); |
|
} |
|
|
|
public findFreeSendRecvEntry(type: WebRTCLineType, isSending: boolean) { |
|
let entry = this.entries.find((entry) => { |
|
return entry.direction === 'sendrecv' && entry.type === type && !(isSending ? entry.sendEntry : entry.recvEntry); |
|
}); |
|
|
|
if(!entry) { |
|
entry = this.createEntry(type); |
|
entry.setDirection('sendrecv'); |
|
} |
|
|
|
return entry; |
|
} |
|
|
|
public getEntryByMid(mid: ConferenceEntry['mid']) { |
|
return this.entriesByMid.get(mid); |
|
} |
|
|
|
public getEntryBySource(source: ConferenceEntry['source']) { |
|
return this.entriesBySource.get(source); |
|
} |
|
|
|
public getEntriesByPeerId(peerId: ConferenceEntry['peerId']) { |
|
return this.entriesByPeerId.get(peerId); |
|
} |
|
|
|
public generateSdp(options: Omit<Parameters<SDPBuilder['addConference']>[0], 'conference'>) { |
|
return SDPBuilder.fromConference({ |
|
conference: this, |
|
...options |
|
}); |
|
} |
|
}
|
|
|