def join_room(room, username): queue = Queue() threading.Thread(target=get_messages_thread, args=(queue, username)).start() room_info = get("/api/find/%s" % room, username) print("Got room info: %s" % room_info) rtc = RTCPeerConnection(rtcConfiguration) channel = Channel(rtc.createDataChannel("data", negotiated=True, id=0)) run(rtc.setRemoteDescription(object_from_string(room_info["offer"]))) answer = run(rtc.createAnswer()) run(rtc.setLocalDescription(answer)) print("Answer: %s" % object_to_string(answer)) post("/api/join/%s" % room, {"answer": object_to_string(answer)}, username) for candidate in rtc.sctp.transport.transport.iceGatherer.getLocalCandidates( ): send_message(username, room_info["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"]))) return channel, rtc
class RTCPeer(): def __init__(self): super().__init__() self.connection = RTCPeerConnection() def test(self): print('test fucntioncll') return def offer(self, sdp, data_type): print("calling the right funtion", data_type) print("insed", sdp) offer = RTCSessionDescription(sdp=sdp, type=data_type) @self.connection.on('datachannel') def on_datachannel(channel): @channel.on("message") def on_message(message): if isinstance(message, str) and message.startswith("ping"): channel.send("pong", message[4:]) @self.connection.on("iceconnectionstatechange") async def on_iceconnectionstatechange(): if pc.iceConnectionState == "failed": await self.connection.close() @self.connection.on("track") def on_track(track): if track.kind == "video": local_video = VideoTransformTrack(track, transform=params["video_transform"]) self.connection.addTrack(local_video) @track.on('ended') async def on_ended(): return # loop = asyncio.get_event_loop() # loop.run_until_complete(asyncio.gather(test1(self.connection, offer))) self.connection.setRemoteDescription(offer) answer = self.connection.createAnswer() print(type(answer)) # answer = asyncio.gather(test2(connection())) # loop.run_until_complete(answer) # loop.run_until_complete(asyncio.gather(test3(self.connection, answer))) res = {} # res = "lde" res["sdp"] = self.connection.localDescription.type res["type"] = self.connection.localDescription.type return res
def test_createAnswer_without_offer(self): pc = RTCPeerConnection() with self.assertRaises(InvalidStateError) as cm: run(pc.createAnswer()) self.assertEqual(str(cm.exception), 'Cannot create answer in signaling state "stable"')
def test_createAnswer_closed(self): pc = RTCPeerConnection() run(pc.close()) with self.assertRaises(InvalidStateError) as cm: run(pc.createAnswer()) self.assertEqual(str(cm.exception), 'RTCPeerConnection is closed')
def test_connect_datachannel(self): pc1 = RTCPeerConnection() pc1_data_messages = [] pc1_states = track_states(pc1) pc2 = RTCPeerConnection() pc2_data_channels = [] pc2_data_messages = [] pc2_states = track_states(pc2) @pc2.on('datachannel') def on_datachannel(channel): self.assertEqual(channel.readyState, 'open') pc2_data_channels.append(channel) @channel.on('message') def on_message(message): pc2_data_messages.append(message) if isinstance(message, str): channel.send('string-echo: ' + message) else: channel.send(b'binary-echo: ' + message) # create data channel dc = pc1.createDataChannel('chat', protocol='bob') self.assertEqual(dc.label, 'chat') self.assertEqual(dc.protocol, 'bob') self.assertEqual(dc.readyState, 'connecting') # send messages dc.send('hello') dc.send('') dc.send(b'\x00\x01\x02\x03') dc.send(b'') dc.send(LONG_DATA) with self.assertRaises(ValueError) as cm: dc.send(1234) self.assertEqual(str(cm.exception), "Cannot send unsupported data type: <class 'int'>") @dc.on('message') def on_message(message): pc1_data_messages.append(message) # create offer offer = run(pc1.createOffer()) self.assertEqual(offer.type, 'offer') self.assertTrue('m=application ' in offer.sdp) self.assertFalse('a=candidate:' in offer.sdp) run(pc1.setLocalDescription(offer)) self.assertEqual(pc1.iceConnectionState, 'new') self.assertEqual(pc1.iceGatheringState, 'complete') self.assertTrue('m=application ' in pc1.localDescription.sdp) self.assertTrue('a=candidate:' in pc1.localDescription.sdp) self.assertTrue('a=sctpmap:5000 webrtc-datachannel 65535' in pc1.localDescription.sdp) self.assertTrue('a=fingerprint:sha-256' in pc1.localDescription.sdp) self.assertTrue('a=setup:actpass' in pc1.localDescription.sdp) # handle offer run(pc2.setRemoteDescription(pc1.localDescription)) self.assertEqual(pc2.remoteDescription, pc1.localDescription) self.assertEqual(len(pc2.getReceivers()), 0) self.assertEqual(len(pc2.getSenders()), 0) self.assertEqual(len(pc2.getSenders()), 0) # create answer answer = run(pc2.createAnswer()) self.assertEqual(answer.type, 'answer') self.assertTrue('m=application ' in answer.sdp) self.assertFalse('a=candidate:' in answer.sdp) run(pc2.setLocalDescription(answer)) self.assertEqual(pc2.iceConnectionState, 'checking') self.assertEqual(pc2.iceGatheringState, 'complete') self.assertTrue('m=application ' in pc2.localDescription.sdp) self.assertTrue('a=candidate:' in pc2.localDescription.sdp) self.assertTrue('a=sctpmap:5000 webrtc-datachannel 65535' in pc2.localDescription.sdp) self.assertTrue('a=fingerprint:sha-256' in pc2.localDescription.sdp) self.assertTrue('a=setup:active' in pc2.localDescription.sdp) # handle answer run(pc1.setRemoteDescription(pc2.localDescription)) self.assertEqual(pc1.remoteDescription, pc2.localDescription) self.assertEqual(pc1.iceConnectionState, 'checking') # check outcome run(asyncio.sleep(1)) self.assertEqual(pc1.iceConnectionState, 'completed') self.assertEqual(pc2.iceConnectionState, 'completed') self.assertEqual(dc.readyState, 'open') # check pc2 got a datachannel self.assertEqual(len(pc2_data_channels), 1) self.assertEqual(pc2_data_channels[0].label, 'chat') self.assertEqual(pc2_data_channels[0].protocol, 'bob') # check pc2 got messages run(asyncio.sleep(1)) self.assertEqual(pc2_data_messages, [ 'hello', '', b'\x00\x01\x02\x03', b'', LONG_DATA, ]) # check pc1 got replies self.assertEqual(pc1_data_messages, [ 'string-echo: hello', 'string-echo: ', b'binary-echo: \x00\x01\x02\x03', b'binary-echo: ', b'binary-echo: ' + LONG_DATA, ]) # close data channel dc.close() self.assertEqual(dc.readyState, 'closed') # close run(pc1.close()) run(pc2.close()) self.assertEqual(pc1.iceConnectionState, 'closed') self.assertEqual(pc2.iceConnectionState, 'closed') # check state changes self.assertEqual(pc1_states['iceConnectionState'], ['new', 'checking', 'completed', 'closed']) self.assertEqual(pc1_states['iceGatheringState'], ['new', 'gathering', 'complete']) self.assertEqual(pc1_states['signalingState'], ['stable', 'have-local-offer', 'stable', 'closed']) self.assertEqual(pc2_states['iceConnectionState'], ['new', 'checking', 'completed', 'closed']) self.assertEqual(pc2_states['iceGatheringState'], ['new', 'gathering', 'complete']) self.assertEqual(pc2_states['signalingState'], ['stable', 'have-remote-offer', 'stable', 'closed'])
def test_connect_video_bidirectional(self): pc1 = RTCPeerConnection() pc1_states = track_states(pc1) pc2 = RTCPeerConnection() pc2_states = track_states(pc2) self.assertEqual(pc1.iceConnectionState, 'new') self.assertEqual(pc1.iceGatheringState, 'new') self.assertIsNone(pc1.localDescription) self.assertIsNone(pc1.remoteDescription) self.assertEqual(pc2.iceConnectionState, 'new') self.assertEqual(pc2.iceGatheringState, 'new') self.assertIsNone(pc2.localDescription) self.assertIsNone(pc2.remoteDescription) # create offer pc1.addTrack(VideoStreamTrack()) offer = run(pc1.createOffer()) self.assertEqual(offer.type, 'offer') self.assertTrue('m=video ' in offer.sdp) self.assertFalse('a=candidate:' in offer.sdp) run(pc1.setLocalDescription(offer)) self.assertEqual(pc1.iceConnectionState, 'new') self.assertEqual(pc1.iceGatheringState, 'complete') self.assertTrue('m=video ' in pc1.localDescription.sdp) self.assertTrue('a=candidate:' in pc1.localDescription.sdp) self.assertTrue('a=sendrecv' in pc1.localDescription.sdp) self.assertTrue('a=fingerprint:sha-256' in pc1.localDescription.sdp) self.assertTrue('a=setup:actpass' in pc1.localDescription.sdp) # handle offer run(pc2.setRemoteDescription(pc1.localDescription)) self.assertEqual(pc2.remoteDescription, pc1.localDescription) self.assertEqual(len(pc2.getReceivers()), 1) # create answer pc2.addTrack(VideoStreamTrack()) answer = run(pc2.createAnswer()) self.assertEqual(answer.type, 'answer') self.assertTrue('m=video ' in answer.sdp) self.assertFalse('a=candidate:' in answer.sdp) run(pc2.setLocalDescription(answer)) self.assertEqual(pc2.iceConnectionState, 'checking') self.assertEqual(pc2.iceGatheringState, 'complete') self.assertTrue('m=video ' in pc2.localDescription.sdp) self.assertTrue('a=candidate:' in pc2.localDescription.sdp) self.assertTrue('a=sendrecv' in pc1.localDescription.sdp) self.assertTrue('a=fingerprint:sha-256' in pc2.localDescription.sdp) self.assertTrue('a=setup:active' in pc2.localDescription.sdp) # handle answer run(pc1.setRemoteDescription(pc2.localDescription)) self.assertEqual(pc1.remoteDescription, pc2.localDescription) self.assertEqual(pc1.iceConnectionState, 'checking') # check outcome run(asyncio.sleep(1)) self.assertEqual(pc1.iceConnectionState, 'completed') self.assertEqual(pc2.iceConnectionState, 'completed') # close run(pc1.close()) run(pc2.close()) self.assertEqual(pc1.iceConnectionState, 'closed') self.assertEqual(pc2.iceConnectionState, 'closed') # check state changes self.assertEqual(pc1_states['iceConnectionState'], ['new', 'checking', 'completed', 'closed']) self.assertEqual(pc1_states['iceGatheringState'], ['new', 'gathering', 'complete']) self.assertEqual(pc1_states['signalingState'], ['stable', 'have-local-offer', 'stable', 'closed']) self.assertEqual(pc2_states['iceConnectionState'], ['new', 'checking', 'completed', 'closed']) self.assertEqual(pc2_states['iceGatheringState'], ['new', 'gathering', 'complete']) self.assertEqual(pc2_states['signalingState'], ['stable', 'have-remote-offer', 'stable', 'closed'])
def test_connect_audio_and_video_and_data_channel(self): pc1 = RTCPeerConnection() pc1_states = track_states(pc1) pc2 = RTCPeerConnection() pc2_states = track_states(pc2) self.assertEqual(pc1.iceConnectionState, 'new') self.assertEqual(pc1.iceGatheringState, 'new') self.assertIsNone(pc1.localDescription) self.assertIsNone(pc1.remoteDescription) self.assertEqual(pc2.iceConnectionState, 'new') self.assertEqual(pc2.iceGatheringState, 'new') self.assertIsNone(pc2.localDescription) self.assertIsNone(pc2.remoteDescription) # create offer pc1.addTrack(AudioStreamTrack()) pc1.addTrack(VideoStreamTrack()) pc1.createDataChannel('chat', protocol='bob') offer = run(pc1.createOffer()) self.assertEqual(offer.type, 'offer') self.assertTrue('m=audio ' in offer.sdp) self.assertTrue('m=video ' in offer.sdp) self.assertTrue('m=application ' in offer.sdp) run(pc1.setLocalDescription(offer)) self.assertEqual(pc1.iceConnectionState, 'new') self.assertEqual(pc1.iceGatheringState, 'complete') # handle offer run(pc2.setRemoteDescription(pc1.localDescription)) self.assertEqual(pc2.remoteDescription, pc1.localDescription) self.assertEqual(len(pc2.getSenders()), 2) self.assertEqual(len(pc2.getReceivers()), 2) # create answer pc2.addTrack(AudioStreamTrack()) pc2.addTrack(VideoStreamTrack()) answer = run(pc2.createAnswer()) self.assertEqual(answer.type, 'answer') self.assertTrue('m=audio ' in answer.sdp) self.assertTrue('m=video ' in answer.sdp) self.assertTrue('m=application ' in answer.sdp) run(pc2.setLocalDescription(answer)) self.assertEqual(pc2.iceConnectionState, 'checking') self.assertEqual(pc2.iceGatheringState, 'complete') self.assertTrue('m=audio ' in pc2.localDescription.sdp) self.assertTrue('m=video ' in pc2.localDescription.sdp) self.assertTrue('m=application ' in pc2.localDescription.sdp) # handle answer run(pc1.setRemoteDescription(pc2.localDescription)) self.assertEqual(pc1.remoteDescription, pc2.localDescription) self.assertEqual(pc1.iceConnectionState, 'checking') # check outcome run(asyncio.sleep(1)) self.assertEqual(pc1.iceConnectionState, 'completed') self.assertEqual(pc2.iceConnectionState, 'completed') # check a single transport is used self.assertBundled(pc1) self.assertBundled(pc2) # close run(pc1.close()) run(pc2.close()) self.assertEqual(pc1.iceConnectionState, 'closed') self.assertEqual(pc2.iceConnectionState, 'closed') # check state changes self.assertEqual(pc1_states['iceConnectionState'], ['new', 'checking', 'completed', 'closed']) self.assertEqual(pc1_states['iceGatheringState'], [ 'new', 'gathering', 'new', 'gathering', 'new', 'gathering', 'complete' ]) self.assertEqual(pc1_states['signalingState'], ['stable', 'have-local-offer', 'stable', 'closed']) self.assertEqual(pc2_states['iceConnectionState'], ['new', 'checking', 'completed', 'closed']) self.assertEqual(pc2_states['iceGatheringState'], ['new', 'gathering', 'complete']) self.assertEqual(pc2_states['signalingState'], ['stable', 'have-remote-offer', 'stable', 'closed'])
def test_connect_audio_mid_changes(self): pc1 = RTCPeerConnection() pc1_states = track_states(pc1) pc2 = RTCPeerConnection() pc2_states = track_states(pc2) self.assertEqual(pc1.iceConnectionState, 'new') self.assertEqual(pc1.iceGatheringState, 'new') self.assertIsNone(pc1.localDescription) self.assertIsNone(pc1.remoteDescription) self.assertEqual(pc2.iceConnectionState, 'new') self.assertEqual(pc2.iceGatheringState, 'new') self.assertIsNone(pc2.localDescription) self.assertIsNone(pc2.remoteDescription) # add audio tracks immediately pc1.addTrack(AudioStreamTrack()) pc1.getTransceivers()[0].mid = 'sdparta_0' # pretend we're Firefox! self.assertEqual(mids(pc1), ['sdparta_0']) pc2.addTrack(AudioStreamTrack()) self.assertEqual(mids(pc2), ['audio']) # create offer offer = run(pc1.createOffer()) self.assertEqual(offer.type, 'offer') self.assertTrue('m=audio ' in offer.sdp) self.assertFalse('a=candidate:' in offer.sdp) run(pc1.setLocalDescription(offer)) self.assertEqual(pc1.iceConnectionState, 'new') self.assertEqual(pc1.iceGatheringState, 'complete') self.assertTrue('m=audio ' in pc1.localDescription.sdp) self.assertTrue('a=candidate:' in pc1.localDescription.sdp) self.assertTrue('a=sendrecv' in pc1.localDescription.sdp) self.assertTrue('a=fingerprint:sha-256' in pc1.localDescription.sdp) self.assertTrue('a=setup:actpass' in pc1.localDescription.sdp) self.assertTrue('a=mid:sdparta_0' in pc1.localDescription.sdp) # handle offer run(pc2.setRemoteDescription(pc1.localDescription)) self.assertEqual(pc2.remoteDescription, pc1.localDescription) self.assertEqual(len(pc2.getReceivers()), 1) self.assertEqual(len(pc2.getSenders()), 1) self.assertEqual(mids(pc2), ['sdparta_0']) # create answer answer = run(pc2.createAnswer()) self.assertEqual(answer.type, 'answer') self.assertTrue('m=audio ' in answer.sdp) self.assertFalse('a=candidate:' in answer.sdp) run(pc2.setLocalDescription(answer)) self.assertEqual(pc2.iceConnectionState, 'checking') self.assertEqual(pc2.iceGatheringState, 'complete') self.assertTrue('m=audio ' in pc2.localDescription.sdp) self.assertTrue('a=candidate:' in pc2.localDescription.sdp) self.assertTrue('a=sendrecv' in pc1.localDescription.sdp) self.assertTrue('a=fingerprint:sha-256' in pc2.localDescription.sdp) self.assertTrue('a=setup:active' in pc2.localDescription.sdp) self.assertTrue('a=mid:sdparta_0' in pc2.localDescription.sdp) # handle answer run(pc1.setRemoteDescription(pc2.localDescription)) self.assertEqual(pc1.remoteDescription, pc2.localDescription) self.assertEqual(pc1.iceConnectionState, 'checking') # check outcome run(asyncio.sleep(1)) self.assertEqual(pc1.iceConnectionState, 'completed') self.assertEqual(pc2.iceConnectionState, 'completed') # close run(pc1.close()) run(pc2.close()) self.assertEqual(pc1.iceConnectionState, 'closed') self.assertEqual(pc2.iceConnectionState, 'closed') # check state changes self.assertEqual(pc1_states['iceConnectionState'], ['new', 'checking', 'completed', 'closed']) self.assertEqual(pc1_states['iceGatheringState'], ['new', 'gathering', 'complete']) self.assertEqual(pc1_states['signalingState'], ['stable', 'have-local-offer', 'stable', 'closed']) self.assertEqual(pc2_states['iceConnectionState'], ['new', 'checking', 'completed', 'closed']) self.assertEqual(pc2_states['iceGatheringState'], ['new', 'gathering', 'complete']) self.assertEqual(pc2_states['signalingState'], ['stable', 'have-remote-offer', 'stable', 'closed'])