admin管理员组文章数量:1023519
I have written react-native application that using RTCPeerConnection
(from react-native-webrtc) that I run on my both Android phones throug USB debugging. Also I have my own local signaling server (I use a native WebSocket as transport). Everything seems written correct, but now I cannot establisch a simple connection beetween 2 peers for some reason on my phones. I noticed that peerConnection.connectionState
is always new
(should be transmitted to connected
state). I cannot figure out why.
This is code of my react-native application (minimized for convenience):
import {Button,SafeAreaView,ScrollView,StyleSheet,Text,View} from 'react-native';
import { mediaDevices,MediaStream,RTCIceCandidate, RTCPeerConnection} from 'react-native-webrtc'
import { reconnectWebSocket, webSocket } from './socket'; //webSocket is `new WebSocket`, logic for reconnecting if state is CLOSED
function App(): React.JSX.Element {
const [localStream, setLocalStream] = useState<MediaStream | null>(null);
const peerConnection = useRef<RTCPeerConnection | null>(null);
const [iceServers, setIceServers] = useState<Object[]>([]);
const [callerId, setCallerId] = useState(Math.floor(Math.random() * 10000)); //ID for caller
let calleeId = useRef<number | null>(null); //ID for callee
useEffect(() => {
console.info(`Caller ID: ${callerId}`)
const getAndSetIceServers = async(): Promise<Object[]> => {
const _iceServers = [{ url: 'stun:freestun:3478' }]
try {
//simplicated
setIceServers(_iceServers);
return Promise.resolve(IceServers);
}
catch (e: any) {
console.log(`Error while fetching TURN`);
//some fall-back
}
}
getAndSetIceServers().then(async() =>
await createPeerConnection()
);
//fired when WebSocket open
const onOpen = async () => {
try {
//send to my server 'connection' event
webSocket.send(JSON.stringify({ type: "connection", data: { callerId: callerId } }));
setCallStatus(CallStatuses.READY);
}
catch (e) {
console.error(e);
}
}
//fired when message from server
const onMessage = async (event: WebSocketMessageEvent) => {
let message = JSON.parse(event.data);
switch (message.type) {
case "candidate":
{
await handleCandidate(message);
break;
}
case "offer":
{
await handleOffer(message);
break;
}
case "answer":
{
await handleAnswer(message);
break;
}
case "icecandidate":
{
await hadleICECandidate(message);
break;
}
case "offline":
{
console.log("offline handling");
calleeId.current = null;
break;
}
}
}
//when WebSocket error
const onError = async (event: WebSocketErrorEvent) => {
console.log("WebSocket error: ", event);
setCallStatus(CallStatuses.NOT_READY);
}
//attach the listeners above to the WebSocket
webSocket.onopen = onOpen;
webSocket.onmessage = onMessage;
webSocket.onerror = onError;
const handleOffer = async (offer: any) => {
calleeId.current = offer.data.callerId;
console.log(`handleOffer calleeId: ${calleeId.current}`);
const description = offer.data.description;
await peerConnection.current.setRemoteDescription(description);
const sessionDescription = await peerConnection.current.createAnswer();
await peerConnection.current.setLocalDescription(sessionDescription);
// send answer
webSocket.send(JSON.stringify({ type: "answer", data: { callerId: callerId, calleeId: calleeId.current, description: sessionDescription } }));
}
const handleAnswer = async (answer: any) => {
calleeId.current = answer.data.callerId;
console.log(`handleAnswer calleeId: ${calleeId.current}`);
const description = answer.data.description;
await peerConnection.current.setRemoteDescription(description);
}
const handleCandidate = async (candidate: any) => {
calleeId.current = candidate.calleeId;
const options = { iceRestart: false } //can be ommitted
const offer = await peerConnection.current.createOffer(options);
await peerConnection.current.setLocalDescription(offer);
//send offer to the server
webSocket.send(JSON.stringify({ type: "offer", data: { callerId: callerId, calleeId: calleeId.current, description: peerConnection.current.localDescription } }));
}
const hadleICECandidate = async (candidate: any) => {
const iceCandidate = candidate.data.candidate as RTCIceCandidate;
console.log("icecandidate handling. Candidate:" + JSON.stringify(iceCandidate));
await peerConnection.current.addIceCandidate(candidate);
}
//reconnect webSocket but here no issues..
let reconnectTimerId = setInterval(() => { reconnectWebSocket(onOpen, onMessage, onError) }, 5000)
return () => {
webSocket.onopen = null;
webSocket.onerror = null;
webSocket.onmessage = null;
webSocket.close(1000, callerId.toString());
clearInterval(reconnectTimerId);
}
}, [])
const createPeerConnection = async () => {
console.debug(`Creating new RTCPeerConnection`);
peerConnection.current = new RTCPeerConnection({iceServers: iceServers})
peerConnection.current.addEventListener("icecandidate", iceCandidateListener);
console.debug(`RTCPeerConnection ${peerConnection.current._pcId} created`);
const _localStream = await mediaDevices.getUserMedia({ audio: true });
_localStream.getTracks().map((track) => peerConnection?.current?.addTrack(track))
setLocalStream(_localStream); //keep localStream in state just for case
}
const iceCandidateListener = (e: any) => {
if (e.candidate) {
console.log(`icecandidate event: ${JSON.stringify(e)}. to calleeId=${calleeId.current}`);
//we need to send local ICE-candidate to peer (according to ICE-trickle approach)
webSocket.send(JSON.stringify({
type: "icecandidate", data: {
calleeId: calleeId.current,
candidate: e.candidate.toJSON()
}
}))
console.log(`icecandidate sent from callerId ${callerId} to calleeId ${calleeId.current}`);
}
}
//BUTTONS
const goOnline = async () => {
console.log("goOnline called");
if (!peerConnection.current)
await createPeerConnection();
webSocket.send(JSON.stringify({ type: "online", data: { callerId: callerId } }));
}
const goOffline = async () => {
console.log("goOffline called");
webSocket.send(JSON.stringify({ type: "offline", data: { callerId: callerId, calleeId: calleeId.current } }));
calleeId.current = null;
setCallStatus(CallStatuses.READY);
}
return (
<SafeAreaView style={styles.container}>
<View style={styles.container}>
<ScrollView
contentContainerStyle={styles.container}
contentInsetAdjustmentBehavior="automatic">
<View style={styles.top}>
<Text>Caller ID: {callerId}</Text>
<Text>Callee ID: {calleeId.current}</Text>
</View>
<View style={styles.bottom}>
<Button title='ONLINE' onPress={goOnline}></Button>
<Button title='OFFLINE' onPress={goOffline}></Button>
</View>
</ScrollView>
</View>
</SafeAreaView>
);
}
export default App;
<script src=".2.0/umd/react.production.min.js"></script>
<script src=".2.0/umd/react-dom.production.min.js"></script>
I have written react-native application that using RTCPeerConnection
(from react-native-webrtc) that I run on my both Android phones throug USB debugging. Also I have my own local signaling server (I use a native WebSocket as transport). Everything seems written correct, but now I cannot establisch a simple connection beetween 2 peers for some reason on my phones. I noticed that peerConnection.connectionState
is always new
(should be transmitted to connected
state). I cannot figure out why.
This is code of my react-native application (minimized for convenience):
import {Button,SafeAreaView,ScrollView,StyleSheet,Text,View} from 'react-native';
import { mediaDevices,MediaStream,RTCIceCandidate, RTCPeerConnection} from 'react-native-webrtc'
import { reconnectWebSocket, webSocket } from './socket'; //webSocket is `new WebSocket`, logic for reconnecting if state is CLOSED
function App(): React.JSX.Element {
const [localStream, setLocalStream] = useState<MediaStream | null>(null);
const peerConnection = useRef<RTCPeerConnection | null>(null);
const [iceServers, setIceServers] = useState<Object[]>([]);
const [callerId, setCallerId] = useState(Math.floor(Math.random() * 10000)); //ID for caller
let calleeId = useRef<number | null>(null); //ID for callee
useEffect(() => {
console.info(`Caller ID: ${callerId}`)
const getAndSetIceServers = async(): Promise<Object[]> => {
const _iceServers = [{ url: 'stun:freestun:3478' }]
try {
//simplicated
setIceServers(_iceServers);
return Promise.resolve(IceServers);
}
catch (e: any) {
console.log(`Error while fetching TURN`);
//some fall-back
}
}
getAndSetIceServers().then(async() =>
await createPeerConnection()
);
//fired when WebSocket open
const onOpen = async () => {
try {
//send to my server 'connection' event
webSocket.send(JSON.stringify({ type: "connection", data: { callerId: callerId } }));
setCallStatus(CallStatuses.READY);
}
catch (e) {
console.error(e);
}
}
//fired when message from server
const onMessage = async (event: WebSocketMessageEvent) => {
let message = JSON.parse(event.data);
switch (message.type) {
case "candidate":
{
await handleCandidate(message);
break;
}
case "offer":
{
await handleOffer(message);
break;
}
case "answer":
{
await handleAnswer(message);
break;
}
case "icecandidate":
{
await hadleICECandidate(message);
break;
}
case "offline":
{
console.log("offline handling");
calleeId.current = null;
break;
}
}
}
//when WebSocket error
const onError = async (event: WebSocketErrorEvent) => {
console.log("WebSocket error: ", event);
setCallStatus(CallStatuses.NOT_READY);
}
//attach the listeners above to the WebSocket
webSocket.onopen = onOpen;
webSocket.onmessage = onMessage;
webSocket.onerror = onError;
const handleOffer = async (offer: any) => {
calleeId.current = offer.data.callerId;
console.log(`handleOffer calleeId: ${calleeId.current}`);
const description = offer.data.description;
await peerConnection.current.setRemoteDescription(description);
const sessionDescription = await peerConnection.current.createAnswer();
await peerConnection.current.setLocalDescription(sessionDescription);
// send answer
webSocket.send(JSON.stringify({ type: "answer", data: { callerId: callerId, calleeId: calleeId.current, description: sessionDescription } }));
}
const handleAnswer = async (answer: any) => {
calleeId.current = answer.data.callerId;
console.log(`handleAnswer calleeId: ${calleeId.current}`);
const description = answer.data.description;
await peerConnection.current.setRemoteDescription(description);
}
const handleCandidate = async (candidate: any) => {
calleeId.current = candidate.calleeId;
const options = { iceRestart: false } //can be ommitted
const offer = await peerConnection.current.createOffer(options);
await peerConnection.current.setLocalDescription(offer);
//send offer to the server
webSocket.send(JSON.stringify({ type: "offer", data: { callerId: callerId, calleeId: calleeId.current, description: peerConnection.current.localDescription } }));
}
const hadleICECandidate = async (candidate: any) => {
const iceCandidate = candidate.data.candidate as RTCIceCandidate;
console.log("icecandidate handling. Candidate:" + JSON.stringify(iceCandidate));
await peerConnection.current.addIceCandidate(candidate);
}
//reconnect webSocket but here no issues..
let reconnectTimerId = setInterval(() => { reconnectWebSocket(onOpen, onMessage, onError) }, 5000)
return () => {
webSocket.onopen = null;
webSocket.onerror = null;
webSocket.onmessage = null;
webSocket.close(1000, callerId.toString());
clearInterval(reconnectTimerId);
}
}, [])
const createPeerConnection = async () => {
console.debug(`Creating new RTCPeerConnection`);
peerConnection.current = new RTCPeerConnection({iceServers: iceServers})
peerConnection.current.addEventListener("icecandidate", iceCandidateListener);
console.debug(`RTCPeerConnection ${peerConnection.current._pcId} created`);
const _localStream = await mediaDevices.getUserMedia({ audio: true });
_localStream.getTracks().map((track) => peerConnection?.current?.addTrack(track))
setLocalStream(_localStream); //keep localStream in state just for case
}
const iceCandidateListener = (e: any) => {
if (e.candidate) {
console.log(`icecandidate event: ${JSON.stringify(e)}. to calleeId=${calleeId.current}`);
//we need to send local ICE-candidate to peer (according to ICE-trickle approach)
webSocket.send(JSON.stringify({
type: "icecandidate", data: {
calleeId: calleeId.current,
candidate: e.candidate.toJSON()
}
}))
console.log(`icecandidate sent from callerId ${callerId} to calleeId ${calleeId.current}`);
}
}
//BUTTONS
const goOnline = async () => {
console.log("goOnline called");
if (!peerConnection.current)
await createPeerConnection();
webSocket.send(JSON.stringify({ type: "online", data: { callerId: callerId } }));
}
const goOffline = async () => {
console.log("goOffline called");
webSocket.send(JSON.stringify({ type: "offline", data: { callerId: callerId, calleeId: calleeId.current } }));
calleeId.current = null;
setCallStatus(CallStatuses.READY);
}
return (
<SafeAreaView style={styles.container}>
<View style={styles.container}>
<ScrollView
contentContainerStyle={styles.container}
contentInsetAdjustmentBehavior="automatic">
<View style={styles.top}>
<Text>Caller ID: {callerId}</Text>
<Text>Callee ID: {calleeId.current}</Text>
</View>
<View style={styles.bottom}>
<Button title='ONLINE' onPress={goOnline}></Button>
<Button title='OFFLINE' onPress={goOffline}></Button>
</View>
</ScrollView>
</View>
</SafeAreaView>
);
}
export default App;
<script src=".2.0/umd/react.production.min.js"></script>
<script src=".2.0/umd/react-dom.production.min.js"></script>
本文标签: react nativeRTCPeerConnectionconnectionState does not change to connected stateStack Overflow
版权声明:本文标题:react native - RTCPeerConnection.connectionState does not change to connected state - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745591616a2157922.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论