Changeset 1096


Ignore:
Timestamp:
Mar 22, 2007 9:00:53 PM (13 years ago)
Author:
bennylp
Message:

Final ICE stream transport

Location:
pjproject/trunk/pjnath
Files:
6 edited
2 moved

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjnath/build/pjnath.dsp

    r1093 r1096  
    9696# Begin Source File 
    9797 
    98 SOURCE=..\src\pjnath\ice_mt.c 
     98SOURCE=..\src\pjnath\ice_stream_transport.c 
    9999# End Source File 
    100100# Begin Source File 
     
    136136# Begin Source File 
    137137 
    138 SOURCE=..\include\pjnath\ice_mt.h 
     138SOURCE=..\include\pjnath\ice_stream_transport.h 
    139139# End Source File 
    140140# Begin Source File 
  • pjproject/trunk/pjnath/include/pjnath.h

    r1093 r1096  
    2121#include <pjnath/errno.h> 
    2222#include <pjnath/ice.h> 
    23 #include <pjnath/ice_mt.h> 
     23#include <pjnath/ice_stream_transport.h> 
    2424#include <pjnath/stun_auth.h> 
    2525#include <pjnath/stun_config.h> 
  • pjproject/trunk/pjnath/include/pjnath/errno.h

    r1092 r1096  
    156156/** 
    157157 * @hideinitializer 
     158 * Invalid ICE candidate ID 
     159 */ 
     160#define PJ_EICEINCANDID             -1 
     161/** 
     162 * @hideinitializer 
     163 * ICE session not available 
     164 */ 
     165#define PJ_ENOICE                   -1 
     166 
     167 /** 
     168 * @hideinitializer 
    158169 * ICE check is in progress 
    159170 */ 
  • pjproject/trunk/pjnath/include/pjnath/ice.h

    r1093 r1096  
    8282{ 
    8383    unsigned         comp_id; 
    84     pj_stun_session *stun_sess; 
    85     pj_sockaddr      local_addr; 
    8684    int              nominated_check_id; 
    8785} pj_ice_comp; 
     
    10098    pj_sockaddr          base_addr; 
    10199    pj_sockaddr          srv_addr; 
     100    pj_stun_session     *stun_sess; 
    102101} pj_ice_cand; 
    103102 
     
    146145{ 
    147146    void        (*on_ice_complete)(pj_ice *ice, pj_status_t status); 
    148     pj_status_t (*on_tx_pkt)(pj_ice *ice, unsigned comp_id, 
     147    pj_status_t (*on_tx_pkt)(pj_ice *ice, unsigned comp_id,  
     148                             unsigned cand_id, 
    149149                             const void *pkt, pj_size_t size, 
    150150                             const pj_sockaddr_t *dst_addr, 
    151151                             unsigned dst_addr_len); 
    152     pj_status_t (*on_rx_data)(pj_ice *ice, unsigned comp_id, 
     152    void        (*on_rx_data)(pj_ice *ice, unsigned comp_id, 
     153                              unsigned cand_id, 
    153154                              void *pkt, pj_size_t size, 
    154155                              const pj_sockaddr_t *src_addr, 
     
    213214                                   pj_ice_role role, 
    214215                                   const pj_ice_cb *cb, 
     216                                   const pj_str_t *local_ufrag, 
     217                                   const pj_str_t *local_passwd, 
    215218                                   pj_ice **p_ice); 
    216219PJ_DECL(pj_status_t) pj_ice_destroy(pj_ice *ice); 
    217 PJ_DECL(pj_status_t) pj_ice_add_comp(pj_ice *ice, 
    218                                      unsigned comp_id, 
    219                                      const pj_sockaddr_t *local_addr, 
    220                                      unsigned addr_len); 
    221 PJ_DECL(pj_status_t) pj_ice_set_credentials(pj_ice *ice, 
    222                                             const pj_str_t *local_ufrag, 
    223                                             const pj_str_t *local_pass, 
    224                                             const pj_str_t *remote_ufrag, 
    225                                             const pj_str_t *remote_pass); 
     220PJ_DECL(pj_status_t) pj_ice_add_comp(pj_ice *ice, unsigned comp_id); 
    226221PJ_DECL(pj_status_t) pj_ice_add_cand(pj_ice *ice, 
    227222                                     unsigned comp_id, 
     
    247242 
    248243PJ_DECL(pj_status_t) pj_ice_create_check_list(pj_ice *ice, 
     244                                              const pj_str_t *rem_ufrag, 
     245                                              const pj_str_t *rem_passwd, 
    249246                                              unsigned rem_cand_cnt, 
    250247                                              const pj_ice_cand rem_cand[]); 
     
    257254PJ_DECL(pj_status_t) pj_ice_on_rx_pkt(pj_ice *ice, 
    258255                                      unsigned comp_id, 
     256                                      unsigned cand_id, 
    259257                                      void *pkt, 
    260258                                      pj_size_t pkt_size, 
  • pjproject/trunk/pjnath/include/pjnath/ice_stream_transport.h

    r1094 r1096  
    1717 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1818 */ 
    19 #ifndef __PJNATH_ICE_MT_H__ 
    20 #define __PJNATH_ICE_MT_H__ 
     19#ifndef __PJNATH_ICE_STREAM_TRANSPORT_H__ 
     20#define __PJNATH_ICE_STREAM_TRANSPORT_H__ 
    2121 
    2222 
     
    2626 */ 
    2727#include <pjnath/ice.h> 
     28#include <pjlib-util/resolver.h> 
    2829#include <pj/ioqueue.h> 
    2930 
     
    3334 
    3435/** 
    35  * @defgroup PJNATH_ICE_MEDIA_TRANSPORT ICE Media Transport 
    36  * @brief ICE Media Transport 
     36 * @defgroup PJNATH_ICE_STREAM_TRANSPORT ICE Stream Transport 
     37 * @brief Transport for media stream using ICE 
    3738 * @ingroup PJNATH_ICE 
    3839 * @{ 
    3940 */ 
    4041 
    41 typedef struct pj_icemt pj_icemt; 
     42typedef struct pj_ice_st pj_ice_st; 
    4243 
    43 typedef struct pj_icemt_cb 
     44typedef struct pj_ice_st_cb 
    4445{ 
    45     void        (*on_ice_complete)(pj_icemt *icemt,  
    46                                    pj_status_t status); 
    47     void        (*on_rx_rtp)(pj_icemt *icemt, 
    48                              void *pkt, pj_size_t size, 
    49                              const pj_sockaddr_t *src_addr, 
    50                              unsigned src_addr_len); 
    51     void        (*on_rx_rtcp)(pj_icemt *icemt, 
    52                               void *pkt, pj_size_t size, 
    53                               const pj_sockaddr_t *src_addr, 
    54                               unsigned src_addr_len); 
     46    void    (*on_rx_data)(pj_ice_st *ice_st, 
     47                          unsigned comp_id, unsigned cand_id, 
     48                          void *pkt, pj_size_t size, 
     49                          const pj_sockaddr_t *src_addr, 
     50                          unsigned src_addr_len); 
    5551 
    56 } pj_icemt_cb; 
     52    void    (*on_stun_srv_resolved)(pj_ice_st *ice_st, 
     53                                    pj_status_t status); 
     54    void    (*on_interface_status)(pj_ice_st *ice_st, 
     55                                   void *notify_data, 
     56                                   pj_status_t status, 
     57                                   int itf_id); 
     58    void    (*on_ice_complete)(pj_ice_st *ice_st,  
     59                               pj_status_t status); 
     60 
     61} pj_ice_st_cb; 
    5762 
    5863 
    59 typedef struct pj_icemt_sock 
     64typedef struct pj_ice_st_comp 
    6065{ 
    61     pj_icemt            *icemt; 
    6266    unsigned             comp_id; 
     67} pj_ice_st_comp; 
     68 
     69 
     70typedef struct pj_ice_st_interface 
     71{ 
     72    pj_ice_st           *ice_st; 
     73    pj_ice_cand_type     type; 
     74    unsigned             comp_id; 
     75    int                  cand_id; 
     76    pj_str_t             foundation; 
     77    pj_uint16_t          local_pref; 
    6378    pj_sock_t            sock; 
    6479    pj_sockaddr          addr; 
     
    7085    pj_sockaddr          src_addr; 
    7186    int                  src_addr_len; 
    72 } pj_icemt_sock; 
     87} pj_ice_st_interface; 
    7388 
    7489 
    75 struct pj_icemt 
     90struct pj_ice_st 
    7691{ 
    77     pj_pool_t       *pool; 
    78     pj_ice          *ice; 
    79     void            *user_data; 
     92    char                     obj_name[PJ_MAX_OBJ_NAME]; 
     93    pj_pool_t               *pool; 
     94    void                    *user_data; 
     95    pj_stun_config           stun_cfg; 
     96    pj_ice_st_cb             cb; 
    8097 
    81     pj_icemt_cb      cb; 
     98    pj_ice                  *ice; 
    8299 
    83     pj_icemt_sock    rtp; 
    84     pj_icemt_sock    rtcp; 
     100    unsigned                 comp_cnt; 
     101    unsigned                 comps[PJ_ICE_MAX_COMP]; 
    85102 
    86     pj_bool_t        has_turn; 
    87     pj_sockaddr      stun_srv; 
     103    unsigned                 itf_cnt; 
     104    pj_ice_st_interface     *itfs[PJ_ICE_MAX_CAND]; 
     105 
     106    pj_dns_resolver         *resolver; 
     107    pj_bool_t                relay_enabled; 
     108    pj_str_t                 stun_domain; 
     109    pj_sockaddr_in           stun_srv; 
    88110}; 
    89111 
    90112 
    91 PJ_DECL(pj_status_t) pj_icemt_create(pj_stun_config *stun_cfg, 
    92                                      const char *name, 
    93                                      pj_ice_role role, 
    94                                      const pj_icemt_cb *cb, 
    95                                      unsigned rtp_port, 
    96                                      pj_bool_t has_rtcp, 
    97                                      pj_bool_t has_turn, 
    98                                      const pj_sockaddr *srv, 
    99                                      pj_icemt **p_icemt); 
    100 PJ_DECL(pj_status_t) pj_icemt_destroy(pj_icemt *icemt); 
     113PJ_DECL(pj_status_t) pj_ice_st_create(pj_stun_config *stun_cfg, 
     114                                      const char *name, 
     115                                      void *user_data, 
     116                                      const pj_ice_st_cb *cb, 
     117                                      pj_ice_st **p_ice_st); 
     118PJ_DECL(pj_status_t) pj_ice_st_destroy(pj_ice_st *ice_st); 
    101119 
     120PJ_DECL(pj_status_t) pj_ice_st_set_stun(pj_ice_st *ice_st, 
     121                                        pj_dns_resolver *resolver, 
     122                                        pj_bool_t enable_relay, 
     123                                        const pj_str_t *domain); 
     124PJ_DECL(pj_status_t) pj_ice_st_set_stun_addr(pj_ice_st *ice_st, 
     125                                             pj_bool_t enable_relay, 
     126                                             const pj_sockaddr_in *srv_addr); 
     127 
     128PJ_DECL(pj_status_t) pj_ice_st_add_comp(pj_ice_st *ice_st, 
     129                                        unsigned comp_id); 
     130 
     131PJ_DECL(pj_status_t) pj_ice_st_add_host_interface(pj_ice_st *ice_st, 
     132                                                  unsigned comp_id, 
     133                                                  pj_uint16_t local_pref, 
     134                                                  const pj_sockaddr_in *addr, 
     135                                                  unsigned *p_itf_id, 
     136                                                  pj_bool_t notify, 
     137                                                  void *notify_data); 
     138PJ_DECL(pj_status_t) pj_ice_st_add_all_host_interfaces(pj_ice_st *ice_st, 
     139                                                       unsigned comp_id, 
     140                                                       unsigned port, 
     141                                                       pj_bool_t notify, 
     142                                                       void *notify_data); 
     143PJ_DECL(pj_status_t) pj_ice_st_add_stun_interface(pj_ice_st *ice_st, 
     144                                                  unsigned comp_id, 
     145                                                  unsigned local_port, 
     146                                                  pj_bool_t notify, 
     147                                                  void *notify_data); 
     148PJ_DECL(pj_status_t) pj_ice_st_add_relay_interface(pj_ice_st *ice_st, 
     149                                                   unsigned comp_id, 
     150                                                   unsigned local_port, 
     151                                                   pj_bool_t notify, 
     152                                                   void *notify_data); 
     153 
     154 
     155PJ_DECL(pj_status_t) pj_ice_st_init_ice(pj_ice_st *ice_st, 
     156                                        pj_ice_role role, 
     157                                        const pj_str_t *local_ufrag, 
     158                                        const pj_str_t *local_passwd); 
     159PJ_DECL(pj_status_t) pj_ice_st_enum_cands(pj_ice_st *ice_st, 
     160                                          unsigned *count, 
     161                                          pj_ice_cand cand[]); 
     162PJ_DECL(pj_status_t) pj_ice_st_start_ice(pj_ice_st *ice_st, 
     163                                         const pj_str_t *rem_ufrag, 
     164                                         const pj_str_t *rem_passwd, 
     165                                         unsigned rem_cand_cnt, 
     166                                         const pj_ice_cand rem_cand[]); 
     167PJ_DECL(pj_status_t) pj_ice_st_stop_ice(pj_ice_st *ice_st); 
     168 
     169PJ_DECL(pj_status_t) pj_ice_st_send_data(pj_ice_st *ice_st, 
     170                                         unsigned comp_id, 
     171                                         const void *data, 
     172                                         pj_size_t data_len); 
    102173 
    103174 
     
    111182 
    112183 
    113 #endif  /* __PJNATH_ICE_MT_H__ */ 
     184#endif  /* __PJNATH_ICE_STREAM_TRANSPORT_H__ */ 
    114185 
  • pjproject/trunk/pjnath/src/pjnath-test/ice_test.c

    r1095 r1096  
    3838static pj_stun_config stun_cfg; 
    3939 
    40 static void on_ice_complete(pj_icemt *icemt,  
     40static void on_ice_complete(pj_ice_st *icest,  
    4141                            pj_status_t status) 
    4242{ 
    43     struct ice_data *id = (struct ice_data*) icemt->user_data; 
     43    struct ice_data *id = (struct ice_data*) icest->user_data; 
    4444    id->complete = PJ_TRUE; 
    4545    id->err_code = status; 
     
    4949 
    5050 
    51 static void on_rx_rtp(pj_icemt *icemt, 
    52                       void *pkt, pj_size_t size, 
    53                       const pj_sockaddr_t *src_addr, 
    54                       unsigned src_addr_len) 
    55 { 
    56     struct ice_data *id = (struct ice_data*) icemt->user_data; 
    57  
    58     id->rx_rtp_cnt++; 
    59     pj_memcpy(id->last_rx_rtp_data, pkt, size); 
    60     id->last_rx_rtp_data[size] = '\0'; 
    61  
    62     PJ_UNUSED_ARG(src_addr); 
    63     PJ_UNUSED_ARG(src_addr_len); 
    64 } 
    65  
    66  
    67 static void on_rx_rtcp(pj_icemt *icemt, 
     51static void on_rx_data(pj_ice_st *icest, 
     52                       unsigned comp_id, unsigned cand_id, 
    6853                       void *pkt, pj_size_t size, 
    6954                       const pj_sockaddr_t *src_addr, 
    7055                       unsigned src_addr_len) 
    7156{ 
    72     struct ice_data *id = (struct ice_data*) icemt->user_data; 
    73  
    74     id->rx_rtcp_cnt++; 
    75     pj_memcpy(id->last_rx_rtcp_data, pkt, size); 
    76     id->last_rx_rtcp_data[size] = '\0'; 
    77  
     57    struct ice_data *id = (struct ice_data*) icest->user_data; 
     58 
     59    if (comp_id == 1) { 
     60        id->rx_rtp_cnt++; 
     61        pj_memcpy(id->last_rx_rtp_data, pkt, size); 
     62        id->last_rx_rtp_data[size] = '\0'; 
     63    } else if (comp_id == 2) { 
     64        id->rx_rtcp_cnt++; 
     65        pj_memcpy(id->last_rx_rtcp_data, pkt, size); 
     66        id->last_rx_rtcp_data[size] = '\0'; 
     67    } else { 
     68        pj_assert(!"Invalid component ID"); 
     69    } 
     70 
     71    PJ_UNUSED_ARG(cand_id); 
    7872    PJ_UNUSED_ARG(src_addr); 
    7973    PJ_UNUSED_ARG(src_addr_len); 
     
    9892static int ice_basic_create_destroy_test() 
    9993{ 
    100     pj_icemt *im; 
    101     pj_ice *ice; 
    102     pj_icemt_cb icemt_cb; 
     94    pj_ice_st *im; 
     95    pj_ice_st_cb icest_cb; 
    10396    pj_status_t status; 
    10497 
    10598    PJ_LOG(3,(THIS_FILE, "...basic create/destroy")); 
    10699 
    107     pj_bzero(&icemt_cb, sizeof(icemt_cb)); 
    108     icemt_cb.on_ice_complete = &on_ice_complete; 
    109     icemt_cb.on_rx_rtp = &on_rx_rtp; 
    110     icemt_cb.on_rx_rtcp = &on_rx_rtcp; 
    111  
    112     status = pj_icemt_create(&stun_cfg, NULL, PJ_ICE_ROLE_CONTROLLING, 
    113                              &icemt_cb, 0, PJ_FALSE, PJ_FALSE, NULL, &im); 
     100    pj_bzero(&icest_cb, sizeof(icest_cb)); 
     101    icest_cb.on_ice_complete = &on_ice_complete; 
     102    icest_cb.on_rx_data = &on_rx_data; 
     103 
     104    status = pj_ice_st_create(&stun_cfg, NULL, NULL, &icest_cb, &im); 
    114105    if (status != PJ_SUCCESS) 
    115106        return -10; 
    116107 
    117     ice = im->ice; 
    118  
    119     pj_icemt_destroy(im); 
     108    pj_ice_st_destroy(im); 
    120109 
    121110    return 0; 
     
    123112 
    124113 
    125 static pj_status_t set_remote_list(pj_icemt *src, pj_icemt *dst) 
    126 { 
    127     unsigned i, count; 
    128     unsigned cand_id[PJ_ICE_MAX_CAND]; 
     114static pj_status_t start_ice(pj_ice_st *ist, pj_ice_st *remote) 
     115{ 
     116    unsigned count; 
    129117    pj_ice_cand cand[PJ_ICE_MAX_CAND]; 
    130118    pj_status_t status; 
    131119 
    132     count = PJ_ARRAY_SIZE(cand_id); 
    133     status = pj_ice_enum_cands(src->ice, &count, cand_id); 
     120    count = PJ_ARRAY_SIZE(cand); 
     121    status = pj_ice_st_enum_cands(remote, &count, cand); 
    134122    if (status != PJ_SUCCESS) 
    135123        return status; 
    136124 
    137     for (i=0; i<count; ++i) { 
    138         pj_ice_cand *p_cand; 
    139         status = pj_ice_get_cand(src->ice, cand_id[i], &p_cand); 
    140         if (status != PJ_SUCCESS) 
    141             return status; 
    142  
    143         pj_memcpy(&cand[i], p_cand, sizeof(pj_ice_cand)); 
    144     } 
    145  
    146     status = pj_ice_create_check_list(dst->ice, count, cand); 
    147     return status; 
    148 } 
     125    return pj_ice_st_start_ice(ist, &remote->ice->rx_ufrag, &remote->ice->rx_pass, 
     126                               count, cand); 
     127} 
     128 
    149129 
    150130 
     
    163143static int perform_ice_test(const char *title, 
    164144                            unsigned wait_before_send, 
    165                             unsigned max_total_time, 
    166                             unsigned ocand_cnt, 
    167                             const pj_ice_cand ocand[], 
    168                             unsigned acand_cnt, 
    169                             const pj_ice_cand acand[]) 
    170 { 
    171     pj_icemt *im1, *im2; 
    172     pj_icemt_cb icemt_cb; 
     145                            unsigned max_total_time) 
     146{ 
     147    pj_ice_st *im1, *im2; 
     148    pj_ice_st_cb icest_cb; 
    173149    struct ice_data *id1, *id2; 
    174150    pj_timestamp t_start, t_end; 
    175151    pj_ice_cand *rcand; 
    176152    pj_str_t data_from_offerer, data_from_answerer; 
    177     unsigned i; 
    178153    pj_status_t status; 
    179154 
    180155    PJ_LOG(3,(THIS_FILE, "...%s", title)); 
    181156 
    182     pj_bzero(&icemt_cb, sizeof(icemt_cb)); 
    183     icemt_cb.on_ice_complete = &on_ice_complete; 
    184     icemt_cb.on_rx_rtp = &on_rx_rtp; 
    185     icemt_cb.on_rx_rtcp = &on_rx_rtcp; 
     157    pj_bzero(&icest_cb, sizeof(icest_cb)); 
     158    icest_cb.on_ice_complete = &on_ice_complete; 
     159    icest_cb.on_rx_data = &on_rx_data; 
    186160 
    187161    /* Create first ICE */ 
    188     status = pj_icemt_create(&stun_cfg, "offerer", PJ_ICE_ROLE_CONTROLLING, 
    189                              &icemt_cb, 0, PJ_FALSE, PJ_FALSE, NULL, &im1); 
     162    status = pj_ice_st_create(&stun_cfg, "offerer", NULL, &icest_cb, &im1); 
    190163    if (status != PJ_SUCCESS) 
    191164        return -20; 
     
    195168    im1->user_data = id1; 
    196169 
    197     /* Add additional candidates */ 
    198     for (i=0; i<ocand_cnt; ++i) { 
    199         status = pj_ice_add_cand(im1->ice, 1, ocand[i].type, 65535, 
    200                                  &ocand[i].foundation, &ocand[i].addr, 
    201                                  &ocand[i].base_addr, &ocand[i].srv_addr, 
    202                                  sizeof(pj_sockaddr_in), NULL); 
    203         if (status != PJ_SUCCESS) 
    204             return -22; 
    205     } 
     170    /* Add first component */ 
     171    status = pj_ice_st_add_comp(im1, 1); 
     172    if (status != PJ_SUCCESS) 
     173        return -21; 
     174 
     175    /* Add host candidate */ 
     176    status = pj_ice_st_add_host_interface(im1, 1, 65535, NULL, NULL, PJ_FALSE, NULL); 
     177    if (status != PJ_SUCCESS) 
     178        return -21; 
    206179 
    207180    /* Create second ICE */ 
    208     status = pj_icemt_create(&stun_cfg, "answerer", PJ_ICE_ROLE_CONTROLLED, 
    209                              &icemt_cb, 0, PJ_FALSE, PJ_FALSE, NULL, &im2); 
     181    status = pj_ice_st_create(&stun_cfg, "answerer", NULL, &icest_cb, &im2); 
    210182    if (status != PJ_SUCCESS) 
    211183        return -25; 
     
    215187    im2->user_data = id2; 
    216188 
    217     /* Add additional candidates */ 
    218     for (i=0; i<acand_cnt; ++i) { 
    219         status = pj_ice_add_cand(im1->ice, 1, acand[i].type, 65535, 
    220                                  &acand[i].foundation, &acand[i].addr, 
    221                                  &acand[i].base_addr, &acand[i].srv_addr, 
    222                                  sizeof(pj_sockaddr_in), NULL); 
    223         if (status != PJ_SUCCESS) 
    224             return -22; 
    225     } 
    226  
    227     /* Set credentials */ 
    228     { 
    229         pj_str_t u1 = pj_str("offerer"); 
    230         pj_str_t p1 = pj_str("pass1"); 
    231         pj_str_t u2 = pj_str("answerer"); 
    232         pj_str_t p2 = pj_str("pass2"); 
    233  
    234         pj_ice_set_credentials(im1->ice, &u1, &p1, &u2, &p2); 
    235         pj_ice_set_credentials(im2->ice, &u2, &p2, &u1, &p1); 
    236     } 
    237  
    238     /* Send offer to im2 */ 
    239     status = set_remote_list(im1, im2); 
     189    /* Add first component */ 
     190    status = pj_ice_st_add_comp(im2, 1); 
     191    if (status != PJ_SUCCESS) 
     192        return -26; 
     193 
     194    /* Add host candidate */ 
     195    status = pj_ice_st_add_host_interface(im2, 1, 65535, NULL, NULL, PJ_FALSE, NULL); 
     196    if (status != PJ_SUCCESS) 
     197        return -27; 
     198 
     199    /* Init ICE on im1 */ 
     200    status = pj_ice_st_init_ice(im1, PJ_ICE_ROLE_CONTROLLING, NULL, NULL); 
     201    if (status != PJ_SUCCESS) 
     202        return -29; 
     203 
     204    /* Init ICE on im2 */ 
     205    status = pj_ice_st_init_ice(im2, PJ_ICE_ROLE_CONTROLLED, NULL, NULL); 
     206    if (status != PJ_SUCCESS) 
     207        return -29; 
     208 
     209    /* Start ICE on im2 */ 
     210    status = start_ice(im2, im1); 
    240211    if (status != PJ_SUCCESS) 
    241212        return -30; 
    242213 
    243     /* Send answer to im1 */ 
    244     status = set_remote_list(im2, im1); 
     214    /* Start ICE on im1 */ 
     215    status = start_ice(im1, im2); 
    245216    if (status != PJ_SUCCESS) 
    246217        return -35; 
     
    248219    /* Mark start time */ 
    249220    pj_get_timestamp(&t_start); 
    250  
    251     /* Both can start now */ 
    252     status = pj_ice_start_check(im1->ice); 
    253     if (status != PJ_SUCCESS) 
    254         return -40; 
    255  
    256 #if 1 
    257     status = pj_ice_start_check(im2->ice); 
    258     if (status != PJ_SUCCESS) 
    259         return -45; 
    260 #endif 
    261221 
    262222    /* Poll for wait_before_send msecs before we send the first data */ 
     
    366326 
    367327 
    368     pj_icemt_destroy(im1); 
    369     pj_icemt_destroy(im2); 
     328    pj_ice_st_destroy(im1); 
     329    pj_ice_st_destroy(im2); 
    370330    return 0; 
    371331} 
     
    378338    pj_ioqueue_t *ioqueue; 
    379339    pj_timer_heap_t *timer_heap; 
    380     pj_ice_cand ocand[PJ_ICE_MAX_CAND]; 
    381     pj_ice_cand acand[PJ_ICE_MAX_CAND]; 
    382     pj_str_t s; 
    383340 
    384341    pool = pj_pool_create(mem, NULL, 4000, 4000, NULL); 
     
    396353 
    397354    /* Direct communication */ 
    398     rc = perform_ice_test("Direct connection", 500, 1000, 0, NULL, 0, NULL); 
     355    rc = perform_ice_test("Direct connection", 500, 1000); 
    399356    if (rc != 0) 
    400357        goto on_return; 
    401358 
    402359    /* Direct communication with invalid address */ 
    403     pj_bzero(ocand, sizeof(ocand)); 
    404     pj_sockaddr_in_init(&ocand[0].addr.ipv4, pj_cstr(&s, "127.0.0.127"), 1234); 
    405     pj_sockaddr_in_init(&ocand[0].base_addr.ipv4, pj_cstr(&s, "127.0.0.128"), 1234); 
    406     ocand[0].comp_id = 1; 
    407     ocand[0].foundation = pj_str("H2"); 
    408     ocand[0].type = PJ_ICE_CAND_TYPE_HOST; 
    409  
    410     rc = perform_ice_test("Direct connection with 1 invalid address", 500, 1000, 1, ocand, 0, NULL); 
     360    rc = perform_ice_test("Direct connection with 1 invalid address", 500, 1000); 
    411361    if (rc != 0) 
    412362        goto on_return; 
    413363 
    414364    /* Direct communication with two components */ 
    415     rc = perform_ice_test("Direct connection with two components", 500, 1000, 0, NULL, 0, NULL); 
     365    rc = perform_ice_test("Direct connection with two components", 500, 1000); 
    416366    if (rc != 0) 
    417367        goto on_return; 
  • pjproject/trunk/pjnath/src/pjnath/ice.c

    r1094 r1096  
    2222#include <pj/array.h> 
    2323#include <pj/assert.h> 
     24#include <pj/guid.h> 
    2425#include <pj/log.h> 
    2526#include <pj/os.h> 
     
    6970{ 
    7071    pj_ice      *ice; 
    71     unsigned     comp_id; 
    72     pj_ice_comp *comp; 
     72    unsigned     lcand_id; 
     73    pj_ice_cand *lcand; 
    7374} stun_data; 
    7475 
     
    133134 
    134135 
     136/* 
     137 * Create ICE stream session. 
     138 */ 
    135139PJ_DEF(pj_status_t) pj_ice_create(pj_stun_config *stun_cfg, 
    136140                                  const char *name, 
    137141                                  pj_ice_role role, 
    138142                                  const pj_ice_cb *cb, 
     143                                  const pj_str_t *local_ufrag, 
     144                                  const pj_str_t *local_passwd, 
    139145                                  pj_ice **p_ice) 
    140146{ 
    141147    pj_pool_t *pool; 
    142148    pj_ice *ice; 
     149    char tmp[32]; 
     150    pj_str_t s; 
    143151    unsigned i; 
    144152    pj_status_t status; 
     
    146154    PJ_ASSERT_RETURN(stun_cfg && cb && p_ice, PJ_EINVAL); 
    147155 
    148     if (!name) 
     156    if (name == NULL) 
    149157        name = "ice%p"; 
    150158 
     
    171179    } 
    172180 
     181    if (local_ufrag == NULL) { 
     182        pj_ansi_snprintf(tmp, sizeof(tmp), "%x", pj_rand()); 
     183        s = pj_str(tmp); 
     184        local_ufrag = &s; 
     185    } 
     186    pj_strdup(ice->pool, &ice->rx_ufrag, local_ufrag); 
     187 
     188    if (local_passwd == NULL) { 
     189        pj_ansi_snprintf(tmp, sizeof(tmp), "%x", pj_rand()); 
     190        s = pj_str(tmp); 
     191        local_passwd = &s; 
     192    } 
     193    pj_strdup(ice->pool, &ice->rx_pass, local_passwd); 
     194 
     195 
    173196    /* Done */ 
    174197    *p_ice = ice; 
    175198 
    176     LOG((ice->obj_name, "ICE media stream created")); 
     199    LOG((ice->obj_name, "ICE stream session created, role is %s agent", 
     200        (ice->role==PJ_ICE_ROLE_CONTROLLING ? "controlling" : "controlled"))); 
    177201 
    178202    return PJ_SUCCESS; 
     
    180204 
    181205 
     206/* 
     207 * Destroy 
     208 */ 
    182209static void destroy_ice(pj_ice *ice, 
    183210                        pj_status_t reason) 
     
    190217 
    191218    for (i=0; i<ice->comp_cnt; ++i) { 
    192         pj_ice_comp *comp = &ice->comp[i]; 
    193  
    194         if (comp->stun_sess) { 
    195             pj_stun_session_destroy(comp->stun_sess); 
    196             comp->stun_sess = NULL; 
     219        /* Nothing to do */ 
     220    } 
     221 
     222    for (i=0; i<ice->lcand_cnt; ++i) { 
     223        if (ice->lcand[i].stun_sess) { 
     224            pj_stun_session_destroy(ice->lcand[i].stun_sess); 
     225            ice->lcand[i].stun_sess = NULL; 
    197226        } 
    198227    } 
     
    223252 
    224253 
     254/* Find component by ID */ 
    225255static pj_ice_comp *find_comp(const pj_ice *ice, unsigned comp_id) 
    226256{ 
     
    228258    for (i=0; i<ice->comp_cnt; ++i) { 
    229259        if (ice->comp[i].comp_id == comp_id) 
    230             return (pj_ice_comp*) &ice->comp[i]; 
     260            return (pj_ice_comp *) &ice->comp[i]; 
    231261    } 
    232262 
     
    235265 
    236266 
    237 PJ_DEF(pj_status_t) pj_ice_add_comp(pj_ice *ice, 
    238                                     unsigned comp_id, 
    239                                     const pj_sockaddr_t *local_addr, 
    240                                     unsigned addr_len) 
    241 { 
    242     pj_stun_session_cb sess_cb; 
     267/* Add a new component */ 
     268PJ_DEF(pj_status_t) pj_ice_add_comp(pj_ice *ice, unsigned comp_id) 
     269{ 
    243270    pj_ice_comp *comp; 
    244     pj_stun_auth_cred auth_cred; 
    245     stun_data *sd; 
    246     pj_status_t status; 
    247  
    248     PJ_ASSERT_RETURN(ice && local_addr && addr_len, PJ_EINVAL); 
     271 
     272    PJ_ASSERT_RETURN(ice && comp_id, PJ_EINVAL); 
    249273    PJ_ASSERT_RETURN(ice->comp_cnt < PJ_ARRAY_SIZE(ice->comp), PJ_ETOOMANY); 
     274    PJ_ASSERT_RETURN(comp_id==ice->comp_cnt+1, PJ_EICEINCOMPID); 
    250275    PJ_ASSERT_RETURN(find_comp(ice, comp_id) == NULL, PJ_EEXISTS); 
    251276 
     
    255280    comp->comp_id = comp_id; 
    256281    comp->nominated_check_id = -1; 
    257     pj_memcpy(&comp->local_addr, local_addr, addr_len); 
    258  
    259     /* Init STUN callbacks */ 
    260     pj_bzero(&sess_cb, sizeof(sess_cb)); 
    261     sess_cb.on_request_complete = &on_stun_request_complete; 
    262     sess_cb.on_rx_indication = &on_stun_rx_indication; 
    263     sess_cb.on_rx_request = &on_stun_rx_request; 
    264     sess_cb.on_send_msg = &on_stun_send_msg; 
    265  
    266     /* Create STUN session for this component */ 
    267     status = pj_stun_session_create(&ice->stun_cfg, ice->obj_name,  
    268                                     &sess_cb, PJ_FALSE, 
    269                                     &comp->stun_sess); 
    270     if (status != PJ_SUCCESS) { 
    271         pj_mutex_unlock(ice->mutex); 
    272         return status; 
    273     } 
    274  
    275     /* Associate data with this STUN session */ 
    276     sd = PJ_POOL_ZALLOC_T(ice->pool, struct stun_data); 
    277     sd->ice = ice; 
    278     sd->comp_id = comp_id; 
    279     sd->comp = comp; 
    280     pj_stun_session_set_user_data(comp->stun_sess, sd); 
    281  
    282     /* Init STUN authentication credential */ 
    283     pj_bzero(&auth_cred, sizeof(auth_cred)); 
    284     auth_cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; 
    285     auth_cred.data.dyn_cred.get_auth = &stun_auth_get_auth; 
    286     auth_cred.data.dyn_cred.get_cred = &stun_auth_get_cred; 
    287     auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 
    288     auth_cred.data.dyn_cred.verify_nonce = &stun_auth_verify_nonce; 
    289     auth_cred.data.dyn_cred.user_data = comp->stun_sess; 
    290     pj_stun_session_set_credential(comp->stun_sess, &auth_cred); 
    291282 
    292283    /* Done */ 
     
    409400 
    410401 
    411 PJ_DEF(pj_status_t) pj_ice_set_credentials(pj_ice *ice, 
    412                                            const pj_str_t *local_ufrag, 
    413                                            const pj_str_t *local_pass, 
    414                                            const pj_str_t *remote_ufrag, 
    415                                            const pj_str_t *remote_pass) 
    416 { 
    417     char buf[128]; 
    418     pj_str_t username; 
    419  
    420     username.ptr = buf; 
    421  
    422     PJ_ASSERT_RETURN(ice && local_ufrag && local_pass && 
    423                      remote_ufrag && remote_pass, PJ_EINVAL); 
    424     PJ_ASSERT_RETURN(local_ufrag->slen + remote_ufrag->slen < 
    425                      sizeof(buf), PJ_ENAMETOOLONG); 
    426  
    427     pj_strcpy(&username, remote_ufrag); 
    428     pj_strcat2(&username, ":"); 
    429     pj_strcat(&username, local_ufrag); 
    430  
    431     pj_strdup(ice->pool, &ice->tx_uname, &username); 
    432     pj_strdup(ice->pool, &ice->tx_ufrag, remote_ufrag); 
    433     pj_strdup(ice->pool, &ice->tx_pass, remote_pass); 
    434  
    435     pj_strcpy(&username, local_ufrag); 
    436     pj_strcat2(&username, ":"); 
    437     pj_strcat(&username, remote_ufrag); 
    438  
    439     pj_strdup(ice->pool, &ice->rx_uname, &username); 
    440     pj_strdup(ice->pool, &ice->rx_ufrag, local_ufrag); 
    441     pj_strdup(ice->pool, &ice->rx_pass, local_pass); 
    442  
    443     return PJ_SUCCESS; 
    444 } 
    445  
    446  
    447402static pj_uint32_t CALC_CAND_PRIO(pj_ice_cand_type type, 
    448403                                  pj_uint32_t local_pref, 
     
    463418 
    464419 
     420/* 
     421 * Add ICE candidate 
     422 */ 
    465423PJ_DEF(pj_status_t) pj_ice_add_cand(pj_ice *ice, 
    466424                                    unsigned comp_id, 
     
    475433{ 
    476434    pj_ice_cand *lcand; 
     435    pj_stun_session_cb sess_cb; 
     436    pj_stun_auth_cred auth_cred; 
     437    stun_data *sd; 
    477438    pj_status_t status = PJ_SUCCESS; 
    478439    char tmp[128]; 
     
    501462        pj_bzero(&lcand->srv_addr, sizeof(lcand->srv_addr)); 
    502463 
    503     if (p_cand_id) 
    504         *p_cand_id = ice->lcand_cnt; 
     464    /* Init STUN callbacks */ 
     465    pj_bzero(&sess_cb, sizeof(sess_cb)); 
     466    sess_cb.on_request_complete = &on_stun_request_complete; 
     467    sess_cb.on_rx_indication = &on_stun_rx_indication; 
     468    sess_cb.on_rx_request = &on_stun_rx_request; 
     469    sess_cb.on_send_msg = &on_stun_send_msg; 
     470 
     471    /* Create STUN session for this candidate */ 
     472    status = pj_stun_session_create(&ice->stun_cfg, ice->obj_name,  
     473                                    &sess_cb, PJ_FALSE, 
     474                                    &lcand->stun_sess); 
     475    if (status != PJ_SUCCESS) { 
     476        pj_mutex_unlock(ice->mutex); 
     477        return status; 
     478    } 
     479 
     480    /* Associate data with this STUN session */ 
     481    sd = PJ_POOL_ZALLOC_T(ice->pool, struct stun_data); 
     482    sd->ice = ice; 
     483    sd->lcand_id = GET_LCAND_ID(lcand); 
     484    sd->lcand = lcand; 
     485    pj_stun_session_set_user_data(lcand->stun_sess, sd); 
     486 
     487    /* Init STUN authentication credential */ 
     488    pj_bzero(&auth_cred, sizeof(auth_cred)); 
     489    auth_cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; 
     490    auth_cred.data.dyn_cred.get_auth = &stun_auth_get_auth; 
     491    auth_cred.data.dyn_cred.get_cred = &stun_auth_get_cred; 
     492    auth_cred.data.dyn_cred.get_password = &stun_auth_get_password; 
     493    auth_cred.data.dyn_cred.verify_nonce = &stun_auth_verify_nonce; 
     494    auth_cred.data.dyn_cred.user_data = lcand->stun_sess; 
     495    pj_stun_session_set_credential(lcand->stun_sess, &auth_cred); 
     496 
    505497 
    506498    pj_ansi_strcpy(tmp, pj_inet_ntoa(lcand->addr.ipv4.sin_addr)); 
     
    518510         (int)pj_htons(lcand->base_addr.ipv4.sin_port), 
    519511         lcand->prio, lcand->prio)); 
     512 
     513    if (p_cand_id) 
     514        *p_cand_id = ice->lcand_cnt; 
    520515 
    521516    ++ice->lcand_cnt; 
     
    10421037 
    10431038PJ_DEF(pj_status_t) pj_ice_create_check_list(pj_ice *ice, 
     1039                                             const pj_str_t *rem_ufrag, 
     1040                                             const pj_str_t *rem_passwd, 
    10441041                                             unsigned rcand_cnt, 
    10451042                                             const pj_ice_cand rcand[]) 
    10461043{ 
    10471044    pj_ice_checklist *clist; 
     1045    char buf[128]; 
     1046    pj_str_t username; 
    10481047    timer_data *td; 
    10491048    unsigned i, j; 
    10501049 
    1051     PJ_ASSERT_RETURN(ice && rcand_cnt && rcand, PJ_EINVAL); 
     1050    PJ_ASSERT_RETURN(ice && rem_ufrag && rem_passwd && rcand_cnt && rcand, 
     1051                     PJ_EINVAL); 
    10521052    PJ_ASSERT_RETURN(rcand_cnt + ice->rcand_cnt <= PJ_ICE_MAX_CAND,  
    10531053                     PJ_ETOOMANY); 
    10541054 
    10551055    pj_mutex_lock(ice->mutex); 
     1056 
     1057    /* Save credentials */ 
     1058    username.ptr = buf; 
     1059 
     1060    pj_strcpy(&username, rem_ufrag); 
     1061    pj_strcat2(&username, ":"); 
     1062    pj_strcat(&username, &ice->rx_ufrag); 
     1063 
     1064    pj_strdup(ice->pool, &ice->tx_uname, &username); 
     1065    pj_strdup(ice->pool, &ice->tx_ufrag, rem_ufrag); 
     1066    pj_strdup(ice->pool, &ice->tx_pass, rem_passwd); 
     1067 
     1068    pj_strcpy(&username, &ice->rx_ufrag); 
     1069    pj_strcat2(&username, ":"); 
     1070    pj_strcat(&username, rem_ufrag); 
     1071 
     1072    pj_strdup(ice->pool, &ice->rx_uname, &username); 
     1073 
    10561074 
    10571075    /* Save remote candidates */ 
     
    11551173 
    11561174    /* Create request */ 
    1157     status = pj_stun_session_create_req(comp->stun_sess,  
     1175    status = pj_stun_session_create_req(lcand->stun_sess,  
    11581176                                        PJ_STUN_BINDING_REQUEST, &tdata); 
    11591177    if (status != PJ_SUCCESS) 
     
    11871205 
    11881206    /* Initiate STUN transaction to send the request */ 
    1189     status = pj_stun_session_send_msg(comp->stun_sess, PJ_FALSE,  
     1207    status = pj_stun_session_send_msg(lcand->stun_sess, PJ_FALSE,  
    11901208                                      &rcand->addr,  
    11911209                                      sizeof(pj_sockaddr_in), tdata); 
     
    13321350{ 
    13331351    stun_data *sd = (stun_data*) pj_stun_session_get_user_data(sess); 
    1334     return (*sd->ice->cb.on_tx_pkt)(sd->ice, sd->comp_id,  
     1352    return (*sd->ice->cb.on_tx_pkt)(sd->ice, sd->lcand->comp_id, sd->lcand_id, 
    13351353                                    pkt, pkt_size,  
    13361354                                    dst_addr, addr_len); 
     
    15351553    sd = (stun_data*) pj_stun_session_get_user_data(sess); 
    15361554    ice = sd->ice; 
    1537     comp = sd->comp; 
     1555    lcand = sd->lcand; 
     1556    comp = find_comp(ice, lcand->comp_id); 
    15381557 
    15391558    pj_mutex_lock(ice->mutex); 
     
    16211640    PJ_TODO(DETERMINE_IF_REQUEST_COMES_FROM_RELAYED_CANDIDATE); 
    16221641    is_relayed = PJ_FALSE; 
    1623  
    1624     /* Next find local candidate, by first finding a check in the checklist 
    1625      * which base address is equal to the local address. 
    1626      */ 
    1627     for (i=0; i<ice->clist.count; ++i) { 
    1628         pj_ice_check *c = &ice->clist.checks[i]; 
    1629         if (sockaddr_cmp(&c->lcand->base_addr, &comp->local_addr)==0) 
    1630             break; 
    1631     } 
    1632  
    1633     /* MUST find a local candidate! */ 
    1634     pj_assert(i != ice->clist.count); 
    1635     if (i == ice->clist.count) { 
    1636         pj_mutex_unlock(ice->mutex); 
    1637         LOG((ice->obj_name, "Error: unable to find local candidate for " 
    1638              "incoming request")); 
    1639         return PJ_SUCCESS; 
    1640     } 
    1641  
    1642     lcand = ice->clist.checks[i].lcand; 
    16431642 
    16441643    /* Now that we have local and remote candidate, check if we already 
     
    17591758    pj_status_t status = PJ_SUCCESS; 
    17601759    pj_ice_comp *comp; 
     1760    unsigned cand_id; 
    17611761    pj_ice_check *check; 
    17621762 
     
    17771777 
    17781778    check = &ice->clist.checks[comp->nominated_check_id]; 
    1779  
    1780     status = (*ice->cb.on_tx_pkt)(ice, comp_id, data, data_len,  
     1779    cand_id = GET_LCAND_ID(check->lcand); 
     1780 
     1781    status = (*ice->cb.on_tx_pkt)(ice, comp_id, cand_id, data, data_len,  
    17811782                                  &check->rcand->addr,  
    17821783                                  sizeof(pj_sockaddr_in)); 
     
    17901791PJ_DEF(pj_status_t) pj_ice_on_rx_pkt( pj_ice *ice, 
    17911792                                      unsigned comp_id, 
     1793                                      unsigned cand_id, 
    17921794                                      void *pkt, 
    17931795                                      pj_size_t pkt_size, 
     
    17971799    pj_status_t status = PJ_SUCCESS; 
    17981800    pj_ice_comp *comp; 
     1801    pj_ice_cand *lcand; 
    17991802    pj_status_t stun_status; 
    18001803 
     
    18091812    } 
    18101813 
     1814    lcand = &ice->lcand[cand_id]; 
     1815 
    18111816    stun_status = pj_stun_msg_check(pkt, pkt_size, PJ_STUN_IS_DATAGRAM); 
    18121817    if (stun_status == PJ_SUCCESS) { 
    1813         status = pj_stun_session_on_rx_pkt(comp->stun_sess, pkt, pkt_size, 
     1818        status = pj_stun_session_on_rx_pkt(lcand->stun_sess, pkt, pkt_size, 
    18141819                                           PJ_STUN_IS_DATAGRAM, 
    18151820                                           NULL, src_addr, src_addr_len); 
    18161821    } else { 
    1817         status = (*ice->cb.on_rx_data)(ice, comp_id, pkt, pkt_size,  
    1818                                        src_addr, src_addr_len); 
     1822        (*ice->cb.on_rx_data)(ice, comp_id, cand_id, pkt, pkt_size,  
     1823                              src_addr, src_addr_len); 
    18191824    } 
    18201825     
  • pjproject/trunk/pjnath/src/pjnath/ice_stream_transport.c

    r1095 r1096  
    1717 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1818 */ 
    19 #include <pjnath/ice_mt.h> 
     19#include <pjnath/ice_stream_transport.h> 
    2020#include <pjnath/errno.h> 
    2121#include <pj/addr_resolv.h> 
    2222#include <pj/assert.h> 
     23#include <pj/log.h> 
    2324#include <pj/pool.h> 
    2425#include <pj/string.h> 
    2526 
    2627 
    27 #define RTP_COMP_ID     1 
    28 #define RTCP_COMP_ID    2 
    29  
    30  
    3128 
    3229/* ICE callbacks */ 
    3330static void        on_ice_complete(pj_ice *ice, pj_status_t status); 
    34 static pj_status_t on_tx_pkt(pj_ice *ice, unsigned comp_id, 
     31static pj_status_t on_tx_pkt(pj_ice *ice,  
     32                             unsigned comp_id, unsigned cand_id, 
    3533                             const void *pkt, pj_size_t size, 
    3634                             const pj_sockaddr_t *dst_addr, 
    3735                             unsigned dst_addr_len); 
    38 static pj_status_t on_rx_data(pj_ice *ice, unsigned comp_id, 
     36static void        on_rx_data(pj_ice *ice,  
     37                              unsigned comp_id, unsigned cand_id, 
    3938                              void *pkt, pj_size_t size, 
    4039                              const pj_sockaddr_t *src_addr, 
     
    4645                             pj_ssize_t bytes_read); 
    4746 
    48 static void destroy_ice_sock(pj_icemt_sock *is); 
    49  
    50 static pj_status_t create_ice_sock(pj_icemt *icemt, 
    51                                    pj_ioqueue_t *ioqueue, 
    52                                    unsigned comp_id, 
    53                                    unsigned port, 
    54                                    pj_icemt_sock *is) 
     47static void destroy_ice_interface(pj_ice_st_interface *is); 
     48static void destroy_ice_st(pj_ice_st *ice_st, pj_status_t reason); 
     49 
     50static void ice_st_perror(pj_ice_st *ice_st, const char *title,  
     51                          pj_status_t status) 
     52{ 
     53    char errmsg[PJ_ERR_MSG_SIZE]; 
     54 
     55    pj_strerror(status, errmsg, sizeof(errmsg)); 
     56    PJ_LOG(1,(ice_st->obj_name, "%s: %s", title, errmsg)); 
     57} 
     58 
     59 
     60/* Get the prefix for the foundation */ 
     61static int get_type_prefix(pj_ice_cand_type type) 
     62{ 
     63    switch (type) { 
     64    case PJ_ICE_CAND_TYPE_HOST:     return 'H'; 
     65    case PJ_ICE_CAND_TYPE_SRFLX:    return 'S'; 
     66    case PJ_ICE_CAND_TYPE_PRFLX:    return 'P'; 
     67    case PJ_ICE_CAND_TYPE_RELAYED:  return 'R'; 
     68    default: 
     69        pj_assert(!"Invalid type"); 
     70        return 'U'; 
     71    } 
     72} 
     73 
     74 
     75/*  
     76 * Create new interface (i.e. socket)  
     77 */ 
     78static pj_status_t create_ice_interface(pj_ice_st *ice_st, 
     79                                        pj_ice_cand_type type, 
     80                                        unsigned comp_id, 
     81                                        pj_uint16_t local_pref, 
     82                                        const pj_sockaddr_in *addr, 
     83                                        pj_ice_st_interface **p_is) 
    5584{ 
    5685    pj_ioqueue_callback ioqueue_cb; 
    57     const pj_str_t H1 = { "H1", 2 }; 
     86    pj_ice_st_interface *is; 
     87    char foundation[32]; 
    5888    int addr_len; 
    5989    pj_status_t status; 
    6090 
    61     pj_bzero(is, sizeof(*is)); 
     91    is = PJ_POOL_ZALLOC_T(ice_st->pool, pj_ice_st_interface); 
     92    is->type = type; 
     93    is->comp_id = comp_id; 
     94    is->cand_id = -1; 
    6295    is->sock = PJ_INVALID_SOCKET; 
    63     is->comp_id = comp_id; 
    64     is->icemt = icemt; 
     96    is->ice_st = ice_st; 
     97    is->local_pref = local_pref; 
    6598 
    6699    status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &is->sock); 
     
    69102 
    70103    /* Bind and get the local IP address */ 
    71     pj_sockaddr_in_init(&is->base_addr.ipv4, NULL, (pj_uint16_t)port); 
     104    if (addr)  
     105        pj_memcpy(&is->base_addr, addr, sizeof(pj_sockaddr_in)); 
     106    else  
     107        pj_sockaddr_in_init(&is->base_addr.ipv4, NULL, 0); 
     108 
    72109    status = pj_sock_bind(is->sock, &is->base_addr, sizeof(pj_sockaddr_in)); 
    73110    if (status != PJ_SUCCESS) 
     
    85122    } 
    86123 
     124    /* Assign foundation */ 
     125    pj_ansi_snprintf(foundation, sizeof(foundation), "%c%x",  
     126                     get_type_prefix(type), 
     127                     (int)pj_ntohl(is->base_addr.ipv4.sin_addr.s_addr)); 
     128    pj_strdup2(ice_st->pool, &is->foundation, foundation); 
     129 
     130 
    87131    /* Register to ioqueue */ 
    88132    pj_bzero(&ioqueue_cb, sizeof(ioqueue_cb)); 
    89133    ioqueue_cb.on_read_complete = &on_read_complete; 
    90     status = pj_ioqueue_register_sock(icemt->pool, ioqueue, is->sock, is, 
    91                                       &ioqueue_cb, &is->key); 
     134    status = pj_ioqueue_register_sock(ice_st->pool, ice_st->stun_cfg.ioqueue,  
     135                                      is->sock, is, &ioqueue_cb, &is->key); 
    92136    if (status != PJ_SUCCESS) 
    93137        goto on_error; 
     
    96140    pj_ioqueue_op_key_init(&is->write_op, sizeof(is->write_op)); 
    97141 
     142    /* Kick start reading the socket */ 
    98143    on_read_complete(is->key, &is->read_op, 0); 
    99144 
    100     /* Add new ICE component */ 
    101     status = pj_ice_add_comp(icemt->ice, comp_id, &is->base_addr, 
    102                              sizeof(pj_sockaddr_in)); 
    103     if (status != PJ_SUCCESS) 
    104         goto on_error; 
    105  
    106     /* Add host candidate */ 
    107     status = pj_ice_add_cand(icemt->ice, comp_id, PJ_ICE_CAND_TYPE_HOST, 
    108                              65535, &H1, &is->base_addr, &is->base_addr, 
    109                              NULL, sizeof(pj_sockaddr_in), NULL); 
    110     if (status != PJ_SUCCESS) 
    111         goto on_error; 
    112      
     145    /* Done */ 
     146    *p_is = is; 
    113147    return PJ_SUCCESS; 
    114148 
    115149on_error: 
    116     destroy_ice_sock(is); 
     150    destroy_ice_interface(is); 
    117151    return status; 
    118152} 
    119153 
    120154 
     155/*  
     156 * This is callback called by ioqueue on incoming packet  
     157 */ 
    121158static void on_read_complete(pj_ioqueue_key_t *key,  
    122159                             pj_ioqueue_op_key_t *op_key,  
    123160                             pj_ssize_t bytes_read) 
    124161{ 
    125     pj_icemt_sock *is = (pj_icemt_sock*) pj_ioqueue_get_user_data(key); 
     162    pj_ice_st_interface *is = (pj_ice_st_interface*)  
     163                              pj_ioqueue_get_user_data(key); 
    126164    pj_ssize_t pkt_size; 
    127165    pj_status_t status; 
    128166 
    129167    if (bytes_read > 0) { 
    130         status = pj_ice_on_rx_pkt(is->icemt->ice, is->comp_id,  
    131                                   is->pkt, bytes_read, 
    132                                   &is->src_addr, is->src_addr_len); 
    133     } 
    134  
     168 
     169        /* If we have an active ICE session, hand over all incoming 
     170         * packets to the ICE session. Otherwise just drop the packet. 
     171         */ 
     172        if (is->ice_st->ice) { 
     173            status = pj_ice_on_rx_pkt(is->ice_st->ice,  
     174                                      is->comp_id, is->cand_id, 
     175                                      is->pkt, bytes_read, 
     176                                      &is->src_addr, is->src_addr_len); 
     177        } 
     178 
     179    } else if (bytes_read < 0) { 
     180        ice_st_perror(is->ice_st, "ioqueue read callback error", -bytes_read); 
     181    } 
     182 
     183    /* Read next packet */ 
    135184    pkt_size = sizeof(is->pkt); 
    136185    is->src_addr_len = sizeof(is->src_addr); 
     
    138187                                 PJ_IOQUEUE_ALWAYS_ASYNC, 
    139188                                 &is->src_addr, &is->src_addr_len); 
    140     pj_assert(status == PJ_SUCCESS || status == PJ_EPENDING); 
    141 } 
    142  
    143  
    144 static void destroy_ice_sock(pj_icemt_sock *is) 
     189    if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
     190        ice_st_perror(is->ice_st, "ioqueue recvfrom() error", status); 
     191    } 
     192} 
     193 
     194 
     195/*  
     196 * Destroy an interface  
     197 */ 
     198static void destroy_ice_interface(pj_ice_st_interface *is) 
    145199{ 
    146200    if (is->key) { 
     
    155209 
    156210 
    157 PJ_DEF(pj_status_t) pj_icemt_create( pj_stun_config *stun_cfg, 
    158                                      const char *name, 
    159                                      pj_ice_role role, 
    160                                      const pj_icemt_cb *cb, 
    161                                      unsigned rtp_port, 
    162                                      pj_bool_t has_rtcp, 
    163                                      pj_bool_t has_turn, 
    164                                      const pj_sockaddr *srv, 
    165                                      pj_icemt **p_icemt) 
     211/*  
     212 * Create ICE stream transport  
     213 */ 
     214PJ_DECL(pj_status_t) pj_ice_st_create(pj_stun_config *stun_cfg, 
     215                                      const char *name, 
     216                                      void *user_data, 
     217                                      const pj_ice_st_cb *cb, 
     218                                      pj_ice_st **p_ice_st) 
    166219{ 
    167220    pj_pool_t *pool; 
    168     pj_icemt *icemt; 
     221    pj_ice_st *ice_st; 
     222 
     223    PJ_ASSERT_RETURN(stun_cfg && cb && p_ice_st, PJ_EINVAL); 
     224    PJ_ASSERT_RETURN(stun_cfg->ioqueue && stun_cfg->timer_heap, PJ_EINVAL); 
     225 
     226    if (name == NULL) 
     227        name = "icest%p"; 
     228 
     229    pool = pj_pool_create(stun_cfg->pf, name, 4000, 4000, NULL); 
     230    ice_st = PJ_POOL_ZALLOC_T(pool, pj_ice_st); 
     231    ice_st->pool = pool; 
     232    pj_memcpy(ice_st->obj_name, pool->obj_name, PJ_MAX_OBJ_NAME); 
     233    ice_st->user_data = user_data; 
     234     
     235    pj_memcpy(&ice_st->cb, cb, sizeof(*cb)); 
     236    pj_memcpy(&ice_st->stun_cfg, stun_cfg, sizeof(*stun_cfg)); 
     237 
     238    PJ_LOG(4,(ice_st->obj_name, "ICE stream transport created")); 
     239 
     240    *p_ice_st = ice_st; 
     241    return PJ_SUCCESS; 
     242} 
     243 
     244 
     245static void destroy_ice_st(pj_ice_st *ice_st, pj_status_t reason) 
     246{ 
     247    unsigned i; 
     248    char obj_name[PJ_MAX_OBJ_NAME]; 
     249 
     250    if (reason == PJ_SUCCESS) { 
     251        pj_memcpy(obj_name, ice_st->obj_name, PJ_MAX_OBJ_NAME); 
     252        PJ_LOG(4,(obj_name, "ICE stream transport shutting down")); 
     253    } 
     254 
     255    /* Destroy ICE if we have ICE */ 
     256    if (ice_st->ice) { 
     257        pj_ice_destroy(ice_st->ice); 
     258        ice_st->ice = NULL; 
     259    } 
     260 
     261    /* Destroy all interfaces */ 
     262    for (i=0; i<ice_st->itf_cnt; ++i) { 
     263        destroy_ice_interface(ice_st->itfs[i]); 
     264        ice_st->itfs[i] = NULL; 
     265    } 
     266    ice_st->itf_cnt = 0; 
     267 
     268    /* Done */ 
     269    pj_pool_release(ice_st->pool); 
     270 
     271    if (reason == PJ_SUCCESS) { 
     272        PJ_LOG(4,(obj_name, "ICE stream transport destroyed")); 
     273    } 
     274} 
     275 
     276 
     277/* 
     278 * Destroy ICE stream transport. 
     279 */ 
     280PJ_DEF(pj_status_t) pj_ice_st_destroy(pj_ice_st *ice_st) 
     281{ 
     282    destroy_ice_st(ice_st, PJ_SUCCESS); 
     283    return PJ_SUCCESS; 
     284} 
     285 
     286 
     287/* 
     288 * Resolve STUN server 
     289 */ 
     290PJ_DEF(pj_status_t) pj_ice_st_set_stun( pj_ice_st *ice_st, 
     291                                        pj_dns_resolver *resolver, 
     292                                        pj_bool_t enable_relay, 
     293                                        const pj_str_t *domain) 
     294{ 
     295    /* Yeah, TODO */ 
     296    PJ_UNUSED_ARG(ice_st); 
     297    PJ_UNUSED_ARG(resolver); 
     298    PJ_UNUSED_ARG(enable_relay); 
     299    PJ_UNUSED_ARG(domain); 
     300    return -1; 
     301} 
     302 
     303 
     304/* 
     305 * Set STUN server address. 
     306 */ 
     307PJ_DEF(pj_status_t) pj_ice_st_set_stun_addr( pj_ice_st *ice_st, 
     308                                             pj_bool_t enable_relay, 
     309                                             const pj_sockaddr_in *srv_addr) 
     310{ 
     311 
     312    PJ_ASSERT_RETURN(ice_st && srv_addr, PJ_EINVAL); 
     313     
     314    ice_st->relay_enabled = enable_relay; 
     315    pj_strdup2(ice_st->pool, &ice_st->stun_domain, 
     316               pj_inet_ntoa(srv_addr->sin_addr)); 
     317    pj_memcpy(&ice_st->stun_srv, srv_addr, sizeof(pj_sockaddr_in)); 
     318 
     319    return PJ_SUCCESS; 
     320} 
     321 
     322 
     323/* 
     324 * Add new component. 
     325 */ 
     326PJ_DEF(pj_status_t) pj_ice_st_add_comp(pj_ice_st *ice_st, 
     327                                       unsigned comp_id) 
     328{ 
     329    /* Verify arguments */ 
     330    PJ_ASSERT_RETURN(ice_st && comp_id, PJ_EINVAL); 
     331 
     332    /* Can only add component when we don't have active ICE session */ 
     333    PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EBUSY); 
     334 
     335    /* Check that we don't have too many components */ 
     336    PJ_ASSERT_RETURN(ice_st->comp_cnt < PJ_ICE_MAX_COMP, PJ_ETOOMANY); 
     337 
     338    /* Component ID must be valid */ 
     339    PJ_ASSERT_RETURN(comp_id <= PJ_ICE_MAX_COMP, PJ_EICEINCOMPID); 
     340 
     341    /* First component ID must be 1, second must be 2, etc., and  
     342     * they must be registered in order. 
     343     */ 
     344    PJ_ASSERT_RETURN(ice_st->comps[comp_id-1] == ice_st->comp_cnt,  
     345                     PJ_EICEINCOMPID); 
     346 
     347    /* All in order, add the component. */ 
     348    ice_st->comps[ice_st->comp_cnt++] = comp_id; 
     349 
     350    return PJ_SUCCESS; 
     351} 
     352 
     353 
     354/* Add interface */ 
     355static void add_interface(pj_ice_st *ice_st, pj_ice_st_interface *is, 
     356                          unsigned *p_itf_id, pj_bool_t notify, 
     357                          void *notify_data) 
     358{ 
     359    unsigned itf_id; 
     360 
     361    itf_id = ice_st->itf_cnt++; 
     362    ice_st->itfs[itf_id] = is; 
     363 
     364    if (p_itf_id) 
     365        *p_itf_id = itf_id; 
     366 
     367    if (notify && ice_st->cb.on_interface_status) { 
     368        (*ice_st->cb.on_interface_status)(ice_st, notify_data,  
     369                                          PJ_SUCCESS, itf_id); 
     370    } 
     371} 
     372 
     373/* 
     374 * Add new host interface. 
     375 */ 
     376PJ_DEF(pj_status_t) pj_ice_st_add_host_interface(pj_ice_st *ice_st, 
     377                                                 unsigned comp_id, 
     378                                                 pj_uint16_t local_pref, 
     379                                                 const pj_sockaddr_in *addr, 
     380                                                 unsigned *p_itf_id, 
     381                                                 pj_bool_t notify, 
     382                                                 void *notify_data) 
     383{ 
     384    pj_ice_st_interface *is; 
     385    pj_status_t status; 
     386 
     387    /* Verify arguments */ 
     388    PJ_ASSERT_RETURN(ice_st && comp_id, PJ_EINVAL); 
     389 
     390    /* Check that component ID present */ 
     391    PJ_ASSERT_RETURN(comp_id <= ice_st->comp_cnt, PJ_EICEINCOMPID); 
     392 
     393    /* Can't add new interface while ICE is running */ 
     394    PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EBUSY); 
     395 
     396    /* Create interface */ 
     397    status = create_ice_interface(ice_st, PJ_ICE_CAND_TYPE_HOST, comp_id, 
     398                                  local_pref, addr, &is); 
     399    if (status != PJ_SUCCESS) 
     400        return status; 
     401 
     402    /* For host interface, the address is the base address */ 
     403    pj_memcpy(&is->addr, &is->base_addr, sizeof(is->addr)); 
     404 
     405    /* Store this interface */ 
     406    add_interface(ice_st, is, p_itf_id, notify, notify_data); 
     407 
     408    return PJ_SUCCESS; 
     409} 
     410 
     411 
     412/* 
     413 * Enumerate and add all host interfaces. 
     414 */ 
     415PJ_DEF(pj_status_t) pj_ice_st_add_all_host_interfaces(pj_ice_st *ice_st, 
     416                                                      unsigned comp_id, 
     417                                                      unsigned port, 
     418                                                      pj_bool_t notify, 
     419                                                      void *notify_data) 
     420{ 
     421    pj_sockaddr_in addr; 
     422    pj_status_t status; 
     423 
     424    /* Yeah, TODO. 
     425     * For now just add the default interface. 
     426     */ 
     427    pj_sockaddr_in_init(&addr, NULL, (pj_uint16_t)port); 
     428     
     429    status = pj_gethostip(&addr.sin_addr); 
     430    if (status != PJ_SUCCESS) 
     431        return status; 
     432 
     433    return pj_ice_st_add_host_interface(ice_st, comp_id, 65535, &addr,  
     434                                        NULL, notify, notify_data); 
     435} 
     436 
     437 
     438/* 
     439 * Add STUN mapping interface. 
     440 */ 
     441PJ_DEF(pj_status_t) pj_ice_st_add_stun_interface(pj_ice_st *ice_st, 
     442                                                 unsigned comp_id, 
     443                                                 unsigned local_port, 
     444                                                 pj_bool_t notify, 
     445                                                 void *notify_data) 
     446{ 
     447    /* Yeah, TODO */ 
     448    PJ_UNUSED_ARG(ice_st); 
     449    PJ_UNUSED_ARG(comp_id); 
     450    PJ_UNUSED_ARG(local_port); 
     451    PJ_UNUSED_ARG(notify); 
     452    PJ_UNUSED_ARG(notify_data); 
     453    return -1; 
     454} 
     455 
     456 
     457/* 
     458 * Add TURN mapping interface. 
     459 */ 
     460PJ_DEF(pj_status_t) pj_ice_st_add_relay_interface(pj_ice_st *ice_st, 
     461                                                  unsigned comp_id, 
     462                                                  unsigned local_port, 
     463                                                  pj_bool_t notify, 
     464                                                  void *notify_data) 
     465{ 
     466    /* Yeah, TODO */ 
     467    PJ_UNUSED_ARG(ice_st); 
     468    PJ_UNUSED_ARG(comp_id); 
     469    PJ_UNUSED_ARG(local_port); 
     470    PJ_UNUSED_ARG(notify); 
     471    PJ_UNUSED_ARG(notify_data); 
     472    return -1; 
     473} 
     474 
     475 
     476/* 
     477 * Create ICE! 
     478 */ 
     479PJ_DEF(pj_status_t) pj_ice_st_init_ice(pj_ice_st *ice_st, 
     480                                       pj_ice_role role, 
     481                                       const pj_str_t *local_ufrag, 
     482                                       const pj_str_t *local_passwd) 
     483{ 
     484    pj_status_t status; 
     485    unsigned i; 
    169486    pj_ice_cb ice_cb; 
    170     pj_status_t status; 
    171  
    172     pool = pj_pool_create(stun_cfg->pf, name, 512, 512, NULL); 
    173     icemt = PJ_POOL_ZALLOC_T(pool, struct pj_icemt); 
    174     icemt->pool = pool; 
    175  
    176  
     487 
     488    /* Check arguments */ 
     489    PJ_ASSERT_RETURN(ice_st, PJ_EINVAL); 
     490    /* Must not have ICE */ 
     491    PJ_ASSERT_RETURN(ice_st->ice == NULL, PJ_EINVALIDOP); 
     492 
     493    /* Init callback */ 
    177494    pj_bzero(&ice_cb, sizeof(ice_cb)); 
    178495    ice_cb.on_ice_complete = &on_ice_complete; 
     496    ice_cb.on_rx_data = &on_rx_data; 
    179497    ice_cb.on_tx_pkt = &on_tx_pkt; 
    180     ice_cb.on_rx_data = &on_rx_data; 
    181  
    182     pj_memcpy(&icemt->cb, cb, sizeof(*cb)); 
    183  
    184     status = pj_ice_create(stun_cfg, name, role, &ice_cb, &icemt->ice); 
    185     if (status != PJ_SUCCESS) 
    186         goto on_error; 
    187  
    188     icemt->ice->user_data = (void*)icemt; 
    189  
    190     icemt->has_turn = has_turn; 
    191     if (srv) 
    192         pj_memcpy(&icemt->stun_srv, srv, sizeof(pj_sockaddr)); 
    193  
    194     status = create_ice_sock(icemt, stun_cfg->ioqueue, RTP_COMP_ID, 
    195                              rtp_port, &icemt->rtp); 
    196     if (status != PJ_SUCCESS) 
    197         goto on_error; 
    198  
    199     if (has_rtcp) { 
    200         if (rtp_port) ++rtp_port; 
    201  
    202         status = create_ice_sock(icemt, stun_cfg->ioqueue, RTCP_COMP_ID, 
    203                                  rtp_port, &icemt->rtcp); 
     498 
     499    /* Create! */ 
     500    status = pj_ice_create(&ice_st->stun_cfg, ice_st->obj_name, role,  
     501                           &ice_cb, local_ufrag, local_passwd, &ice_st->ice); 
     502    if (status != PJ_SUCCESS) 
     503        return status; 
     504 
     505    /* Associate user data */ 
     506    ice_st->ice->user_data = (void*)ice_st; 
     507 
     508    /* Add components */ 
     509    for (i=0; i<ice_st->comp_cnt; ++i) { 
     510        status = pj_ice_add_comp(ice_st->ice, ice_st->comps[i]); 
    204511        if (status != PJ_SUCCESS) 
    205512            goto on_error; 
    206513    } 
    207514 
    208     *p_icemt = icemt; 
     515    /* Add candidates */ 
     516    for (i=0; i<ice_st->itf_cnt; ++i) { 
     517        pj_ice_st_interface *is= ice_st->itfs[i]; 
     518        status = pj_ice_add_cand(ice_st->ice, is->comp_id, is->type,  
     519                                 is->local_pref, &is->foundation, 
     520                                 &is->addr, &is->base_addr, NULL,  
     521                                 sizeof(pj_sockaddr_in),  
     522                                 (unsigned*)&is->cand_id); 
     523        if (status != PJ_SUCCESS) 
     524            goto on_error; 
     525    } 
     526 
    209527    return PJ_SUCCESS; 
    210528 
    211529on_error: 
    212     if (icemt->ice) 
    213         pj_ice_destroy(icemt->ice); 
    214     pj_pool_release(pool); 
     530    for (i=0; i<ice_st->itf_cnt; ++i) { 
     531        ice_st->itfs[i]->cand_id = -1; 
     532    } 
     533    if (ice_st->ice) { 
     534        pj_ice_destroy(ice_st->ice); 
     535        ice_st->ice = NULL; 
     536    } 
    215537    return status; 
    216538} 
    217539 
    218540 
    219 PJ_DEF(pj_status_t) pj_icemt_destroy(pj_icemt *icemt) 
    220 { 
    221     destroy_ice_sock(&icemt->rtp); 
    222     destroy_ice_sock(&icemt->rtcp); 
    223  
    224     pj_ice_destroy(icemt->ice); 
    225     pj_pool_release(icemt->pool); 
    226  
    227     return PJ_SUCCESS; 
    228 } 
    229  
    230  
     541/* 
     542 * Enum candidates 
     543 */ 
     544PJ_DEF(pj_status_t) pj_ice_st_enum_cands(pj_ice_st *ice_st, 
     545                                         unsigned *count, 
     546                                         pj_ice_cand cand[]) 
     547{ 
     548    unsigned i, cnt; 
     549    pj_ice_cand *pcand; 
     550    pj_status_t status; 
     551 
     552    PJ_ASSERT_RETURN(ice_st && count && cand, PJ_EINVAL); 
     553    PJ_ASSERT_RETURN(ice_st->ice, PJ_EINVALIDOP); 
     554 
     555    cnt = pj_ice_get_cand_cnt(ice_st->ice); 
     556    cnt = (cnt > *count) ? *count : cnt; 
     557    *count = 0; 
     558 
     559    for (i=0; i<cnt; ++i) { 
     560        status = pj_ice_get_cand(ice_st->ice, i, &pcand); 
     561        if (status != PJ_SUCCESS) 
     562            return status; 
     563 
     564        pj_memcpy(&cand[i], pcand, sizeof(pj_ice_cand)); 
     565    } 
     566 
     567    *count = cnt; 
     568    return PJ_SUCCESS; 
     569} 
     570 
     571 
     572/* 
     573 * Start ICE processing ! 
     574 */ 
     575PJ_DEF(pj_status_t) pj_ice_st_start_ice( pj_ice_st *ice_st, 
     576                                         const pj_str_t *rem_ufrag, 
     577                                         const pj_str_t *rem_passwd, 
     578                                         unsigned rem_cand_cnt, 
     579                                         const pj_ice_cand rem_cand[]) 
     580{ 
     581    pj_status_t status; 
     582 
     583    status = pj_ice_create_check_list(ice_st->ice, rem_ufrag, rem_passwd, 
     584                                      rem_cand_cnt, rem_cand); 
     585    if (status != PJ_SUCCESS) 
     586        return status; 
     587 
     588    return pj_ice_start_check(ice_st->ice); 
     589} 
     590 
     591 
     592/* 
     593 * Stop ICE! 
     594 */ 
     595PJ_DECL(pj_status_t) pj_ice_st_stop_ice(pj_ice_st *ice_st) 
     596{ 
     597    if (ice_st->ice) { 
     598        pj_ice_destroy(ice_st->ice); 
     599        ice_st->ice = NULL; 
     600    } 
     601 
     602    return PJ_SUCCESS; 
     603} 
     604 
     605 
     606/* 
     607 * Send data to peer agent. 
     608 */ 
     609PJ_DEF(pj_status_t) pj_ice_st_send_data( pj_ice_st *ice_st, 
     610                                         unsigned comp_id, 
     611                                         const void *data, 
     612                                         pj_size_t data_len) 
     613{ 
     614    if (!ice_st->ice) 
     615        return PJ_ENOICE; 
     616 
     617    return pj_ice_send_data(ice_st->ice, comp_id, data, data_len); 
     618} 
     619 
     620 
     621 
     622/* 
     623 * Callback called by ICE session when ICE processing is complete, either 
     624 * successfully or with failure. 
     625 */ 
    231626static void on_ice_complete(pj_ice *ice, pj_status_t status) 
    232627{ 
    233     pj_icemt *icemt = (pj_icemt*)ice->user_data; 
    234     (*icemt->cb.on_ice_complete)(icemt, status); 
    235 } 
    236  
    237  
    238 static pj_status_t on_tx_pkt(pj_ice *ice, unsigned comp_id, 
     628    pj_ice_st *ice_st = (pj_ice_st*)ice->user_data; 
     629    if (ice_st->cb.on_ice_complete) { 
     630        (*ice_st->cb.on_ice_complete)(ice_st, status); 
     631    } 
     632} 
     633 
     634 
     635/* 
     636 * Callback called by ICE session when it wants to send outgoing packet. 
     637 */ 
     638static pj_status_t on_tx_pkt(pj_ice *ice,  
     639                             unsigned comp_id, unsigned cand_id, 
    239640                             const void *pkt, pj_size_t size, 
    240641                             const pj_sockaddr_t *dst_addr, 
    241642                             unsigned dst_addr_len) 
    242643{ 
    243     pj_icemt *icemt = (pj_icemt*)ice->user_data; 
    244     pj_icemt_sock *is; 
     644    pj_ice_st *ice_st = (pj_ice_st*)ice->user_data; 
     645    pj_ice_st_interface *is = NULL; 
     646    unsigned i; 
    245647    pj_ssize_t pkt_size; 
    246648    pj_status_t status; 
    247649 
    248     if (comp_id == RTP_COMP_ID) 
    249         is = &icemt->rtp; 
    250     else if (comp_id == RTCP_COMP_ID) 
    251         is = &icemt->rtcp; 
    252     else { 
    253         pj_assert(!"Invalid comp_id"); 
    254         return -1; 
     650    PJ_UNUSED_ARG(comp_id); 
     651 
     652    for (i=0; i<ice_st->itf_cnt; ++i) { 
     653        if (ice_st->itfs[i]->cand_id == (int)cand_id) { 
     654            is = ice_st->itfs[i]; 
     655            break; 
     656        } 
     657    } 
     658    if (is == NULL) { 
     659        return PJ_EICEINCANDID; 
    255660    } 
    256661 
     
    264669 
    265670 
    266 static pj_status_t on_rx_data(pj_ice *ice, unsigned comp_id, 
    267                               void *pkt, pj_size_t size, 
    268                               const pj_sockaddr_t *src_addr, 
    269                               unsigned src_addr_len) 
    270 { 
    271     pj_icemt *icemt = (pj_icemt*)ice->user_data; 
    272  
    273     if (comp_id == RTP_COMP_ID && icemt->cb.on_rx_rtp) { 
    274         (*icemt->cb.on_rx_rtp)(icemt, pkt, size, src_addr, src_addr_len); 
    275     } else if (comp_id == RTCP_COMP_ID && icemt->cb.on_rx_rtcp) { 
    276         (*icemt->cb.on_rx_rtcp)(icemt, pkt, size, src_addr, src_addr_len); 
    277     } 
    278     return PJ_SUCCESS; 
    279 } 
    280  
    281  
     671/* 
     672 * Callback called by ICE session when it receives application data. 
     673 */ 
     674static void on_rx_data(pj_ice *ice,  
     675                       unsigned comp_id, unsigned cand_id, 
     676                       void *pkt, pj_size_t size, 
     677                       const pj_sockaddr_t *src_addr, 
     678                       unsigned src_addr_len) 
     679{ 
     680    pj_ice_st *ice_st = (pj_ice_st*)ice->user_data; 
     681 
     682    if (ice_st->cb.on_rx_data) { 
     683        (*ice_st->cb.on_rx_data)(ice_st, comp_id, cand_id,  
     684                                 pkt, size, src_addr, src_addr_len); 
     685    } 
     686} 
     687 
     688 
Note: See TracChangeset for help on using the changeset viewer.