code: async def connect(self):
          
          if not self._local_candidates_end:
              raise ConnectionError('Local candidates gathering was not performed')
  
          if (self.remote_username is None or
             self.remote_password is None):
              raise ConnectionError('Remote username or password is missing')
  
          # 5.7.1. Forming Candidate Pairs
          for remote_candidate in self._remote_candidates:
              for protocol in self._protocols:
                  if (protocol.local_candidate.can_pair_with(remote_candidate) and
                     not self._find_pair(protocol, remote_candidate)):
                      pair = CandidatePair(protocol, remote_candidate)
                      self._check_list.append(pair)
          self.sort_check_list()
  
          self._unfreeze_initial()
  
          # handle early checks
          for check in self._early_checks:
              self.check_incoming(*check)
          self._early_checks = []
  
          # perform checks
          while True:
              if not self.check_periodic():
                  break
              await asyncio.sleep(0.02)
  
          # wait for completion
          if self._check_list:
              res = await self._check_list_state.get()
          else:
              res = ICE_FAILED
  
          # cancel remaining checks
          for check in self._check_list:
              if check.handle:
                  check.handle.cancel()
  
          if res != ICE_COMPLETED:
              raise ConnectionError('ICE negotiation failed')
  
          # start consent freshness tests
          self._query_consent_handle = asyncio.ensure_future(self.query_consent())
docs: Perform ICE handshake.
  
          This coroutine returns if a candidate pair was successfuly nominated
          and raises an exception otherwise.