Ignore:
Timestamp:
Apr 13, 2009 8:54:10 AM (15 years ago)
Author:
bennylp
Message:

Ticket #780: Update TURN from draft 09 to draft 13:

  • new rules for permissions:
    • permission must be created and refreshed explicitly with CreatePermission?
    • transmitting data does not refresh permission
  • attributes changed/added: XOR-PEER-ADDRESS, XOR-RELAYED-ADDRESS, EVEN-PORT, DONT-FRAGMENT
  • attribute(s) removed: REQUESTED-PROPS
  • new status codes: 401 (Forbidden), 507 (Insufficient Capacity)
  • removed status codes: 443 (Invalid IP address), 444 (Invalid Port), 508 (Insufficient Port Capacity)
File:
1 edited

Legend:

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

    r2407 r2589  
    2929#include <pj/os.h> 
    3030#include <pj/pool.h> 
     31#include <pj/rand.h> 
    3132#include <pj/sock.h> 
    3233 
    3334#define PJ_TURN_CHANNEL_MIN         0x4000 
    34 #define PJ_TURN_CHANNEL_MAX         0xFFFE  /* inclusive */ 
    35 #define PJ_TURN_PEER_HTABLE_SIZE    8 
     35#define PJ_TURN_CHANNEL_MAX         0x7FFF  /* inclusive */ 
     36#define PJ_TURN_CHANNEL_HTABLE_SIZE 8 
     37#define PJ_TURN_PERM_HTABLE_SIZE    8 
     38#define PJ_TURN_RENEWAL_BEFORE      10  /* seconds before renewals */ 
    3639 
    3740static const char *state_names[] =  
     
    5457}; 
    5558 
    56  
    57 struct peer 
    58 { 
    59     pj_uint16_t     ch_id; 
     59/* This structure describes a channel binding. A channel binding is index by 
     60 * the channel number or IP address and port number of the peer. 
     61 */ 
     62struct ch_t 
     63{ 
     64    /* The channel number */ 
     65    pj_uint16_t     num; 
     66 
     67    /* PJ_TRUE if we've received successful response to ChannelBind request 
     68     * for this channel. 
     69     */ 
    6070    pj_bool_t       bound; 
     71 
     72    /* The peer IP address and port */ 
    6173    pj_sockaddr     addr; 
     74 
     75    /* The channel binding expiration */ 
    6276    pj_time_val     expiry; 
    6377}; 
    6478 
     79 
     80/* This structure describes a permission. A permission is identified by the 
     81 * IP address only. 
     82 */ 
     83struct perm_t 
     84{ 
     85    /* Cache of hash value to speed-up lookup */ 
     86    pj_uint32_t     hval; 
     87 
     88    /* The permission IP address. The port number MUST be zero */ 
     89    pj_sockaddr     addr; 
     90 
     91    /* Number of peers that uses this permission. */ 
     92    unsigned        peer_cnt; 
     93 
     94    /* Automatically renew this permission once it expires? */ 
     95    pj_bool_t       renew; 
     96 
     97    /* The permission expiration */ 
     98    pj_time_val     expiry; 
     99 
     100    /* Arbitrary/random pointer value (token) to map this perm with the  
     101     * request to create it. It is used to invalidate this perm when the  
     102     * request fails. 
     103     */ 
     104    void           *req_token; 
     105}; 
     106 
     107 
     108/* The TURN client session structure */ 
    65109struct pj_turn_session 
    66110{ 
     
    103147    pj_sockaddr          relay_addr; 
    104148 
    105     pj_hash_table_t     *peer_table; 
     149    pj_hash_table_t     *ch_table; 
     150    pj_hash_table_t     *perm_table; 
    106151 
    107152    pj_uint32_t          send_ind_tsx_id[3]; 
     
    143188                                pj_status_t status, 
    144189                                const pj_dns_srv_record *rec); 
    145 static struct peer *lookup_peer_by_addr(pj_turn_session *sess, 
    146                                         const pj_sockaddr_t *addr, 
    147                                         unsigned addr_len, 
    148                                         pj_bool_t update, 
    149                                         pj_bool_t bind_channel); 
    150 static struct peer *lookup_peer_by_chnum(pj_turn_session *sess, 
    151                                          pj_uint16_t chnum); 
     190static struct ch_t *lookup_ch_by_addr(pj_turn_session *sess, 
     191                                      const pj_sockaddr_t *addr, 
     192                                      unsigned addr_len, 
     193                                      pj_bool_t update, 
     194                                      pj_bool_t bind_channel); 
     195static struct ch_t *lookup_ch_by_chnum(pj_turn_session *sess, 
     196                                       pj_uint16_t chnum); 
     197static struct perm_t *lookup_perm(pj_turn_session *sess, 
     198                                  const pj_sockaddr_t *addr, 
     199                                  unsigned addr_len, 
     200                                  pj_bool_t update); 
     201static void invalidate_perm(pj_turn_session *sess, 
     202                            struct perm_t *perm); 
    152203static void on_timer_event(pj_timer_heap_t *th, pj_timer_entry *e); 
    153204 
     
    225276 
    226277    /* Peer hash table */ 
    227     sess->peer_table = pj_hash_create(pool, PJ_TURN_PEER_HTABLE_SIZE); 
     278    sess->ch_table = pj_hash_create(pool, PJ_TURN_CHANNEL_HTABLE_SIZE); 
     279 
     280    /* Permission hash table */ 
     281    sess->perm_table = pj_hash_create(pool, PJ_TURN_PERM_HTABLE_SIZE); 
    228282 
    229283    /* Session lock */ 
     
    483537 
    484538 
     539/* 
     540 * Set software name 
     541 */ 
     542PJ_DEF(pj_status_t) pj_turn_session_set_software_name( pj_turn_session *sess, 
     543                                                       const pj_str_t *sw) 
     544{ 
     545    pj_status_t status; 
     546 
     547    pj_lock_acquire(sess->lock); 
     548    status = pj_stun_session_set_software_name(sess->stun, sw); 
     549    pj_lock_release(sess->lock); 
     550 
     551    return status; 
     552} 
     553 
     554 
    485555/** 
    486556 * Set the server or domain name of the server. 
     
    705775 
    706776/* 
     777 * Install or renew permissions 
     778 */ 
     779PJ_DEF(pj_status_t) pj_turn_session_set_perm( pj_turn_session *sess, 
     780                                              unsigned addr_cnt, 
     781                                              const pj_sockaddr addr[], 
     782                                              unsigned options) 
     783{ 
     784    pj_stun_tx_data *tdata; 
     785    pj_hash_iterator_t it_buf, *it; 
     786    void *req_token; 
     787    unsigned i, attr_added=0; 
     788    pj_status_t status; 
     789 
     790    PJ_ASSERT_RETURN(sess && addr_cnt && addr, PJ_EINVAL); 
     791 
     792    pj_lock_acquire(sess->lock); 
     793 
     794    /* Create a bare CreatePermission request */ 
     795    status = pj_stun_session_create_req(sess->stun,  
     796                                        PJ_STUN_CREATE_PERM_REQUEST, 
     797                                        PJ_STUN_MAGIC, NULL, &tdata); 
     798    if (status != PJ_SUCCESS) { 
     799        pj_lock_release(sess->lock); 
     800        return status; 
     801    } 
     802 
     803    /* Create request token to map the request to the perm structures 
     804     * which the request belongs. 
     805     */ 
     806    req_token = (void*)(long)pj_rand(); 
     807 
     808    /* Process the addresses */ 
     809    for (i=0; i<addr_cnt; ++i) { 
     810        struct perm_t *perm; 
     811 
     812        /* Lookup the perm structure and create if it doesn't exist */ 
     813        perm = lookup_perm(sess, &addr[i], pj_sockaddr_get_len(&addr[i]), 
     814                           PJ_TRUE); 
     815        perm->renew = (options & 0x01); 
     816 
     817        /* Only add to the request if the request doesn't contain this 
     818         * address yet. 
     819         */ 
     820        if (perm->req_token != req_token) { 
     821            perm->req_token = req_token; 
     822 
     823            /* Add XOR-PEER-ADDRESS */ 
     824            status = pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
     825                                                   PJ_STUN_ATTR_XOR_PEER_ADDR, 
     826                                                   PJ_TRUE, 
     827                                                   &addr[i], 
     828                                                   sizeof(addr[i])); 
     829            if (status != PJ_SUCCESS) 
     830                goto on_error; 
     831 
     832            ++attr_added; 
     833        } 
     834    } 
     835 
     836    pj_assert(attr_added != 0); 
     837 
     838    /* Send the request */ 
     839    status = pj_stun_session_send_msg(sess->stun, req_token, PJ_FALSE,  
     840                                      (sess->conn_type==PJ_TURN_TP_UDP), 
     841                                      sess->srv_addr, 
     842                                      pj_sockaddr_get_len(sess->srv_addr),  
     843                                      tdata); 
     844    if (status != PJ_SUCCESS) { 
     845        /* tdata is already destroyed */ 
     846        tdata = NULL; 
     847        goto on_error; 
     848    } 
     849 
     850    pj_lock_release(sess->lock); 
     851    return PJ_SUCCESS; 
     852 
     853on_error: 
     854    /* destroy tdata */ 
     855    if (tdata) { 
     856        pj_stun_msg_destroy_tdata(sess->stun, tdata); 
     857    } 
     858    /* invalidate perm structures associated with this request */ 
     859    it = pj_hash_first(sess->perm_table, &it_buf); 
     860    while (it) { 
     861        struct perm_t *perm = (struct perm_t*) 
     862                              pj_hash_this(sess->perm_table, it); 
     863        it = pj_hash_next(sess->perm_table, it); 
     864        if (perm->req_token == req_token) 
     865            invalidate_perm(sess, perm); 
     866    } 
     867    pj_lock_release(sess->lock); 
     868    return status; 
     869} 
     870 
     871/* 
    707872 * Send REFRESH 
    708873 */ 
     
    758923                                            unsigned addr_len) 
    759924{ 
    760     struct peer *peer; 
     925    struct ch_t *ch; 
     926    struct perm_t *perm; 
    761927    pj_status_t status; 
    762928 
     
    772938    pj_lock_acquire(sess->lock); 
    773939 
    774     /* Lookup peer to see whether we've assigned a channel number 
    775      * to this peer. 
    776      */ 
    777     peer = lookup_peer_by_addr(sess, addr, addr_len, PJ_TRUE, PJ_FALSE); 
    778     pj_assert(peer != NULL); 
    779  
    780     if (peer->ch_id != PJ_TURN_INVALID_CHANNEL && peer->bound) { 
    781         /* Peer is assigned Channel number, we can use ChannelData */ 
     940    /* Lookup permission first */ 
     941    perm = lookup_perm(sess, addr, pj_sockaddr_get_len(addr), PJ_FALSE); 
     942    if (perm == NULL) { 
     943        /* Permission doesn't exist, install it first */ 
     944        char ipstr[PJ_INET6_ADDRSTRLEN+2]; 
     945 
     946        PJ_LOG(4,(sess->obj_name,  
     947                  "sendto(): IP %s has no permission, requesting it first..", 
     948                  pj_sockaddr_print(addr, ipstr, sizeof(ipstr), 2))); 
     949 
     950        status = pj_turn_session_set_perm(sess, 1, (const pj_sockaddr*)addr,  
     951                                          0); 
     952        if (status != PJ_SUCCESS) { 
     953            pj_lock_release(sess->lock); 
     954            return status; 
     955        } 
     956    } 
     957 
     958    /* See if the peer is bound to a channel number */ 
     959    ch = lookup_ch_by_addr(sess, addr, pj_sockaddr_get_len(addr),  
     960                           PJ_FALSE, PJ_FALSE); 
     961    if (ch && ch->num != PJ_TURN_INVALID_CHANNEL && ch->bound) { 
     962        /* Peer is assigned a channel number, we can use ChannelData */ 
    782963        pj_turn_channel_data *cd = (pj_turn_channel_data*)sess->tx_pkt; 
    783964         
     
    789970        } 
    790971 
    791         cd->ch_number = pj_htons((pj_uint16_t)peer->ch_id); 
     972        cd->ch_number = pj_htons((pj_uint16_t)ch->num); 
    792973        cd->length = pj_htons((pj_uint16_t)pkt_len); 
    793974        pj_memcpy(cd+1, pkt, pkt_len); 
     
    800981 
    801982    } else { 
    802         /* Peer has not been assigned Channel number, must use Send 
    803          * Indication. 
    804          */ 
     983        /* Use Send Indication. */ 
    805984        pj_stun_sockaddr_attr peer_attr; 
    806985        pj_stun_binary_attr data_attr; 
     
    818997            goto on_return; 
    819998 
    820         /* Add PEER-ADDRESS */ 
    821         pj_stun_sockaddr_attr_init(&peer_attr, PJ_STUN_ATTR_PEER_ADDR, 
     999        /* Add XOR-PEER-ADDRESS */ 
     1000        pj_stun_sockaddr_attr_init(&peer_attr, PJ_STUN_ATTR_XOR_PEER_ADDR, 
    8221001                                   PJ_TRUE, addr, addr_len); 
    8231002        pj_stun_msg_add_attr(&send_ind, (pj_stun_attr_hdr*)&peer_attr); 
     
    8551034                                                 unsigned addr_len) 
    8561035{ 
    857     struct peer *peer; 
     1036    struct ch_t *ch; 
    8581037    pj_stun_tx_data *tdata; 
    8591038    pj_uint16_t ch_num; 
     
    8721051        goto on_return; 
    8731052 
    874     /* Lookup peer */ 
    875     peer = lookup_peer_by_addr(sess, peer_adr, addr_len, PJ_TRUE, PJ_FALSE); 
    876     pj_assert(peer); 
    877  
    878     if (peer->ch_id != PJ_TURN_INVALID_CHANNEL) { 
     1053    /* Lookup if this peer has already been assigned a number */ 
     1054    ch = lookup_ch_by_addr(sess, peer_adr, pj_sockaddr_get_len(peer_adr), 
     1055                           PJ_TRUE, PJ_FALSE); 
     1056    pj_assert(ch); 
     1057 
     1058    if (ch->num != PJ_TURN_INVALID_CHANNEL) { 
    8791059        /* Channel is already bound. This is a refresh request. */ 
    880         ch_num = peer->ch_id; 
     1060        ch_num = ch->num; 
    8811061    } else { 
    8821062        PJ_ASSERT_ON_FAIL(sess->next_ch <= PJ_TURN_CHANNEL_MAX,  
    8831063                            {status=PJ_ETOOMANY; goto on_return;}); 
    884         peer->ch_id = ch_num = sess->next_ch++; 
     1064        ch->num = ch_num = sess->next_ch++; 
    8851065    } 
    8861066 
     
    8901070                              PJ_STUN_SET_CH_NB(ch_num)); 
    8911071 
    892     /* Add PEER-ADDRESS attribute */ 
     1072    /* Add XOR-PEER-ADDRESS attribute */ 
    8931073    pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
    894                                   PJ_STUN_ATTR_PEER_ADDR, PJ_TRUE, 
     1074                                  PJ_STUN_ATTR_XOR_PEER_ADDR, PJ_TRUE, 
    8951075                                  peer_adr, addr_len); 
    8961076 
     
    8981078     * for future reference when we receive the ChannelBind response. 
    8991079     */ 
    900     status = pj_stun_session_send_msg(sess->stun, peer, PJ_FALSE,  
     1080    status = pj_stun_session_send_msg(sess->stun, ch, PJ_FALSE,  
    9011081                                      (sess->conn_type==PJ_TURN_TP_UDP), 
    9021082                                      sess->srv_addr, 
     
    9501130        /* This must be ChannelData. */ 
    9511131        pj_turn_channel_data cd; 
    952         struct peer *peer; 
     1132        struct ch_t *ch; 
    9531133 
    9541134        if (pkt_len < 4) { 
     
    9811161        } 
    9821162 
    983         /* Lookup peer */ 
    984         peer = lookup_peer_by_chnum(sess, cd.ch_number); 
    985         if (!peer || !peer->bound) { 
     1163        /* Lookup channel */ 
     1164        ch = lookup_ch_by_chnum(sess, cd.ch_number); 
     1165        if (!ch || !ch->bound) { 
    9861166            status = PJ_ENOTFOUND; 
    9871167            goto on_return; 
     
    9911171        if (sess->cb.on_rx_data) { 
    9921172            (*sess->cb.on_rx_data)(sess, ((pj_uint8_t*)pkt)+sizeof(cd),  
    993                                    cd.length, &peer->addr, 
    994                                    pj_sockaddr_get_len(&peer->addr)); 
     1173                                   cd.length, &ch->addr, 
     1174                                   pj_sockaddr_get_len(&ch->addr)); 
    9951175        } 
    9961176 
     
    10901270{ 
    10911271    const pj_stun_lifetime_attr *lf_attr; 
    1092     const pj_stun_relayed_addr_attr *raddr_attr; 
     1272    const pj_stun_xor_relayed_addr_attr *raddr_attr; 
    10931273    const pj_stun_sockaddr_attr *mapped_attr; 
    10941274    pj_str_t s; 
     
    11381318     * address family. 
    11391319     */ 
    1140     raddr_attr = (const pj_stun_relayed_addr_attr*) 
    1141                  pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_RELAYED_ADDR, 0); 
     1320    raddr_attr = (const pj_stun_xor_relayed_addr_attr*) 
     1321                 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_RELAYED_ADDR, 0); 
    11421322    if (raddr_attr == NULL && method==PJ_STUN_ALLOCATE_METHOD) { 
    11431323        on_session_fail(sess, method, PJNATH_EINSTUNMSG, 
     
    13021482        { 
    13031483            /* Successful ChannelBind response */ 
    1304             struct peer *peer = (struct peer*)token; 
    1305  
    1306             pj_assert(peer->ch_id != PJ_TURN_INVALID_CHANNEL); 
    1307             peer->bound = PJ_TRUE; 
     1484            struct ch_t *ch = (struct ch_t*)token; 
     1485 
     1486            pj_assert(ch->num != PJ_TURN_INVALID_CHANNEL); 
     1487            ch->bound = PJ_TRUE; 
    13081488 
    13091489            /* Update hash table */ 
    1310             lookup_peer_by_addr(sess, &peer->addr, 
    1311                                 pj_sockaddr_get_len(&peer->addr), 
    1312                                 PJ_TRUE, PJ_TRUE); 
     1490            lookup_ch_by_addr(sess, &ch->addr, 
     1491                              pj_sockaddr_get_len(&ch->addr), 
     1492                              PJ_TRUE, PJ_TRUE); 
    13131493 
    13141494        } else { 
     
    13331513        } 
    13341514 
     1515    } else if (method == PJ_STUN_CREATE_PERM_METHOD) { 
     1516        /* Handle CreatePermission response */ 
     1517        if (status==PJ_SUCCESS &&  
     1518            PJ_STUN_IS_SUCCESS_RESPONSE(response->hdr.type))  
     1519        { 
     1520            /* No special handling when the request is successful. */ 
     1521        } else { 
     1522            /* Iterate the permission table and invalidate all permissions 
     1523             * that are related to this request. 
     1524             */ 
     1525            pj_hash_iterator_t it_buf, *it; 
     1526            char ipstr[PJ_INET6_ADDRSTRLEN+10]; 
     1527            int err_code; 
     1528            char errbuf[PJ_ERR_MSG_SIZE]; 
     1529            pj_str_t reason; 
     1530 
     1531            if (status != PJ_SUCCESS) { 
     1532                err_code = status; 
     1533                reason = pj_strerror(status, errbuf, sizeof(errbuf)); 
     1534            } else { 
     1535                const pj_stun_errcode_attr *eattr; 
     1536 
     1537                eattr = (const pj_stun_errcode_attr*) 
     1538                        pj_stun_msg_find_attr(response,  
     1539                                              PJ_STUN_ATTR_ERROR_CODE, 0); 
     1540                if (eattr) { 
     1541                    err_code = eattr->err_code; 
     1542                    reason = eattr->reason; 
     1543                } else { 
     1544                    err_code = -1; 
     1545                    reason = pj_str("?"); 
     1546                } 
     1547            } 
     1548 
     1549            it = pj_hash_first(sess->perm_table, &it_buf); 
     1550            while (it) { 
     1551                struct perm_t *perm = (struct perm_t*) 
     1552                                      pj_hash_this(sess->perm_table, it); 
     1553                it = pj_hash_next(sess->perm_table, it); 
     1554 
     1555                if (perm->req_token == token) { 
     1556                    PJ_LOG(1,(sess->obj_name,  
     1557                              "CreatePermission failed for IP %s: %d/%.*s", 
     1558                              pj_sockaddr_print(&perm->addr, ipstr,  
     1559                                                sizeof(ipstr), 2), 
     1560                              err_code, (int)reason.slen, reason.ptr)); 
     1561 
     1562                    invalidate_perm(sess, perm); 
     1563                } 
     1564            } 
     1565        } 
     1566 
    13351567    } else { 
    13361568        PJ_LOG(4,(sess->obj_name, "Unexpected STUN %s response", 
     
    13531585{ 
    13541586    pj_turn_session *sess; 
    1355     pj_stun_peer_addr_attr *peer_attr; 
     1587    pj_stun_xor_peer_addr_attr *peer_attr; 
    13561588    pj_stun_icmp_attr *icmp; 
    13571589    pj_stun_data_attr *data_attr; 
     
    13801612    } 
    13811613 
    1382     /* Get PEER-ADDRESS attribute */ 
    1383     peer_attr = (pj_stun_peer_addr_attr*) 
    1384                 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_PEER_ADDR, 0); 
     1614    /* Get XOR-PEER-ADDRESS attribute */ 
     1615    peer_attr = (pj_stun_xor_peer_addr_attr*) 
     1616                pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_PEER_ADDR, 0); 
    13851617 
    13861618    /* Get DATA attribute */ 
     
    13881620                pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_DATA, 0); 
    13891621 
    1390     /* Must have both PEER-ADDRESS and DATA attributes */ 
     1622    /* Must have both XOR-PEER-ADDRESS and DATA attributes */ 
    13911623    if (!peer_attr || !data_attr) { 
    13921624        PJ_LOG(4,(sess->obj_name,  
     
    14731705 * Lookup peer descriptor from its address. 
    14741706 */ 
    1475 static struct peer *lookup_peer_by_addr(pj_turn_session *sess, 
    1476                                         const pj_sockaddr_t *addr, 
    1477                                         unsigned addr_len, 
    1478                                         pj_bool_t update, 
    1479                                         pj_bool_t bind_channel) 
    1480 { 
    1481     unsigned hval = 0; 
    1482     struct peer *peer; 
    1483  
    1484     peer = (struct peer*) pj_hash_get(sess->peer_table, addr, addr_len, &hval); 
    1485     if (peer == NULL && update) { 
    1486         peer = PJ_POOL_ZALLOC_T(sess->pool, struct peer); 
    1487         peer->ch_id = PJ_TURN_INVALID_CHANNEL; 
    1488         pj_memcpy(&peer->addr, addr, addr_len); 
     1707static struct ch_t *lookup_ch_by_addr(pj_turn_session *sess, 
     1708                                      const pj_sockaddr_t *addr, 
     1709                                      unsigned addr_len, 
     1710                                      pj_bool_t update, 
     1711                                      pj_bool_t bind_channel) 
     1712{ 
     1713    pj_uint32_t hval = 0; 
     1714    struct ch_t *ch; 
     1715 
     1716    ch = (struct ch_t*)  
     1717         pj_hash_get(sess->ch_table, addr, addr_len, &hval); 
     1718    if (ch == NULL && update) { 
     1719        ch = PJ_POOL_ZALLOC_T(sess->pool, struct ch_t); 
     1720        ch->num = PJ_TURN_INVALID_CHANNEL; 
     1721        pj_memcpy(&ch->addr, addr, addr_len); 
    14891722 
    14901723        /* Register by peer address */ 
    1491         pj_hash_set(sess->pool, sess->peer_table, &peer->addr, addr_len, 
    1492                     hval, peer); 
    1493     } 
    1494  
    1495     if (peer && update) { 
    1496         pj_gettimeofday(&peer->expiry); 
    1497         if (peer->bound) { 
    1498             peer->expiry.sec += PJ_TURN_CHANNEL_TIMEOUT - 10; 
    1499         } else { 
    1500             peer->expiry.sec += PJ_TURN_PERM_TIMEOUT - 10; 
    1501         } 
     1724        pj_hash_set(sess->pool, sess->ch_table, &ch->addr, addr_len, 
     1725                    hval, ch); 
     1726    } 
     1727 
     1728    if (ch && update) { 
     1729        pj_gettimeofday(&ch->expiry); 
     1730        ch->expiry.sec += PJ_TURN_PERM_TIMEOUT - PJ_TURN_RENEWAL_BEFORE; 
    15021731 
    15031732        if (bind_channel) { 
    15041733            pj_uint32_t hval = 0; 
    15051734            /* Register by channel number */ 
    1506             pj_assert(peer->ch_id != PJ_TURN_INVALID_CHANNEL && peer->bound); 
    1507  
    1508             if (pj_hash_get(sess->peer_table, &peer->ch_id,  
    1509                             sizeof(peer->ch_id), &hval)==0) { 
    1510                 pj_hash_set(sess->pool, sess->peer_table, &peer->ch_id, 
    1511                             sizeof(peer->ch_id), hval, peer); 
     1735            pj_assert(ch->num != PJ_TURN_INVALID_CHANNEL && ch->bound); 
     1736 
     1737            if (pj_hash_get(sess->ch_table, &ch->num,  
     1738                            sizeof(ch->num), &hval)==0) { 
     1739                pj_hash_set(sess->pool, sess->ch_table, &ch->num, 
     1740                            sizeof(ch->num), hval, ch); 
    15121741            } 
    15131742        } 
    15141743    } 
    15151744 
    1516     return peer; 
    1517 } 
    1518  
    1519  
    1520 /* 
    1521  * Lookup peer descriptor from its channel number. 
    1522  */ 
    1523 static struct peer *lookup_peer_by_chnum(pj_turn_session *sess, 
     1745    return ch; 
     1746} 
     1747 
     1748 
     1749/* 
     1750 * Lookup channel descriptor from its channel number. 
     1751 */ 
     1752static struct ch_t *lookup_ch_by_chnum(pj_turn_session *sess, 
    15241753                                         pj_uint16_t chnum) 
    15251754{ 
    1526     return (struct peer*) pj_hash_get(sess->peer_table, &chnum,  
     1755    return (struct ch_t*) pj_hash_get(sess->ch_table, &chnum,  
    15271756                                      sizeof(chnum), NULL); 
    15281757} 
    15291758 
     1759 
     1760/* 
     1761 * Lookup permission and optionally create if it doesn't exist. 
     1762 */ 
     1763static struct perm_t *lookup_perm(pj_turn_session *sess, 
     1764                                  const pj_sockaddr_t *addr, 
     1765                                  unsigned addr_len, 
     1766                                  pj_bool_t update) 
     1767{ 
     1768    pj_uint32_t hval = 0; 
     1769    pj_sockaddr perm_addr; 
     1770    struct perm_t *perm; 
     1771 
     1772    /* make sure port number if zero */ 
     1773    if (pj_sockaddr_get_port(addr) != 0) { 
     1774        pj_memcpy(&perm_addr, addr, addr_len); 
     1775        pj_sockaddr_set_port(&perm_addr, 0); 
     1776        addr = &perm_addr; 
     1777    } 
     1778 
     1779    /* lookup and create if it doesn't exist and wanted */ 
     1780    perm = (struct perm_t*)  
     1781           pj_hash_get(sess->perm_table, addr, addr_len, &hval); 
     1782    if (perm == NULL && update) { 
     1783        perm = PJ_POOL_ZALLOC_T(sess->pool, struct perm_t); 
     1784        pj_memcpy(&perm->addr, addr, addr_len); 
     1785        perm->hval = hval; 
     1786 
     1787        pj_hash_set(sess->pool, sess->perm_table, &perm->addr, addr_len, 
     1788                    perm->hval, perm); 
     1789    } 
     1790 
     1791    if (perm && update) { 
     1792        pj_gettimeofday(&perm->expiry); 
     1793        perm->expiry.sec += PJ_TURN_PERM_TIMEOUT - PJ_TURN_RENEWAL_BEFORE; 
     1794 
     1795    } 
     1796 
     1797    return perm; 
     1798} 
     1799 
     1800/* 
     1801 * Delete permission 
     1802 */ 
     1803static void invalidate_perm(pj_turn_session *sess, 
     1804                            struct perm_t *perm) 
     1805{ 
     1806    pj_hash_set(NULL, sess->perm_table, &perm->addr, 
     1807                pj_sockaddr_get_len(&perm->addr), perm->hval, NULL); 
     1808} 
    15301809 
    15311810/* 
     
    15651844 
    15661845        /* Scan hash table to refresh bound channels */ 
    1567         it = pj_hash_first(sess->peer_table, &itbuf); 
     1846        it = pj_hash_first(sess->ch_table, &itbuf); 
    15681847        while (it) { 
    1569             struct peer *peer = (struct peer*)  
    1570                                 pj_hash_this(sess->peer_table, it); 
    1571             if (peer->bound && PJ_TIME_VAL_LTE(peer->expiry, now)) { 
     1848            struct ch_t *ch = (struct ch_t*)  
     1849                              pj_hash_this(sess->ch_table, it); 
     1850            if (ch->bound && PJ_TIME_VAL_LTE(ch->expiry, now)) { 
    15721851 
    15731852                /* Send ChannelBind to refresh channel binding and  
    15741853                 * permission. 
    15751854                 */ 
    1576                 pj_turn_session_bind_channel(sess, &peer->addr, 
    1577                                              pj_sockaddr_get_len(&peer->addr)); 
     1855                pj_turn_session_bind_channel(sess, &ch->addr, 
     1856                                             pj_sockaddr_get_len(&ch->addr)); 
    15781857                pkt_sent = PJ_TRUE; 
    15791858            } 
    15801859 
    1581             it = pj_hash_next(sess->peer_table, it); 
     1860            it = pj_hash_next(sess->ch_table, it); 
    15821861        } 
    15831862 
Note: See TracChangeset for help on using the changeset viewer.