Ignore:
Timestamp:
Mar 21, 2007 9:12:22 AM (17 years ago)
Author:
bennylp
Message:

s/stun_endpoint/stun_setting

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjnath/src/pjnath/ice.c

    r1089 r1090  
    6565static void destroy_ice(pj_ice *ice, 
    6666                        pj_status_t reason); 
    67 static void ice_set_state(pj_ice *ice, 
    68                           pj_ice_state new_state); 
    6967static pj_status_t start_periodic_check(pj_timer_heap_t *th,  
    7068                                        pj_timer_entry *te); 
     
    169167                        pj_status_t reason) 
    170168{ 
     169    unsigned i; 
     170 
    171171    if (reason == PJ_SUCCESS) { 
    172172        LOG((ice->obj_name, "Destroying ICE session")); 
     173    } 
     174 
     175    for (i=0; i<ice->comp_cnt; ++i) { 
     176        pj_ice_comp *comp = &ice->comp[i]; 
     177 
     178        if (comp->stun_sess) { 
     179            pj_stun_session_destroy(comp->stun_sess); 
     180            comp->stun_sess = NULL; 
     181        } 
     182    } 
     183 
     184    if (ice->clist.timer.id) { 
     185        pj_timer_heap_cancel(ice->stun_cfg.timer_heap, &ice->clist.timer); 
     186        ice->clist.timer.id = PJ_FALSE; 
    173187    } 
    174188 
     
    198212 
    199213 
    200 static void ice_set_state(pj_ice *ice, 
    201                           pj_ice_state new_state) 
    202 { 
    203     ice->state = new_state; 
    204 } 
     214/* This function is called when ICE processing completes */ 
     215static void on_ice_complete(pj_ice *ice, pj_status_t status) 
     216{ 
     217} 
     218 
     219 
     220/* This function is called when one check completes */ 
     221static pj_bool_t on_check_complete(pj_ice *ice, 
     222                                   pj_ice_check *check) 
     223{ 
     224    unsigned i; 
     225 
     226    /* If there is at least one nominated pair in the valid list: 
     227     * - The agent MUST remove all Waiting and Frozen pairs in the check 
     228     *   list for the same component as the nominated pairs for that 
     229     *   media stream 
     230     * - If an In-Progress pair in the check list is for the same 
     231     *   component as a nominated pair, the agent SHOULD cease 
     232     *   retransmissions for its check if its pair priority is lower 
     233     *   than the lowest priority nominated pair for that component 
     234     */ 
     235    if (check->nominated) { 
     236        for (i=0; i<ice->clist.count; ++i) { 
     237            pj_ice_check *c; 
     238            if (c->lcand->comp_id == check->lcand->comp_id && 
     239                (c->state==PJ_ICE_CHECK_STATE_FROZEN || 
     240                 c->state==PJ_ICE_CHECK_STATE_WAITING) 
     241            { 
     242                check_set_state(ice, check, PJ_ICE_CHECK_STATE_FAILED, 
     243                                PJ_ECANCELLED); 
     244            } 
     245        } 
     246    } 
     247 
     248    /* Once there is at least one nominated pair in the valid list for 
     249     * every component of at least one media stream: 
     250     * - The agent MUST change the state of processing for its check 
     251     *   list for that media stream to Completed. 
     252     * - The agent MUST continue to respond to any checks it may still 
     253     *   receive for that media stream, and MUST perform triggered 
     254     *   checks if required by the processing of Section 7.2. 
     255     * - The agent MAY begin transmitting media for this media stream as 
     256     *   described in Section 11.1 
     257     */ 
     258    /* TODO */ 
     259 
     260    /* Once there is at least one nominated pair in the valid list for 
     261     * each component of each media stream: 
     262     * - The agent sets the state of ICE processing overall to 
     263     *   Completed. 
     264     * - If an agent is controlling, it examines the highest priority 
     265     *   nominated candidate pair for each component of each media 
     266     *   stream.  If any of those candidate pairs differ from the 
     267     *   default candidate pairs in the most recent offer/answer 
     268     *   exchange, the controlling agent MUST generate an updated offer 
     269     *   as described in Section 9.  If the controlling agent is using 
     270     *   an aggressive nomination algorithm, this may result in several 
     271     *   updated offers as the pairs selected for media change.  An 
     272     *   agent MAY delay sending the offer for a brief interval (one 
     273     *   second is RECOMMENDED) in order to allow the selected pairs to 
     274     *   stabilize. 
     275     */ 
     276    /* TODO */ 
     277 
     278 
     279    /* For now, just see if we have a valid pair in component 1 and 
     280     * just terminate ICE. 
     281     */ 
     282    for (i=0; i<ice->valid_cnt; ++i) { 
     283        pj_ice_check *c = ice->clist.checks[ice->valid_list[i]]; 
     284        if (c->lcand->comp_id == 1) 
     285            break; 
     286    } 
     287 
     288    if (i != ice->valid_cnt) { 
     289        /* ICE succeeded */ 
     290        on_ice_complete(ice, PJ_SUCCESS); 
     291        return PJ_TRUE; 
     292    } 
     293 
     294    /* We don't have valid pair for component 1. 
     295     * See if we have performed all checks in the checklist. If we do, 
     296     * then mark ICE processing as failed. 
     297     */ 
     298    for (i=0; i<ice->clist.count; ++i) { 
     299        pj_ice_check *c = &ice->clist.checks[i]; 
     300        if (c->state < PJ_ICE_CHECK_STATE_SUCCEEDED) { 
     301            break; 
     302        } 
     303    } 
     304 
     305    if (i == ice->clist.count) { 
     306        /* All checks have completed */ 
     307        on_ice_complete(ice, -1); 
     308        return PJ_TRUE; 
     309    } 
     310 
     311    /* We still have checks to perform */ 
     312    return PJ_FALSE; 
     313} 
     314 
    205315 
    206316static void resolver_cb(void *user_data, 
     
    633743    PJ_TODO(GATHER_MAPPED_AND_RELAYED_CANDIDATES); 
    634744 
    635     ice_set_state(ice, PJ_ICE_STATE_CAND_COMPLETE); 
    636  
    637745    return PJ_SUCCESS; 
    638746} 
     
    883991} 
    884992 
     993/* Sort checklist based on priority */ 
    885994static void sort_checklist(pj_ice_checklist *clist) 
    886995{ 
     
    9021011                      sizeof(pj_ice_check)); 
    9031012            pj_memcpy(&clist->checks[highest], &tmp, sizeof(pj_ice_check)); 
     1013        } 
     1014    } 
     1015} 
     1016 
     1017/* Sort valid list based on priority */ 
     1018static void sort_valid_list(pj_ice *ice) 
     1019{ 
     1020    unsigned i; 
     1021 
     1022    for (i=0; i<ice->valid_cnt-1; ++i) { 
     1023        unsigned j, highest = i; 
     1024        pj_ice_check *ci = ice->clist.checks[ice->valid_list[i]]; 
     1025 
     1026        for (j=i+1; j<ice->valid_cnt; ++j) { 
     1027            pj_ice_check *cj = ice->clist.checks[ice->valid_list[j]]; 
     1028 
     1029            if (cj->prio > ci->prio) { 
     1030                highest = j; 
     1031            } 
     1032        } 
     1033 
     1034        if (highest != i) { 
     1035            unsigned tmp = ice->valid_list[i]; 
     1036            ice->valid_list[i] = ice->valid_list[j]; 
     1037            ice->valid_list[j] = tmp; 
    9041038        } 
    9051039    } 
     
    10201154 
    10211155    /* Generate checklist */ 
    1022     clist = &ice->cklist; 
     1156    clist = &ice->clist; 
    10231157    for (i=0; i<ice->lcand_cnt; ++i) { 
    10241158        for (j=0; j<ice->rcand_cnt; ++j) { 
     
    11311265                              prio); 
    11321266 
    1133     /* Add USE-CANDIDATE */ 
     1267    /* Add USE-CANDIDATE and set this check to nominated */ 
    11341268    if (ice->role == PJ_ICE_ROLE_CONTROLLING) { 
    11351269        pj_stun_msg_add_empty_attr(tdata->pool, tdata->msg,  
    11361270                                   PJ_STUN_ATTR_USE_CANDIDATE); 
     1271        check->nominated = PJ_TRUE; 
    11371272    } 
    11381273 
     
    12481383    LOG((ice->obj_name, "Starting ICE check..")); 
    12491384 
    1250     clist = &ice->cklist; 
     1385    clist = &ice->clist; 
    12511386 
    12521387    if (clist->count == 0) 
     
    13801515    check_set_state(ice, check, PJ_ICE_CHECK_STATE_SUCCEEDED, PJ_SUCCESS); 
    13811516 
    1382  
    13831517    /* This is a valid pair, so add this to the valid list */ 
    1384     valid_check = &ice->valid_list.checks[ice->valid_list.count++]; 
    1385     valid_check->lcand = lcand; 
    1386     valid_check->rcand = rcand; 
    1387     valid_check->prio = CALC_CHECK_PRIO(ice, lcand, rcand); 
    1388     valid_check->state = PJ_ICE_CHECK_STATE_SUCCEEDED; 
    1389     valid_check->nominated = (pj_stun_msg_find_attr(tdata->msg,  
    1390                                                     PJ_STUN_ATTR_USE_CANDIDATE, 
    1391                                                     0) != NULL); 
    1392     valid_check->err_code = PJ_SUCCESS; 
     1518    ice->valid_list[ice->valid_cnt++] = rd->ckid; 
    13931519 
    13941520    /* Sort valid_list */ 
    1395     sort_checklist(&ice->valid_list); 
     1521    sort_valid_list(ice); 
     1522 
     1523    /* Inform about check completion. 
     1524     * This may terminate ICE processing. 
     1525     */ 
     1526    if (on_check_complete(ice, check)) { 
     1527        /* ICE complete! */ 
     1528        pj_mutex_unlock(ice->mutex); 
     1529        return; 
     1530    } 
    13961531 
    13971532    /* If the pair had a component ID of 1, the agent MUST change the 
     
    14531588    pj_ice *ice; 
    14541589    pj_stun_priority_attr *ap; 
     1590    pj_stun_use_candidate_attr *uc; 
    14551591    pj_ice_comp *comp; 
    14561592    pj_ice_cand *lcand; 
     
    14641600    PJ_UNUSED_ARG(pkt_len); 
    14651601 
    1466     /* Only accepts Binding request */ 
     1602    /* Reject any requests except Binding request */ 
    14671603    if (msg->hdr.type != PJ_STUN_BINDING_REQUEST) { 
    1468         LOG((ice->obj_name, "Received non-Binding request, ignored")); 
    1469         return PJ_SUCCESS; 
    1470     } 
     1604        pj_str_t err_msg = pj_str("Expecting Binding Request only"); 
     1605        status = pj_stun_session_create_response(sess, msg,  
     1606                                                 PJ_STUN_SC_BAD_REQUEST, 
     1607                                                 &err_msg, &tdata); 
     1608        if (status != PJ_SUCCESS) { 
     1609            return status; 
     1610        } 
     1611 
     1612        status = pj_stun_session_send_msg(sess, PJ_TRUE,  
     1613                                          src_addr, src_addr_len, tdata); 
     1614 
     1615        return status; 
     1616    } 
     1617 
    14711618 
    14721619    sd = (stun_data*) pj_stun_session_get_user_data(sess); 
     
    14851632    } 
    14861633 
     1634    /* Get USE-CANDIDATE attribute */ 
     1635    uc = (pj_stun_use_candidate_attr*) 
     1636         pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_USE_CANDIDATE, 0); 
     1637 
    14871638    /* For simplicity, ignore incoming requests when we don't have remote 
    14881639     * candidates yet. The peer agent should retransmit the STUN request 
     
    14931644        return PJ_SUCCESS; 
    14941645    } 
     1646 
     1647    /*  
     1648     * First send response to this request  
     1649     */ 
     1650    status = pj_stun_session_create_response(sess, msg, 0, NULL, &tdata); 
     1651    if (status != PJ_SUCCESS) { 
     1652        pj_mutex_unlock(ice->mutex); 
     1653        return status; 
     1654    } 
     1655 
     1656    status = pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,  
     1657                                           PJ_STUN_ATTR_XOR_MAPPED_ADDR, 
     1658                                           PJ_TRUE, src_addr, src_addr_len); 
     1659 
     1660    status = pj_stun_session_send_msg(sess, PJ_TRUE,  
     1661                                      src_addr, src_addr_len, tdata); 
    14951662 
    14961663 
     
    15331700    is_relayed = PJ_FALSE; 
    15341701 
    1535     /* Next find local candidate */ 
    1536     /* Just pick up  
    1537  
    1538  
    1539  
    1540     /* 7.2.1.2.  Learning Peer Reflexive Candidates */ 
    1541     PJ_TODO(LEARN_PEER_REFLEXIVE_CANDIDATES); 
    1542  
    1543     /* Reject any requests except Binding request */ 
    1544     if (msg->hdr.type != PJ_STUN_BINDING_REQUEST) { 
    1545         status = pj_stun_session_create_response(sess, msg,  
    1546                                                  PJ_STUN_SC_BAD_REQUEST, 
    1547                                                  NULL, &tdata); 
    1548         if (status != PJ_SUCCESS) { 
    1549             pj_mutex_unlock(ice->mutex); 
    1550             return status; 
     1702    /* Next find local candidate, by first finding a check in the checklist 
     1703     * which base address is equal to the local address. 
     1704     */ 
     1705    for (i=0; i<ice->clist.count; ++i) { 
     1706        pj_ice_check *c = &ice->clist.checks[i]; 
     1707        if (sockaddr_cmp(&c->lcand->base_addr, &comp->local_addr)==0) 
     1708            break; 
     1709    } 
     1710 
     1711    /* MUST find a local candidate! */ 
     1712    pj_assert(i != ice->clist.count); 
     1713    if (i == ice->clist.count) { 
     1714        pj_mutex_unlock(ice->mutex); 
     1715        LOG((ice->obj_name, "Error: unable to find local candidate for " 
     1716             "incoming request")); 
     1717        return PJ_SUCCESS; 
     1718    } 
     1719 
     1720    lcand = ice->clist.checks[i].lcand; 
     1721 
     1722    /* Now that we have local and remote candidate, check if we already 
     1723     * have this pair in our checklist. 
     1724     */ 
     1725    for (i=0; i<ice->clist.count; ++i) { 
     1726        pj_ice_check *c = &ice->clist.checks[i]; 
     1727        if (c->lcand == lcand && c->rcand == rcand) 
     1728            break; 
     1729    } 
     1730 
     1731    /* If the pair is already on the check list: 
     1732     * - If the state of that pair is Waiting or Frozen, its state is 
     1733     *   changed to In-Progress and a check for that pair is performed 
     1734     *   immediately.  This is called a triggered check. 
     1735     * 
     1736     * - If the state of that pair is In-Progress, the agent SHOULD 
     1737     *   generate an immediate retransmit of the Binding Request for the 
     1738     *   check in progress.  This is to facilitate rapid completion of 
     1739     *   ICE when both agents are behind NAT. 
     1740     *  
     1741     * - If the state of that pair is Failed or Succeeded, no triggered 
     1742     *   check is sent. 
     1743     */ 
     1744    if (i != ice->clist.count) { 
     1745        pj_ice_check *c = &ice->clist.checks[i]; 
     1746 
     1747        /* If USE-CANDIDATE is present, set nominated flag */ 
     1748        c->nominated = (uc != NULL); 
     1749 
     1750        if (c->state == PJ_ICE_CHECK_STATE_FROZEN || 
     1751            c->state == PJ_ICE_CHECK_STATE_WAITING) 
     1752        { 
     1753            LOG((ice->obj_name, "Performing triggered check for check %d",i)); 
     1754            perform_check(ice, &ice->clist, i); 
     1755 
     1756        } else if (c->state == PJ_ICE_CHECK_STATE_IN_PROGRESS) { 
     1757            /* Should retransmit here, but how?? 
     1758             * TODO 
     1759             */ 
     1760        } else if (c->state == PJ_ICE_CHECK_STATE_SUCCEEDED) { 
     1761            /* Check complete for this component. 
     1762             * Note this may end ICE process. 
     1763             */ 
     1764            pj_bool_t complete; 
     1765 
     1766            complete = on_check_complete(ice, c); 
     1767            if (complete) { 
     1768                pj_mutex_unlock(ice->mutex); 
     1769                return PJ_SUCCESS; 
     1770            } 
    15511771        } 
    15521772 
    1553         status = pj_stun_session_send_msg(sess, PJ_TRUE,  
    1554                                           src_addr, src_addr_len, tdata); 
    1555  
    1556         pj_mutex_unlock(ice->mutex); 
    1557         return status; 
    1558     } 
    1559  
    1560     status = pj_stun_session_create_response(sess, msg, 0, NULL, &tdata); 
    1561     if (status != PJ_SUCCESS) { 
    1562         pj_mutex_unlock(ice->mutex); 
    1563         return status; 
    1564     } 
    1565  
    1566     status = pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,  
    1567                                            PJ_STUN_ATTR_XOR_MAPPED_ADDR, 
    1568                                            PJ_TRUE, src_addr, src_addr_len); 
    1569  
    1570     status = pj_stun_session_send_msg(sess, PJ_TRUE,  
    1571                                       src_addr, src_addr_len, tdata); 
    1572  
    1573     /* 7.2.1.3.  Triggered Checks: 
    1574      * Next, the agent constructs a pair whose local candidate is equal to 
    1575      * the transport address on which the STUN request was received, and a 
    1576      * remote candidate equal to the source transport address where the 
    1577      * request came from (which may be peer-reflexive remote candidate that 
    1578      * was just learned).  
    1579      */ 
    1580      
     1773    } 
     1774    /* If the pair is not already on the check list: 
     1775     * - The pair is inserted into the check list based on its priority. 
     1776     * - Its state is set to In-Progress 
     1777     * - A triggered check for that pair is performed immediately. 
     1778     */ 
     1779    /* Note: only do this if we don't have too many checks in checklist */ 
     1780    else if (ice->clist.count < PJ_ICE_MAX_CHECKS) { 
     1781 
     1782        pj_ice_check *c = &ice->clist.checks[ice->clist.count]; 
     1783 
     1784        c->lcand = lcand; 
     1785        c->rcand = rcand; 
     1786        c->prio = CALC_CHECK_PRIO(ice, lcand, rcand); 
     1787        c->state = PJ_ICE_CHECK_STATE_WAITING; 
     1788        c->nominated = (uc != NULL); 
     1789        c->err_code = PJ_SUCCESS; 
     1790 
     1791        LOG((ice->obj_name, "New triggered check added: %d",  
     1792             ice->clist.count)); 
     1793        perform_check(ice, &ice->clist, ice->clist.count++); 
     1794 
     1795    } else { 
     1796        LOG((ice->obj_name, "Error: unable to perform triggered check: " 
     1797             "TOO MANY CHECKS IN CHECKLIST!")); 
     1798    } 
     1799 
    15811800    pj_mutex_unlock(ice->mutex); 
    15821801    return status; 
Note: See TracChangeset for help on using the changeset viewer.