Пример #1
0
  void NiceConnection::updateIceState(IceState state) {
      { // New scope for our lock
          boost::unique_lock<boost::recursive_mutex> lock(stateMutex_);
          if(iceState_==state)
              return;

          ELOG_INFO("%s - NICE State Changing from %u to %u %p", transportName->c_str(), this->iceState_, state, this);
          this->iceState_ = state;
          switch( iceState_) {
          case NICE_FINISHED:
              return;
          case NICE_FAILED:
              this->running_=false;
              break;

          case NICE_READY:
              char ipaddr[NICE_ADDRESS_STRING_LEN];
              NiceCandidate* local, *remote;
              nice_agent_get_selected_pair(agent_, 1, 1, &local, &remote);
              nice_address_to_string(&local->addr, ipaddr);
              ELOG_INFO("Selected pair:\nlocal candidate addr: %s:%d",ipaddr, nice_address_get_port(&local->addr));
              nice_address_to_string(&remote->addr, ipaddr);
              ELOG_INFO("remote candidate addr: %s:%d",ipaddr, nice_address_get_port(&remote->addr));
              break;
          default:
              break;
          }
      }

      // Important: send this outside our state lock.  Otherwise, serious risk of deadlock.
      if (this->listener_ != NULL)
          this->listener_->updateIceState(state, this);
  }
Пример #2
0
static void
cb_component_state_changed(NiceAgent *agent, guint _stream_id,
    guint component_id, guint state,
    gpointer data)
{

  g_debug("SIGNAL: state changed %d %d %s[%d]\n",
      _stream_id, component_id, state_name[state], state);

  if (state == NICE_COMPONENT_STATE_READY) {
    NiceCandidate *local, *remote;

    // Get current selected candidate pair and print IP address used
    if (nice_agent_get_selected_pair (agent, _stream_id, component_id,
                &local, &remote)) {
      gchar ipaddr[INET6_ADDRSTRLEN];

      nice_address_to_string(&local->addr, ipaddr);
      printf("\nNegotiation complete: ([%s]:%d,",
          ipaddr, nice_address_get_port(&local->addr));
      nice_address_to_string(&remote->addr, ipaddr);
      printf(" [%s]:%d)\n", ipaddr, nice_address_get_port(&remote->addr));
    }

    // Listen to stdin and send data written to it
    printf("\nSend lines to remote (Ctrl-D to quit):\n");
    g_io_add_watch(io_stdin, G_IO_IN, stdin_send_data_cb, agent);
    printf("> ");
    fflush (stdout);
  } else if (state == NICE_COMPONENT_STATE_FAILED) {
    g_main_loop_quit (gloop);
  }
}
Пример #3
0
static void
test_ipv6 (void)
{
  NiceAddress addr, other, v4addr;
  gchar str[NICE_ADDRESS_STRING_LEN];
  struct sockaddr_in6 sin, sin2;

  g_assert (nice_address_set_from_string (&v4addr, "172.1.0.1") == TRUE);

  memset (&sin, 0, sizeof (sin));
  memset (&sin2, 0, sizeof (sin2));

  memset (&addr, 0, sizeof (NiceAddress));
  memset (&other, 0, sizeof (NiceAddress));
  nice_address_init (&addr);
  nice_address_init (&other);
  nice_address_set_ipv6 (&addr, (guchar *)
      "\x00\x11\x22\x33"
      "\x44\x55\x66\x77"
      "\x88\x99\xaa\xbb"
      "\xcc\xdd\xee\xff");
  g_assert (addr.s.ip6.sin6_family == AF_INET6);

  nice_address_to_string (&addr, str);
  g_assert (0 == strcmp (str, "11:2233:4455:6677:8899:aabb:ccdd:eeff"));

  nice_address_set_port (&addr, 9876); /* in native byte order */
  nice_address_set_from_string (&other, "11:2233:4455:6677:8899:aabb:ccdd:eeff");
  nice_address_set_port (&other, 9876); /* in native byte order */

  nice_address_copy_to_sockaddr (&other, (struct sockaddr*)&sin2);
  nice_address_copy_to_sockaddr (&addr, (struct sockaddr*)&sin);
  g_assert (nice_address_equal (&addr, &other) == TRUE);
  nice_address_to_string (&addr, str);
  nice_address_to_string (&other, str);

  g_assert (memcmp (&sin, &sin2, sizeof(sin)) == 0);

  /* private IPv6 address */
  nice_address_set_ipv6 (&addr, (guchar *)
      "\xfc\x00\x00\x00"
      "\x00\x00\x00\x00"
      "\x00\x00\x00\x00"
      "\x00\x00\x00\x01");
  g_assert (nice_address_is_private (&addr) == TRUE);
  nice_address_set_ipv6 (&addr, (guchar *)
      "\x00\x00\x00\x00"
      "\x00\x00\x00\x00"
      "\x00\x00\x00\x00"
      "\x00\x00\x00\x01");
  g_assert (nice_address_is_private (&addr) == TRUE);

  /* mismatching address families */
  g_assert (nice_address_equal (&addr, &v4addr) != TRUE);

  /* mismatched type */
  addr.s.addr.sa_family = AF_UNSPEC;
  /*g_assert (nice_address_equal (&addr, &v4addr) != TRUE);*/
}
Пример #4
0
static void
test_ipv4 (void)
{
  NiceAddress addr;
  NiceAddress other;
  gchar str[NICE_ADDRESS_STRING_LEN];

  nice_address_init (&addr);
  nice_address_init (&other);
  nice_address_set_ipv4 (&addr, 0x01020304);
  g_assert (addr.s.ip4.sin_family == AF_INET);

  nice_address_to_string (&addr, str);
  g_assert (0 == strcmp (str, "1.2.3.4"));

  nice_address_to_string (&addr, str);

  /* same address */
  nice_address_set_ipv4 (&other, 0x01020304);
  g_assert (TRUE == nice_address_equal (&addr, &other));

  /* from sockaddr_in */
  nice_address_set_port (&other, 9876); /* in native byte order */
  other.s.ip4.sin_family = AF_INET;
  nice_address_set_from_string (&addr, "1.2.3.4");
  nice_address_set_port (&addr, 9876); /* in native byte order */
  nice_address_to_string (&addr, str);
  nice_address_to_string (&other, str);
  g_assert (TRUE == nice_address_equal (&addr, &other));

  /* different IP */
  nice_address_set_ipv4 (&other, 0x01020305);
  g_assert (FALSE == nice_address_equal (&addr, &other));

  /* different port */
  nice_address_set_ipv4 (&other, 0x01020304);
  nice_address_set_port (&addr, 1);
  g_assert (FALSE == nice_address_equal (&addr, &other));

  /* test private address check */
  {
    NiceAddress *heap_addr = nice_address_new ();
    g_assert (nice_address_set_from_string (heap_addr, "127.0.0.1") == TRUE);
    g_assert (nice_address_is_private (heap_addr) == TRUE);
    g_assert (nice_address_set_from_string (heap_addr, "127.0.0.1.1") != TRUE);
    nice_address_free (heap_addr);
  }
}
Пример #5
0
  CandidatePair NiceConnection::getSelectedPair(){
    char ipaddr[NICE_ADDRESS_STRING_LEN];
    CandidatePair selectedPair;
    NiceCandidate* local, *remote;
    nice_agent_get_selected_pair(agent_, 1, 1, &local, &remote);
    nice_address_to_string(&local->addr, ipaddr);
    selectedPair.erizoCandidateIp = std::string(ipaddr);
    selectedPair.erizoCandidatePort = nice_address_get_port(&local->addr);
    ELOG_INFO("Selected pair:\nlocal candidate addr: %s:%d",ipaddr, nice_address_get_port(&local->addr));
    nice_address_to_string(&remote->addr, ipaddr);
    selectedPair.clientCandidateIp = std::string(ipaddr);
    selectedPair.clientCandidatePort = nice_address_get_port(&remote->addr);
    ELOG_INFO("remote candidate addr: %s:%d",ipaddr, nice_address_get_port(&remote->addr));
    return selectedPair;

  }
Пример #6
0
static void
_get_addr (const NiceAddress *addr, gchar **dst_addr, guint *dst_port)
{
  gchar *addr_str = g_new0 (gchar, INET6_ADDRSTRLEN);
  nice_address_to_string (addr, addr_str);
  *dst_port = nice_address_get_port (addr);
  *dst_addr = addr_str;
}
Пример #7
0
NS_IMETHODIMP
otICECandidate::GetIp(nsACString & aIp)
{
  char str[NICE_ADDRESS_STRING_LEN];
  nice_address_to_string(&mCandidate->addr, str);

  aIp = str;
  return NS_OK;
}
Пример #8
0
NS_IMETHODIMP
otICECandidate::GetRelIp(nsACString & aRelIp)
{
  char str[NICE_ADDRESS_STRING_LEN];
  nice_address_to_string(&mCandidate->base_addr, str);

  //aRelIp.Assign(str);
  aRelIp.AssignLiteral("");
  return NS_OK;
}
Пример #9
0
int  _video_send_print_local_data(NiceAgent *agent, guint stream_id, guint component_id)
{
	int result = EXIT_FAILURE;
	gchar *local_ufrag = NULL;
	gchar *local_password = NULL;
	gchar ipaddr[INET6_ADDRSTRLEN];
	GSList *cands = NULL, *item;

	if (!nice_agent_get_local_credentials(agent, stream_id,
	&local_ufrag, &local_password))
	goto end;

	cands = nice_agent_get_local_candidates(agent, stream_id, component_id);
	if (cands == NULL)
	goto end;

	mInfo_SendVideo = (gchar*)malloc(181*sizeof(gchar));

	//printf("%s %s", local_ufrag, local_password);
	sprintf(mInfo_SendVideo, "%s %s", local_ufrag, local_password);
	for (item = cands; item; item = item->next) {
	NiceCandidate *c = (NiceCandidate *)item->data;

		nice_address_to_string(&c->addr, ipaddr);

		// (foundation),(prio),(addr),(port),(type)
		/*printf(" %s,%u,%s,%u,%s",
		c->foundation,
		c->priority,
		ipaddr,
		nice_address_get_port(&c->addr),
		candidate_type_name[c->type]);*/
		sprintf(mInfo_SendVideo + strlen(mInfo_SendVideo), " %s,%u,%s,%u,%s",
		c->foundation,
		c->priority,
		ipaddr,
		nice_address_get_port(&c->addr),
		candidate_type_name[c->type]);
	}
	printf("\n");

	//printf("\nmInfo_SendVideo:\n");
	//printf("%s\n", mInfo_SendVideo);
	result = EXIT_SUCCESS;

	end:
	if (local_ufrag)
		g_free(local_ufrag);
	if (local_password)
		g_free(local_password);
	if (cands)
		g_slist_free_full(cands, (GDestroyNotify)&nice_candidate_free);

	return result;
}
Пример #10
0
static guint nice_address_hash (const NiceAddress * key)
{
  gchar ip[INET6_ADDRSTRLEN];
  gchar *str;
  guint hash;

  nice_address_to_string (key, ip);
  str = g_strdup_printf ("%s:%u", ip, nice_address_get_port (key));
  hash = g_str_hash (str);
  g_free (str);

  return hash;
}
Пример #11
0
void
local_credentials_to_string(NiceAgent *agent, guint stream_id, guint component_id, gchar** out) {
  gchar buf[1024];
  gchar tmp[1024];
  gchar *local_ufrag = NULL;
  gchar *local_password = NULL;
  gchar ipaddr[INET6_ADDRSTRLEN];
  GSList *cands = NULL, *item;

  if(!nice_agent_get_local_credentials(agent, stream_id,
      &local_ufrag, &local_password)) {
    g_critical("Error reading local credentials!");
    g_object_unref(agent);
    exit(1);
  }

  cands = nice_agent_get_local_candidates(agent, stream_id, component_id);
  if(cands == NULL) {
    g_critical("Error reading local candidates!");
    g_object_unref(agent);
    exit(1);
  }

  sprintf(buf, "%s %s", local_ufrag, local_password);

  for (item = cands; item; item = item->next) {
    NiceCandidate *c = (NiceCandidate *)item->data;

    nice_address_to_string(&c->addr, ipaddr);

    // (foundation),(prio),(addr),(port),(type)
    sprintf(tmp, " %s,%u,%s,%u,%s",
        c->foundation,
        c->priority,
        ipaddr,
        nice_address_get_port(&c->addr),
        candidate_type_name[c->type]);
    strcat(buf, tmp);
  }
  sprintf(tmp, "\n");
  strcat(buf, tmp);

  g_free(local_ufrag);
  g_free(local_password);
  g_slist_free_full(cands, (GDestroyNotify)&nice_candidate_free);

  *out = g_malloc(strlen(buf)+1);
  strcpy(*out, buf);
}
Пример #12
0
void NiceConnection::gatheringDone(uint stream_id) {
    int currentCompId = 1;
    lcands = nice_agent_get_local_candidates(agent_, stream_id, currentCompId++);
    NiceCandidate *cand;
    GSList* iterator;
    gchar *ufrag = NULL, *upass = NULL;
    nice_agent_get_local_credentials(agent_, stream_id, &ufrag, &upass);
    //////False candidate for testing when there is no network (like in the train) :)
    /*
    	NiceCandidate* thecandidate = nice_candidate_new(NICE_CANDIDATE_TYPE_HOST);
    	NiceAddress* naddr = nice_address_new();
    	nice_address_set_from_string(naddr, "127.0.0.1");
    	nice_address_set_port(naddr, 50000);
    	thecandidate->addr = *naddr;
    	char* uname = (char*) malloc(50);
    	char* pass = (char*) malloc(50);
    	sprintf(thecandidate->foundation, "%s", "1");
    	sprintf(uname, "%s", "Pedro");
    	sprintf(pass, "%s", "oooo");

    	thecandidate->username = uname;
    	thecandidate->password = pass;
    	thecandidate->stream_id = (guint) 1;
    	thecandidate->component_id = 1;
    	thecandidate->priority = 1000;
    	thecandidate->transport = NICE_CANDIDATE_TRANSPORT_UDP;
    	lcands = g_slist_append(lcands, thecandidate);
    */

    //	ELOG_DEBUG("gathering done %u",stream_id);
    //ELOG_DEBUG("Candidates---------------------------------------------------->");
    while (lcands != NULL) {
        for (iterator = lcands; iterator; iterator = iterator->next) {
            char address[40], baseAddress[40];
            cand = (NiceCandidate*) iterator->data;
            nice_address_to_string(&cand->addr, address);
            nice_address_to_string(&cand->base_addr, baseAddress);
            if (strstr(address, ":") != NULL) {
                ELOG_DEBUG("Ignoring IPV6 candidate %s", address);
                continue;
            }
//			ELOG_DEBUG("foundation %s", cand->foundation);
//			ELOG_DEBUG("compid %u", cand->component_id);
//			ELOG_DEBUG("stream_id %u", cand->stream_id);
//			ELOG_DEBUG("priority %u", cand->priority);
//			ELOG_DEBUG("username %s", cand->username);
//			ELOG_DEBUG("password %s", cand->password);
            CandidateInfo cand_info;
            cand_info.componentId = cand->component_id;
            cand_info.foundation = cand->foundation;
            cand_info.priority = cand->priority;
            cand_info.hostAddress = std::string(address);
            cand_info.hostPort = nice_address_get_port(&cand->addr);
            cand_info.mediaType = mediaType;

            /*
             *   NICE_CANDIDATE_TYPE_HOST,
             * 	  NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE,
             *	  NICE_CANDIDATE_TYPE_PEER_REFLEXIVE,
             * 	  NICE_CANDIDATE_TYPE_RELAYED,
             */
            switch (cand->type) {
            case NICE_CANDIDATE_TYPE_HOST:
                cand_info.hostType = HOST;
                break;
            case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE:
                cand_info.hostType = SRLFX;
                cand_info.baseAddress = std::string(baseAddress);
                cand_info.basePort = nice_address_get_port(&cand->base_addr);
                break;
            case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE:
                cand_info.hostType = PRFLX;
                break;
            case NICE_CANDIDATE_TYPE_RELAYED:
                ELOG_DEBUG("WARNING TURN NOT IMPLEMENTED YET");
                cand_info.hostType = RELAY;
                break;
            default:
                break;
            }
            cand_info.netProtocol = "udp";
            cand_info.transProtocol = std::string(*transportName);

            cand_info.username = std::string(ufrag);

            cand_info.password = std::string(upass);
            /*
            if (cand->username)
            	cand_info.username = std::string(cand->username);
            else
            	cand_info.username = std::string("(null)");

            if (cand->password)
            	cand_info.password = std::string(cand->password);
            else
            	cand_info.password = std::string("(null)");
            */

            localCandidates->push_back(cand_info);
        }
        lcands = nice_agent_get_local_candidates(agent_, stream_id,
                 currentCompId++);
    }
    ELOG_INFO("candidate_gathering done with %d candidates", localCandidates->size());

    if (localCandidates->size()==0) {
        ELOG_WARN("No local candidates found, check your network connection");
        exit(0);
    }
    updateIceState(NICE_CANDIDATES_GATHERED);
}
Пример #13
0
static void *
example_thread(void *data)
{
  NiceAgent *agent;
  NiceCandidate *local, *remote;
  GIOChannel* io_stdin;
  guint stream_id;
  gchar *line = NULL;
  int rval;

#ifdef G_OS_WIN32
  io_stdin = g_io_channel_win32_new_fd(_fileno(stdin));
#else
  io_stdin = g_io_channel_unix_new(fileno(stdin));
#endif
  g_io_channel_set_flags (io_stdin, G_IO_FLAG_NONBLOCK, NULL);

  // Create the nice agent
  agent = nice_agent_new(g_main_loop_get_context (gloop),
      NICE_COMPATIBILITY_RFC5245);
  if (agent == NULL)
    g_error("Failed to create agent");

  // Set the STUN settings and controlling mode
  if (stun_addr) {
    g_object_set(agent, "stun-server", stun_addr, NULL);
    g_object_set(agent, "stun-server-port", stun_port, NULL);
  }
  g_object_set(agent, "controlling-mode", controlling, NULL);

  // Connect to the signals
  g_signal_connect(agent, "candidate-gathering-done",
      G_CALLBACK(cb_candidate_gathering_done), NULL);
  g_signal_connect(agent, "new-selected-pair",
      G_CALLBACK(cb_new_selected_pair), NULL);
  g_signal_connect(agent, "component-state-changed",
      G_CALLBACK(cb_component_state_changed), NULL);

  // Create a new stream with one component
  stream_id = nice_agent_add_stream(agent, 1);
  if (stream_id == 0)
    g_error("Failed to add stream");

  // Attach to the component to receive the data
  // Without this call, candidates cannot be gathered
  nice_agent_attach_recv(agent, stream_id, 1,
      g_main_loop_get_context (gloop), cb_nice_recv, NULL);

  // Start gathering local candidates
  if (!nice_agent_gather_candidates(agent, stream_id))
    g_error("Failed to start candidate gathering");

  g_debug("waiting for candidate-gathering-done signal...");

  g_mutex_lock(&gather_mutex);
  while (!exit_thread && !candidate_gathering_done)
    g_cond_wait(&gather_cond, &gather_mutex);
  g_mutex_unlock(&gather_mutex);
  if (exit_thread)
    goto end;

  // Candidate gathering is done. Send our local candidates on stdout
  printf("Copy this line to remote client:\n");
  printf("\n  ");
  print_local_data(agent, stream_id, 1);
  printf("\n");

  // Listen on stdin for the remote candidate list
  printf("Enter remote data (single line, no wrapping):\n");
  printf("> ");
  fflush (stdout);
  while (!exit_thread) {
    GIOStatus s = g_io_channel_read_line (io_stdin, &line, NULL, NULL, NULL);
    if (s == G_IO_STATUS_NORMAL) {
      // Parse remote candidate list and set it on the agent
      rval = parse_remote_data(agent, stream_id, 1, line);
      if (rval == EXIT_SUCCESS) {
        g_free (line);
        break;
      } else {
        fprintf(stderr, "ERROR: failed to parse remote data\n");
        printf("Enter remote data (single line, no wrapping):\n");
        printf("> ");
        fflush (stdout);
      }
      g_free (line);
    } else if (s == G_IO_STATUS_AGAIN) {
      g_usleep (100000);
    }
  }

  g_debug("waiting for state READY or FAILED signal...");
  g_mutex_lock(&negotiate_mutex);
  while (!exit_thread && !negotiation_done)
    g_cond_wait(&negotiate_cond, &negotiate_mutex);
  g_mutex_unlock(&negotiate_mutex);
  if (exit_thread)
    goto end;

  // Get current selected candidate pair and print IP address used
  if (nice_agent_get_selected_pair (agent, stream_id, 1,
          &local, &remote)) {
    gchar ipaddr[INET6_ADDRSTRLEN];

    nice_address_to_string(&local->addr, ipaddr);
    printf("\nNegotiation complete: ([%s]:%d,",
        ipaddr, nice_address_get_port(&local->addr));
    nice_address_to_string(&remote->addr, ipaddr);
    printf(" [%s]:%d)\n", ipaddr, nice_address_get_port(&remote->addr));
  }

  // Listen to stdin and send data written to it
  printf("\nSend lines to remote (Ctrl-D to quit):\n");
  printf("> ");
  fflush (stdout);
  while (!exit_thread) {
    GIOStatus s = g_io_channel_read_line (io_stdin, &line, NULL, NULL, NULL);
    if (s == G_IO_STATUS_NORMAL) {
      nice_agent_send(agent, stream_id, 1, strlen(line), line);
      g_free (line);
      printf("> ");
      fflush (stdout);
    } else if (s == G_IO_STATUS_AGAIN) {
      g_usleep (100000);
    } else {
      // Ctrl-D was pressed.
      nice_agent_send(agent, stream_id, 1, 1, "\0");
      break;
    }
  }

end:
  g_io_channel_unref (io_stdin);
  g_object_unref(agent);
  g_main_loop_quit (gloop);

  return NULL;
}
Пример #14
0
  void NiceConnection::getCandidate(uint stream_id, uint component_id, const std::string &foundation) {
    GSList* lcands = nice_agent_get_local_candidates(agent_, stream_id, component_id);
    // We only want to get the new candidates
    int listLength = g_slist_length(lcands);
    ELOG_DEBUG("List length %u, candsDelivered %u", listLength, candsDelivered_);
    if (candsDelivered_ <= g_slist_length(lcands)){
      lcands = g_slist_nth(lcands, (candsDelivered_));
    }
    ELOG_DEBUG("getCandidate %u", g_slist_length(lcands));
    for (GSList* iterator = lcands; iterator; iterator = iterator->next) {
      ELOG_DEBUG("Candidate");
      char address[NICE_ADDRESS_STRING_LEN], baseAddress[NICE_ADDRESS_STRING_LEN];
      NiceCandidate *cand = (NiceCandidate*) iterator->data;
      nice_address_to_string(&cand->addr, address);
      nice_address_to_string(&cand->base_addr, baseAddress);
      candsDelivered_++;
      if (strstr(address, ":") != NULL) { // We ignore IPv6 candidates at this point
        continue;
      }
      CandidateInfo cand_info;
      cand_info.componentId = cand->component_id;
      cand_info.foundation = cand->foundation;
      cand_info.priority = cand->priority;
      cand_info.hostAddress = std::string(address);
      cand_info.hostPort = nice_address_get_port(&cand->addr);
      cand_info.mediaType = mediaType;

      /*
       *   NICE_CANDIDATE_TYPE_HOST,
       *    NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE,
       *    NICE_CANDIDATE_TYPE_PEER_REFLEXIVE,
       *    NICE_CANDIDATE_TYPE_RELAYED,
       */
      switch (cand->type) {
        case NICE_CANDIDATE_TYPE_HOST:
          cand_info.hostType = HOST;
          break;
        case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE:
          cand_info.hostType = SRFLX;
          cand_info.rAddress = std::string(baseAddress);
          cand_info.rPort = nice_address_get_port(&cand->base_addr);
          break;
        case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE:
          cand_info.hostType = PRFLX;
          break;
        case NICE_CANDIDATE_TYPE_RELAYED:
          char turnAddres[NICE_ADDRESS_STRING_LEN];
          ELOG_DEBUG("TURN LOCAL CANDIDATE");
          nice_address_to_string(&cand->turn->server,turnAddres);
          ELOG_DEBUG("address %s", address);
          ELOG_DEBUG("baseAddress %s", baseAddress);
          ELOG_DEBUG("stream_id %u", cand->stream_id);
          ELOG_DEBUG("priority %u", cand->priority);
          ELOG_DEBUG("TURN ADDRESS %s", turnAddres);

          cand_info.hostType = RELAY;
          cand_info.rAddress = std::string(baseAddress);
          cand_info.rPort = nice_address_get_port(&cand->base_addr);
          break;
        default:
          break;
      }
      cand_info.netProtocol = "udp";
      cand_info.transProtocol = std::string(*transportName.get());
      cand_info.username = ufrag_;
      cand_info.password = upass_;
      //localCandidates->push_back(cand_info);
      this->getNiceListener()->onCandidate(cand_info, this);
    }
    // for nice_agent_get_local_candidates,  the caller owns the returned GSList as well as the candidates contained within it.
    // let's free everything in the list, as well as the list.
    g_slist_free_full(lcands, (GDestroyNotify)&nice_candidate_free);

  }
Пример #15
0
NiceSocket *
nice_http_socket_new (NiceSocket *base_socket,
    NiceAddress *addr, gchar *username, gchar *password)
{
  HttpPriv *priv;
  NiceSocket *sock = NULL;

  if (addr) {
    sock = g_slice_new0 (NiceSocket);
    sock->priv = priv = g_slice_new0 (HttpPriv);

    priv->base_socket = base_socket;
    priv->addr = *addr;
    priv->username = g_strdup (username);
    priv->password = g_strdup (password);
    priv->recv_buf = NULL;
    priv->recv_buf_length = 0;
    priv->recv_buf_pos = 0;
    priv->recv_buf_fill = 0;
    priv->content_length = 0;

    sock->type = NICE_SOCKET_TYPE_HTTP;
    sock->fileno = priv->base_socket->fileno;
    sock->addr = priv->base_socket->addr;
    sock->send_messages = socket_send_messages;
    sock->send_messages_reliable = socket_send_messages_reliable;
    sock->recv_messages = socket_recv_messages;
    sock->is_reliable = socket_is_reliable;
    sock->can_send = socket_can_send;
    sock->set_writable_callback = socket_set_writable_callback;
    sock->close = socket_close;

    /* Send HTTP CONNECT */
    {
      gchar *msg = NULL;
      gchar *credential = NULL;
      gchar host[INET6_ADDRSTRLEN];
      gint port = nice_address_get_port (&priv->addr);
      GOutputVector local_bufs;
      NiceOutputMessage local_messages;

      nice_address_to_string (&priv->addr, host);

      if (username) {
        gchar * userpass = g_strdup_printf ("%s:%s", username,
            password ? password : "");
        gchar * auth = g_base64_encode ((guchar *)userpass, strlen (userpass));
        credential = g_strdup_printf ("Proxy-Authorization: Basic %s\r\n", auth);
        g_free (auth);
        g_free (userpass);
      }
      msg = g_strdup_printf ("CONNECT %s:%d HTTP/1.0\r\n"
          "Host: %s\r\n"
          "User-Agent: %s\r\n"
          "Content-Length: 0\r\n"
          "Proxy-Connection: Keep-Alive\r\n"
          "Connection: Keep-Alive\r\n"
          "Cache-Control: no-cache\r\n"
          "Pragma: no-cache\r\n"
          "%s\r\n", host, port, host, HTTP_USER_AGENT,
          credential? credential : "" );
      g_free (credential);

      local_bufs.buffer = msg;
      local_bufs.size = strlen (msg);
      local_messages.buffers = &local_bufs;
      local_messages.n_buffers = 1;

      nice_socket_send_messages_reliable (priv->base_socket, NULL,
          &local_messages, 1);
      priv->state = HTTP_STATE_INIT;
      g_free (msg);
    }
  }

  return sock;
}
Пример #16
0
void soy_net_xmpp_agent_add_local_candidates (soynetXMPPAgent* self, LmMessageNode* transport, GSList* lcands) {
	GSList* _tmp0_ = NULL;
#line 98 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
	g_return_if_fail (self != NULL);
#line 98 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
	g_return_if_fail (transport != NULL);
#line 99 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
	_tmp0_ = lcands;
#line 357 "XMPPAgent.c"
	{
		GSList* nice_candidate_collection = NULL;
		GSList* nice_candidate_it = NULL;
#line 99 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
		nice_candidate_collection = _tmp0_;
#line 99 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
		for (nice_candidate_it = nice_candidate_collection; nice_candidate_it != NULL; nice_candidate_it = nice_candidate_it->next) {
#line 365 "XMPPAgent.c"
			NiceCandidate* nice_candidate = NULL;
#line 99 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
			nice_candidate = (NiceCandidate*) nice_candidate_it->data;
#line 369 "XMPPAgent.c"
			{
				gchar* addr = NULL;
				gchar* _tmp1_ = NULL;
				NiceCandidate* _tmp2_ = NULL;
				const gchar* _tmp3_ = NULL;
				LmMessageNode* candidate = NULL;
				LmMessageNode* _tmp4_ = NULL;
				LmMessageNode* _tmp5_ = NULL;
				LmMessageNode* _tmp6_ = NULL;
				LmMessageNode* _tmp7_ = NULL;
				NiceCandidate* _tmp8_ = NULL;
				guint _tmp9_ = 0U;
				gchar* _tmp10_ = NULL;
				gchar* _tmp11_ = NULL;
				LmMessageNode* _tmp12_ = NULL;
				NiceCandidate* _tmp13_ = NULL;
				gchar* _tmp14_ = NULL;
				gint _tmp14__length1 = 0;
				LmMessageNode* _tmp15_ = NULL;
				LmMessageNode* _tmp16_ = NULL;
				const gchar* _tmp17_ = NULL;
				LmMessageNode* _tmp18_ = NULL;
				LmMessageNode* _tmp19_ = NULL;
				NiceCandidate* _tmp20_ = NULL;
				guint _tmp21_ = 0U;
				gchar* _tmp22_ = NULL;
				gchar* _tmp23_ = NULL;
				LmMessageNode* _tmp24_ = NULL;
				NiceCandidate* _tmp25_ = NULL;
				guint32 _tmp26_ = 0U;
				gchar* _tmp27_ = NULL;
				gchar* _tmp28_ = NULL;
				LmMessageNode* _tmp29_ = NULL;
				LmMessageNode* _tmp30_ = NULL;
				GeeHashMap* _tmp31_ = NULL;
				NiceCandidate* _tmp32_ = NULL;
				NiceCandidateType _tmp33_ = 0;
				gpointer _tmp34_ = NULL;
				gchar* _tmp35_ = NULL;
#line 100 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp1_ = g_new0 (gchar, 100);
#line 100 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				addr = (gchar*) _tmp1_;
#line 101 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp2_ = nice_candidate;
#line 101 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp3_ = addr;
#line 101 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				nice_address_to_string (&_tmp2_->addr, _tmp3_);
#line 103 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp4_ = transport;
#line 103 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp5_ = lm_message_node_add_child (_tmp4_, "candidate", NULL);
#line 103 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp6_ = _lm_message_node_ref0 (_tmp5_);
#line 103 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				candidate = _tmp6_;
#line 104 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp7_ = candidate;
#line 104 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp8_ = nice_candidate;
#line 104 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp9_ = _tmp8_->stream_id;
#line 104 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp10_ = g_strdup_printf ("%u", _tmp9_);
#line 104 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp11_ = _tmp10_;
#line 104 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				lm_message_node_set_attribute (_tmp7_, "component", _tmp11_);
#line 104 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_g_free0 (_tmp11_);
#line 105 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp12_ = candidate;
#line 105 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp13_ = nice_candidate;
#line 105 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp14_ = _tmp13_->foundation;
#line 105 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp14__length1 = -1;
#line 105 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				lm_message_node_set_attribute (_tmp12_, "foundation", (const gchar*) _tmp14_);
#line 108 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp15_ = candidate;
#line 108 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				lm_message_node_set_attribute (_tmp15_, "id", "TBD");
#line 109 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp16_ = candidate;
#line 109 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp17_ = addr;
#line 109 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				lm_message_node_set_attribute (_tmp16_, "ip", _tmp17_);
#line 112 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp18_ = candidate;
#line 112 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				lm_message_node_set_attribute (_tmp18_, "network", "0");
#line 113 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp19_ = candidate;
#line 113 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp20_ = nice_candidate;
#line 113 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp21_ = nice_address_get_port (&_tmp20_->addr);
#line 113 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp22_ = g_strdup_printf ("%u", _tmp21_);
#line 113 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp23_ = _tmp22_;
#line 113 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				lm_message_node_set_attribute (_tmp19_, "port", _tmp23_);
#line 113 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_g_free0 (_tmp23_);
#line 114 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp24_ = candidate;
#line 114 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp25_ = nice_candidate;
#line 114 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp26_ = _tmp25_->priority;
#line 114 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp27_ = g_strdup_printf ("%u", _tmp26_);
#line 114 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp28_ = _tmp27_;
#line 114 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				lm_message_node_set_attribute (_tmp24_, "priority", _tmp28_);
#line 114 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_g_free0 (_tmp28_);
#line 115 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp29_ = candidate;
#line 115 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				lm_message_node_set_attribute (_tmp29_, "protocol", "udp");
#line 116 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp30_ = candidate;
#line 116 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp31_ = soy_net_xmpp_agent_candidate_type_strs;
#line 116 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp32_ = nice_candidate;
#line 116 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp33_ = _tmp32_->type;
#line 116 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp34_ = gee_abstract_map_get ((GeeAbstractMap*) _tmp31_, (gpointer) ((gintptr) ((gint) _tmp33_)));
#line 116 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_tmp35_ = (gchar*) _tmp34_;
#line 116 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				lm_message_node_set_attribute (_tmp30_, "type", _tmp35_);
#line 116 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_g_free0 (_tmp35_);
#line 99 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_lm_message_node_unref0 (candidate);
#line 99 "/home/jeff/Documents/libraries/libsoy/src/net/XMPPAgent.gs"
				_g_free0 (addr);
#line 517 "XMPPAgent.c"
			}
		}
	}
}
Пример #17
0
  void NiceConnection::gatheringDone(uint stream_id) {
    if (this->checkIceState() >= NICE_FINISHED) {
      ELOG_DEBUG("gathering Done after FINISHED");
      nice_agent_remove_stream (agent_,1);
      return;
    }
    ELOG_DEBUG("Gathering Done %p", this);
    int currentCompId = 1;
    GSList* lcands = nice_agent_get_local_candidates(agent_, stream_id, currentCompId++);
    gchar *ufrag = NULL, *upass = NULL;
    nice_agent_get_local_credentials(agent_, stream_id, &ufrag, &upass);
    while (lcands != NULL) {
      for (GSList* iterator = lcands; iterator; iterator = iterator->next) {
        char address[NICE_ADDRESS_STRING_LEN], baseAddress[NICE_ADDRESS_STRING_LEN];
        NiceCandidate *cand = (NiceCandidate*) iterator->data;
        nice_address_to_string(&cand->addr, address);
        nice_address_to_string(&cand->base_addr, baseAddress);
        if (strstr(address, ":") != NULL) {
          ELOG_DEBUG("Ignoring IPV6 candidate %s %p", address, this);
          continue;
        }

        CandidateInfo cand_info;
        cand_info.componentId = cand->component_id;
        cand_info.foundation = cand->foundation;
        cand_info.priority = cand->priority;
        cand_info.hostAddress = std::string(address);
        cand_info.hostPort = nice_address_get_port(&cand->addr);
        cand_info.mediaType = mediaType;

        /*
         *   NICE_CANDIDATE_TYPE_HOST,
         * 	  NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE,
         *	  NICE_CANDIDATE_TYPE_PEER_REFLEXIVE,
         * 	  NICE_CANDIDATE_TYPE_RELAYED,
         */
        switch (cand->type) {
          case NICE_CANDIDATE_TYPE_HOST:
            cand_info.hostType = HOST;
            break;
          case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE:
            cand_info.hostType = SRFLX;
            cand_info.rAddress = std::string(baseAddress);
            cand_info.rPort = nice_address_get_port(&cand->base_addr);
            break;
          case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE:
            cand_info.hostType = PRFLX;
            break;
          case NICE_CANDIDATE_TYPE_RELAYED:
            char turnAddres[NICE_ADDRESS_STRING_LEN];
            ELOG_DEBUG("TURN LOCAL CANDIDATE");
            nice_address_to_string(&cand->turn->server,turnAddres);
        		ELOG_DEBUG("address %s", address);
        		ELOG_DEBUG("baseAddress %s", baseAddress);
        		ELOG_DEBUG("stream_id %u", cand->stream_id);
        		ELOG_DEBUG("priority %u", cand->priority);
        		ELOG_DEBUG("TURN ADDRESS %s", turnAddres);
           
            cand_info.hostType = RELAY;
            cand_info.rAddress = std::string(baseAddress);
            cand_info.rPort = nice_address_get_port(&cand->base_addr);
            break;
          default:
            break;
        }
        cand_info.netProtocol = "udp";
        cand_info.transProtocol = std::string(*transportName.get());
        cand_info.username = std::string(ufrag);
        cand_info.password = std::string(upass);
        localCandidates->push_back(cand_info);
      }
      // for nice_agent_get_local_candidates,  the caller owns the returned GSList as well as the candidates contained within it.
      // let's free everything in the list, as well as the list.
      g_slist_free_full(lcands, (GDestroyNotify)&nice_candidate_free);
      lcands = nice_agent_get_local_candidates(agent_, stream_id, currentCompId++);
    }
    // According to libnice, this is how these must be free'd
    g_free(ufrag);
    g_free(upass);

    ELOG_INFO("candidate_gathering done with %lu candidates %p", localCandidates->size(), this);

    if (localCandidates->size()==0){
      ELOG_WARN("No local candidates found, check your network connection");
      exit(0);
    }
    updateIceState(NICE_CANDIDATES_GATHERED);
  }
Пример #18
0
OwrCandidate * _owr_candidate_new_from_nice_candidate(NiceCandidate *nice_candidate)
{
    OwrCandidate *owr_candidate;
    OwrCandidateType candidate_type = -1;
    OwrComponentType component_type = -1;
    OwrTransportType transport_type = -1;
    gchar *address;
    guint port;

    g_return_val_if_fail(nice_candidate, NULL);

    switch (nice_candidate->type) {
    case NICE_CANDIDATE_TYPE_HOST:
        candidate_type = OWR_CANDIDATE_TYPE_HOST;
        break;

    case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE:
        candidate_type = OWR_CANDIDATE_TYPE_SERVER_REFLEXIVE;
        break;

    case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE:
        candidate_type = OWR_CANDIDATE_TYPE_PEER_REFLEXIVE;
        break;

    case NICE_CANDIDATE_TYPE_RELAYED:
        candidate_type = OWR_CANDIDATE_TYPE_RELAY;
        break;
    }
    g_return_val_if_fail(candidate_type != (OwrCandidateType)-1, NULL);

    switch (nice_candidate->component_id) {
    case NICE_COMPONENT_TYPE_RTP:
        component_type = OWR_COMPONENT_TYPE_RTP;
        break;

    case NICE_COMPONENT_TYPE_RTCP:
        component_type = OWR_COMPONENT_TYPE_RTCP;
        break;
    }
    g_return_val_if_fail(component_type != (OwrComponentType)-1, NULL);

    switch (nice_candidate->transport) {
    case NICE_CANDIDATE_TRANSPORT_UDP:
        transport_type = OWR_TRANSPORT_TYPE_UDP;
        break;

    case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
        transport_type = OWR_TRANSPORT_TYPE_TCP_ACTIVE;
        break;

    case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
        transport_type = OWR_TRANSPORT_TYPE_TCP_PASSIVE;
        break;

    case NICE_CANDIDATE_TRANSPORT_TCP_SO:
        transport_type = OWR_TRANSPORT_TYPE_TCP_SO;
        break;
    }
    g_return_val_if_fail(transport_type != (OwrTransportType)-1, NULL);

    owr_candidate = owr_candidate_new(candidate_type, component_type);

    g_object_set(G_OBJECT(owr_candidate), "transport_type", transport_type, NULL);

    address = g_new0(gchar, NICE_ADDRESS_STRING_LEN);
    nice_address_to_string(&nice_candidate->addr, address);
    g_object_set(G_OBJECT(owr_candidate), "address", address, NULL);
    g_free(address);

    port = nice_address_get_port(&nice_candidate->addr);
    g_object_set(G_OBJECT(owr_candidate), "port", port, NULL);

    address = g_new0(gchar, NICE_ADDRESS_STRING_LEN);
    nice_address_to_string(&nice_candidate->base_addr, address);
    g_object_set(G_OBJECT(owr_candidate), "base-address", address, NULL);
    g_free(address);

    port = nice_address_get_port(&nice_candidate->base_addr);
    g_object_set(G_OBJECT(owr_candidate), "base-port", port, NULL);

    g_object_set(G_OBJECT(owr_candidate), "priority", nice_candidate->priority, NULL);
    g_object_set(G_OBJECT(owr_candidate), "foundation", nice_candidate->foundation, NULL);

    g_object_set(G_OBJECT(owr_candidate), "ufrag", nice_candidate->username, NULL);
    g_object_set(G_OBJECT(owr_candidate), "password", nice_candidate->password, NULL);

    return owr_candidate;
}
Пример #19
0
/* 
 * Timer callback that handles scheduling new candidate discovery
 * processes (paced by the Ta timer), and handles running of the 
 * existing discovery processes.
 *
 * This function is designed for the g_timeout_add() interface.
 *
 * @return will return FALSE when no more pending timers.
 */
static gboolean priv_discovery_tick_unlocked (gpointer pointer)
{
  CandidateDiscovery *cand;
  NiceAgent *agent = pointer;
  GSList *i;
  int not_done = 0; /* note: track whether to continue timer */
  size_t buffer_len = 0;

  {
    static int tick_counter = 0;
    if (tick_counter++ % 50 == 0)
      nice_debug ("Agent %p : discovery tick #%d with list %p (1)", agent, tick_counter, agent->discovery_list);
  }

  for (i = agent->discovery_list; i ; i = i->next) {
    cand = i->data;

    if (cand->pending != TRUE) {
      cand->pending = TRUE;

      if (agent->discovery_unsched_items)
	--agent->discovery_unsched_items;

      if (nice_debug_is_enabled ()) {
        gchar tmpbuf[INET6_ADDRSTRLEN];
        nice_address_to_string (&cand->server, tmpbuf);
        nice_debug ("Agent %p : discovery - scheduling cand type %u addr %s.",
            agent, cand->type, tmpbuf);
      }
      if (nice_address_is_valid (&cand->server) &&
          (cand->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ||
              cand->type == NICE_CANDIDATE_TYPE_RELAYED)) {

        if (cand->component->state == NICE_COMPONENT_STATE_DISCONNECTED ||
            cand->component->state == NICE_COMPONENT_STATE_FAILED)
          agent_signal_component_state_change (agent,
					       cand->stream->id,
					       cand->component->id,
					       NICE_COMPONENT_STATE_GATHERING);

        if (cand->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE) {
          buffer_len = stun_usage_bind_create (&cand->stun_agent,
              &cand->stun_message, cand->stun_buffer, sizeof(cand->stun_buffer));
        } else if (cand->type == NICE_CANDIDATE_TYPE_RELAYED) {
          uint8_t *username = (uint8_t *)cand->turn->username;
          gsize username_len = strlen (cand->turn->username);
          uint8_t *password = (uint8_t *)cand->turn->password;
          gsize password_len = strlen (cand->turn->password);
          StunUsageTurnCompatibility turn_compat =
              agent_to_turn_compatibility (agent);

          if (turn_compat == STUN_USAGE_TURN_COMPATIBILITY_MSN ||
              turn_compat == STUN_USAGE_TURN_COMPATIBILITY_OC2007) {
            username = g_base64_decode ((gchar *)username, &username_len);
            password = g_base64_decode ((gchar *)password, &password_len);
          }

          buffer_len = stun_usage_turn_create (&cand->stun_agent,
              &cand->stun_message,  cand->stun_buffer, sizeof(cand->stun_buffer),
              cand->stun_resp_msg.buffer == NULL ? NULL : &cand->stun_resp_msg,
              STUN_USAGE_TURN_REQUEST_PORT_NORMAL,
              -1, -1,
              username, username_len,
              password, password_len,
              turn_compat);

          if (turn_compat == STUN_USAGE_TURN_COMPATIBILITY_MSN ||
              turn_compat == STUN_USAGE_TURN_COMPATIBILITY_OC2007) {
            g_free (username);
            g_free (password);
          }
        }

	if (buffer_len > 0) {
          if (nice_socket_is_reliable (cand->nicesock)) {
            stun_timer_start_reliable (&cand->timer, agent->stun_reliable_timeout);
          } else {
            stun_timer_start (&cand->timer,
                agent->stun_initial_timeout,
                agent->stun_max_retransmissions);
          }

          /* send the conncheck */
          agent_socket_send (cand->nicesock, &cand->server,
              buffer_len, (gchar *)cand->stun_buffer);

	  /* case: success, start waiting for the result */
	  g_get_current_time (&cand->next_tick);

	} else {
	  /* case: error in starting discovery, start the next discovery */
	  cand->done = TRUE;
	  cand->stun_message.buffer = NULL;
	  cand->stun_message.buffer_len = 0;
	  continue;
	}
      }
      else
	/* allocate relayed candidates */
	g_assert_not_reached ();

      ++not_done; /* note: new discovery scheduled */
    }

    if (cand->done != TRUE) {
      GTimeVal now;

      g_get_current_time (&now);

      if (cand->stun_message.buffer == NULL) {
	nice_debug ("Agent %p : STUN discovery was cancelled, marking discovery done.", agent);
	cand->done = TRUE;
      }
      else if (priv_timer_expired (&cand->next_tick, &now)) {
        switch (stun_timer_refresh (&cand->timer)) {
          case STUN_USAGE_TIMER_RETURN_TIMEOUT:
            {
              /* Time out */
              /* case: error, abort processing */
              StunTransactionId id;

              stun_message_id (&cand->stun_message, id);
              stun_agent_forget_transaction (&cand->stun_agent, id);

              cand->done = TRUE;
              cand->stun_message.buffer = NULL;
              cand->stun_message.buffer_len = 0;
              nice_debug ("Agent %p : bind discovery timed out, aborting discovery item.", agent);
              break;
            }
          case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
            {
              /* case: not ready complete, so schedule next timeout */
              unsigned int timeout = stun_timer_remainder (&cand->timer);

              stun_debug ("STUN transaction retransmitted (timeout %dms).",
                  timeout);

              /* retransmit */
              agent_socket_send (cand->nicesock, &cand->server,
                  stun_message_length (&cand->stun_message),
                  (gchar *)cand->stun_buffer);

              /* note: convert from milli to microseconds for g_time_val_add() */
              cand->next_tick = now;
              g_time_val_add (&cand->next_tick, timeout * 1000);

              ++not_done; /* note: retry later */
              break;
            }
          case STUN_USAGE_TIMER_RETURN_SUCCESS:
            {
              unsigned int timeout = stun_timer_remainder (&cand->timer);

              cand->next_tick = now;
              g_time_val_add (&cand->next_tick, timeout * 1000);

              ++not_done; /* note: retry later */
              break;
            }
          default:
            /* Nothing to do. */
            break;
	}

      } else {
	++not_done; /* note: discovery not expired yet */
      }
    }
  }

  if (not_done == 0) {
    nice_debug ("Agent %p : Candidate gathering FINISHED, stopping discovery timer.", agent);

    discovery_free (agent);

    agent_gathering_done (agent);

    /* note: no pending timers, return FALSE to stop timer */
    return FALSE;
  }

  return TRUE;
}