async def test_signaling_process() -> None: domain = Domain(name="test") webrtc = WebRTCConnection(node=domain) offer_payload = await webrtc._set_offer() offer_dict = json.loads(offer_payload) aiortc_session = object_from_string(offer_payload) assert "sdp" in offer_dict assert "type" in offer_dict assert offer_dict["type"] == "offer" assert isinstance(aiortc_session, RTCSessionDescription) answer_webrtc = WebRTCConnection(node=domain) answer_payload = await answer_webrtc._set_answer(payload=offer_payload) answer_dict = json.loads(answer_payload) aiortc_session = object_from_string(answer_payload) assert "sdp" in answer_dict assert "type" in answer_dict assert answer_dict["type"] == "answer" assert isinstance(aiortc_session, RTCSessionDescription) response = await webrtc._process_answer(payload=answer_payload) assert response is None
async def run(pc): session = ClientSession() async with session.ws_connect("ws://39.102.116.49:8080") as ws: async for msg in ws: if msg.type == WSMsgType.TEXT: data = json.loads(msg.data) if data["type"] == "offerOrAnswer": await pc.setRemoteDescription( object_from_string(json.dumps(data["msg"]))) if data["msg"]["type"] == "offer": pc.addTrack(FlagVideoStreamTrack()) await pc.setLocalDescription(await pc.createAnswer()) await ws.send_str( json.dumps({ "type": "offerOrAnswer", "msg": json.loads( object_to_string(pc.localDescription)), })) elif data["type"] == "candidate": try: await pc.addIceCandidate( object_from_string(json.dumps(data["msg"]))) except: pass
def host_room(room, username): queue = Queue() threading.Thread(target=get_messages_thread, args=(queue, username)).start() rtc = RTCPeerConnection(rtcConfiguration) channel = Channel(rtc.createDataChannel("data", negotiated=True, id=0)) offer = run(rtc.createOffer()) run(rtc.setLocalDescription(offer)) res = post("/api/host/%s" % room, { "room": room, "offer": object_to_string(offer) }, username) print("Got res %s" % res) run(rtc.setRemoteDescription(object_from_string(res["answer"]))) for candidate in rtc.sctp.transport.transport.iceGatherer.getLocalCandidates( ): send_message(username, res["username"], "ice", fix_candidate(object_to_string(candidate))) time.sleep(3) while not queue.empty(): for message in queue.get(): if message["type"] == "ice": print("Got candidate: %s" % message["data"]) rtc.sctp.transport.transport.addRemoteCandidate( object_from_string(fix_candidate2(message["data"]))) rtc.sctp.transport.transport.addRemoteCandidate(None) return channel, rtc
async def consume_signaling(self, pc, signaling): # Async keep-alive connection thread while self.available: sleep_time = 0 if self._msg == "": await asyncio.sleep(sleep_time) continue obj = object_from_string(self._msg) if isinstance(obj, RTCSessionDescription): await pc.setRemoteDescription(obj) if obj.type == "offer": # send answer await pc.setLocalDescription(await pc.createAnswer()) local_description = object_to_string(pc.localDescription) response = { MSG_FIELD.TYPE: NODE_EVENTS.WEBRTC_ANSWER, MSG_FIELD.FROM: self._origin, MSG_FIELD.PAYLOAD: local_description, } forward_payload = { MSG_FIELD.TYPE: GRID_EVENTS.FORWARD, MSG_FIELD.DESTINATION: self._destination, MSG_FIELD.CONTENT: response, } self._grid.send(json.dumps(forward_payload)) sleep_time = 10 self._msg = "" raise Exception
async def consume_signaling(self, pc, signaling): while True: if self._msg == "": await asyncio.sleep(5) continue obj = object_from_string(self._msg) if isinstance(obj, RTCSessionDescription): await pc.setRemoteDescription(obj) if obj.type == "offer": # send answer await pc.setLocalDescription(await pc.createAnswer()) local_description = object_to_string(pc.localDescription) response = { MSG_FIELD.TYPE: NODE_EVENTS.WEBRTC_ANSWER, MSG_FIELD.FROM: self._origin, MSG_FIELD.PAYLOAD: local_description, } forward_payload = { MSG_FIELD.TYPE: GRID_EVENTS.FORWARD, MSG_FIELD.DESTINATION: self._destination, MSG_FIELD.CONTENT: response, } self._grid.send(json.dumps(forward_payload)) elif isinstance(obj, RTCIceCandidate): pc.addIceCandidate(obj) elif obj is BYE: print("Exiting") break self._msg = ""
async def websocket_coroutine(): session = aiohttp.ClientSession() async with session.ws_connect(WEBSOCKET_URI) as ws: print("websocket connected") request = json.dumps({ "what": "call" }) await ws.send_str(request) async for msg in ws: print(msg) if msg.type == aiohttp.WSMsgType.TEXT: params = json.loads(msg.data) print(params) if params["what"] == "offer": print("offer received") uv4l_sdp = object_from_string(params["data"]) await pc.setRemoteDescription(uv4l_sdp) await pc.setLocalDescription(await pc.createAnswer()) local_sdp = object_to_string(pc.localDescription) print(local_sdp) print(type(local_sdp)) await ws.send_str(json.dumps({ "what": "answer", "data": local_sdp })) elif params['what'] == 'hangup': print("hangup received") await ws.close() break else: print(msg) elif msg.type == aiohttp.WSMsgType.ERROR: break
async def receive(self): if self.__messages: message = self.__messages.pop(0) else: message = await self.websocket.recv() message = json.loads(message)['msg'] print('<', message) return object_from_string(message)
async def receive(self): message = self._webrtc_server.receive_message(self._room, self.__peer_id) # if self._javascript_callable: # print('ColabSignaling: sending message to Javascript peer:', message) # else: # print('ColabSignaling: sending message to Python peer:', message) if message and type(message) == str and not self._javascript_callable: message = object_from_string(message) return message
async def receive(self): if self.__messages: message = self.__messages.pop(0) else: message = self.recv_nowait() if message: message = json.loads(message)["msg"] if message: logger.debug("< " + message) return object_from_string(message)
async def create_answer(self, offer): offer = object_from_string(offer) await self.pc.setRemoteDescription(offer) await self.pc.setLocalDescription(await self.pc.createAnswer()) @self.pc.on("datachannel") def on_datachannel(channel): self.channel = channel return object_to_string(self.pc.localDescription)
def send_sync(self, message): print('send:', message) if type(message) == str: message_json = json.loads(message) if 'candidate' in message_json: message_json['type'] = 'candidate' message_json["id"] = message_json["sdpMid"] message_json["label"] = message_json["sdpMLineIndex"] message = json.dumps(message_json) message = object_from_string(message) loop = asyncio.get_event_loop() return loop.run_until_complete(self.send(message))
def test_candidate_from_string(self): candidate = object_from_string( '{"candidate": "candidate:0 1 UDP 2122252543 192.168.99.7 33543 typ host", "id": "audio", "label": 0, "type": "candidate"}') # noqa self.assertEqual(candidate.component, 1) self.assertEqual(candidate.foundation, '0') self.assertEqual(candidate.ip, '192.168.99.7') self.assertEqual(candidate.port, 33543) self.assertEqual(candidate.priority, 2122252543) self.assertEqual(candidate.protocol, 'UDP') self.assertEqual(candidate.sdpMid, 'audio') self.assertEqual(candidate.sdpMLineIndex, 0) self.assertEqual(candidate.type, 'host')
async def WebRTCSignalingService(request): ws = web.WebSocketResponse() await ws.prepare(request) async for msg in ws: print(msg) if msg.type == aiohttp.WSMsgType.TEXT: params = json.loads(msg.data) print(type(params)) print(params) if params["what"] == "call": print("call received") # prepare media pc.addTrack(VideoStreamTrack) await pc.setLocalDescription(await pc.createOffer()) uv4l_sdp = object_to_string(pc.localDescription) print(type(uv4l_sdp)) await ws.send_str( json.dumps({ "what": "offer", "data": uv4l_sdp })) elif params["what"] == "answer": print("answer received") local_sdp = object_from_string(params["data"]) await pc.setRemoteDescription(local_sdp) print('setRemoteDescription(<local_sdp>)') # await pc.setRemoteDescription(local_sdp) elif params["what"] == "addIceCandidate": print("addIceCandidate received") elif params['what'] == 'hangup': print("hangup received") await ws.close() else: await ws.send_json(msg.data + '\n received.') elif msg.type == aiohttp.WSMsgType.ERROR: print('ws connection closed with exception %s' % ws.exception()) print('websocket connection closed') return ws
async def consume_signaling(self, pc, signaling): """Consume signaling to go through all the webrtc connection protocol. Args: pc: Peer Connection. signaling: Webrtc signaling instance. Exception: ConnectionClosedException: Exception used to finish this connection and close this thread. """ # Async keep-alive connection thread while self.available: sleep_time = 0 if self._msg == "": await asyncio.sleep(sleep_time) continue obj = object_from_string(self._msg) if isinstance(obj, RTCSessionDescription): await pc.setRemoteDescription(obj) if obj.type == "offer": # send answer await pc.setLocalDescription(await pc.createAnswer()) local_description = object_to_string(pc.localDescription) response = { MSG_FIELD.TYPE: NODE_EVENTS.WEBRTC_ANSWER, MSG_FIELD.FROM: self._origin, MSG_FIELD.PAYLOAD: local_description, } forward_payload = { MSG_FIELD.TYPE: GRID_EVENTS.FORWARD, MSG_FIELD.DESTINATION: self._destination, MSG_FIELD.CONTENT: response, } self._grid.send(json.dumps(forward_payload)) sleep_time = 10 self._msg = "" raise Exception
async def _process_answer(self, payload: str) -> Union[str, None]: # Converts payload received by # the other peer in aioRTC Object # instance. try: msg = object_from_string(payload) # Check if Object instance is a # description of RTC Session. if isinstance(msg, RTCSessionDescription): # Use the target's network address/metadata # to set the remote description of this peer. # This will basically say to this peer how to find/connect # with to other peer. await self.peer_connection.setRemoteDescription(msg) # If it's an offer message type, # generates your own local description # and send it back in order to tell # to the other peer how to find you. if msg.type == "offer": # Set peer_connection to generate an offer message type. await self.peer_connection.setLocalDescription( await self.peer_connection.createAnswer()) # Generates the local description structure # and serialize it to string afterwards. local_description = object_to_string( self.peer_connection.localDescription) # Returns the answer peer's local description return local_description except Exception as e: log = f"Got an exception in WebRTCConnection _process_answer. {e}" logger.error(log) raise e return None
def test_bye_from_string(self): self.assertEqual(object_from_string('{"type": "bye"}'), BYE)
async def set_answer(self, answer): answer = object_from_string(answer) await self.pc.setRemoteDescription(answer)