Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React from 'react';
- import { Text, TouchableOpacity, Clipboard } from 'react-native';
- import { View, SafeAreaView, Button, StyleSheet } from 'react-native';
- import { RTCSessionDescription, RTCPeerConnection, RTCView, mediaDevices } from 'react-native-webrtc';
- export default function App() {
- // Aarenet: variables for Aareswitch
- let peerConnection;
- let remoteAnswer
- let sdpVariable
- let cid;
- let rtcConfig = {};
- let sdpSent = false;
- let ws = new WebSocket("wss://siptest.aarenet.com:8449/anrtcp");
- // Aarenet: WebSocket
- ws.onopen = function (event) {
- console.log("[open] Connection established");
- console.log("Sending to server");
- var config = {
- type: "register",
- userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36",
- locationParam: { "notifications": true, "audio": true, "video": true },
- locationHref: "https://siptest.aarenet.com:8449/webphone.jsp",
- isRtcUser: false,
- username: "aan1_cfs_demo_39",
- password: "Wph4cf20"
- };
- var message = JSON.stringify(config);
- if (ws.readyState === 1) {
- console.log('wsSend: ' + message);
- ws.send(message);
- } else {
- console.log('failed to send message. ws state: ' + ws.readyState);
- }
- };
- ws.onmessage = function (event) {
- let message = JSON.parse(event.data);
- if (message.type !== 'keepalive')
- console.log(`[message] Data received from server: ${event.data}`);
- if (message.type == "welcome") {
- rtcConfig = message.config.rtcConfig;
- }
- if (message.type == "answer") {
- var answer = message;
- if (answer.sdp.includes("m=video 0")) {
- var index = answer.sdp.indexOf("m=video 0");
- var s1 = answer.sdp.substring(0, index);
- var s2 = answer.sdp.substring(index);
- s2 = s2.replace(/(a=recvonly|a=sendonly)/, "a=inactive");
- answer.sdp = s1 + s2;
- }
- try {
- remoteAnswer = new RTCSessionDescription(answer);
- } catch (error) {
- console.error(error);
- }
- peerConnection.setRemoteDescription(remoteAnswer).then(
- peerConnection.createAnswer().then(e => {
- peerConnection.setLocalDescription(e).then(() => {
- sdpVariable = peerConnection.localDescription.sdp;
- window.setTimeout(() => {
- console.log('window.setTimeout');
- let config =
- {
- "type": "answer",
- "cid": "s123345",
- "destination": "00041766524456",
- "sdp": sdpVariable
- };
- var message = JSON.stringify(config);
- if (ws.readyState === 1) {
- console.log('wsSend: ' + message);
- // Aarenet: making sure the offer is only sent once.
- if (sdpSent === false) {
- console.log(message);
- ws.send(message);
- // Aarenet: setting sdpSent to true so we don't send multiple calls to the Web Socket, we send this from here because
- // this is where we get all the ice candidates but we don't want to send an offer after every ice candidate that is registered and
- // we make sure all of them are registered before calling by waiting 2 seconds.
- sdpSent = true;
- // Aarenet: copying the sdp to the clipboard to analise better from the PC
- Clipboard.setString(sdpVariable);
- console.log(sdpVariable);
- }
- } else {
- console.log('failed to send message. ws state: ' + ws.readyState);
- }
- }, 2000);
- }).catch((error) => {
- console.log(error);
- });
- }).catch((error) => {
- console.log(error);
- })
- ).catch((error) => {
- console.log(error);
- });
- }
- };
- ws.onclose = function (event) {
- if (event.wasClean) {
- console.log(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
- } else {
- // e.g. server process killed or network down
- // event.code is usually 1006 in this case
- console.log('[close] Connection died');
- }
- };
- ws.onerror = function (error) {
- console.log(`[error] ${error.message}`);
- };
- // Aarenet: code from demo app
- const [localStream, setLocalStream] = React.useState();
- const [remoteStream, setRemoteStream] = React.useState();
- const [cachedLocalPC, setCachedLocalPC] = React.useState();
- const [cachedRemotePC, setCachedRemotePC] = React.useState();
- const [isMuted, setIsMuted] = React.useState(false);
- const startLocalStream = async () => {
- console.log('testing startLocalStream')
- // isFront will determine if the initial camera should face user or environment
- const isFront = true;
- const devices = await mediaDevices.enumerateDevices();
- const facing = isFront ? 'front' : 'environment';
- const videoSourceId = devices.find(device => device.kind === 'videoinput' && device.facing === facing);
- const facingMode = isFront ? 'user' : 'environment';
- // Aarenet: changed the video to false, since we are testing audio with Aareswitch.
- const constraints = {
- audio: true,
- video: false, /* {
- mandatory: {
- minWidth: 500, // Provide your own width, height and frame rate here
- minHeight: 300,
- minFrameRate: 30,
- },
- facingMode,
- optional: videoSourceId ? [{ sourceId: videoSourceId }] : [],
- }, */
- };
- const newStream = await mediaDevices.getUserMedia(constraints);
- setLocalStream(newStream);
- };
- // Aarenet: here is what happens when you press on the call button - a RTCPeerConnection is created.
- const callAareswitch = async () => {
- console.log('callAareswitch');
- // Aarenet: rtcConfig is set from a message with type welcome coming in to the Web Socket ws.onmessage method
- peerConnection = new RTCPeerConnection(rtcConfig, { optional: [{ DtlsSrtpKeyAgreement: true }] });
- // Aarenet: probably not necessary to have this in a try catch block, but why not.
- try {
- peerConnection.addStream(localStream);
- } catch (error) {
- console.error(error);
- }
- // Aarenet: this creates the sdp and when it is ready we set it to the sdpVariable.
- peerConnection.createOffer().then(sdp => peerConnection.setLocalDescription(sdp)).then(() => {
- // just to get the onicecandidates to start
- }).catch((error) => {
- console.log(error);
- });
- // Aarenet: added a timeout so we do not miss the ice candidates coming in
- let count = 0;
- peerConnection.onicecandidate = e => {
- Clipboard.setString(JSON.stringify(e.candidate));
- console.log(JSON.stringify(e.candidate))
- console.log('onicecandidate');
- count++;
- window.setTimeout(() => {
- console.log('window.setTimeout');
- peerConnection.createOffer().then(sdp => peerConnection.setLocalDescription(sdp)).then(() => {
- sdpVariable = peerConnection.localDescription.sdp;
- let config =
- {
- "type": "offer",
- "cid": "s123345",
- "destination": "00041766524456",
- "sdp": sdpVariable
- };
- var message = JSON.stringify(config);
- if (ws.readyState === 1) {
- console.log('wsSend: ' + message);
- // Aarenet: making sure the offer is only sent once.
- if (sdpSent === false) {
- ws.send(message);
- // Aarenet: setting sdpSent to true so we don't send multiple calls to the Web Socket, we send this from here because
- // this is where we get all the ice candidates but we don't want to send an offer after every ice candidate that is registered and
- // we make sure all of them are registered before calling by waiting 1 second.
- sdpSent = true;
- // Aarenet: copying the sdp to the clipboard to analyze better from the PC
- Clipboard.setString(sdpVariable);
- console.log(sdpVariable);
- console.log(count);
- }
- } else {
- console.log('failed to send message. ws state: ' + ws.readyState);
- }
- }).catch((error) => {
- console.log(error);
- });
- }, 1000);
- };
- /* // Aarenet: not sure what this does but it was in the demo app in the call section so it might be necessary.
- setCachedLocalPC(peerConnection);
- */
- peerConnection.onaddstream = e => { console.log(e.message) };
- peerConnection.onremovestream = e => { console.log(e.message) };
- peerConnection.onnegotiationneeded = e => {
- /* peerConnection.createOffer().then(sdp => peerConnection.setLocalDescription(sdp)).then(() => {
- console.log(peerConnection.localDescription.sdp);
- let config =
- {
- "type": "offer",
- "cid": "s123345",
- "destination": "00041766524456",
- "sdp": peerConnection.localDescription.sdp
- };
- var message = JSON.stringify(config);
- ws.send(message);
- }).catch((error) => {
- console.log(error);
- }); */
- // console.log(e.constructor.name); // RTCEvent
- };
- /*peerConnection.onconnectionstatechange = e => { console.log(e.message) };
- peerConnection.oniceconnectionstatechange = e => { console.log(e.message) };
- peerConnection.onicegatheringstatechange = e => { console.log(e.message) };
- peerConnection.onsignalingstatechange = e => { console.log(e.message) };
- peerConnection.ontrack = e => { console.log(e.message) }; */
- }
- const startCall = async () => {
- console.log('testing startCall')
- // You'll most likely need to use a STUN server at least. Look into TURN and decide if that's necessary for your project
- const configuration = { iceServers: [{ url: 'stun:stun.l.google.com:19302' }] };
- const localPC = new RTCPeerConnection(configuration);
- const remotePC = new RTCPeerConnection(configuration);
- // could also use "addEventListener" for these callbacks, but you'd need to handle removing them as well
- localPC.onicecandidate = e => {
- try {
- console.log('localPC icecandidate:', e.candidate);
- if (e.candidate) {
- remotePC.addIceCandidate(e.candidate);
- }
- } catch (err) {
- console.error(`Error adding remotePC iceCandidate: ${err}`);
- }
- };
- remotePC.onicecandidate = e => {
- try {
- console.log('remotePC icecandidate:', e.candidate);
- if (e.candidate) {
- localPC.addIceCandidate(e.candidate);
- }
- } catch (err) {
- console.error(`Error adding localPC iceCandidate: ${err}`);
- }
- };
- remotePC.onaddstream = e => {
- console.log('remotePC tracking with ', e);
- if (e.stream && remoteStream !== e.stream) {
- console.log('RemotePC received the stream', e.stream);
- setRemoteStream(e.stream);
- }
- };
- // AddTrack not supported yet, so have to use old school addStream instead
- // newStream.getTracks().forEach(track => localPC.addTrack(track, newStream));
- localPC.addStream(localStream);
- try {
- const offer = await localPC.createOffer();
- console.log('Offer from localPC, setLocalDescription');
- await localPC.setLocalDescription(offer);
- console.log('remotePC, setRemoteDescription');
- console.log(localPC.localDescription.sdp)
- Clipboard.setString(localPC.localDescription.sdp);
- await remotePC.setRemoteDescription(localPC.localDescription);
- console.log('RemotePC, createAnswer');
- const answer = await remotePC.createAnswer();
- console.log(`Answer from remotePC: ${answer.sdp}`);
- console.log('remotePC, setLocalDescription');
- await remotePC.setLocalDescription(answer);
- console.log('localPC, setRemoteDescription');
- await localPC.setRemoteDescription(remotePC.localDescription);
- } catch (err) {
- console.error(err);
- }
- setCachedLocalPC(localPC);
- setCachedRemotePC(remotePC);
- };
- const switchCamera = () => {
- localStream.getVideoTracks().forEach(track => track._switchCamera());
- };
- // Mutes the local's outgoing audio
- const toggleMute = () => {
- if (!remoteStream) return;
- localStream.getAudioTracks().forEach(track => {
- console.log(track.enabled ? 'muting' : 'unmuting', ' local track', track);
- track.enabled = !track.enabled;
- setIsMuted(!track.enabled);
- });
- };
- const closeStreams = () => {
- if (cachedLocalPC) {
- cachedLocalPC.removeStream(localStream);
- cachedLocalPC.close();
- }
- if (cachedRemotePC) {
- cachedRemotePC.removeStream(remoteStream);
- cachedRemotePC.close();
- }
- setLocalStream();
- setRemoteStream();
- setCachedRemotePC();
- setCachedLocalPC();
- };
- // Aarenet: added this line '<Button title="Call" onPress={callAareswitch} />' so that we have a button we can call from
- // it calls the callAareswitch funtion every time you press it.
- return (
- <SafeAreaView style={styles.container}>
- <Button title="Call" onPress={callAareswitch} />
- {!localStream && <Button title="Click to start stream" onPress={startLocalStream} />}
- {localStream && <Button title="Click to start call" onPress={startCall} disabled={!!remoteStream} />}
- {(
- <View style={styles.toggleButtons}>
- <Button title="Switch camera" onPress={switchCamera} />
- <Button title={`${isMuted ? 'Unmute' : 'Mute'} stream`} onPress={toggleMute} disabled={!remoteStream} />
- </View>
- )}
- <View style={styles.rtcview}>
- {localStream && <RTCView style={styles.rtc} streamURL={localStream.toURL()} />}
- </View>
- <View style={styles.rtcview}>
- {remoteStream && <RTCView style={styles.rtc} streamURL={remoteStream.toURL()} />}
- </View>
- <Button title="Click to stop call" onPress={closeStreams} disabled={!remoteStream} />
- </SafeAreaView>
- );
- }
- const styles = StyleSheet.create({
- container: {
- backgroundColor: '#313131',
- justifyContent: 'space-between',
- alignItems: 'center',
- height: '100%',
- },
- text: {
- fontSize: 30,
- },
- rtcview: {
- justifyContent: 'center',
- alignItems: 'center',
- height: '40%',
- width: '80%',
- backgroundColor: 'black',
- },
- rtc: {
- width: '80%',
- height: '100%',
- },
- toggleButtons: {
- width: '100%',
- flexDirection: 'row',
- justifyContent: 'space-around',
- },
- });
Advertisement
Add Comment
Please, Sign In to add comment