Ignore:
Timestamp:
Apr 14, 2008 1:48:39 AM (16 years ago)
Author:
bennylp
Message:

More ticket #485: huge changeset to integrate TURN with ICE and PJSUA-LIB/pjsua. Still experimental

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/branches/projects/ice-turn07/pjnath/src/pjnath/ice_strans.c

    r1913 r1926  
    4141static pj_status_t ice_tx_pkt(pj_ice_sess *ice,  
    4242                              unsigned comp_id, 
     43                              unsigned cand_id, 
    4344                              const void *pkt, pj_size_t size, 
    4445                              const pj_sockaddr_t *dst_addr, 
     
    7475                                     unsigned src_addr_len); 
    7576 
     77/* TURN callbacks */ 
     78static void turn_on_rx_data(pj_turn_sock *turn_sock, 
     79                            void *pkt, 
     80                            unsigned pkt_len, 
     81                            const pj_sockaddr_t *peer_addr, 
     82                            unsigned addr_len); 
     83static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state, 
     84                          pj_turn_state_t new_state); 
     85 
     86 
    7687/* Keep-alive timer */ 
    7788static void start_ka_timer(pj_ice_strans *ice_st); 
     
    8192#define ice_st_perror(ice_st,msg,rc) pjnath_perror(ice_st->obj_name,msg,rc) 
    8293 
     94/* Validate configuration */ 
     95static pj_status_t pj_ice_strans_cfg_check_valid(const pj_ice_strans_cfg *cfg) 
     96{ 
     97    pj_status_t status; 
     98 
     99    status = pj_stun_config_check_valid(&cfg->stun_cfg); 
     100    if (!status) 
     101        return status; 
     102 
     103    /* If TURN is specified then TURN credential must be specified */ 
     104    PJ_ASSERT_RETURN(!pj_sockaddr_has_addr(&cfg->turn_srv) || 
     105                      cfg->turn_cred.type != PJ_STUN_AUTH_NONE, 
     106                     PJ_EINVAL); 
     107 
     108    return PJ_SUCCESS; 
     109} 
     110 
     111 
    83112/*  
    84113 * Create ICE stream transport  
    85114 */ 
    86 PJ_DEF(pj_status_t) pj_ice_strans_create( pj_stun_config *stun_cfg, 
     115PJ_DEF(pj_status_t) pj_ice_strans_create( const pj_ice_strans_cfg *cfg, 
    87116                                          const char *name, 
    88117                                          unsigned comp_cnt, 
     
    93122    pj_pool_t *pool; 
    94123    pj_ice_strans *ice_st; 
    95  
    96     PJ_ASSERT_RETURN(stun_cfg && comp_cnt && cb && p_ice_st, PJ_EINVAL); 
    97     PJ_ASSERT_RETURN(stun_cfg->ioqueue && stun_cfg->timer_heap, PJ_EINVAL); 
     124    pj_status_t status; 
     125 
     126    status = pj_ice_strans_cfg_check_valid(cfg); 
     127    if (status != PJ_SUCCESS) 
     128        return status; 
     129 
     130    PJ_ASSERT_RETURN(comp_cnt && cb && p_ice_st, PJ_EINVAL); 
    98131 
    99132    if (name == NULL) 
    100133        name = "icstr%p"; 
    101134 
    102     pool = pj_pool_create(stun_cfg->pf, name, PJNATH_POOL_LEN_ICE_STRANS,  
     135    pool = pj_pool_create(cfg->stun_cfg.pf, name, PJNATH_POOL_LEN_ICE_STRANS,  
    103136                          PJNATH_POOL_INC_ICE_STRANS, NULL); 
    104137    ice_st = PJ_POOL_ZALLOC_T(pool, pj_ice_strans); 
    105138    ice_st->pool = pool; 
     139    pj_memcpy(&ice_st->cfg, cfg, sizeof(*cfg)); 
     140    pj_stun_auth_cred_dup(pool, &ice_st->cfg.turn_cred, &cfg->turn_cred); 
    106141    pj_memcpy(ice_st->obj_name, pool->obj_name, PJ_MAX_OBJ_NAME); 
    107142    ice_st->user_data = user_data; 
     
    112147 
    113148    pj_memcpy(&ice_st->cb, cb, sizeof(*cb)); 
    114     pj_memcpy(&ice_st->stun_cfg, stun_cfg, sizeof(*stun_cfg)); 
    115149 
    116150 
     
    179213    PJ_UNUSED_ARG(domain); 
    180214    return -1; 
    181 } 
    182  
    183 /* 
    184  * Set STUN server address. 
    185  */ 
    186 PJ_DEF(pj_status_t) pj_ice_strans_set_stun_srv( pj_ice_strans *ice_st, 
    187                                                 const pj_sockaddr_in *stun_srv, 
    188                                                 const pj_sockaddr_in *turn_srv) 
    189 { 
    190     PJ_ASSERT_RETURN(ice_st, PJ_EINVAL); 
    191     /* Must not have pending resolver job */ 
    192     PJ_ASSERT_RETURN(ice_st->has_rjob==PJ_FALSE, PJ_EINVALIDOP); 
    193  
    194     if (stun_srv) { 
    195         pj_memcpy(&ice_st->stun_srv, stun_srv, sizeof(pj_sockaddr_in)); 
    196     } else { 
    197         pj_bzero(&ice_st->stun_srv, sizeof(pj_sockaddr_in)); 
    198     } 
    199  
    200     if (turn_srv) { 
    201         pj_memcpy(&ice_st->turn_srv, turn_srv, sizeof(pj_sockaddr_in)); 
    202     } else { 
    203         pj_bzero(&ice_st->turn_srv, sizeof(pj_sockaddr_in)); 
    204     } 
    205  
    206     return PJ_SUCCESS; 
    207215} 
    208216 
     
    328336    pj_bzero(&ioqueue_cb, sizeof(ioqueue_cb)); 
    329337    ioqueue_cb.on_read_complete = &on_read_complete; 
    330     status = pj_ioqueue_register_sock(ice_st->pool, ice_st->stun_cfg.ioqueue,  
     338    status = pj_ioqueue_register_sock(ice_st->pool,  
     339                                      ice_st->cfg.stun_cfg.ioqueue,  
    331340                                      comp->sock, comp, &ioqueue_cb,  
    332341                                      &comp->key); 
     
    388397             * as default candidate. 
    389398             */ 
    390             if (ifs[i].ipv4.sin_addr.s_addr == comp->local_addr.ipv4.sin_addr.s_addr) { 
     399            if (ifs[i].ipv4.sin_addr.s_addr ==  
     400                    comp->local_addr.ipv4.sin_addr.s_addr)  
     401            { 
    391402                set_default = PJ_TRUE; 
    392403                local_pref = 65535; 
     
    464475         *    the binding alive. 
    465476         *  
    466          * 2) this could be a packet (STUN or not STUN) sent from the STUN 
    467          *    relay server. In this case, still there are few options to do 
    468          *    for this packet: a) process this locally if this packet is 
    469          *    related to TURN session management (e.g. Allocate response), 
    470          *    b) forward this packet to ICE if this is related to ICE 
     477         * 2) this could be a STUN request or response sent as part of ICE 
    471478         *    discovery process. 
    472479         * 
    473          * 3) this could be a STUN request or response sent as part of ICE 
    474          *    discovery process. 
    475          * 
    476          * 4) this could be application's packet, e.g. when ICE processing 
     480         * 3) this could be application's packet, e.g. when ICE processing 
    477481         *    is done and agents start sending RTP/RTCP packets to each 
    478482         *    other, or when ICE processing is not done and this ICE stream 
    479483         *    transport decides to allow sending data. 
    480484         * 
    481          * So far we don't have good solution for this. 
    482          * The process below is just a workaround. 
    483485         */ 
     486        unsigned cand_id; 
     487 
     488        /* Find candidate ID for this packet */ 
     489        for (cand_id=0; cand_id<comp->cand_cnt; ++cand_id) { 
     490            if (comp->cand_list[cand_id].type != PJ_ICE_CAND_TYPE_RELAYED) 
     491                break; 
     492        } 
     493        if (cand_id == comp->cand_cnt) { 
     494            //pj_assert(!"We should have at least one host/srflx candidate"); 
     495            //cand_id = 0; 
     496            PJ_LOG(2,(ice_st->obj_name,  
     497                      "Received pkt on comp %d which doesn't have host/srflx " 
     498                      "candidate", 
     499                      comp->comp_id)); 
     500            goto next_packet; 
     501        } 
     502 
     503        /* Is this a STUN message? */ 
    484504        status = pj_stun_msg_check(comp->pkt, bytes_read,  
    485505                                   PJ_STUN_IS_DATAGRAM); 
     
    496516                                                   comp->src_addr_len); 
    497517            } else if (ice_st->ice) { 
    498                 PJ_TODO(DISTINGUISH_BETWEEN_LOCAL_AND_RELAY); 
    499  
    500518                TRACE_PKT((comp->ice_st->obj_name,  
    501519                          "Component %d RX packet from %s:%d", 
     
    505523 
    506524                status = pj_ice_sess_on_rx_pkt(ice_st->ice, comp->comp_id,  
    507                                                comp->pkt, bytes_read, 
     525                                               cand_id, comp->pkt, bytes_read, 
    508526                                               &comp->src_addr,  
    509527                                               comp->src_addr_len); 
     
    525543 
    526544    /* Read next packet */ 
     545next_packet: 
    527546    for (retry=0; retry<RETRY;) { 
    528547        pkt_size = sizeof(comp->pkt); 
     
    552571static void destroy_component(pj_ice_strans_comp *comp) 
    553572{ 
     573    if (comp->turn_relay) { 
     574        pj_turn_sock_destroy(comp->turn_relay); 
     575        comp->turn_relay = NULL; 
     576    } 
     577 
    554578    if (comp->stun_sess) { 
    555579        pj_stun_session_destroy(comp->stun_sess); 
     
    611635                  pj_ntohs(comp->local_addr.ipv4.sin_port))); 
    612636        status = pj_stun_session_send_msg(comp->stun_sess, &comp->cand_list[j], 
    613                                           PJ_FALSE, PJ_TRUE, &ice_st->stun_srv, 
     637                                          PJ_FALSE, PJ_TRUE,  
     638                                          &ice_st->cfg.stun_srv, 
    614639                                          sizeof(pj_sockaddr_in), tdata); 
    615640        if (status != PJ_SUCCESS) { 
     
    638663    ice_st->ka_timer.user_data = ice_st; 
    639664     
    640     if (pj_timer_heap_schedule(ice_st->stun_cfg.timer_heap,  
     665    if (pj_timer_heap_schedule(ice_st->cfg.stun_cfg.timer_heap,  
    641666                               &ice_st->ka_timer, &delay)==PJ_SUCCESS) 
    642667    { 
     
    653678        return; 
    654679 
    655     pj_timer_heap_cancel(ice_st->stun_cfg.timer_heap, &ice_st->ka_timer); 
     680    pj_timer_heap_cancel(ice_st->cfg.stun_cfg.timer_heap, &ice_st->ka_timer); 
    656681    ice_st->ka_timer.id = PJ_FALSE; 
    657682} 
     
    671696    PJ_ASSERT_RETURN(ice_st && comp, PJ_EINVAL); 
    672697     
    673     /* Bail out if STUN server is still being resolved */ 
    674     if (ice_st->has_rjob) 
    675         return PJ_EBUSY; 
    676  
    677698    /* Just return (successfully) if STUN server is not configured */ 
    678     if (ice_st->stun_srv.sin_family == 0) 
     699    if (ice_st->cfg.stun_srv.addr.sa_family == 0) 
    679700        return PJ_SUCCESS; 
    680701 
     
    684705    sess_cb.on_request_complete = &stun_on_request_complete; 
    685706    sess_cb.on_send_msg = &stun_on_send_msg; 
    686     status = pj_stun_session_create(&ice_st->stun_cfg, ice_st->obj_name, 
     707    status = pj_stun_session_create(&ice_st->cfg.stun_cfg, ice_st->obj_name, 
    687708                                    &sess_cb, PJ_FALSE, &comp->stun_sess); 
    688709    if (status != PJ_SUCCESS) 
     
    711732    /* Add new alias to this component */ 
    712733    cand->type = PJ_ICE_CAND_TYPE_SRFLX; 
    713     cand->status = PJ_EPENDING; 
     734    cand->status = PJ_SUCCESS; 
    714735    cand->ice_cand_id = -1; 
    715736    cand->local_pref = 65535; 
     
    721742    /* Send STUN binding request */ 
    722743    status = pj_stun_session_send_msg(comp->stun_sess, (void*)cand, PJ_FALSE,  
    723                                       PJ_TRUE, &ice_st->stun_srv,  
     744                                      PJ_TRUE, &ice_st->cfg.stun_srv,  
    724745                                      sizeof(pj_sockaddr_in), tdata); 
    725746    if (status != PJ_SUCCESS) { 
     
    753774    PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EBUSY); 
    754775     
    755     /* Can't add new component while resolver is running */ 
    756     PJ_ASSERT_RETURN(ice_st->has_rjob == PJ_FALSE, PJ_EBUSY); 
    757  
    758776 
    759777    /* Create component */ 
     
    762780        return status; 
    763781 
    764     if ((options & PJ_ICE_ST_OPT_DISABLE_STUN) == 0) { 
     782    /* Start STUN mapped address resolution */ 
     783    if ((options & PJ_ICE_ST_OPT_DISABLE_STUN) == 0 && 
     784        pj_sockaddr_has_addr(&ice_st->cfg.stun_srv))  
     785    { 
    765786        status = get_stun_mapped_addr(ice_st, comp); 
    766787        if (status != PJ_SUCCESS) { 
     
    769790        } 
    770791    } 
     792 
     793    /* Create TURN relay if wanted. */ 
     794    if ((options & PJ_ICE_ST_OPT_DISABLE_RELAY) == 0 && 
     795        pj_sockaddr_has_addr(&ice_st->cfg.turn_srv))  
     796    { 
     797        pj_turn_sock_cb turn_sock_cb; 
     798        char ipaddr[PJ_INET6_ADDRSTRLEN+8]; 
     799        pj_str_t s; 
     800 
     801        pj_assert(comp->cand_cnt < PJ_ICE_ST_MAX_CAND); 
     802 
     803        /* Init TURN socket */ 
     804        pj_bzero(&turn_sock_cb, sizeof(turn_sock_cb)); 
     805        turn_sock_cb.on_rx_data = &turn_on_rx_data; 
     806        turn_sock_cb.on_state = &turn_on_state; 
     807 
     808        status = pj_turn_sock_create(&ice_st->cfg.stun_cfg, pj_AF_INET(), 
     809                                     ice_st->cfg.turn_conn_type, 
     810                                     &turn_sock_cb, 0, comp, 
     811                                     &comp->turn_relay); 
     812        if (status != PJ_SUCCESS) { 
     813            destroy_component(comp); 
     814            return status; 
     815        } 
     816 
     817        pj_sockaddr_print(&ice_st->cfg.turn_srv, ipaddr, sizeof(ipaddr), 0); 
     818 
     819        ++comp->pending_cnt; 
     820 
     821        /* Start allocation */ 
     822        status = pj_turn_sock_init(comp->turn_relay, pj_cstr(&s, ipaddr),  
     823                                   pj_sockaddr_get_port(&ice_st->cfg.turn_srv), 
     824                                   NULL, &ice_st->cfg.turn_cred,  
     825                                   &ice_st->cfg.turn_alloc_param); 
     826        if (status != PJ_SUCCESS) { 
     827            if (comp->turn_relay) { 
     828                pj_turn_sock_destroy(comp->turn_relay); 
     829            } 
     830            comp->turn_relay = NULL; 
     831            --comp->pending_cnt; 
     832            destroy_component(comp); 
     833            return status; 
     834        } 
     835 
     836    } 
     837 
    771838 
    772839    /* Store this component */ 
     
    849916 
    850917    /* Create! */ 
    851     status = pj_ice_sess_create(&ice_st->stun_cfg, ice_st->obj_name, role, 
     918    status = pj_ice_sess_create(&ice_st->cfg.stun_cfg, ice_st->obj_name, role, 
    852919                                ice_st->comp_cnt, &ice_cb,  
    853920                                local_ufrag, local_passwd, &ice_st->ice); 
     
    877944        for (j=0; j<comp->cand_cnt; ++j) { 
    878945            pj_ice_strans_cand *cand = &comp->cand_list[j]; 
     946            pj_sockaddr_t *local_addr, *relay_addr; 
    879947 
    880948            /* Skip if candidate is not ready */ 
     
    886954            } 
    887955 
     956            if (cand->type == PJ_ICE_CAND_TYPE_RELAYED) { 
     957                local_addr = &cand->addr; 
     958                relay_addr = &cand->addr; 
     959            } else { 
     960                local_addr = &comp->local_addr; 
     961                relay_addr = NULL; 
     962            } 
    888963            status = pj_ice_sess_add_cand(ice_st->ice, comp->comp_id,  
    889964                                          cand->type, cand->local_pref,  
     
    9781053 
    9791054/* 
    980  * Send packet using non-ICE means (e.g. when ICE was not negotiated). 
     1055 * Application wants to send outgoing packet. 
    9811056 */ 
    9821057PJ_DEF(pj_status_t) pj_ice_strans_sendto( pj_ice_strans *ice_st, 
     
    9981073    /* If ICE is available, send data with ICE */ 
    9991074    if (ice_st->ice) { 
    1000         return pj_ice_sess_send_data(ice_st->ice, comp_id, data, data_len); 
     1075        if (comp->turn_relay) { 
     1076            pj_turn_sock_lock(comp->turn_relay); 
     1077        } 
     1078        status = pj_ice_sess_send_data(ice_st->ice, comp_id, data, data_len); 
     1079        if (comp->turn_relay) { 
     1080            pj_turn_sock_unlock(comp->turn_relay); 
     1081        } 
     1082        return status; 
    10011083    } 
    10021084 
     
    10291111static pj_status_t ice_tx_pkt(pj_ice_sess *ice,  
    10301112                              unsigned comp_id,  
     1113                              unsigned cand_id, 
    10311114                              const void *pkt, pj_size_t size, 
    10321115                              const pj_sockaddr_t *dst_addr, 
     
    10341117{ 
    10351118    pj_ice_strans *ice_st = (pj_ice_strans*)ice->user_data; 
    1036     pj_ice_strans_comp *comp = NULL; 
    1037     pj_ssize_t pkt_size; 
     1119    pj_ice_strans_comp *comp; 
     1120    pj_ice_strans_cand *cand; 
    10381121    pj_status_t status; 
    10391122 
    1040     PJ_TODO(TX_TO_RELAY); 
    1041  
    10421123    PJ_ASSERT_RETURN(comp_id && comp_id <= ice_st->comp_cnt, PJ_EINVAL); 
     1124 
    10431125    comp = ice_st->comp[comp_id-1]; 
     1126    cand = &comp->cand_list[cand_id]; 
    10441127 
    10451128    TRACE_PKT((comp->ice_st->obj_name,  
    1046               "Component %d TX packet to %s:%d", 
    1047               comp_id, 
     1129              "Component %d candidate %d TX packet to %s:%d", 
     1130              comp_id, cand_id, 
    10481131              pj_inet_ntoa(((pj_sockaddr_in*)dst_addr)->sin_addr), 
    10491132              (int)pj_ntohs(((pj_sockaddr_in*)dst_addr)->sin_port))); 
    10501133 
    1051     pkt_size = size; 
    1052     status = pj_ioqueue_sendto(comp->key, &comp->write_op,  
    1053                                pkt, &pkt_size, 0, 
    1054                                dst_addr, dst_addr_len); 
     1134    if (cand->type == PJ_ICE_CAND_TYPE_RELAYED) { 
     1135        if (comp->turn_relay) { 
     1136            status = pj_turn_sock_sendto(comp->turn_relay, pkt, size, 
     1137                                         dst_addr, dst_addr_len); 
     1138        } else { 
     1139            status = PJ_EINVALIDOP; 
     1140        } 
     1141    } else { 
     1142        pj_ssize_t pkt_size = size; 
     1143        status = pj_ioqueue_sendto(comp->key, &comp->write_op,  
     1144                                   pkt, &pkt_size, 0, 
     1145                                   dst_addr, dst_addr_len); 
     1146    } 
    10551147     
    10561148    return (status==PJ_SUCCESS||status==PJ_EPENDING) ? PJ_SUCCESS : status; 
     
    12071299} 
    12081300 
     1301 
     1302/* Callback when TURN client has received a packet */ 
     1303static void turn_on_rx_data(pj_turn_sock *turn_sock, 
     1304                            void *pkt, 
     1305                            unsigned pkt_len, 
     1306                            const pj_sockaddr_t *peer_addr, 
     1307                            unsigned addr_len) 
     1308{ 
     1309    pj_ice_strans_comp *comp; 
     1310    unsigned cand_id; 
     1311    pj_status_t status; 
     1312 
     1313    comp = (pj_ice_strans_comp*) pj_turn_sock_get_user_data(turn_sock); 
     1314    if (comp == NULL) { 
     1315        return; 
     1316    } 
     1317 
     1318    /* Find candidate ID for this packet */ 
     1319    for (cand_id=0; cand_id<comp->cand_cnt; ++cand_id) { 
     1320        if (comp->cand_list[cand_id].type == PJ_ICE_CAND_TYPE_RELAYED) 
     1321            break; 
     1322    } 
     1323    if (cand_id == comp->cand_cnt) { 
     1324        pj_assert(!"Missing relay candidate"); 
     1325        return; 
     1326    } 
     1327 
     1328    /* Hand over the packet to ICE */ 
     1329    status = pj_ice_sess_on_rx_pkt(comp->ice_st->ice, comp->comp_id,  
     1330                                   cand_id, pkt, pkt_len, 
     1331                                   peer_addr, addr_len); 
     1332 
     1333    if (status != PJ_SUCCESS) { 
     1334        ice_st_perror(comp->ice_st, "Error processing packet from TURN relay",  
     1335                      status); 
     1336    } 
     1337} 
     1338 
     1339 
     1340/* Callback when TURN client state has changed */ 
     1341static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state, 
     1342                          pj_turn_state_t new_state) 
     1343{ 
     1344    pj_ice_strans_comp *comp; 
     1345 
     1346    comp = (pj_ice_strans_comp*) pj_turn_sock_get_user_data(turn_sock); 
     1347    if (comp == NULL) { 
     1348        /* Not interested in further state notification once the relay is 
     1349         * disconnecting. 
     1350         */ 
     1351        return; 
     1352    } 
     1353 
     1354    PJ_LOG(5,(comp->ice_st->obj_name, "TURN client state changed %s --> %s", 
     1355              pj_turn_state_name(old_state), pj_turn_state_name(new_state))); 
     1356 
     1357    if (old_state < PJ_TURN_STATE_READY && 
     1358        new_state >= PJ_TURN_STATE_READY) 
     1359    { 
     1360        pj_assert(comp->pending_cnt > 0); 
     1361        comp->pending_cnt--; 
     1362    } 
     1363 
     1364    if (new_state == PJ_TURN_STATE_READY) { 
     1365        pj_turn_session_info rel_info; 
     1366        char ipaddr[PJ_INET6_ADDRSTRLEN+8]; 
     1367        pj_ice_strans_cand *cand; 
     1368 
     1369        /* Get allocation info */ 
     1370        pj_turn_sock_get_info(turn_sock, &rel_info); 
     1371 
     1372        /* Add a relay candidate to this component */ 
     1373        pj_assert(comp->cand_cnt < PJ_ICE_ST_MAX_CAND); 
     1374        cand = &comp->cand_list[comp->cand_cnt++]; 
     1375 
     1376        /* Add new candidate to this component */ 
     1377        cand->type = PJ_ICE_CAND_TYPE_RELAYED; 
     1378        cand->status = PJ_SUCCESS; 
     1379        cand->ice_cand_id = -1; 
     1380        cand->local_pref = 65535; 
     1381        pj_sockaddr_cp(&cand->addr, &rel_info.relay_addr); 
     1382        pj_ice_calc_foundation(comp->ice_st->pool, &cand->foundation,  
     1383                               PJ_ICE_CAND_TYPE_RELAYED,  
     1384                               &rel_info.relay_addr); 
     1385 
     1386        PJ_LOG(4,(comp->ice_st->obj_name,  
     1387                  "Component %d cand %d: relay address: %s", 
     1388                  comp->comp_id, cand - comp->cand_list, 
     1389                  pj_sockaddr_print(&rel_info.relay_addr, ipaddr,  
     1390                                     sizeof(ipaddr), 3))); 
     1391 
     1392    } else if (new_state >= PJ_TURN_STATE_DEALLOCATING) { 
     1393        /* Unregister ourself from the TURN relay */ 
     1394        pj_turn_sock_set_user_data(turn_sock, NULL); 
     1395        comp->turn_relay = NULL; 
     1396 
     1397        PJ_LOG(4,(comp->ice_st->obj_name, "Relay destroyed")); 
     1398    } 
     1399} 
     1400 
Note: See TracChangeset for help on using the changeset viewer.