Ejemplo n.º 1
0
/* Start ICE negotiation on the endpoint, based on parameter from
 * the other endpoint.
 */
static pj_status_t start_ice(struct ice_ept *ept, const struct ice_ept *remote)
{
    pj_ice_sess_cand rcand[32];
    unsigned i, rcand_cnt = 0;
    pj_status_t status;

    /* Enum remote candidates */
    for (i=0; i<remote->cfg.comp_cnt; ++i) {
	unsigned cnt = PJ_ARRAY_SIZE(rcand) - rcand_cnt;
	status = pj_ice_strans_enum_cands(remote->ice, i+1, &cnt, rcand+rcand_cnt);
	if (status != PJ_SUCCESS) {
	    app_perror(INDENT "err: pj_ice_strans_enum_cands()", status);
	    return status;
	}
	rcand_cnt += cnt;
    }

    status = pj_ice_strans_start_ice(ept->ice, &remote->ufrag, &remote->pass,
				     rcand_cnt, rcand);
    if (status != PJ_SUCCESS) {
	app_perror(INDENT "err: pj_ice_strans_start_ice()", status);
	return status;
    }

    return PJ_SUCCESS;
}
Ejemplo n.º 2
0
static int extract_sdp_to_xml(struct ice_trans_s* icetrans,char buffer[], unsigned maxlen, ice_option_t opt, char *usrid)
{
    char *p = buffer;
    unsigned comp;
    int printed;
    pj_str_t local_ufrag, local_pwd;
    pj_status_t status;

    //Me: add

    PRINT(" <registerPeer>");
    PRINT("<device> <uniqueId>%s</uniqueId> </device>", usrid);



    /* Write "dummy" SDP v=, o=, s=, and t= lines */
    // Me: comment
    //PRINT("v=0\no=- 3414953978 3414953978 IN IP4 localhost\ns=ice\nt=0 0\n");

    /* Get ufrag and pwd from current session */
    pj_ice_strans_get_ufrag_pwd(icetrans->icest, &local_ufrag, &local_pwd,
                                NULL, NULL);


    /* Write the a=ice-ufrag and a=ice-pwd attributes */
    // Me: comment
    //PRINT("a=ice-ufrag:%.*s\na=ice-pwd:%.*s\n",
    //      (int)local_ufrag.slen,
    //      local_ufrag.ptr,
    //      (int)local_pwd.slen,
    //      local_pwd.ptr);

    PRINT("<ufrag>%.*s</ufrag> <pwd>%.*s</pwd>",
          (int)local_ufrag.slen,
          local_ufrag.ptr,
          (int)local_pwd.slen,
          local_pwd.ptr);


    PRINT(" <candidateList>");

    /* Write each component */
    for (comp=0; comp<opt.comp_cnt; ++comp) {
        unsigned j, cand_cnt;
        pj_ice_sess_cand cand[PJ_ICE_ST_MAX_CAND];
        char ipaddr[PJ_INET6_ADDRSTRLEN];

        /* Get default candidate for the component */
        status = pj_ice_strans_get_def_cand(icetrans->icest, comp+1, &cand[0]);
        if (status != PJ_SUCCESS)
            return -status;

        /* Write the default address */
        if (comp==0) {
            /* For component 1, default address is in m= and c= lines */
            // Me: comment
            // PRINT("m=audio %d RTP/AVP 0\n"
            //      "c=IN IP4 %s\n",
            //      (int)pj_sockaddr_get_port(&cand[0].addr),
            //      pj_sockaddr_print(&cand[0].addr, ipaddr,
            //                        sizeof(ipaddr), 0));

            PRINT("<comp_1> <port>%d</port>"
                  "<ip>%s</ip> </comp_1>",
                  (int)pj_sockaddr_get_port(&cand[0].addr),
                  pj_sockaddr_print(&cand[0].addr, ipaddr,
                                    sizeof(ipaddr), 0));

        } else if (comp==1) {
            /* For component 2, default address is in a=rtcp line */
            //Me: comment
            //PRINT("a=rtcp:%d IN IP4 %s\n",
            //      (int)pj_sockaddr_get_port(&cand[0].addr),
            //      pj_sockaddr_print(&cand[0].addr, ipaddr,
            //                        sizeof(ipaddr), 0));
        } else {
            /* For other components, we'll just invent this.. */
            // Me: comment
            //PRINT("a=Xice-defcand:%d IN IP4 %s\n",
            //      (int)pj_sockaddr_get_port(&cand[0].addr),
            //      pj_sockaddr_print(&cand[0].addr, ipaddr,
            //                        sizeof(ipaddr), 0));
        }

        /* Enumerate all candidates for this component */
        cand_cnt = PJ_ARRAY_SIZE(cand);
        status = pj_ice_strans_enum_cands(icetrans->icest, comp+1,
                                          &cand_cnt, cand);
        if (status != PJ_SUCCESS)
            return -status;

        /* And encode the candidates as SDP */
        //const int buffer_xml_len = 2048;
        //char buffer_xml[buffer_xml_len];
        for (j=0; j<cand_cnt; ++j) {
            printed = print_cand_to_xml(p, maxlen - (unsigned)(p-buffer), &cand[j]);
            if (printed < 0)
                return -PJ_ETOOSMALL;
         //   printed = print_cand_to_xml(p, maxlen - (unsigned)(p-buffer), &cand[j]);
         //   if (printed < 0)
          //      return -PJ_ETOOSMALL;
            p += printed;
        }
    }
    PRINT("</candidateList>");

    PRINT(" </registerPeer>");

    if (p == buffer+maxlen)
        return -PJ_ETOOSMALL;

    *p = '\0';

    //printf("DEBUGGGGGG: %s \n", (p - buffer);
    return (int)(p - buffer);
}
Ejemplo n.º 3
0
int krx_ice_start_session(krx_ice* k) {

  pj_status_t r;

  if(!k) { return - 1; } 
  if(!k->ice_st) { return -2; } 

  if(pj_ice_strans_has_sess(k->ice_st)) {
    printf("Error: ice already has a session.\n");
    return -3;
  }

  
  r = pj_ice_strans_init_ice(k->ice_st, PJ_ICE_SESS_ROLE_CONTROLLED, NULL, NULL);
  if(r != PJ_SUCCESS) {
    printf("Error: cannot initialize an ice session.\n");
    return -4;
  }

  /* this is where we can create an sdp */
  char sdp_buf[8096] = { 0 } ;
  sprintf(sdp_buf,
          "v=0\n" 
          "o=- 123456789 34234324 IN IP4 localhost\n"    /* - [identifier] [session version] IN IP4 localhost */
          "s=krx_ice\n"                                  /* software */
          "t=0 0\n"                                      /* start, ending time */
          "a=ice-ufrag:%s\n"
          "a=ice-pwd:%s\n"
          ,
          k->ice_ufrag,
          k->ice_pwd
  );

  /* write each component */
  for(int i = 0; i < k->ncomp; ++i) {

    pj_ice_sess_cand cand[PJ_ICE_ST_MAX_CAND] = { 0 } ;
    char ipaddr[PJ_INET6_ADDRSTRLEN] = { 0 } ;

    /* get default candidate for component, note that compoments start numbering from 1, not zero. */
    r = pj_ice_strans_get_def_cand(k->ice_st, 1, &cand[0]);
    if(r != PJ_SUCCESS) {
      printf("Error: cannot retrieve default candidate for component: %d\n", i+1);
      continue;
    }

    if(i == 0) {
      int offset = strlen(sdp_buf);
      sprintf(sdp_buf + offset, 
              "m=video %d RTP/SAVPF 120\n"
              "c=IN IP4 %s\n"
              ,
              (int)pj_sockaddr_get_port(&cand[0].addr),
              pj_sockaddr_print(&cand[0].addr, ipaddr, sizeof(ipaddr), 0)              
      );

      /* print all candidates */
      unsigned num_cands = PJ_ARRAY_SIZE(cand);
      printf("Found number of candidates: %d\n", num_cands);      

      // (ice_st && ice_st->ice && comp_id && comp_id <= ice_st->comp_cnt && count && cand),
      printf("ice: %p\n", k->ice_st);
      r = pj_ice_strans_enum_cands(k->ice_st, i + 1, &num_cands, cand);
      if(r != PJ_SUCCESS) {
        printf("Error: cannot retrieve candidates.\n");
        exit(1);
      }


#if 1

      for(int j = 0; j < num_cands; ++j) {
        int offset = strlen(sdp_buf);
        char* start_addr = sdp_buf + offset;
        krx_ice_candidate_to_string(sdp_buf, sizeof(sdp_buf)-offset, &cand[j]);
        char* end_addr = sdp_buf + strlen(sdp_buf);
        printf("--------\n%s\n--------------\n", sdp_buf);
      }

      offset = strlen(sdp_buf);
      char* start_addr = sdp_buf + offset;
      krx_ice_candidate_to_string(sdp_buf + offset, sizeof(sdp_buf)-offset, &cand[1]);
      char* end_addr = sdp_buf + strlen(sdp_buf);
#endif
    }


  }


  printf("SDP: %s\n", sdp_buf);
          

  r = pj_ice_strans_init_ice(k->ice_st, PJ_ICE_SESS_ROLE_CONTROLLED, NULL, NULL);
  CHECK_PJ_STATUS(r, "Error: cannot init ice session.\n", -4);

  return 0;
}
Ejemplo n.º 4
0
/* 
 * Encode ICE information in SDP.
 */
static int encode_session(char buffer[], unsigned maxlen)
{
    char *p = buffer;
    unsigned comp;
    int printed;
    pj_str_t local_ufrag, local_pwd;
    pj_status_t status;

    /* Write "dummy" SDP v=, o=, s=, and t= lines */
    PRINT("v=0\no=- 3414953978 3414953978 IN IP4 localhost\ns=ice\nt=0 0\n", 
	  0, 0, 0, 0, 0, 0);

    /* Get ufrag and pwd from current session */
    pj_ice_strans_get_ufrag_pwd(icedemo.icest, &local_ufrag, &local_pwd,
				NULL, NULL);

    /* Write the a=ice-ufrag and a=ice-pwd attributes */
    PRINT("a=ice-ufrag:%.*s\na=ice-pwd:%.*s\n",
	   (int)local_ufrag.slen,
	   local_ufrag.ptr,
	   (int)local_pwd.slen,
	   local_pwd.ptr, 
	   0, 0);

    /* Write each component */
    for (comp=0; comp<icedemo.opt.comp_cnt; ++comp) {
	unsigned j, cand_cnt;
	pj_ice_sess_cand cand[PJ_ICE_ST_MAX_CAND];
	char ipaddr[PJ_INET6_ADDRSTRLEN];

	/* Get default candidate for the component */
	status = pj_ice_strans_get_def_cand(icedemo.icest, comp+1, &cand[0]);
	if (status != PJ_SUCCESS)
	    return -status;

	/* Write the default address */
	if (comp==0) {
	    /* For component 1, default address is in m= and c= lines */
	    PRINT("m=audio %d RTP/AVP 0\n"
		  "c=IN IP4 %s\n",
		  (int)pj_sockaddr_get_port(&cand[0].addr),
		  pj_sockaddr_print(&cand[0].addr, ipaddr,
				    sizeof(ipaddr), 0),
		  0, 0, 0, 0);
	} else if (comp==1) {
	    /* For component 2, default address is in a=rtcp line */
	    PRINT("a=rtcp:%d IN IP4 %s\n",
		  (int)pj_sockaddr_get_port(&cand[0].addr),
		  pj_sockaddr_print(&cand[0].addr, ipaddr,
				    sizeof(ipaddr), 0),
		  0, 0, 0, 0);
	} else {
	    /* For other components, we'll just invent this.. */
	    PRINT("a=Xice-defcand:%d IN IP4 %s\n",
		  (int)pj_sockaddr_get_port(&cand[0].addr),
		  pj_sockaddr_print(&cand[0].addr, ipaddr,
				    sizeof(ipaddr), 0),
		  0, 0, 0, 0);
	}

	/* Enumerate all candidates for this component */
	status = pj_ice_strans_enum_cands(icedemo.icest, comp+1,
					  &cand_cnt, cand);
	if (status != PJ_SUCCESS)
	    return -status;

	/* And encode the candidates as SDP */
	for (j=0; j<cand_cnt; ++j) {
	    printed = print_cand(p, maxlen - (p-buffer), &cand[j]);
	    if (printed < 0)
		return -PJ_ETOOSMALL;
	    p += printed;
	}
    }

    if (p == buffer+maxlen)
	return -PJ_ETOOSMALL;

    *p = '\0';
    return p - buffer;
}
Ejemplo n.º 5
0
/* Encode ICE information in SDP */
static pj_status_t encode_session_in_sdp(struct transport_ice *tp_ice,
					 pj_pool_t *sdp_pool,
					 pjmedia_sdp_session *sdp_local,
					 unsigned media_index,
					 unsigned comp_cnt,
					 pj_bool_t restart_session)
{
    enum { 
	ATTR_BUF_LEN = 160,	/* Max len of a=candidate attr */
	RATTR_BUF_LEN= 160	/* Max len of a=remote-candidates attr */
    };
    pjmedia_sdp_media *m = sdp_local->media[media_index];
    pj_str_t local_ufrag, local_pwd;
    pjmedia_sdp_attr *attr;
    pj_status_t status;

    /* Must have a session */
    PJ_ASSERT_RETURN(pj_ice_strans_has_sess(tp_ice->ice_st), PJ_EBUG);

    /* Get ufrag and pwd from current session */
    pj_ice_strans_get_ufrag_pwd(tp_ice->ice_st, &local_ufrag, &local_pwd,
				NULL, NULL);

    /* The listing of candidates depends on whether ICE has completed
     * or not. When ICE has completed:
     *
     * 9.1.2.2: Existing Media Streams with ICE Completed
     *   The agent MUST include a candidate attributes for candidates
     *   matching the default destination for each component of the 
     *   media stream, and MUST NOT include any other candidates.
     *
     * When ICE has not completed, we shall include all candidates.
     *
     * Except when we have detected that remote is offering to restart
     * the session, in this case we will answer with full ICE SDP and
     * new ufrag/pwd pair.
     */
    if (!restart_session && pj_ice_strans_sess_is_complete(tp_ice->ice_st)) {
	const pj_ice_sess_check *check;
	char *attr_buf;
	pjmedia_sdp_conn *conn;
	pjmedia_sdp_attr *a_rtcp;
	pj_str_t rem_cand;
	unsigned comp;

	/* Encode ice-ufrag attribute */
	attr = pjmedia_sdp_attr_create(sdp_pool, STR_ICE_UFRAG.ptr,
				       &local_ufrag);
	pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);

	/* Encode ice-pwd attribute */
	attr = pjmedia_sdp_attr_create(sdp_pool, STR_ICE_PWD.ptr, 
				       &local_pwd);
	pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);

	/* Prepare buffer */
	attr_buf = (char*) pj_pool_alloc(sdp_pool, ATTR_BUF_LEN);
	rem_cand.ptr = (char*) pj_pool_alloc(sdp_pool, RATTR_BUF_LEN);
	rem_cand.slen = 0;

	/* 9.1.2.2: Existing Media Streams with ICE Completed
	 *   The default destination for media (i.e., the values of 
	 *   the IP addresses and ports in the m and c line used for
	 *   that media stream) MUST be the local candidate from the
	 *   highest priority nominated pair in the valid list for each
	 *   component.
	 */
	check = pj_ice_strans_get_valid_pair(tp_ice->ice_st, 1);
	if (check == NULL) {
	    pj_assert(!"Shouldn't happen");
	    return PJ_EBUG;
	}

	/* Override connection line address and media port number */
	conn = m->conn;
	if (conn == NULL)
	    conn = sdp_local->conn;

	conn->addr.ptr = (char*) pj_pool_alloc(sdp_pool, 
					       PJ_INET6_ADDRSTRLEN);
	pj_sockaddr_print(&check->lcand->addr, conn->addr.ptr, 
			  PJ_INET6_ADDRSTRLEN, 0);
	conn->addr.slen = pj_ansi_strlen(conn->addr.ptr);
	m->desc.port = pj_sockaddr_get_port(&check->lcand->addr);

	/* Override address RTCP attribute if it's present */
	if (comp_cnt == 2 &&
	    (check = pj_ice_strans_get_valid_pair(tp_ice->ice_st, 
						  COMP_RTCP)) != NULL &&
	    (a_rtcp = pjmedia_sdp_attr_find(m->attr_count, m->attr, 
					    &STR_RTCP, 0)) != NULL) 
	{
	    pjmedia_sdp_attr_remove(&m->attr_count, m->attr, a_rtcp);

	    a_rtcp = pjmedia_sdp_attr_create_rtcp(sdp_pool, 
						  &check->lcand->addr);
	    if (a_rtcp)
		pjmedia_sdp_attr_add(&m->attr_count, m->attr, a_rtcp);
	}

	/* Encode only candidates matching the default destination 
	 * for each component 
	 */
	for (comp=0; comp < comp_cnt; ++comp) {
	    int len;
	    pj_str_t value;

	    /* Get valid pair for this component */
	    check = pj_ice_strans_get_valid_pair(tp_ice->ice_st, comp+1);
	    if (check == NULL)
		continue;

	    /* Print and add local candidate in the pair */
	    value.ptr = attr_buf;
	    value.slen = print_sdp_cand_attr(attr_buf, ATTR_BUF_LEN, 
					     check->lcand);
	    if (value.slen < 0) {
		pj_assert(!"Not enough attr_buf to print candidate");
		return PJ_EBUG;
	    }

	    attr = pjmedia_sdp_attr_create(sdp_pool, STR_CANDIDATE.ptr,
					   &value);
	    pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);

	    /* Append to a=remote-candidates attribute */
	    if (pj_ice_strans_get_role(tp_ice->ice_st) == 
				    PJ_ICE_SESS_ROLE_CONTROLLING) 
	    {
		char rem_addr[PJ_INET6_ADDRSTRLEN];

		pj_sockaddr_print(&check->rcand->addr, rem_addr, 
				  sizeof(rem_addr), 0);
		len = pj_ansi_snprintf(
			   rem_cand.ptr + rem_cand.slen,
			   RATTR_BUF_LEN - rem_cand.slen,
			   "%s%u %s %u", 
			   (rem_cand.slen==0? "" : " "),
			   comp+1, rem_addr,
			   pj_sockaddr_get_port(&check->rcand->addr)
			   );
		if (len < 1 || len >= RATTR_BUF_LEN) {
		    pj_assert(!"Not enough buffer to print "
			       "remote-candidates");
		    return PJ_EBUG;
		}

		rem_cand.slen += len;
	    }
	}

	/* 9.1.2.2: Existing Media Streams with ICE Completed
	 *   In addition, if the agent is controlling, it MUST include
	 *   the a=remote-candidates attribute for each media stream 
	 *   whose check list is in the Completed state.  The attribute
	 *   contains the remote candidates from the highest priority 
	 *   nominated pair in the valid list for each component of that
	 *   media stream.
	 */
	if (pj_ice_strans_get_role(tp_ice->ice_st) == 
				    PJ_ICE_SESS_ROLE_CONTROLLING) 
	{
	    attr = pjmedia_sdp_attr_create(sdp_pool, STR_REM_CAND.ptr, 
					   &rem_cand);
	    pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);
	}

    } else if (pj_ice_strans_has_sess(tp_ice->ice_st)) {
	/* Encode all candidates to SDP media */
	char *attr_buf;
	unsigned comp;

	/* If ICE is not restarted, encode current ICE ufrag/pwd.
	 * Otherwise generate new one.
	 */
	if (!restart_session) {
	    attr = pjmedia_sdp_attr_create(sdp_pool, STR_ICE_UFRAG.ptr,
					   &local_ufrag);
	    pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);

	    attr = pjmedia_sdp_attr_create(sdp_pool, STR_ICE_PWD.ptr, 
					   &local_pwd);
	    pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);

	} else {
	    pj_str_t str;

	    str.slen = PJ_ICE_UFRAG_LEN;
	    str.ptr = (char*) pj_pool_alloc(sdp_pool, str.slen);
	    pj_create_random_string(str.ptr, str.slen);
	    attr = pjmedia_sdp_attr_create(sdp_pool, STR_ICE_UFRAG.ptr, &str);
	    pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);

	    str.ptr = (char*) pj_pool_alloc(sdp_pool, str.slen);
	    pj_create_random_string(str.ptr, str.slen);
	    attr = pjmedia_sdp_attr_create(sdp_pool, STR_ICE_PWD.ptr, &str);
	    pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);
	}

	/* Create buffer to encode candidates as SDP attribute */
	attr_buf = (char*) pj_pool_alloc(sdp_pool, ATTR_BUF_LEN);

	for (comp=0; comp < comp_cnt; ++comp) {
	    unsigned cand_cnt;
	    pj_ice_sess_cand cand[PJ_ICE_ST_MAX_CAND];
	    unsigned i;

	    cand_cnt = PJ_ARRAY_SIZE(cand);
	    status = pj_ice_strans_enum_cands(tp_ice->ice_st, comp+1,
					      &cand_cnt, cand);
	    if (status != PJ_SUCCESS)
		return status;

	    for (i=0; i<cand_cnt; ++i) {
		pj_str_t value;

		value.slen = print_sdp_cand_attr(attr_buf, ATTR_BUF_LEN, 
						 &cand[i]);
		if (value.slen < 0) {
		    pj_assert(!"Not enough attr_buf to print candidate");
		    return PJ_EBUG;
		}

		value.ptr = attr_buf;
		attr = pjmedia_sdp_attr_create(sdp_pool, 
					       STR_CANDIDATE.ptr,
					       &value);
		pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);
	    }
	}
    } else {
	/* ICE has failed, application should have terminated this call */
    }

    /* Removing a=rtcp line when there is only one component. */
    if (comp_cnt == 1) {
	attr = pjmedia_sdp_attr_find(m->attr_count, m->attr, &STR_RTCP, NULL);
	if (attr)
	    pjmedia_sdp_attr_remove(&m->attr_count, m->attr, attr);
    }
    

    return PJ_SUCCESS;
}