I try to implement webrtc in python but I can not contact StunServer and I dont understand why and how to do. Here my code ( not really big ) :
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QListWidget, QListWidgetItem
from PyQt5.QtCore import pyqtSignal
import socketio
from aiortc import RTCPeerConnection, RTCConfiguration, RTCIceServer
import requests
import logging
class MainWindow(QWidget):
ice_candidate_signal = pyqtSignal(dict)
def __init__(self):
super().__init__()
logging.basicConfig(level=logging.DEBUG)
self.init_ui()
self.sio = socketio.Client()
self.sio.connect('http://localhost:5000')
self.sio.on('ice-candidate', self.emit_ice_candidate_signal)
# self.pc = RTCPeerConnection(RTCConfiguration(iceServers=[RTCIceServer(urls=["stun:bn-turn1.xirsys.com", "turn:bn-turn1.xirsys.com:80?transport=udp", "turn:bn-turn1.xirsys.com:3478?transport=udp", "turn:bn-turn1.xirsys.com:80?transport=tcp", "turn:bn-turn1.xirsys.com:3478?transport=tcp", "turns:bn-turn1.xirsys.com:443?transport=tcp", "turns:bn-turn1.xirsys.com:5349?transport=tcp" ], credential="0kYXFmQL9xojOrUy4VFemlTnNPVFZpp7jfPjpB3AjxahuRe4QWrCs6Ll1vDc7TTjAAAAAGAG2whXZWJUdXRzUGx1cw==", username="285ff060-5a58-11eb-b269-0242ac140004")]))
configuration = RTCConfiguration(iceServers=[RTCIceServer(urls=["stun:stun.l.google.com:19302"])])
self.pc = RTCPeerConnection(configuration)
self.pc.on('icecandidate', self.on_ice_candidate)
self.pc.on('connectionstatechange', self.on_connection_state_change)
self.data_channel = self.pc.createDataChannel("dataChannel")
print(self.data_channel.readyState)
self.generated_candidate = None
self.start_offer_generation()
self.candidate_buttons = {}
#self.sio.on('sdp-answer', lambda data: self.show_call_popup())
#self.generate_fake_ice_candidate()
self.load_existing_ice_candidates()
def start_offer_generation(self):
import asyncio
loop = asyncio.get_event_loop()
loop.run_until_complete(self.create_offer())
def on_connection_state_change(self):
print(f'Connection state changed: {self.pc.connectionState}')
def on_ice_candidate(self, candidate):
print("on_ice_candidate")
if candidate and not self.generated_candidate:
self.generated_candidate = candidate
print(candidate)
candidate_dict = {
'candidate': candidate.candidate,
'sdpMid': candidate.sdpMid,
'sdpMLineIndex': candidate.sdpMLineIndex
}
print(candidate_dict)
# send Ice candidate to server
self.sio.emit('ice-candidate', candidate_dict)
# add Ice candidate to btn List
self.handle_ice_candidate(candidate_dict)
elif not candidate:
print("All ICE candidates have been generated")
def init_ui(self):
self.setWindowTitle('Communicationwith signal server')
self.setGeometry(100, 100, 400, 300)
self.layout = QVBoxLayout()
self.list_widget = QListWidget()
self.layout.addWidget(self.list_widget)
self.setLayout(self.layout)
self.ice_candidate_signal.connect(self.handle_ice_candidate)
def emit_ice_candidate_signal(self, data):
print("emit_ice_candidate_signal")
self.ice_candidate_signal.emit(data)
def load_existing_ice_candidates(self):
response = requests.get('http://localhost:3000/get-ice-candidates')
if response.status_code == 200:
existing_candidates = response.json()
for candidate_data in existing_candidates:
self.handle_ice_candidate(candidate_data)
else:
print(f'Failed to load existing ICE candidates: {response.status_code}')
def handle_ice_candidate(self, data):
print("handle_ice_candidate")
candidate_button = QPushButton(f'Candidat {len(self.candidate_buttons) + 1}')
candidate_button.clicked.connect(lambda: self.create_offer(data))
list_item = QListWidgetItem()
self.list_widget.addItem(list_item)
self.list_widget.setItemWidget(list_item, candidate_button)
self.candidate_buttons[candidate_button] = data
async def create_offer(self):
print("Creating offer...")
offer = await self.pc.createOffer()
await self.pc.setLocalDescription(offer)
self.sio.emit('sdp-offer', {'sdp': offer.sdp, 'type': offer.type})
print("Offer created")
def generate_fake_ice_candidate(self):
fake_candidate = {
'candidate': 'candidate:8421630491 1 udp 1686052607 1.2.3.4 46154 typ srflx raddr 10.0.0.17 rport 46154 generation 0',
'sdpMid': 'audio',
'sdpMLineIndex': 0
}
self.sio.emit('ice-candidate', fake_candidate)
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
the log are here :
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:5000
DEBUG:urllib3.connectionpool:http://localhost:5000 "GET /socket.io/?transport=polling&EIO=4&t=1698214121.4026575 HTTP/1.1" 200 118
DEBUG:asyncio:Using proactor: IocpProactor
connecting
Creating offer...
DEBUG:aiortc.rtcpeerconnection:RTCPeerConnection() setLocalDescription(offer)
v=0
o=- 3907202921 3907202921 IN IP4 0.0.0.0
s=-
t=0 0
a=group:BUNDLE 0
a=msid-semantic:WMS *
m=application 9 DTLS/SCTP 5000
c=IN IP4 0.0.0.0
a=mid:0
a=sctpmap:5000 webrtc-datachannel 65535
a=max-message-size:65536
a=ice-ufrag:IlMN
a=ice-pwd:ZS54A6477WIAoFnHt8XCEP
a=fingerprint:sha-256 98:5A:74:2B:D5:AE:25:54:22:D2:8B:A3:3F:E9:1F:38:B1:D9:44:AA:09:1F:5C:26:2B:3D:A5:35:54:41:87:42
a=setup:actpass
DEBUG:aiortc.rtcpeerconnection:RTCPeerConnection() iceGatheringState new -> gathering
DEBUG:aioice.ice:Connection(0) protocol(0) connection_made(<_ProactorDatagramTransport fd=1200>)
INFO:aioice.ice:Connection(0) Could not bind to 169.254.141.142 - [WinError 10049] The requested address is not valid in its context
INFO:aioice.ice:Connection(0) Could not bind to 169.254.18.182 - [WinError 10049] The requested address is not valid in its context
DEBUG:aioice.ice:Connection(0) protocol(1) connection_made(<_ProactorDatagramTransport fd=1196>)
DEBUG:aioice.ice:Connection(0) protocol(2) connection_made(<_ProactorDatagramTransport fd=1248>)
DEBUG:aioice.ice:Connection(0) protocol(0) > ('74.125.204.127', 19302) Message(message_method=Method.BINDING, message_class=Class.REQUEST, transaction_id=b'\xb2l\tl1\xa2\x1elMb\xf2\xb0')
DEBUG:aioice.ice:Connection(0) protocol(2) > ('74.125.204.127', 19302) Message(message_method=Method.BINDING, message_class=Class.REQUEST, transaction_id=b'4\xb1\x08\t\x98m\x1c\x042\xa1\xf0\xa2')
DEBUG:aioice.ice:Connection(0) protocol(0) error_received([WinError 1231] The network location cannot be reached. For information about network troubleshooting, see Windows Help)
DEBUG:aioice.ice:Connection(0) protocol(2) error_received([WinError 1231] The network location cannot be reached. For information about network troubleshooting, see Windows Help)
DEBUG:aioice.ice:Connection(0) protocol(1) > ('74.125.204.127', 19302) Message(message_method=Method.BINDING, message_class=Class.REQUEST, transaction_id=b'-\xc3\xc4\xd3\x1e\xf3\xc3\n\xc8|qA')
DEBUG:aioice.ice:Connection(0) protocol(1) < ('74.125.204.127', 19302) Message(message_method=Method.BINDING, message_class=Class.RESPONSE, transaction_id=b'-\xc3\xc4\xd3\x1e\xf3\xc3\n\xc8|qA')
DEBUG:aioice.ice:Connection(0) protocol(0) > ('74.125.204.127', 19302) Message(message_method=Method.BINDING, message_class=Class.REQUEST, transaction_id=b'\xb2l\tl1\xa2\x1elMb\xf2\xb0')
DEBUG:aioice.ice:Connection(0) protocol(2) > ('74.125.204.127', 19302) Message(message_method=Method.BINDING, message_class=Class.REQUEST, transaction_id=b'4\xb1\x08\t\x98m\x1c\x042\xa1\xf0\xa2')
DEBUG:aioice.ice:Connection(0) protocol(0) error_received([WinError 1231] The network location cannot be reached. For information about network troubleshooting, see Windows Help)
DEBUG:aioice.ice:Connection(0) protocol(2) error_received([WinError 1231] The network location cannot be reached. For information about network troubleshooting, see Windows Help)
DEBUG:aioice.ice:Connection(0) protocol(0) > ('74.125.204.127', 19302) Message(message_method=Method.BINDING, message_class=Class.REQUEST, transaction_id=b'\xb2l\tl1\xa2\x1elMb\xf2\xb0')
DEBUG:aioice.ice:Connection(0) protocol(2) > ('74.125.204.127', 19302) Message(message_method=Method.BINDING, message_class=Class.REQUEST, transaction_id=b'4\xb1\x08\t\x98m\x1c\x042\xa1\xf0\xa2')
DEBUG:aioice.ice:Connection(0) protocol(0) error_received([WinError 1231] The network location cannot be reached. For information about network troubleshooting, see Windows Help)
DEBUG:aioice.ice:Connection(0) protocol(2) error_received([WinError 1231] The network location cannot be reached. For information about network troubleshooting, see Windows Help)
DEBUG:aioice.ice:Connection(0) protocol(0) > ('74.125.204.127', 19302) Message(message_method=Method.BINDING, message_class=Class.REQUEST, transaction_id=b'\xb2l\tl1\xa2\x1elMb\xf2\xb0')
DEBUG:aioice.ice:Connection(0) protocol(2) > ('74.125.204.127', 19302) Message(message_method=Method.BINDING, message_class=Class.REQUEST, transaction_id=b'4\xb1\x08\t\x98m\x1c\x042\xa1\xf0\xa2')
DEBUG:aioice.ice:Connection(0) protocol(0) error_received([WinError 1231] The network location cannot be reached. For information about network troubleshooting, see Windows Help)
DEBUG:aioice.ice:Connection(0) protocol(2) error_received([WinError 1231] The network location cannot be reached. For information about network troubleshooting, see Windows Help)
DEBUG:aiortc.rtcpeerconnection:RTCPeerConnection() iceGatheringState gathering -> complete
Offer created
DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:3000
DEBUG:urllib3.connectionpool:http://localhost:3000 "GET /get-ice-candidates HTTP/1.1" 200 2
and the server :
const http = require("http");
const socketIo = require("socket.io");
const express = require("express");
const app = express();
const server = http.createServer();
const io = socketIo(server, {
cors: {
origin: "*",
},
});
let iceCandidates = [];
app.get("/get-ice-candidates", (req, res) => {
console.log("Get ICE Candidates");
res.json(iceCandidates);
});
app.listen(3000, () => {
console.log("Server is running on port 3000");
});
io.on("connection", (socket) => {
console.log("Client connected:", socket.id);
socket.on("disconnect", () => {
console.log("Client disconnected:", socket.id);
});
// Handle SDP Offer
socket.on("sdp-offer", (data) => {
console.log("SDP Offer received:", data);
socket.broadcast.emit("sdp-offer", data); // Forward the SDP Offer to other clients
});
// Handle SDP Answer
socket.on("sdp-answer", (data) => {
data.senderId = socket.id;
console.log("SDP Answer received:", data);
socket.broadcast.emit("sdp-answer", data); // Forward the SDP Answer to other clients
});
// Handle ICE Candidate
socket.on("ice-candidate", (data) => {
console.log("ICE Candidate received:", data);
iceCandidates.push(data);
socket.broadcast.emit("ice-candidate", data); // Forward the ICE Candidate to other clients
});
socket.on("message", (data) => {
console.log("Message received:", data);
socket.broadcast.emit("message", data);
});
});
server.listen(5000, () => {
console.log("Signaling server listening on port 5000");
});
the probleme is clearly this I think :
DEBUG:aioice.ice:Connection(0) protocol(2) > ('74.125.204.127', 19302) Message(message_method=Method.BINDING, message_class=Class.REQUEST, transaction_id=b'4\xb1\x08\t\x98m\x1c\x042\xa1\xf0\xa2')
DEBUG:aioice.ice:Connection(0) protocol(0) error_received([WinError 1231] The network location cannot be reached. For information about network troubleshooting, see Windows Help)
DEBUG:aioice.ice:Connection(0) protocol(2) error_received([WinError 1231] The network location cannot be reached. For information about network troubleshooting, see Windows Help)
Is someone understand and can help me ?
Thank you very much for your answer
I tried many solutions like turn off firewall etc.. Actually I can contact turn server if I try to ping 74.125.204.127 for exemple , I can not contact