Changeset 1096 for pjproject/trunk
- Timestamp:
- Mar 22, 2007 9:00:53 PM (18 years ago)
- Location:
- pjproject/trunk/pjnath
- Files:
-
- 6 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjnath/build/pjnath.dsp
r1093 r1096 96 96 # Begin Source File 97 97 98 SOURCE=..\src\pjnath\ice_ mt.c98 SOURCE=..\src\pjnath\ice_stream_transport.c 99 99 # End Source File 100 100 # Begin Source File … … 136 136 # Begin Source File 137 137 138 SOURCE=..\include\pjnath\ice_ mt.h138 SOURCE=..\include\pjnath\ice_stream_transport.h 139 139 # End Source File 140 140 # Begin Source File -
pjproject/trunk/pjnath/include/pjnath.h
r1093 r1096 21 21 #include <pjnath/errno.h> 22 22 #include <pjnath/ice.h> 23 #include <pjnath/ice_ mt.h>23 #include <pjnath/ice_stream_transport.h> 24 24 #include <pjnath/stun_auth.h> 25 25 #include <pjnath/stun_config.h> -
pjproject/trunk/pjnath/include/pjnath/errno.h
r1092 r1096 156 156 /** 157 157 * @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 158 169 * ICE check is in progress 159 170 */ -
pjproject/trunk/pjnath/include/pjnath/ice.h
r1093 r1096 82 82 { 83 83 unsigned comp_id; 84 pj_stun_session *stun_sess;85 pj_sockaddr local_addr;86 84 int nominated_check_id; 87 85 } pj_ice_comp; … … 100 98 pj_sockaddr base_addr; 101 99 pj_sockaddr srv_addr; 100 pj_stun_session *stun_sess; 102 101 } pj_ice_cand; 103 102 … … 146 145 { 147 146 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, 149 149 const void *pkt, pj_size_t size, 150 150 const pj_sockaddr_t *dst_addr, 151 151 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, 153 154 void *pkt, pj_size_t size, 154 155 const pj_sockaddr_t *src_addr, … … 213 214 pj_ice_role role, 214 215 const pj_ice_cb *cb, 216 const pj_str_t *local_ufrag, 217 const pj_str_t *local_passwd, 215 218 pj_ice **p_ice); 216 219 PJ_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); 220 PJ_DECL(pj_status_t) pj_ice_add_comp(pj_ice *ice, unsigned comp_id); 226 221 PJ_DECL(pj_status_t) pj_ice_add_cand(pj_ice *ice, 227 222 unsigned comp_id, … … 247 242 248 243 PJ_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, 249 246 unsigned rem_cand_cnt, 250 247 const pj_ice_cand rem_cand[]); … … 257 254 PJ_DECL(pj_status_t) pj_ice_on_rx_pkt(pj_ice *ice, 258 255 unsigned comp_id, 256 unsigned cand_id, 259 257 void *pkt, 260 258 pj_size_t pkt_size, -
pjproject/trunk/pjnath/include/pjnath/ice_stream_transport.h
r1094 r1096 17 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 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__ 21 21 22 22 … … 26 26 */ 27 27 #include <pjnath/ice.h> 28 #include <pjlib-util/resolver.h> 28 29 #include <pj/ioqueue.h> 29 30 … … 33 34 34 35 /** 35 * @defgroup PJNATH_ICE_ MEDIA_TRANSPORT ICE MediaTransport36 * @brief ICE Media Transport36 * @defgroup PJNATH_ICE_STREAM_TRANSPORT ICE Stream Transport 37 * @brief Transport for media stream using ICE 37 38 * @ingroup PJNATH_ICE 38 39 * @{ 39 40 */ 40 41 41 typedef struct pj_ice mt pj_icemt;42 typedef struct pj_ice_st pj_ice_st; 42 43 43 typedef struct pj_ice mt_cb44 typedef struct pj_ice_st_cb 44 45 { 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); 55 51 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; 57 62 58 63 59 typedef struct pj_ice mt_sock64 typedef struct pj_ice_st_comp 60 65 { 61 pj_icemt *icemt;62 66 unsigned comp_id; 67 } pj_ice_st_comp; 68 69 70 typedef 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; 63 78 pj_sock_t sock; 64 79 pj_sockaddr addr; … … 70 85 pj_sockaddr src_addr; 71 86 int src_addr_len; 72 } pj_ice mt_sock;87 } pj_ice_st_interface; 73 88 74 89 75 struct pj_ice mt90 struct pj_ice_st 76 91 { 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; 80 97 81 pj_ice mt_cb cb;98 pj_ice *ice; 82 99 83 pj_icemt_sock rtp;84 pj_icemt_sock rtcp;100 unsigned comp_cnt; 101 unsigned comps[PJ_ICE_MAX_COMP]; 85 102 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; 88 110 }; 89 111 90 112 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); 113 PJ_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); 118 PJ_DECL(pj_status_t) pj_ice_st_destroy(pj_ice_st *ice_st); 101 119 120 PJ_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); 124 PJ_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 128 PJ_DECL(pj_status_t) pj_ice_st_add_comp(pj_ice_st *ice_st, 129 unsigned comp_id); 130 131 PJ_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); 138 PJ_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); 143 PJ_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); 148 PJ_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 155 PJ_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); 159 PJ_DECL(pj_status_t) pj_ice_st_enum_cands(pj_ice_st *ice_st, 160 unsigned *count, 161 pj_ice_cand cand[]); 162 PJ_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[]); 167 PJ_DECL(pj_status_t) pj_ice_st_stop_ice(pj_ice_st *ice_st); 168 169 PJ_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); 102 173 103 174 … … 111 182 112 183 113 #endif /* __PJNATH_ICE_ MT_H__ */184 #endif /* __PJNATH_ICE_STREAM_TRANSPORT_H__ */ 114 185 -
pjproject/trunk/pjnath/src/pjnath-test/ice_test.c
r1095 r1096 38 38 static pj_stun_config stun_cfg; 39 39 40 static void on_ice_complete(pj_ice mt *icemt,40 static void on_ice_complete(pj_ice_st *icest, 41 41 pj_status_t status) 42 42 { 43 struct ice_data *id = (struct ice_data*) ice mt->user_data;43 struct ice_data *id = (struct ice_data*) icest->user_data; 44 44 id->complete = PJ_TRUE; 45 45 id->err_code = status; … … 49 49 50 50 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, 51 static void on_rx_data(pj_ice_st *icest, 52 unsigned comp_id, unsigned cand_id, 68 53 void *pkt, pj_size_t size, 69 54 const pj_sockaddr_t *src_addr, 70 55 unsigned src_addr_len) 71 56 { 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); 78 72 PJ_UNUSED_ARG(src_addr); 79 73 PJ_UNUSED_ARG(src_addr_len); … … 98 92 static int ice_basic_create_destroy_test() 99 93 { 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; 103 96 pj_status_t status; 104 97 105 98 PJ_LOG(3,(THIS_FILE, "...basic create/destroy")); 106 99 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); 114 105 if (status != PJ_SUCCESS) 115 106 return -10; 116 107 117 ice = im->ice; 118 119 pj_icemt_destroy(im); 108 pj_ice_st_destroy(im); 120 109 121 110 return 0; … … 123 112 124 113 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]; 114 static pj_status_t start_ice(pj_ice_st *ist, pj_ice_st *remote) 115 { 116 unsigned count; 129 117 pj_ice_cand cand[PJ_ICE_MAX_CAND]; 130 118 pj_status_t status; 131 119 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); 134 122 if (status != PJ_SUCCESS) 135 123 return status; 136 124 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 149 129 150 130 … … 163 143 static int perform_ice_test(const char *title, 164 144 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; 173 149 struct ice_data *id1, *id2; 174 150 pj_timestamp t_start, t_end; 175 151 pj_ice_cand *rcand; 176 152 pj_str_t data_from_offerer, data_from_answerer; 177 unsigned i;178 153 pj_status_t status; 179 154 180 155 PJ_LOG(3,(THIS_FILE, "...%s", title)); 181 156 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; 186 160 187 161 /* 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); 190 163 if (status != PJ_SUCCESS) 191 164 return -20; … … 195 168 im1->user_data = id1; 196 169 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; 206 179 207 180 /* 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); 210 182 if (status != PJ_SUCCESS) 211 183 return -25; … … 215 187 im2->user_data = id2; 216 188 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); 240 211 if (status != PJ_SUCCESS) 241 212 return -30; 242 213 243 /* S end answer toim1 */244 status = s et_remote_list(im2, im1);214 /* Start ICE on im1 */ 215 status = start_ice(im1, im2); 245 216 if (status != PJ_SUCCESS) 246 217 return -35; … … 248 219 /* Mark start time */ 249 220 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 1257 status = pj_ice_start_check(im2->ice);258 if (status != PJ_SUCCESS)259 return -45;260 #endif261 221 262 222 /* Poll for wait_before_send msecs before we send the first data */ … … 366 326 367 327 368 pj_ice mt_destroy(im1);369 pj_ice mt_destroy(im2);328 pj_ice_st_destroy(im1); 329 pj_ice_st_destroy(im2); 370 330 return 0; 371 331 } … … 378 338 pj_ioqueue_t *ioqueue; 379 339 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;383 340 384 341 pool = pj_pool_create(mem, NULL, 4000, 4000, NULL); … … 396 353 397 354 /* Direct communication */ 398 rc = perform_ice_test("Direct connection", 500, 1000 , 0, NULL, 0, NULL);355 rc = perform_ice_test("Direct connection", 500, 1000); 399 356 if (rc != 0) 400 357 goto on_return; 401 358 402 359 /* 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); 411 361 if (rc != 0) 412 362 goto on_return; 413 363 414 364 /* 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); 416 366 if (rc != 0) 417 367 goto on_return; -
pjproject/trunk/pjnath/src/pjnath/ice.c
r1094 r1096 22 22 #include <pj/array.h> 23 23 #include <pj/assert.h> 24 #include <pj/guid.h> 24 25 #include <pj/log.h> 25 26 #include <pj/os.h> … … 69 70 { 70 71 pj_ice *ice; 71 unsigned comp_id;72 pj_ice_c omp *comp;72 unsigned lcand_id; 73 pj_ice_cand *lcand; 73 74 } stun_data; 74 75 … … 133 134 134 135 136 /* 137 * Create ICE stream session. 138 */ 135 139 PJ_DEF(pj_status_t) pj_ice_create(pj_stun_config *stun_cfg, 136 140 const char *name, 137 141 pj_ice_role role, 138 142 const pj_ice_cb *cb, 143 const pj_str_t *local_ufrag, 144 const pj_str_t *local_passwd, 139 145 pj_ice **p_ice) 140 146 { 141 147 pj_pool_t *pool; 142 148 pj_ice *ice; 149 char tmp[32]; 150 pj_str_t s; 143 151 unsigned i; 144 152 pj_status_t status; … … 146 154 PJ_ASSERT_RETURN(stun_cfg && cb && p_ice, PJ_EINVAL); 147 155 148 if ( !name)156 if (name == NULL) 149 157 name = "ice%p"; 150 158 … … 171 179 } 172 180 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 173 196 /* Done */ 174 197 *p_ice = ice; 175 198 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"))); 177 201 178 202 return PJ_SUCCESS; … … 180 204 181 205 206 /* 207 * Destroy 208 */ 182 209 static void destroy_ice(pj_ice *ice, 183 210 pj_status_t reason) … … 190 217 191 218 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; 197 226 } 198 227 } … … 223 252 224 253 254 /* Find component by ID */ 225 255 static pj_ice_comp *find_comp(const pj_ice *ice, unsigned comp_id) 226 256 { … … 228 258 for (i=0; i<ice->comp_cnt; ++i) { 229 259 if (ice->comp[i].comp_id == comp_id) 230 return (pj_ice_comp *) &ice->comp[i];260 return (pj_ice_comp *) &ice->comp[i]; 231 261 } 232 262 … … 235 265 236 266 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 */ 268 PJ_DEF(pj_status_t) pj_ice_add_comp(pj_ice *ice, unsigned comp_id) 269 { 243 270 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); 249 273 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); 250 275 PJ_ASSERT_RETURN(find_comp(ice, comp_id) == NULL, PJ_EEXISTS); 251 276 … … 255 280 comp->comp_id = comp_id; 256 281 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);291 282 292 283 /* Done */ … … 409 400 410 401 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 447 402 static pj_uint32_t CALC_CAND_PRIO(pj_ice_cand_type type, 448 403 pj_uint32_t local_pref, … … 463 418 464 419 420 /* 421 * Add ICE candidate 422 */ 465 423 PJ_DEF(pj_status_t) pj_ice_add_cand(pj_ice *ice, 466 424 unsigned comp_id, … … 475 433 { 476 434 pj_ice_cand *lcand; 435 pj_stun_session_cb sess_cb; 436 pj_stun_auth_cred auth_cred; 437 stun_data *sd; 477 438 pj_status_t status = PJ_SUCCESS; 478 439 char tmp[128]; … … 501 462 pj_bzero(&lcand->srv_addr, sizeof(lcand->srv_addr)); 502 463 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 505 497 506 498 pj_ansi_strcpy(tmp, pj_inet_ntoa(lcand->addr.ipv4.sin_addr)); … … 518 510 (int)pj_htons(lcand->base_addr.ipv4.sin_port), 519 511 lcand->prio, lcand->prio)); 512 513 if (p_cand_id) 514 *p_cand_id = ice->lcand_cnt; 520 515 521 516 ++ice->lcand_cnt; … … 1042 1037 1043 1038 PJ_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, 1044 1041 unsigned rcand_cnt, 1045 1042 const pj_ice_cand rcand[]) 1046 1043 { 1047 1044 pj_ice_checklist *clist; 1045 char buf[128]; 1046 pj_str_t username; 1048 1047 timer_data *td; 1049 1048 unsigned i, j; 1050 1049 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); 1052 1052 PJ_ASSERT_RETURN(rcand_cnt + ice->rcand_cnt <= PJ_ICE_MAX_CAND, 1053 1053 PJ_ETOOMANY); 1054 1054 1055 1055 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 1056 1074 1057 1075 /* Save remote candidates */ … … 1155 1173 1156 1174 /* Create request */ 1157 status = pj_stun_session_create_req( comp->stun_sess,1175 status = pj_stun_session_create_req(lcand->stun_sess, 1158 1176 PJ_STUN_BINDING_REQUEST, &tdata); 1159 1177 if (status != PJ_SUCCESS) … … 1187 1205 1188 1206 /* 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, 1190 1208 &rcand->addr, 1191 1209 sizeof(pj_sockaddr_in), tdata); … … 1332 1350 { 1333 1351 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, 1335 1353 pkt, pkt_size, 1336 1354 dst_addr, addr_len); … … 1535 1553 sd = (stun_data*) pj_stun_session_get_user_data(sess); 1536 1554 ice = sd->ice; 1537 comp = sd->comp; 1555 lcand = sd->lcand; 1556 comp = find_comp(ice, lcand->comp_id); 1538 1557 1539 1558 pj_mutex_lock(ice->mutex); … … 1621 1640 PJ_TODO(DETERMINE_IF_REQUEST_COMES_FROM_RELAYED_CANDIDATE); 1622 1641 is_relayed = PJ_FALSE; 1623 1624 /* Next find local candidate, by first finding a check in the checklist1625 * 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;1643 1642 1644 1643 /* Now that we have local and remote candidate, check if we already … … 1759 1758 pj_status_t status = PJ_SUCCESS; 1760 1759 pj_ice_comp *comp; 1760 unsigned cand_id; 1761 1761 pj_ice_check *check; 1762 1762 … … 1777 1777 1778 1778 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, 1781 1782 &check->rcand->addr, 1782 1783 sizeof(pj_sockaddr_in)); … … 1790 1791 PJ_DEF(pj_status_t) pj_ice_on_rx_pkt( pj_ice *ice, 1791 1792 unsigned comp_id, 1793 unsigned cand_id, 1792 1794 void *pkt, 1793 1795 pj_size_t pkt_size, … … 1797 1799 pj_status_t status = PJ_SUCCESS; 1798 1800 pj_ice_comp *comp; 1801 pj_ice_cand *lcand; 1799 1802 pj_status_t stun_status; 1800 1803 … … 1809 1812 } 1810 1813 1814 lcand = &ice->lcand[cand_id]; 1815 1811 1816 stun_status = pj_stun_msg_check(pkt, pkt_size, PJ_STUN_IS_DATAGRAM); 1812 1817 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, 1814 1819 PJ_STUN_IS_DATAGRAM, 1815 1820 NULL, src_addr, src_addr_len); 1816 1821 } else { 1817 status = (*ice->cb.on_rx_data)(ice, comp_id, pkt, pkt_size,1818 1822 (*ice->cb.on_rx_data)(ice, comp_id, cand_id, pkt, pkt_size, 1823 src_addr, src_addr_len); 1819 1824 } 1820 1825 -
pjproject/trunk/pjnath/src/pjnath/ice_stream_transport.c
r1095 r1096 17 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 19 #include <pjnath/ice_ mt.h>19 #include <pjnath/ice_stream_transport.h> 20 20 #include <pjnath/errno.h> 21 21 #include <pj/addr_resolv.h> 22 22 #include <pj/assert.h> 23 #include <pj/log.h> 23 24 #include <pj/pool.h> 24 25 #include <pj/string.h> 25 26 26 27 27 #define RTP_COMP_ID 128 #define RTCP_COMP_ID 229 30 31 28 32 29 /* ICE callbacks */ 33 30 static 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, 31 static pj_status_t on_tx_pkt(pj_ice *ice, 32 unsigned comp_id, unsigned cand_id, 35 33 const void *pkt, pj_size_t size, 36 34 const pj_sockaddr_t *dst_addr, 37 35 unsigned dst_addr_len); 38 static pj_status_t on_rx_data(pj_ice *ice, unsigned comp_id, 36 static void on_rx_data(pj_ice *ice, 37 unsigned comp_id, unsigned cand_id, 39 38 void *pkt, pj_size_t size, 40 39 const pj_sockaddr_t *src_addr, … … 46 45 pj_ssize_t bytes_read); 47 46 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) 47 static void destroy_ice_interface(pj_ice_st_interface *is); 48 static void destroy_ice_st(pj_ice_st *ice_st, pj_status_t reason); 49 50 static 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 */ 61 static 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 */ 78 static 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) 55 84 { 56 85 pj_ioqueue_callback ioqueue_cb; 57 const pj_str_t H1 = { "H1", 2 }; 86 pj_ice_st_interface *is; 87 char foundation[32]; 58 88 int addr_len; 59 89 pj_status_t status; 60 90 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; 62 95 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; 65 98 66 99 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &is->sock); … … 69 102 70 103 /* 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 72 109 status = pj_sock_bind(is->sock, &is->base_addr, sizeof(pj_sockaddr_in)); 73 110 if (status != PJ_SUCCESS) … … 85 122 } 86 123 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 87 131 /* Register to ioqueue */ 88 132 pj_bzero(&ioqueue_cb, sizeof(ioqueue_cb)); 89 133 ioqueue_cb.on_read_complete = &on_read_complete; 90 status = pj_ioqueue_register_sock(ice mt->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); 92 136 if (status != PJ_SUCCESS) 93 137 goto on_error; … … 96 140 pj_ioqueue_op_key_init(&is->write_op, sizeof(is->write_op)); 97 141 142 /* Kick start reading the socket */ 98 143 on_read_complete(is->key, &is->read_op, 0); 99 144 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; 113 147 return PJ_SUCCESS; 114 148 115 149 on_error: 116 destroy_ice_ sock(is);150 destroy_ice_interface(is); 117 151 return status; 118 152 } 119 153 120 154 155 /* 156 * This is callback called by ioqueue on incoming packet 157 */ 121 158 static void on_read_complete(pj_ioqueue_key_t *key, 122 159 pj_ioqueue_op_key_t *op_key, 123 160 pj_ssize_t bytes_read) 124 161 { 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); 126 164 pj_ssize_t pkt_size; 127 165 pj_status_t status; 128 166 129 167 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 */ 135 184 pkt_size = sizeof(is->pkt); 136 185 is->src_addr_len = sizeof(is->src_addr); … … 138 187 PJ_IOQUEUE_ALWAYS_ASYNC, 139 188 &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 */ 198 static void destroy_ice_interface(pj_ice_st_interface *is) 145 199 { 146 200 if (is->key) { … … 155 209 156 210 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 */ 214 PJ_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) 166 219 { 167 220 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 245 static 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 */ 280 PJ_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 */ 290 PJ_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 */ 307 PJ_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 */ 326 PJ_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 */ 355 static 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 */ 376 PJ_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 */ 415 PJ_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 */ 441 PJ_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 */ 460 PJ_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 */ 479 PJ_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; 169 486 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 */ 177 494 pj_bzero(&ice_cb, sizeof(ice_cb)); 178 495 ice_cb.on_ice_complete = &on_ice_complete; 496 ice_cb.on_rx_data = &on_rx_data; 179 497 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]); 204 511 if (status != PJ_SUCCESS) 205 512 goto on_error; 206 513 } 207 514 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 209 527 return PJ_SUCCESS; 210 528 211 529 on_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 } 215 537 return status; 216 538 } 217 539 218 540 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 */ 544 PJ_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 */ 575 PJ_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 */ 595 PJ_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 */ 609 PJ_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 */ 231 626 static void on_ice_complete(pj_ice *ice, pj_status_t status) 232 627 { 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 */ 638 static pj_status_t on_tx_pkt(pj_ice *ice, 639 unsigned comp_id, unsigned cand_id, 239 640 const void *pkt, pj_size_t size, 240 641 const pj_sockaddr_t *dst_addr, 241 642 unsigned dst_addr_len) 242 643 { 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; 245 647 pj_ssize_t pkt_size; 246 648 pj_status_t status; 247 649 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; 255 660 } 256 661 … … 264 669 265 670 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 */ 674 static 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.