def test_cannot_pair_ipv4_ipv6(self): candidate_a = Candidate.from_sdp( '6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0') candidate_b = Candidate.from_sdp( '6815297761 1 udp 659136 2a02:0db8:85a3:0000:0000:8a2e:0370:7334 12345' ' typ host generation 0') self.assertFalse(candidate_a.can_pair_with(candidate_b))
def test_add_remote_candidate_mdns(self): """ mDNS is not supported yet, ignore such candidates. """ conn_a = ice.Connection(ice_controlling=True) conn_a.add_remote_candidate( Candidate( foundation="some-foundation", component=1, transport="udp", priority=1234, host="a64e1aa4-8c7e-4671-ab02-e6a3483b1cd9.local", port=1234, type="host", )) self.assertEqual(len(conn_a.remote_candidates), 0) self.assertEqual(conn_a._remote_candidates_end, False) conn_a.add_remote_candidate( Candidate( foundation="some-foundation", component=1, transport="udp", priority=1234, host="1.2.3.4", port=1234, type="host", )) self.assertEqual(len(conn_a.remote_candidates), 1) self.assertEqual(conn_a.remote_candidates[0].host, "1.2.3.4") self.assertEqual(conn_a._remote_candidates_end, False)
def test_set_remote_candidates_mdns(self): conn_a = ice.Connection(ice_controlling=True) conn_a.remote_candidates = [ Candidate( foundation='some-foundation', component=1, transport='udp', priority=1234, host='a64e1aa4-8c7e-4671-ab02-e6a3483b1cd9.local', port=1234, type='host', ), Candidate( foundation='some-foundation', component=1, transport='udp', priority=1234, host='1.2.3.4', port=1234, type='host', ) ] self.assertEqual(len(conn_a.remote_candidates), 1) self.assertEqual(conn_a.remote_candidates[0].host, '1.2.3.4') self.assertEqual(conn_a._remote_candidates_end, True)
def test_set_remote_candidates_mdns(self): conn_a = ice.Connection(ice_controlling=True) conn_a.remote_candidates = [ Candidate( foundation="some-foundation", component=1, transport="udp", priority=1234, host="a64e1aa4-8c7e-4671-ab02-e6a3483b1cd9.local", port=1234, type="host", ), Candidate( foundation="some-foundation", component=1, transport="udp", priority=1234, host="1.2.3.4", port=1234, type="host", ), ] self.assertEqual(len(conn_a.remote_candidates), 1) self.assertEqual(conn_a.remote_candidates[0].host, "1.2.3.4") self.assertEqual(conn_a._remote_candidates_end, True)
def test_cannot_pair_different_transports(self): candidate_a = Candidate.from_sdp( '6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0') candidate_b = Candidate.from_sdp( '6815297761 1 tcp 659136 1.2.3.4 12345 typ host generation 0 tcptype active' ) self.assertFalse(candidate_a.can_pair_with(candidate_b))
def test_cannot_pair_different_components(self): candidate_a = Candidate.from_sdp( "6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0" ) candidate_b = Candidate.from_sdp( "6815297761 2 udp 659136 1.2.3.4 12345 typ host generation 0" ) self.assertFalse(candidate_a.can_pair_with(candidate_b))
def test_can_pair_ipv4(self): candidate_a = Candidate.from_sdp( "6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0" ) candidate_b = Candidate.from_sdp( "6815297761 1 udp 659136 1.2.3.4 12345 typ host generation 0" ) self.assertTrue(candidate_a.can_pair_with(candidate_b))
def test_can_pair_ipv6(self): candidate_a = Candidate.from_sdp( "6815297761 1 udp 659136 2a02:0db8:85a3:0000:0000:8a2e:0370:7334 31102" " typ host generation 0" ) candidate_b = Candidate.from_sdp( "6815297761 1 udp 659136 2a02:0db8:85a3:0000:0000:8a2e:0370:7334 12345" " typ host generation 0" ) self.assertTrue(candidate_a.can_pair_with(candidate_b))
def test_response_with_invalid_address(self): connection = ice.Connection(ice_controlling=True) connection.remote_password = "******" connection.remote_username = "******" protocol = ProtocolMock() protocol.response_addr = ("3.4.5.6", 3456) protocol.response_message = "bad" pair = ice.CandidatePair( protocol, Candidate( foundation="some-foundation", component=1, transport="udp", priority=2345, host="2.3.4.5", port=2345, type="host", ), ) self.assertEqual( repr(pair), "CandidatePair(('1.2.3.4', 1234) -> ('2.3.4.5', 2345))" ) run(connection.check_start(pair)) self.assertEqual(pair.state, ice.CandidatePair.State.FAILED)
def test_add_remote_candidate(self): conn_a = ice.Connection(ice_controlling=True) remote_candidate = Candidate(foundation='some-foundation', component=1, transport='udp', priority=1234, host='1.2.3.4', port=1234, type='host') # add candidate conn_a.add_remote_candidate(remote_candidate) self.assertEqual(len(conn_a.remote_candidates), 1) self.assertEqual(conn_a._remote_candidates_end, False) # end-of-candidates conn_a.add_remote_candidate(None) self.assertEqual(len(conn_a.remote_candidates), 1) self.assertEqual(conn_a._remote_candidates_end, True) # try adding another candidate with self.assertRaises(ValueError) as cm: conn_a.add_remote_candidate(remote_candidate) self.assertEqual( str(cm.exception), 'Cannot add remote candidate after end-of-candidates.') self.assertEqual(len(conn_a.remote_candidates), 1) self.assertEqual(conn_a._remote_candidates_end, True)
def test_set_remote_candidates(self): conn_a = ice.Connection(ice_controlling=True) remote_candidates = [ Candidate(foundation='some-foundation', component=1, transport='udp', priority=1234, host='1.2.3.4', port=1234, type='host') ] # set candidates conn_a.remote_candidates = remote_candidates self.assertEqual(len(conn_a.remote_candidates), 1) self.assertEqual(conn_a._remote_candidates_end, True) # try setting candidates again with self.assertRaises(ValueError) as cm: conn_a.remote_candidates = remote_candidates self.assertEqual( str(cm.exception), 'Cannot set remote candidates after end-of-candidates.') self.assertEqual(len(conn_a.remote_candidates), 1) self.assertEqual(conn_a._remote_candidates_end, True)
async def _handle_ice_candidates(self): """ (*Coroutine*) Coroutine that handle the ICE candidates negotiation. """ while self.readyState == PeerState.CONNECTING or self.readyState == PeerState.CONNECTED: signal = await self._get_signal() if 'type' in signal: if signal['type'] == 'status' and signal[ 'status'] == 'unpaired': if self.readyState == PeerState.CONNECTED: logging.info('unpaired received, disconnecting...') self.disconnection_event.set() elif 'candidate' in signal: logging.info('Got ice candidate:') candi = Candidate.from_sdp(signal['candidate']['candidate']) candidate = RTCIceCandidate( component=candi.component, foundation=candi.foundation, ip=candi.host, port=candi.port, priority=candi.priority, protocol=candi.transport, relatedAddress=candi.related_address, relatedPort=candi.related_port, tcpType=candi.tcptype, type=candi.type, sdpMLineIndex=signal['candidate']['sdpMLineIndex'], sdpMid=signal['candidate']['sdpMid']) logging.debug(candidate) self._pc.addIceCandidate(candidate) else: raise Exception('Received an unexpected signal: ', signal)
def test_repr(self): candidate = Candidate.from_sdp( '6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0') self.assertEqual( repr(candidate), 'Candidate(6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0)' )
async def test_add_remote_candidate_mdns_good(self): """ Add an mDNS candidate which can be resolved. """ hostname = mdns.create_mdns_hostname() publisher = await mdns.create_mdns_protocol() await publisher.publish(hostname, "1.2.3.4") conn_a = ice.Connection(ice_controlling=True) await conn_a.add_remote_candidate( Candidate( foundation="some-foundation", component=1, transport="udp", priority=1234, host=hostname, port=1234, type="host", )) self.assertEqual(len(conn_a.remote_candidates), 1) self.assertEqual(conn_a.remote_candidates[0].host, "1.2.3.4") self.assertEqual(conn_a._remote_candidates_end, False) # close await conn_a.close() await publisher.close()
async def test_add_remote_candidate(self): conn_a = ice.Connection(ice_controlling=True) remote_candidate = Candidate( foundation="some-foundation", component=1, transport="udp", priority=1234, host="1.2.3.4", port=1234, type="host", ) # add candidate await conn_a.add_remote_candidate(remote_candidate) self.assertEqual(len(conn_a.remote_candidates), 1) self.assertEqual(conn_a.remote_candidates[0].host, "1.2.3.4") self.assertEqual(conn_a._remote_candidates_end, False) # end-of-candidates await conn_a.add_remote_candidate(None) self.assertEqual(len(conn_a.remote_candidates), 1) self.assertEqual(conn_a._remote_candidates_end, True) # try adding another candidate with self.assertRaises(ValueError) as cm: await conn_a.add_remote_candidate(remote_candidate) self.assertEqual( str(cm.exception), "Cannot add remote candidate after end-of-candidates.") self.assertEqual(len(conn_a.remote_candidates), 1) self.assertEqual(conn_a._remote_candidates_end, True)
def candidate_to_aioice(x): return Candidate(component=x.component, foundation=x.foundation, host=x.ip, port=x.port, priority=x.priority, transport=x.protocol, tcptype=x.tcpType, type=x.type)
async def add_candidate_to_pc(self, pc_id, candidate=RTCIceCandidate): logger.info("add_candidate_to_pc {}".format(candidate)) if candidate: this_candidate = candidate.get("candidate") if this_candidate: logger.info("---------- {}".format(candidate["candidate"])) candidate_inst = Candidate.from_sdp(candidate["candidate"]) rTCIceCandidate = candidate_from_aioice(candidate_inst) rTCIceCandidate.sdp = candidate["sdpMid"] rTCIceCandidate.sdpMLineIndex = candidate["sdpMLineIndex"]
def test_connect_no_remote_credentials(self): """ If remote credentials have not been provided, connect fails. """ conn = ice.Connection(ice_controlling=True) run(conn.gather_candidates()) conn.remote_candidates = [Candidate.from_sdp( '6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0')] with self.assertRaises(ConnectionError) as cm: run(conn.connect()) self.assertEqual(str(cm.exception), 'Remote username or password is missing') run(conn.close())
def test_connect_no_local_candidates(self): """ If local candidates have not been gathered, connect fails. """ conn = ice.Connection(ice_controlling=True) conn.remote_candidates = [Candidate.from_sdp( '6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0')] conn.remote_username = '******' conn.remote_password = '******' with self.assertRaises(ConnectionError): run(conn.connect()) run(conn.close())
def test_connect_timeout(self): # lower STUN retries stun.RETRY_MAX = 2 conn = ice.Connection(ice_controlling=True) run(conn.gather_candidates()) conn.remote_candidates = [Candidate.from_sdp( '6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0')] conn.remote_username = '******' conn.remote_password = '******' with self.assertRaises(ConnectionError): run(conn.connect()) run(conn.close())
def candidate_to_aioice(x: RTCIceCandidate) -> Candidate: return Candidate( component=x.component, foundation=x.foundation, host=x.ip, port=x.port, priority=x.priority, related_address=x.relatedAddress, related_port=x.relatedPort, transport=x.protocol, tcptype=x.tcpType, type=x.type, )
def test_connect_no_gather(self): """ If local candidates gathering was not performed, connect fails. """ conn = ice.Connection(ice_controlling=True) conn.remote_candidates = [Candidate.from_sdp( '6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0')] conn.remote_username = '******' conn.remote_password = '******' with self.assertRaises(ConnectionError) as cm: run(conn.connect()) self.assertEqual(str(cm.exception), 'Local candidates gathering was not performed') run(conn.close())
async def test_connect_no_remote_credentials(self): """ If remote credentials have not been provided, connect fails. """ conn = ice.Connection(ice_controlling=True) await conn.gather_candidates() await conn.add_remote_candidate( Candidate.from_sdp( "6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0")) await conn.add_remote_candidate(None) with self.assertRaises(ConnectionError) as cm: await conn.connect() self.assertEqual(str(cm.exception), "Remote username or password is missing") await conn.close()
def test_from_sdp_no_generation(self): candidate = Candidate.from_sdp( '6815297761 1 udp 659136 1.2.3.4 31102 typ host') self.assertEqual(candidate.foundation, '6815297761') self.assertEqual(candidate.component, 1) self.assertEqual(candidate.transport, 'udp') self.assertEqual(candidate.priority, 659136) self.assertEqual(candidate.host, '1.2.3.4') self.assertEqual(candidate.port, 31102) self.assertEqual(candidate.type, 'host') self.assertEqual(candidate.generation, None) self.assertEqual(candidate.to_sdp(), '6815297761 1 udp 659136 1.2.3.4 31102 typ host')
def test_add_remote_candidate_unknown_type(self): conn_a = ice.Connection(ice_controlling=True) conn_a.add_remote_candidate( Candidate( foundation="some-foundation", component=1, transport="udp", priority=1234, host="1.2.3.4", port=1234, type="bogus", )) self.assertEqual(len(conn_a.remote_candidates), 0) self.assertEqual(conn_a._remote_candidates_end, False)
def test_from_sdp_no_generation(self): candidate = Candidate.from_sdp("6815297761 1 udp 659136 1.2.3.4 31102 typ host") self.assertEqual(candidate.foundation, "6815297761") self.assertEqual(candidate.component, 1) self.assertEqual(candidate.transport, "udp") self.assertEqual(candidate.priority, 659136) self.assertEqual(candidate.host, "1.2.3.4") self.assertEqual(candidate.port, 31102) self.assertEqual(candidate.type, "host") self.assertEqual(candidate.generation, None) self.assertEqual( candidate.to_sdp(), "6815297761 1 udp 659136 1.2.3.4 31102 typ host" )
async def test_connect_no_gather(self): """ If local candidates gathering was not performed, connect fails. """ conn = ice.Connection(ice_controlling=True) await conn.add_remote_candidate( Candidate.from_sdp( "6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0")) await conn.add_remote_candidate(None) conn.remote_username = "******" conn.remote_password = "******" with self.assertRaises(ConnectionError) as cm: await conn.connect() self.assertEqual(str(cm.exception), "Local candidates gathering was not performed") await conn.close()
def test_connect_no_local_candidates(self): """ If local candidates gathering yielded no candidates, connect fails. """ conn = ice.Connection(ice_controlling=True) conn._local_candidates_end = True conn.add_remote_candidate( Candidate.from_sdp( "6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0")) conn.add_remote_candidate(None) conn.remote_username = "******" conn.remote_password = "******" with self.assertRaises(ConnectionError) as cm: run(conn.connect()) self.assertEqual(str(cm.exception), "ICE negotiation failed") run(conn.close())
def test_connect_timeout(self): # lower STUN retries stun.RETRY_MAX = 1 conn = ice.Connection(ice_controlling=True) run(conn.gather_candidates()) conn.add_remote_candidate( Candidate.from_sdp( "6815297761 1 udp 659136 1.2.3.4 31102 typ host generation 0")) conn.add_remote_candidate(None) conn.remote_username = "******" conn.remote_password = "******" with self.assertRaises(ConnectionError) as cm: run(conn.connect()) self.assertEqual(str(cm.exception), "ICE negotiation failed") run(conn.close())
class ProtocolMock: local_candidate = Candidate(foundation='some-foundation', component=1, transport='udp', priority=1234, host='1.2.3.4', port=1234, type='host') sent_message = None async def request(self, message, addr, integrity_key=None): return (self.response_message, self.response_addr) def send_stun(self, message, addr): self.sent_message = message