diff --git a/app/mobile/src/context/REFACTORFAIL b/app/mobile/src/context/REFACTORFAIL deleted file mode 100644 index 785be5de..00000000 --- a/app/mobile/src/context/REFACTORFAIL +++ /dev/null @@ -1,469 +0,0 @@ -import { useEffect, useContext, useState, useRef } from 'react'; -import { Alert } from 'react-native'; -import { createWebsocket } from 'api/fetchUtil'; -import { addContactRing } from 'api/addContactRing'; -import { addCall } from 'api/addCall'; -import { keepCall } from 'api/keepCall'; -import { removeCall } from 'api/removeCall'; -import { removeContactCall } from 'api/removeContactCall'; - -import { - ScreenCapturePickerView, - RTCPeerConnection, - RTCIceCandidate, - RTCSessionDescription, - RTCView, - MediaStream, - MediaStreamTrack, - mediaDevices, - registerGlobals -} from 'react-native-webrtc'; - -export function useRingContext() { - const [state, setState] = useState({ - ringing: new Map(), - callStatus: null, - cardId: null, - localStream: null, - localVideo: false, - localAudio: false, - remoteStream: null, - removeVideo: false, - removeAudio: false, - }); - const access = useRef(null); - - const EXPIRE = 3000 - const RING = 2000 - const ringing = useRef(new Map()); - const calling = useRef(null); - const ws = useRef(null); - const pc = useRef(null); - const stream = useRef(null); - const accessVideo = useRef(false); - const accessAudio = useRef(false); - const videoTrack = useRef(); - const audioTrack = useRef(); - const candidates = useRef([]); - const offers = useRef([]); - const processing = useRef(false); - const connected = useRef(false); - - const iceServers = [ - { - urls: 'stun:35.165.123.117:5001?transport=udp', - username: 'user', - credential: 'pass' - }, - { - urls: 'turn:35.165.123.117:5001?transport=udp', - username: 'user', - credential: 'pass' - } - ]; - - const constraints = { - mandatory: { - OfferToReceiveAudio: true, - OfferToReceiveVideo: true, - VoiceActivityDetection: true - } - }; - - const updateState = (value) => { - setState((s) => ({ ...s, ...value })) - } - - const polite = async () => { - if (processing.current || !connected.current) { - return; - } - - processing.current = true; - - while (offers.current.length > 0) { - descriptions = offers.current; - offers.current = []; - - try { - for (let i = 0; i < descriptions.length; i++) { - const description = descriptions[i]; - stream.current = null; - - if (description == null) { - const offer = await pc.current.createOffer(constraints); - await pc.current.setLocalDescription(offer); - ws.current.send(JSON.stringify({ description: offer })); - } - else { - if (description.type === 'offer' && pc.current.signalingState !== 'stable') { - const rollback = new RTCSessionDescription({ type: "rollback" }); - await pc.current.setLocalDescription(rollback); - } - const offer = new RTCSessionDescription(description); - await pc.current.setRemoteDescription(offer); - if (description.type === 'offer') { - const answer = await pc.current.createAnswer(); - await pc.current.setLocalDescription(answer); - ws.current.send(JSON.stringify({ description: answer })); - } - } - } - } - catch (err) { - Alert.alert('webrtc error', err.toString()); - } - } - - processing.current = false; - } - - const impolite = async () => { - if (processing.current || !connected.current) { - return; - } - - processing.current = true; - while (offers.current.length > 0) { - descriptions = offers.current; - offers.current = []; - - for (let i = 0; i < descriptions.length; i++) { - const description = descriptions[i]; - stream.current = null; - - try { - if (description == null) { - const offer = await pc.current.createOffer(constraints); - await pc.current.setLocalDescription(offer); - ws.current.send(JSON.stringify({ description: offer })); - } - else { - if (description.type === 'offer' && pc.current.signalingState !== 'stable') { - continue; - } - if (description.type === 'answer' && pc.current.signalingState === 'stable') { - const offer = await pc.current.createOffer(constraints); - await pc.current.setLocalDescription(offer); - ws.current.send(JSON.stringify({ description: offer })); - continue; - } - - const offer = new RTCSessionDescription(description); - await pc.current.setRemoteDescription(offer); - - if (description.type === 'offer') { - const answer = await pc.current.createAnswer(); - await pc.current.setLocalDescription(answer); - ws.current.send(JSON.stringify({ description: answer })); - } - } - } - catch (err) { - Alert.alert('webrtc error', err.toString()); - } - } - } - processing.current = false; - } - - const connect = async (politePolicy, node, token, clearRing, clearAlive) => { - - // connect signal socket - candidates.current = []; - connected.current = false; - updateState({ remoteVideo: false, remoteAudio: false, remoteStream: null, localVideo: false, localAudio: false, localStream: null }); - - pc.current = new RTCPeerConnection({ iceServers }); - pc.current.addEventListener( 'connectionstatechange', event => { - console.log("CONNECTION STATE", event); - } ); - pc.current.addEventListener( 'icecandidate', event => { - ws.current.send(JSON.stringify({ candidate: event.candidate })); - } ); - pc.current.addEventListener( 'icecandidateerror', event => { - console.log("ICE ERROR"); - } ); - pc.current.addEventListener( 'iceconnectionstatechange', event => { - console.log("ICE STATE CHANGE", event); - } ); - pc.current.addEventListener( 'negotiationneeded', async (ev) => { - offers.current.push(null); - if (politePolicy) { - policy(); - } - else { - impolite(); - } - } ); - pc.current.addEventListener( 'signalingstatechange', event => { - console.log("ICE SIGNALING", event); - } ); - pc.current.addEventListener( 'track', event => { - if (stream.current == null) { - stream.current = new MediaStream(); - updateState({ remoteStream: stream.current }); - } - if (event.track.kind === 'audio') { - updateState({ remoteAudio: true }); - } - if (event.track.kind === 'video') { - updateState({ remoteVideo: true }); - } - stream.current.addTrack(event.track, stream.current); - } ); - - videoTrack.current = false; - audioTrack.current = false; - accessVideo.current = false; - accessAudio.current = false; - try { - const stream = await mediaDevices.getUserMedia({ - video: false, - audio: true, - }); - accessAudio.current = true; - updateState({ localAudio: true }); - for (const track of stream.getTracks()) { - if (track.kind === 'audio') { - audioTrack.current = track; - } - pc.current.addTrack(track); - } - } - catch (err) { - console.log(err); - } - - ws.current = createWebsocket(`wss://${node}/signal`); - ws.current.onmessage = async (ev) => { - // handle messages [impolite] - try { - const signal = JSON.parse(ev.data); - if (signal.status === 'connected') { - clearRing(); - updateState({ callStatus: "connected" }); - if (!politePolicy) { - connected.current = true; - impolite(); - } - } - else if (signal.status === 'closed') { - ws.current.close(); - } - else if (signal.description) { - offers.current.push(signal.description); - impolite(); - } - else if (signal.candidate) { - if (pc.current.remoteDescription == null) { - return; - } - const candidate = new RTCIceCandidate(signal.candidate); - await pc.current.addIceCandidate(candidate); - } - } - catch (err) { - console.log(err); - } - } - ws.current.onclose = (e) => { - // update state to disconnected - pc.current.close(); - clearRing(); - clearAlive(); - calling.current = null; - if (videoTrack.current) { - videoTrack.current.stop(); - videoTrack.current = null; - } - if (audioTrack.current) { - audioTrack.current.stop(); - audioTrack.current = null; - } - updateState({ callStatus: null }); - } - ws.current.onopen = async () => { - ws.current.send(JSON.stringify({ AppToken: token })); - if (politePolicy) { - connected.current = true; - polite(); - } - } - ws.current.error = (e) => { - console.log(e) - ws.current.close(); - } - } - - const actions = { - setSession: (token) => { - - if (access.current) { - throw new Error("invalid ring state"); - } - access.current = token; - ringing.current = new Map(); - calling.current = null; - updateState({ callStatus: null, ringing: ringing.current }); - }, - clearSession: () => { - access.current = null; - }, - ring: (cardId, callId, calleeToken) => { - const key = `${cardId}:${callId}` - const call = ringing.current.get(key) || { cardId, calleeToken, callId } - call.expires = Date.now() + EXPIRE; - ringing.current.set(key, call); - updateState({ ringing: ringing.current }); - setTimeout(() => { - updateState({ ringing: ringing.current }); - }, EXPIRE); - }, - ignore: async (cardId, callId) => { - const key = `${cardId}:${callId}` - const call = ringing.current.get(key); - if (call) { - call.status = 'ignored' - ringing.current.set(key, call); - updateState({ ringing: ringing.current }); - } - }, - decline: async (cardId, contactNode, contactToken, callId) => { - const key = `${cardId}:${callId}` - const call = ringing.current.get(key); - if (call) { - call.status = 'declined' - ringing.current.set(key, call); - updateState({ ringing: ringing.current }); - try { - await removeContactCall(contactNode, contactToken, callId); - } - catch (err) { - console.log(err); - } - } - }, - accept: async (cardId, callId, contactNode, contactToken, calleeToken) => { - if (calling.current) { - throw new Error("active session"); - } - - const key = `${cardId}:${callId}` - const call = ringing.current.get(key); - if (call) { - call.status = 'accepted' - ringing.current.set(key, call); - updateState({ ringing: ringing.current, callStatus: "connecting", cardId }); - - calling.current = { callId, contactNode, contactToken, host: false }; - await connect(impolite, contactNode, calleeToken, () => {}, () => {}); - } - }, - end: async () => { - if (!calling.current) { - throw new Error('inactive session'); - } - try { - const { host, callId, contactNode, contactToken } = calling.current; - if (host) { - const { server, token } = access.current; - await removeCall(server, token, callId); - } - else { - await removeContactCall(contactNode, contactToken, callId); - } - } - catch (err) { - console.log(err); - } - ws.current.close(); - }, - call: async (cardId, contactNode, contactToken) => { - if (calling.current) { - throw new Error("active session"); - } - - // create call - const { server, token } = access.current; - const call = await addCall(server, token, cardId); - const { id, keepAlive, callerToken, calleeToken } = call; - try { - await addContactRing(contactNode, contactToken, { index, callId: id, calleeToken }); - } - catch (err) { - console.log(err); - } - const aliveInterval = setInterval(async () => { - try { - await keepCall(server, token, id); - } - catch (err) { - console.log(err); - } - }, keepAlive * 1000); - let index = 0; - const ringInterval = setInterval(async () => { - try { - await addContactRing(contactNode, contactToken, { index, callId: id, calleeToken }); - index += 1; - } - catch (err) { - console.log(err); - } - }, RING); - - updateState({ callStatus: "ringing", cardId }); - calling.current = { callId: id, host: true }; - await connect(polite, server, callerToken, () => clearInterval(ringInterval), () => clearInterval(aliveInterval)); - }, - enableVideo: async () => { - if (!accessVideo.current) { - const stream = await mediaDevices.getUserMedia({ - audio: true, - video: { - frameRate: 30, - facingMode: 'user' - } - }); - accessVideo.current = true; - accessAudio.current = true; - updateState({ localStream: stream }); - for (const track of stream.getTracks()) { - if (track.kind === 'audio') { - audioTrack.current = track; - } - if (track.kind === 'video') { - videoTrack.current = track; - } - pc.current.addTrack(track); - } - } - else { - videoTrack.current.enabled = true; - } - updateState({ localVideo: true, localAudio: true }); - }, - disableVideo: async () => { - if (videoTrack.current) { - videoTrack.current.enabled = false; - } - updateState({ localVideo: false }); - }, - enableAudio: async () => { - if (accessAudio.current) { - audioTrack.current.enabled = true; - updateState({ localAudio: true }); - } - }, - disableAudio: async () => { - if (accessAudio.current) { - audioTrack.current.enabled = false; - updateState({ localAudio: false }); - } - }, - } - - return { state, actions } -} - diff --git a/net/web/src/context/useRingContext.hook.js b/net/web/src/context/useRingContext.hook.js index d6b4043b..f2253b12 100644 --- a/net/web/src/context/useRingContext.hook.js +++ b/net/web/src/context/useRingContext.hook.js @@ -74,14 +74,11 @@ export function useRingContext() { stream.current = null; if (description == null) { -console.log("SENDING ENW POLITE OFFER"); const offer = await pc.current.createOffer(); await pc.current.setLocalDescription(offer); ws.current.send(JSON.stringify({ description: pc.current.localDescription })); } else { - -console.log("polite: ", description); if (description.type === 'offer' && pc.current.signalingState !== 'stable') { await pc.current.setLocalDescription({ type: "rollback" }); } @@ -142,7 +139,6 @@ console.log("polite: ", description); candidates.current = []; for (let i = 0; i < servers.length; i++) { const server = servers[i]; -console.log("MY ICE2:", server); ws.current.send(JSON.stringify(server)); } } @@ -156,12 +152,7 @@ console.log("MY ICE2:", server); processing.current = false; } - const connect = async (policy, node, token, clearRing, clearAlive) => { - - // connect signal socket - connected.current = false; - candidates.current = []; - updateState({ remoteVideo: false, remoteAudio: false, remoteStream: null, localVideo: false, localAudio: false, localStream: null }); + const transmit = async (policy) => { pc.current = new RTCPeerConnection({ iceServers }); pc.current.ontrack = (ev) => { @@ -178,13 +169,7 @@ console.log("MY ICE2:", server); stream.current.addTrack(ev.track); }; pc.current.onicecandidate = ({candidate}) => { - if (pc.current.remoteDescription == null) { - candidates.current.push({ candidate }); - } - else { -console.log("MY ICE", candidate); - ws.current.send(JSON.stringify({ candidate })); - } + ws.current.send(JSON.stringify({ candidate })); }; pc.current.onnegotiationneeded = async () => { offers.current.push(null); @@ -196,10 +181,6 @@ console.log("MY ICE", candidate); } }; - videoTrack.current = false; - audioTrack.current = false; - accessVideo.current = false; - accessAudio.current = false; try { const stream = await navigator.mediaDevices.getUserMedia({ video: false, @@ -217,6 +198,19 @@ console.log("MY ICE", candidate); catch (err) { console.log(err); } + } + + const connect = async (policy, node, token, clearRing, clearAlive) => { + + // connect signal socket + connected.current = false; + candidates.current = []; + updateState({ remoteVideo: false, remoteAudio: false, remoteStream: null, localVideo: false, localAudio: false, localStream: null }); + + videoTrack.current = false; + audioTrack.current = false; + accessVideo.current = false; + accessAudio.current = false; const protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://'; ws.current = createWebsocket(`${protocol}${node}/signal`); @@ -229,7 +223,8 @@ console.log("MY ICE", candidate); updateState({ callStatus: "connected" }); if (policy === 'polite') { connected.current = true; - polite(); + await polite(); + await transmit('polite'); } } else if (signal.status === 'closed') { @@ -245,13 +240,8 @@ console.log("MY ICE", candidate); } } else if (signal.candidate) { - //if (pc.current.remoteDescription == null) { - // return; - // } const candidate = new RTCIceCandidate(signal.candidate); -console.log("THEIR ICE:", candidate); await pc.current.addIceCandidate(candidate); - } } catch (err) { @@ -278,7 +268,8 @@ console.log("THEIR ICE:", candidate); ws.current.send(JSON.stringify({ AppToken: token })); if (policy === 'impolite') { connected.current = true; - impolite(); + await impolite(); + await transmit('impolite'); } } ws.current.error = (e) => {