Changeset 4728 for pjproject/trunk
- Timestamp:
- Feb 4, 2014 10:13:56 AM (11 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/src/pjlib-util/cli_console.c
r4537 r4728 46 46 pj_thread_t *input_thread; 47 47 pj_bool_t thread_quit; 48 pj_sem_t *thread_sem; 49 pj_cli_console_cfg cfg; 48 pj_sem_t *thread_sem; 49 pj_cli_console_cfg cfg; 50 50 51 51 struct async_input_t 52 { 52 { 53 53 char *buf; 54 unsigned maxlen; 54 unsigned maxlen; 55 55 pj_sem_t *sem; 56 56 } input; … … 127 127 if (!pool) 128 128 return PJ_ENOMEM; 129 129 130 130 sess = PJ_POOL_ZALLOC_T(pool, pj_cli_sess); 131 131 fe = PJ_POOL_ZALLOC_T(pool, struct cli_console_fe); … … 136 136 } 137 137 sess->fe = &fe->base; 138 sess->log_level = param->log_level; 138 sess->log_level = param->log_level; 139 139 sess->op = PJ_POOL_ZALLOC_T(pool, struct pj_cli_sess_op); 140 140 fe->base.op = PJ_POOL_ZALLOC_T(pool, struct pj_cli_front_end_op); … … 155 155 156 156 pj_cli_register_front_end(cli, &fe->base); 157 if (param->prompt_str.slen == 0) { 157 if (param->prompt_str.slen == 0) { 158 158 pj_str_t prompt_sign = pj_str(">>> "); 159 159 fe->cfg.prompt_str.ptr = pj_pool_alloc(fe->pool, prompt_sign.slen+1); 160 pj_strcpy(&fe->cfg.prompt_str, &prompt_sign); 160 pj_strcpy(&fe->cfg.prompt_str, &prompt_sign); 161 161 } else { 162 fe->cfg.prompt_str.ptr = pj_pool_alloc(fe->pool, 162 fe->cfg.prompt_str.ptr = pj_pool_alloc(fe->pool, 163 163 param->prompt_str.slen+1); 164 164 pj_strcpy(&fe->cfg.prompt_str, ¶m->prompt_str); 165 } 166 fe->cfg.prompt_str.ptr[fe->cfg.prompt_str.slen] = 0; 165 } 166 fe->cfg.prompt_str.ptr[fe->cfg.prompt_str.slen] = 0; 167 167 168 168 if (param->quit_command.slen) … … 184 184 send_data.ptr = data_str; 185 185 send_data.slen = 0; 186 186 187 187 pj_strcat(&send_data, &fe->cfg.prompt_str); 188 188 send_data.ptr[send_data.slen] = 0; … … 191 191 } 192 192 193 static void send_err_arg(pj_cli_sess *sess, 194 const pj_cli_exec_info *info, 193 static void send_err_arg(pj_cli_sess *sess, 194 const pj_cli_exec_info *info, 195 195 const pj_str_t *msg, 196 196 pj_bool_t with_return) … … 219 219 220 220 send_data.ptr[send_data.slen] = 0; 221 printf("%s", send_data.ptr); 222 } 223 224 static void send_inv_arg(pj_cli_sess *sess, 221 printf("%s", send_data.ptr); 222 } 223 224 static void send_inv_arg(pj_cli_sess *sess, 225 225 const pj_cli_exec_info *info, 226 226 pj_bool_t with_return) … … 230 230 } 231 231 232 static void send_too_many_arg(pj_cli_sess *sess, 232 static void send_too_many_arg(pj_cli_sess *sess, 233 233 const pj_cli_exec_info *info, 234 234 pj_bool_t with_return) … … 238 238 } 239 239 240 static void send_hint_arg(pj_str_t *send_data, 240 static void send_hint_arg(pj_str_t *send_data, 241 241 const pj_str_t *desc, 242 242 pj_ssize_t cmd_len, … … 257 257 } 258 258 259 static void send_ambi_arg(pj_cli_sess *sess, 259 static void send_ambi_arg(pj_cli_sess *sess, 260 260 const pj_cli_exec_info *info, 261 261 pj_bool_t with_return) … … 270 270 pj_ssize_t max_length = 0; 271 271 pj_ssize_t cmd_length = 0; 272 const pj_str_t *cmd_desc = 0;273 272 static const pj_str_t sc_type = {"sc", 2}; 274 273 static const pj_str_t choice_type = {"choice", 6}; 275 274 send_data.ptr = data; 276 275 send_data.slen = 0; 277 276 278 277 if (with_return) 279 278 pj_strcat2(&send_data, "\r\n"); … … 284 283 pj_strcat2(&send_data, " "); 285 284 } 286 pj_strcat2(&send_data, "^"); 285 pj_strcat2(&send_data, "^"); 287 286 /* Get the max length of the command name */ 288 287 for (i=0;i<info->hint_cnt;++i) { 289 if ((&hint[i].type) && (hint[i].type.slen > 0)) { 290 if (pj_stricmp(&hint[i].type, &sc_type) == 0) { 288 if ((&hint[i].type) && (hint[i].type.slen > 0)) { 289 if (pj_stricmp(&hint[i].type, &sc_type) == 0) { 291 290 if ((i > 0) && (!pj_stricmp(&hint[i-1].desc, &hint[i].desc))) { 292 291 cmd_length += (hint[i].name.slen + 3); 293 292 } else { 294 293 cmd_length = hint[i].name.slen; 295 } 294 } 296 295 } else { 297 296 cmd_length = hint[i].name.slen; 298 297 } 299 } else { 298 } else { 300 299 cmd_length = hint[i].name.slen; 301 300 } … … 308 307 cmd_length = 0; 309 308 for (i=0;i<info->hint_cnt;++i) { 310 if ((&hint[i].type) && (hint[i].type.slen > 0)) { 309 if ((&hint[i].type) && (hint[i].type.slen > 0)) { 311 310 if (pj_stricmp(&hint[i].type, &sc_type) == 0) { 312 311 parse_state = OP_SHORTCUT; … … 316 315 parse_state = OP_TYPE; 317 316 } 318 } else { 317 } else { 319 318 parse_state = OP_NORMAL; 320 319 } … … 324 323 cmd_length = hint[i].name.slen; 325 324 } 326 325 327 326 switch (parse_state) { 328 327 case OP_CHOICE: 329 328 pj_strcat2(&send_data, "["); 330 329 pj_strcat(&send_data, &hint[i].name); 331 pj_strcat2(&send_data, "]"); 330 pj_strcat2(&send_data, "]"); 332 331 break; 333 332 case OP_TYPE: 334 333 pj_strcat2(&send_data, "<"); 335 334 pj_strcat(&send_data, &hint[i].type); 336 pj_strcat2(&send_data, ">"); 335 pj_strcat2(&send_data, ">"); 337 336 break; 338 337 case OP_SHORTCUT: 339 338 /* Format : "Command | sc | description" */ 340 { 339 { 341 340 cmd_length += hint[i].name.slen; 342 341 if ((i > 0) && (!pj_stricmp(&hint[i-1].desc, &hint[i].desc))) { 343 342 pj_strcat2(&send_data, " | "); 344 cmd_length += 3; 343 cmd_length += 3; 345 344 } else { 346 345 pj_strcat2(&send_data, "\r\n "); 347 346 } 348 pj_strcat(&send_data, &hint[i].name); 347 pj_strcat(&send_data, &hint[i].name); 349 348 } 350 349 break; 351 350 default: 352 351 pj_strcat(&send_data, &hint[i].name); 353 cmd_desc = &hint[i].desc;354 352 break; 355 353 } 356 357 if ((parse_state == OP_TYPE) || (parse_state == OP_CHOICE) || 354 355 if ((parse_state == OP_TYPE) || (parse_state == OP_CHOICE) || 358 356 ((i+1) >= info->hint_cnt) || 359 (pj_strncmp(&hint[i].desc, &hint[i+1].desc, hint[i].desc.slen))) 357 (pj_strncmp(&hint[i].desc, &hint[i+1].desc, hint[i].desc.slen))) 360 358 { 361 359 /* Add description info */ … … 364 362 cmd_length = 0; 365 363 } 366 } 364 } 367 365 pj_strcat2(&send_data, "\r\n"); 368 366 pj_strcat(&send_data, &fe->cfg.prompt_str); 369 367 send_data.ptr[send_data.slen] = 0; 370 printf("%s", send_data.ptr); 368 printf("%s", send_data.ptr); 371 369 } 372 370 … … 375 373 pj_status_t status; 376 374 pj_bool_t retval = PJ_TRUE; 377 375 378 376 pj_pool_t *pool; 379 377 pj_cli_cmd_val *cmd_val; … … 388 386 389 387 cmd_val = PJ_POOL_ZALLOC_T(pool, pj_cli_cmd_val); 390 391 status = pj_cli_sess_parse(sess, recv_buf, cmd_val, 388 389 status = pj_cli_sess_parse(sess, recv_buf, cmd_val, 392 390 pool, &info); 393 391 394 392 switch (status) { 395 393 case PJ_CLI_EINVARG: 396 send_inv_arg(sess, &info, PJ_TRUE); 394 send_inv_arg(sess, &info, PJ_TRUE); 397 395 break; 398 396 case PJ_CLI_ETOOMANYARGS: … … 403 401 send_ambi_arg(sess, &info, PJ_TRUE); 404 402 break; 405 case PJ_SUCCESS: 406 if (info.hint_cnt > 0) { 407 /* Compelete command */ 408 send_ambi_arg(sess, &info, PJ_TRUE); 403 case PJ_SUCCESS: 404 if (info.hint_cnt > 0) { 405 /* Compelete command */ 406 send_ambi_arg(sess, &info, PJ_TRUE); 409 407 } else { 410 408 retval = PJ_FALSE; 411 } 412 break; 413 } 414 415 pj_pool_release(pool); 416 return retval; 409 } 410 break; 411 } 412 413 pj_pool_release(pool); 414 return retval; 417 415 } 418 416 … … 421 419 pj_status_t status; 422 420 pj_bool_t retval = PJ_TRUE; 423 424 pj_pool_t *pool; 421 422 pj_pool_t *pool; 425 423 pj_cli_exec_info info; 426 424 pj_cli_t *cli = sess->fe->cli; 427 425 struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe; 428 426 char *recv_buf = fe->input.buf; 429 427 430 428 printf("\r\n"); 431 429 432 430 pool = pj_pool_create(pj_cli_get_param(cli)->pf, "handle_exec", 433 431 PJ_CLI_CONSOLE_POOL_SIZE, PJ_CLI_CONSOLE_POOL_INC, 434 NULL); 435 436 status = pj_cli_sess_exec(sess, recv_buf, 432 NULL); 433 434 status = pj_cli_sess_exec(sess, recv_buf, 437 435 pool, &info); 438 436 439 437 switch (status) { 440 438 case PJ_CLI_EINVARG: 441 send_inv_arg(sess, &info, PJ_FALSE); 439 send_inv_arg(sess, &info, PJ_FALSE); 442 440 break; 443 441 case PJ_CLI_ETOOMANYARGS: … … 452 450 break; 453 451 case PJ_SUCCESS: 454 send_prompt_str(sess); 455 break; 456 } 457 458 pj_pool_release(pool); 459 return retval; 452 send_prompt_str(sess); 453 break; 454 } 455 456 pj_pool_release(pool); 457 return retval; 460 458 } 461 459 462 460 static int readline_thread(void * p) 463 { 461 { 464 462 struct cli_console_fe * fe = (struct cli_console_fe *)p; 465 463 … … 473 471 474 472 if (fgets(recv_buf, fe->input.maxlen, stdin) == NULL) { 475 /* 473 /* 476 474 * Be friendly to users who redirect commands into 477 475 * program, when file ends, resume with kbd. … … 488 486 puts("Cannot switch back to console from file redirection"); 489 487 if (fe->cfg.quit_command.slen) { 490 pj_memcpy(recv_buf, fe->cfg.quit_command.ptr, 488 pj_memcpy(recv_buf, fe->cfg.quit_command.ptr, 491 489 fe->input.maxlen); 492 490 } 493 recv_buf[fe->cfg.quit_command.slen] = '\0'; 491 recv_buf[fe->cfg.quit_command.slen] = '\0'; 494 492 } else { 495 493 puts("Switched back to console from file redirection"); … … 506 504 break; 507 505 } 508 input_len = pj_ansi_strlen(fe->input.buf); 506 input_len = pj_ansi_strlen(fe->input.buf); 509 507 if ((input_len > 1) && (fe->input.buf[input_len-2] == '?')) { 510 508 fe->input.buf[input_len-1] = 0; … … 516 514 } 517 515 518 pj_sem_post(fe->input.sem); 516 pj_sem_post(fe->input.sem); 519 517 pj_sem_wait(fe->thread_sem); 520 } 518 } 521 519 522 520 return 0; 523 521 } 524 522 525 PJ_DEF(pj_status_t) pj_cli_console_process(pj_cli_sess *sess, 523 PJ_DEF(pj_status_t) pj_cli_console_process(pj_cli_sess *sess, 526 524 char *buf, 527 525 unsigned maxlen) -
pjproject/trunk/pjlib-util/src/pjlib-util/cli_telnet.c
r4537 r4728 37 37 (defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0) 38 38 39 #define EADDRINUSE WSAEADDRINUSE 39 #define EADDRINUSE WSAEADDRINUSE 40 40 41 41 #endif … … 67 67 * This specify the state for the telnet option negotiation. 68 68 */ 69 enum cli_telnet_option_states 70 { 69 enum cli_telnet_option_states 70 { 71 71 OPT_DISABLE, /* Option disable */ 72 72 OPT_ENABLE, /* Option enable */ 73 73 OPT_EXPECT_DISABLE, /* Already send disable req, expecting resp */ 74 74 OPT_EXPECT_ENABLE, /* Already send enable req, expecting resp */ 75 OPT_EXPECT_DISABLE_REV, /* Already send disable req, expecting resp, 75 OPT_EXPECT_DISABLE_REV, /* Already send disable req, expecting resp, 76 76 * need to send enable req */ 77 77 OPT_EXPECT_ENABLE_REV /* Already send enable req, expecting resp, … … 199 199 }; 200 200 201 enum terminal_cmd 201 enum terminal_cmd 202 202 { 203 203 TC_ESC = 27, … … 207 207 TC_LEFT = 68, 208 208 TC_END = 70, 209 TC_HOME = 72, 209 TC_HOME = 72, 210 210 TC_CTRL_C = 3, 211 211 TC_CR = 13, … … 229 229 230 230 /** 231 * This structure contains the command line shown to the user. 232 * The telnet also needs to maintain and manage command cursor position. 231 * This structure contains the command line shown to the user. 232 * The telnet also needs to maintain and manage command cursor position. 233 233 * Due to that reason, the insert/delete character process from buffer will 234 234 * consider its current cursor position. … … 252 252 253 253 /** 254 * This structure contains the command history executed by user. 254 * This structure contains the command history executed by user. 255 255 * Besides storing the command history, it is necessary to be able 256 256 * to browse it. … … 291 291 pj_thread_t *worker_thread; 292 292 pj_bool_t is_quitting; 293 pj_mutex_t *mutex; 293 pj_mutex_t *mutex; 294 294 } cli_telnet_fe; 295 295 … … 305 305 306 306 /** 307 * Return the number of characters between the current cursor position 307 * Return the number of characters between the current cursor position 308 308 * to the end of line. 309 309 */ … … 314 314 315 315 /** 316 * Insert character to the receive buffer. 317 */ 318 static pj_bool_t recv_buf_insert(telnet_recv_buf *recv_buf, 319 unsigned char *data) 320 { 316 * Insert character to the receive buffer. 317 */ 318 static pj_bool_t recv_buf_insert(telnet_recv_buf *recv_buf, 319 unsigned char *data) 320 { 321 321 if (recv_buf->len+1 >= PJ_CLI_MAX_CMDBUF) { 322 322 return PJ_FALSE; 323 } else { 323 } else { 324 324 if (*data == '\t' || *data == '?' || *data == '\r') { 325 325 /* Always insert to the end of line */ … … 328 328 /* Insert based on the current cursor pos */ 329 329 unsigned cur_pos = recv_buf->cur_pos; 330 unsigned rlen = recv_buf_right_len(recv_buf); 331 if (rlen > 0) { 330 unsigned rlen = recv_buf_right_len(recv_buf); 331 if (rlen > 0) { 332 332 /* Shift right characters */ 333 pj_memmove(&recv_buf->rbuf[cur_pos+1], 334 &recv_buf->rbuf[cur_pos], 333 pj_memmove(&recv_buf->rbuf[cur_pos+1], 334 &recv_buf->rbuf[cur_pos], 335 335 rlen+1); 336 } 336 } 337 337 recv_buf->rbuf[cur_pos] = *data; 338 338 } … … 356 356 unsigned cur_pos = recv_buf->cur_pos; 357 357 /* Shift left characters */ 358 pj_memmove(&recv_buf->rbuf[cur_pos-1], &recv_buf->rbuf[cur_pos], 358 pj_memmove(&recv_buf->rbuf[cur_pos-1], &recv_buf->rbuf[cur_pos], 359 359 rlen); 360 360 } … … 362 362 --recv_buf->len; 363 363 recv_buf->rbuf[recv_buf->len] = 0; 364 } 364 } 365 365 return PJ_TRUE; 366 366 } … … 373 373 374 374 /** 375 * Insert the command to history. If the entered command is not on the list, 376 * a new entry will be created. All entered command will be moved to 377 * the first entry of the history. 378 */ 379 static pj_status_t insert_history(cli_telnet_sess *sess, 375 * Insert the command to history. If the entered command is not on the list, 376 * a new entry will be created. All entered command will be moved to 377 * the first entry of the history. 378 */ 379 static pj_status_t insert_history(cli_telnet_sess *sess, 380 380 char *cmd_val) 381 381 { … … 393 393 in_history = pj_list_search(sess->history, (void*)&cmd, compare_str); 394 394 if (!in_history) { 395 if (pj_list_size(sess->history) < PJ_CLI_MAX_CMD_HISTORY) { 395 if (pj_list_size(sess->history) < PJ_CLI_MAX_CMD_HISTORY) { 396 396 char *data_history; 397 397 in_history = PJ_POOL_ZALLOC_T(sess->pool, cmd_history); 398 398 pj_list_init(in_history); 399 data_history = (char *)pj_pool_calloc(sess->pool, 399 data_history = (char *)pj_pool_calloc(sess->pool, 400 400 sizeof(char), PJ_CLI_MAX_CMDBUF); 401 401 in_history->command.ptr = data_history; … … 404 404 /* Get the oldest history */ 405 405 in_history = sess->history->prev; 406 } 406 } 407 407 } else { 408 408 pj_list_insert_nodes_after(in_history->prev, in_history->next); … … 416 416 417 417 /** 418 * Get the next or previous history of the shown/active history. 418 * Get the next or previous history of the shown/active history. 419 419 */ 420 420 static pj_str_t* get_prev_history(cli_telnet_sess *sess, pj_bool_t is_forward) … … 434 434 return NULL; 435 435 } else { 436 if (is_forward) { 437 node = (node->next==root)?node->next->next:node->next; 436 if (is_forward) { 437 node = (node->next==root)?node->next->next:node->next; 438 438 } else { 439 node = (node->prev==root)?node->prev->prev:node->prev; 439 node = (node->prev==root)?node->prev->prev:node->prev; 440 440 } 441 441 retval = &node->command; … … 451 451 * referenced - (RFC-854). 452 452 */ 453 static pj_bool_t send_telnet_cmd(cli_telnet_sess *sess, 454 cli_telnet_command cmd, 453 static pj_bool_t send_telnet_cmd(cli_telnet_sess *sess, 454 cli_telnet_command cmd, 455 455 unsigned char option) 456 { 456 { 457 457 unsigned char buf[3]; 458 458 PJ_ASSERT_RETURN(sess, PJ_FALSE); … … 470 470 * For local option: send WILL. 471 471 * For remote option: send DO. 472 * This method also handle the state transition of the ENABLE 472 * This method also handle the state transition of the ENABLE 473 473 * negotiation process. 474 474 */ 475 static pj_bool_t send_enable_option(cli_telnet_sess *sess, 476 pj_bool_t is_local, 475 static pj_bool_t send_enable_option(cli_telnet_sess *sess, 476 pj_bool_t is_local, 477 477 unsigned char option) 478 478 { … … 500 500 *state = OPT_EXPECT_ENABLE; 501 501 break; 502 case OPT_EXPECT_DISABLE_REV: 502 case OPT_EXPECT_DISABLE_REV: 503 503 *state = OPT_DISABLE; 504 504 break; … … 509 509 } 510 510 511 static pj_bool_t send_cmd_do(cli_telnet_sess *sess, 511 static pj_bool_t send_cmd_do(cli_telnet_sess *sess, 512 512 unsigned char option) 513 513 { … … 515 515 } 516 516 517 static pj_bool_t send_cmd_will(cli_telnet_sess *sess, 517 static pj_bool_t send_cmd_will(cli_telnet_sess *sess, 518 518 unsigned char option) 519 519 { … … 523 523 /** 524 524 * This method will handle receiving telnet's ENABLE option negotiation. 525 * This method also handle the state transition of the ENABLE 526 * negotiation process. 527 */ 528 static pj_bool_t receive_enable_option(cli_telnet_sess *sess, 529 pj_bool_t is_local, 525 * This method also handle the state transition of the ENABLE 526 * negotiation process. 527 */ 528 static pj_bool_t receive_enable_option(cli_telnet_sess *sess, 529 pj_bool_t is_local, 530 530 unsigned char option) 531 531 { … … 550 550 } 551 551 break; 552 case OPT_EXPECT_ENABLE: 552 case OPT_EXPECT_ENABLE: 553 553 *state = OPT_ENABLE; 554 554 break; 555 case OPT_EXPECT_DISABLE: 555 case OPT_EXPECT_DISABLE: 556 556 *state = OPT_DISABLE; 557 557 break; 558 558 case OPT_EXPECT_ENABLE_REV: 559 559 *state = OPT_EXPECT_DISABLE; 560 send_telnet_cmd(sess, is_local?WONT:DONT, option); 560 send_telnet_cmd(sess, is_local?WONT:DONT, option); 561 561 break; 562 562 case OPT_EXPECT_DISABLE_REV: … … 566 566 return PJ_FALSE; 567 567 } 568 return PJ_TRUE; 568 return PJ_TRUE; 569 569 } 570 570 571 571 /** 572 572 * This method will handle receiving telnet's DISABLE option negotiation. 573 * This method also handle the state transition of the DISABLE 574 * negotiation process. 575 */ 576 static pj_bool_t receive_disable_option(cli_telnet_sess *sess, 577 pj_bool_t is_local, 573 * This method also handle the state transition of the DISABLE 574 * negotiation process. 575 */ 576 static pj_bool_t receive_disable_option(cli_telnet_sess *sess, 577 pj_bool_t is_local, 578 578 unsigned char option) 579 579 { … … 585 585 sess_opt = &sess->telnet_option[option]; 586 586 state = is_local?(&sess_opt->local_state):(&sess_opt->peer_state); 587 587 588 588 switch (*state) { 589 589 case OPT_ENABLE: … … 595 595 /* Ignore if already enabled */ 596 596 break; 597 case OPT_EXPECT_ENABLE: 597 case OPT_EXPECT_ENABLE: 598 598 case OPT_EXPECT_DISABLE: 599 599 *state = OPT_DISABLE; … … 601 601 case OPT_EXPECT_ENABLE_REV: 602 602 *state = OPT_DISABLE; 603 send_telnet_cmd(sess, is_local?WONT:DONT, option); 603 send_telnet_cmd(sess, is_local?WONT:DONT, option); 604 604 break; 605 605 case OPT_EXPECT_DISABLE_REV: … … 610 610 return PJ_FALSE; 611 611 } 612 return PJ_TRUE; 612 return PJ_TRUE; 613 613 } 614 614 … … 633 633 } 634 634 635 static void set_local_option(cli_telnet_sess *sess, 636 unsigned char option, 637 pj_bool_t enable) 635 static void set_local_option(cli_telnet_sess *sess, 636 unsigned char option, 637 pj_bool_t enable) 638 638 { 639 639 sess->telnet_option[option].local_is_enable = enable; 640 640 } 641 641 642 static void set_peer_option(cli_telnet_sess *sess, 643 unsigned char option, 644 pj_bool_t enable) 642 static void set_peer_option(cli_telnet_sess *sess, 643 unsigned char option, 644 pj_bool_t enable) 645 645 { 646 646 sess->telnet_option[option].peer_is_enable = enable; 647 647 } 648 648 649 static pj_bool_t is_local_option_state_ena(cli_telnet_sess *sess, 649 static pj_bool_t is_local_option_state_ena(cli_telnet_sess *sess, 650 650 unsigned char option) 651 { 651 { 652 652 return (sess->telnet_option[option].local_state == OPT_ENABLE); 653 653 } 654 654 655 static void send_return_key(cli_telnet_sess *sess) 656 { 655 static void send_return_key(cli_telnet_sess *sess) 656 { 657 657 telnet_sess_send2(sess, (unsigned char*)"\r\n", 2); 658 658 } … … 671 671 send_data.ptr = data_str; 672 672 send_data.slen = 0; 673 673 674 674 pj_strcat(&send_data, &fe->cfg.prompt_str); 675 675 … … 681 681 * the error position of the source command. 682 682 */ 683 static void send_err_arg(cli_telnet_sess *sess, 684 const pj_cli_exec_info *info, 683 static void send_err_arg(cli_telnet_sess *sess, 684 const pj_cli_exec_info *info, 685 685 const pj_str_t *msg, 686 686 pj_bool_t with_return, … … 715 715 } 716 716 717 static void send_inv_arg(cli_telnet_sess *sess, 717 static void send_inv_arg(cli_telnet_sess *sess, 718 718 const pj_cli_exec_info *info, 719 719 pj_bool_t with_return, … … 724 724 } 725 725 726 static void send_too_many_arg(cli_telnet_sess *sess, 726 static void send_too_many_arg(cli_telnet_sess *sess, 727 727 const pj_cli_exec_info *info, 728 728 pj_bool_t with_return, … … 733 733 } 734 734 735 static void send_hint_arg(cli_telnet_sess *sess, 736 pj_str_t *send_data, 735 static void send_hint_arg(cli_telnet_sess *sess, 736 pj_str_t *send_data, 737 737 const pj_str_t *desc, 738 738 pj_ssize_t cmd_len, … … 756 756 * is ambiguous. It will show the matching command as the hint information. 757 757 */ 758 static void send_ambi_arg(cli_telnet_sess *sess, 758 static void send_ambi_arg(cli_telnet_sess *sess, 759 759 const pj_cli_exec_info *info, 760 760 pj_bool_t with_return, … … 770 770 pj_ssize_t max_length = 0; 771 771 pj_ssize_t cmd_length = 0; 772 const pj_str_t *cmd_desc = 0;773 772 static const pj_str_t sc_type = {"sc", 2}; 774 773 static const pj_str_t choice_type = {"choice", 6}; 775 774 send_data.ptr = data; 776 775 send_data.slen = 0; 777 776 778 777 if (with_return) 779 778 pj_strcat2(&send_data, "\r\n"); … … 787 786 /* Get the max length of the command name */ 788 787 for (i=0;i<info->hint_cnt;++i) { 789 if ((&hint[i].type) && (hint[i].type.slen > 0)) { 790 if (pj_stricmp(&hint[i].type, &sc_type) == 0) { 788 if ((&hint[i].type) && (hint[i].type.slen > 0)) { 789 if (pj_stricmp(&hint[i].type, &sc_type) == 0) { 791 790 if ((i > 0) && (!pj_stricmp(&hint[i-1].desc, &hint[i].desc))) { 792 791 cmd_length += (hint[i].name.slen + 3); 793 792 } else { 794 793 cmd_length = hint[i].name.slen; 795 } 794 } 796 795 } else { 797 796 cmd_length = hint[i].name.slen; 798 797 } 799 } else { 798 } else { 800 799 cmd_length = hint[i].name.slen; 801 800 } … … 805 804 } 806 805 } 807 806 808 807 cmd_length = 0; 809 808 /* Build hint information */ 810 for (i=0;i<info->hint_cnt;++i) { 811 if ((&hint[i].type) && (hint[i].type.slen > 0)) { 809 for (i=0;i<info->hint_cnt;++i) { 810 if ((&hint[i].type) && (hint[i].type.slen > 0)) { 812 811 if (pj_stricmp(&hint[i].type, &sc_type) == 0) { 813 812 parse_state = OP_SHORTCUT; … … 817 816 parse_state = OP_TYPE; 818 817 } 819 } else { 818 } else { 820 819 parse_state = OP_NORMAL; 821 820 } 822 821 823 822 if (parse_state != OP_SHORTCUT) { 824 823 pj_strcat2(&send_data, "\r\n "); 825 824 cmd_length = hint[i].name.slen; 826 } 827 825 } 826 828 827 switch (parse_state) { 829 828 case OP_CHOICE: 830 /* Format : "[Choice Value] description" */ 829 /* Format : "[Choice Value] description" */ 831 830 pj_strcat2(&send_data, "["); 832 831 pj_strcat(&send_data, &hint[i].name); 833 pj_strcat2(&send_data, "]"); 832 pj_strcat2(&send_data, "]"); 834 833 break; 835 834 case OP_TYPE: … … 837 836 pj_strcat2(&send_data, "<"); 838 837 pj_strcat(&send_data, &hint[i].name); 839 pj_strcat2(&send_data, ">"); 838 pj_strcat2(&send_data, ">"); 840 839 break; 841 840 case OP_SHORTCUT: 842 841 /* Format : "Command | sc | description" */ 843 { 842 { 844 843 cmd_length += hint[i].name.slen; 845 844 if ((i > 0) && (!pj_stricmp(&hint[i-1].desc, &hint[i].desc))) { 846 845 pj_strcat2(&send_data, " | "); 847 cmd_length += 3; 846 cmd_length += 3; 848 847 } else { 849 848 pj_strcat2(&send_data, "\r\n "); 850 849 } 851 pj_strcat(&send_data, &hint[i].name); 850 pj_strcat(&send_data, &hint[i].name); 852 851 } 853 852 break; … … 855 854 /* Command */ 856 855 pj_strcat(&send_data, &hint[i].name); 857 cmd_desc = &hint[i].desc; 858 break; 859 } 860 861 if ((parse_state == OP_TYPE) || (parse_state == OP_CHOICE) || 856 break; 857 } 858 859 if ((parse_state == OP_TYPE) || (parse_state == OP_CHOICE) || 862 860 ((i+1) >= info->hint_cnt) || 863 (pj_strncmp(&hint[i].desc, &hint[i+1].desc, hint[i].desc.slen))) 861 (pj_strncmp(&hint[i].desc, &hint[i+1].desc, hint[i].desc.slen))) 864 862 { 865 863 /* Add description info */ 866 send_hint_arg(sess, &send_data, 867 &hint[i].desc, cmd_length, 864 send_hint_arg(sess, &send_data, 865 &hint[i].desc, cmd_length, 868 866 max_length); 869 867 870 868 cmd_length = 0; 871 } 872 } 873 pj_strcat2(&send_data, "\r\n"); 869 } 870 } 871 pj_strcat2(&send_data, "\r\n"); 874 872 pj_strcat(&send_data, &fe->cfg.prompt_str); 875 873 if (with_last_cmd) 876 874 pj_strcat2(&send_data, (char *)sess->rcmd->rbuf); 877 875 878 telnet_sess_send(sess, &send_data); 876 telnet_sess_send(sess, &send_data); 879 877 } 880 878 … … 882 880 * This method is to send command completion of the entered command. 883 881 */ 884 static void send_comp_arg(cli_telnet_sess *sess, 882 static void send_comp_arg(cli_telnet_sess *sess, 885 883 pj_cli_exec_info *info) 886 884 { … … 893 891 send_data.slen = 0; 894 892 895 pj_strcat(&send_data, &info->hint[0].name); 893 pj_strcat(&send_data, &info->hint[0].name); 896 894 897 895 telnet_sess_send(sess, &send_data); … … 902 900 */ 903 901 static pj_bool_t handle_alfa_num(cli_telnet_sess *sess, unsigned char *data) 904 { 902 { 905 903 if (is_local_option_state_ena(sess, TERM_ECHO)) { 906 904 if (recv_buf_right_len(sess->rcmd) > 0) { 907 /* Cursor is not at EOL, insert character */ 905 /* Cursor is not at EOL, insert character */ 908 906 unsigned char echo[5] = {0x1b, 0x5b, 0x31, 0x40, 0x00}; 909 907 echo[4] = *data; … … 914 912 } 915 913 return PJ_TRUE; 916 } 914 } 917 915 return PJ_FALSE; 918 916 } … … 926 924 if (recv_buf_backspace(sess->rcmd)) { 927 925 if (rlen) { 928 /* 929 * Cursor is not at the end of line, move the characters 926 /* 927 * Cursor is not at the end of line, move the characters 930 928 * after the cursor to left 931 929 */ … … 934 932 telnet_sess_send2(sess, echo, 5); 935 933 } else { 936 const static unsigned char echo[3] = {0x08, 0x20, 0x08}; 934 const static unsigned char echo[3] = {0x08, 0x20, 0x08}; 937 935 telnet_sess_send2(sess, echo, 3); 938 936 } … … 942 940 } 943 941 944 /* 945 * Syntax error handler for parser. 942 /* 943 * Syntax error handler for parser. 946 944 */ 947 945 static void on_syntax_error(pj_scanner *scanner) … … 958 956 pj_scanner scanner; 959 957 PJ_USE_EXCEPTION; 960 pj_scan_init(&scanner, cmd->ptr, cmd->slen, PJ_SCAN_AUTOSKIP_WS, 958 pj_scan_init(&scanner, cmd->ptr, cmd->slen, PJ_SCAN_AUTOSKIP_WS, 961 959 &on_syntax_error); 962 960 PJ_TRY { … … 966 964 } 967 965 PJ_CATCH_ANY { 968 pj_scan_fini(&scanner); 966 pj_scan_fini(&scanner); 969 967 return PJ_GET_EXCEPTION(); 970 968 } … … 981 979 pj_bool_t retval = PJ_TRUE; 982 980 unsigned len; 983 981 984 982 pj_pool_t *pool; 985 983 pj_cli_cmd_val *cmd_val; … … 990 988 991 989 cmd_val = PJ_POOL_ZALLOC_T(pool, pj_cli_cmd_val); 992 993 status = pj_cli_sess_parse(&sess->base, (char *)&sess->rcmd->rbuf, cmd_val, 994 pool, &info); 990 991 status = pj_cli_sess_parse(&sess->base, (char *)&sess->rcmd->rbuf, cmd_val, 992 pool, &info); 995 993 996 994 len = (unsigned)pj_ansi_strlen((char *)sess->rcmd->rbuf); … … 998 996 switch (status) { 999 997 case PJ_CLI_EINVARG: 1000 send_inv_arg(sess, &info, PJ_TRUE, PJ_TRUE); 998 send_inv_arg(sess, &info, PJ_TRUE, PJ_TRUE); 1001 999 break; 1002 1000 case PJ_CLI_ETOOMANYARGS: … … 1015 1013 telnet_sess_send2(sess, data_sent, rlen); 1016 1014 } 1017 if (info.hint_cnt > 0) { 1015 if (info.hint_cnt > 0) { 1018 1016 /* Complete command */ 1019 1017 pj_str_t cmd = pj_str((char *)sess->rcmd->rbuf); … … 1026 1024 if (hint_info->slen >= last_token.slen) { 1027 1025 hint_info->slen -= last_token.slen; 1028 pj_memmove(hint_info->ptr, 1029 &hint_info->ptr[last_token.slen], 1030 hint_info->slen); 1031 } 1026 pj_memmove(hint_info->ptr, 1027 &hint_info->ptr[last_token.slen], 1028 hint_info->slen); 1029 } 1032 1030 send_comp_arg(sess, &info); 1033 1031 1034 pj_memcpy(&sess->rcmd->rbuf[len], info.hint[0].name.ptr, 1032 pj_memcpy(&sess->rcmd->rbuf[len], info.hint[0].name.ptr, 1035 1033 info.hint[0].name.slen); 1036 1034 1037 1035 len += (unsigned)info.hint[0].name.slen; 1038 sess->rcmd->rbuf[len] = 0; 1036 sess->rcmd->rbuf[len] = 0; 1039 1037 } 1040 1038 } else { … … 1046 1044 sess->rcmd->cur_pos = sess->rcmd->len; 1047 1045 1048 pj_pool_release(pool); 1049 return retval; 1046 pj_pool_release(pool); 1047 return retval; 1050 1048 } 1051 1049 … … 1057 1055 pj_status_t status; 1058 1056 pj_bool_t retval = PJ_TRUE; 1059 1060 pj_pool_t *pool; 1061 pj_cli_exec_info info; 1062 1057 1058 pj_pool_t *pool; 1059 pj_cli_exec_info info; 1060 1063 1061 send_return_key(sess); 1064 1062 insert_history(sess, (char *)&sess->rcmd->rbuf); … … 1066 1064 pool = pj_pool_create(sess->pool->factory, "handle_return", 1067 1065 PJ_CLI_TELNET_POOL_SIZE, PJ_CLI_TELNET_POOL_INC, 1068 NULL); 1069 1070 status = pj_cli_sess_exec(&sess->base, (char *)&sess->rcmd->rbuf, 1066 NULL); 1067 1068 status = pj_cli_sess_exec(&sess->base, (char *)&sess->rcmd->rbuf, 1071 1069 pool, &info); 1072 1070 1073 1071 switch (status) { 1074 1072 case PJ_CLI_EINVARG: 1075 send_inv_arg(sess, &info, PJ_FALSE, PJ_FALSE); 1073 send_inv_arg(sess, &info, PJ_FALSE, PJ_FALSE); 1076 1074 break; 1077 1075 case PJ_CLI_ETOOMANYARGS: … … 1088 1086 send_prompt_str(sess); 1089 1087 break; 1090 } 1088 } 1091 1089 if (retval) { 1092 1090 sess->rcmd->rbuf[0] = 0; … … 1095 1093 } 1096 1094 1097 pj_pool_release(pool); 1098 return retval; 1095 pj_pool_release(pool); 1096 return retval; 1099 1097 } 1100 1098 … … 1106 1104 if (recv_buf_right_len(sess->rcmd)) { 1107 1105 unsigned char *data = &sess->rcmd->rbuf[sess->rcmd->cur_pos++]; 1108 telnet_sess_send2(sess, data, 1); 1106 telnet_sess_send2(sess, data, 1); 1109 1107 return PJ_TRUE; 1110 1108 } … … 1116 1114 */ 1117 1115 static pj_bool_t handle_left_key(cli_telnet_sess *sess) 1118 { 1116 { 1119 1117 static const unsigned char move_cursor_left = 0x08; 1120 1118 if (sess->rcmd->cur_pos) { … … 1151 1149 send_data.slen = sess->rcmd->cur_pos; 1152 1150 } 1153 1151 1154 1152 if (sess->rcmd->len > (unsigned)history->slen) { 1155 1153 /* Clear the command currently shown*/ … … 1159 1157 1160 1158 /* Move cursor position to the beginning of line */ 1161 pj_memset(&send_data.ptr[send_data.slen], MOVE_CURSOR_LEFT, 1159 pj_memset(&send_data.ptr[send_data.slen], MOVE_CURSOR_LEFT, 1162 1160 buf_len); 1163 1161 send_data.slen += buf_len; 1164 } 1162 } 1165 1163 /* Send data */ 1166 1164 pj_strcat(&send_data, history); … … 1175 1173 } 1176 1174 1177 static pj_status_t process_vt100_cmd(cli_telnet_sess *sess, 1175 static pj_status_t process_vt100_cmd(cli_telnet_sess *sess, 1178 1176 unsigned char *cmd) 1179 { 1177 { 1180 1178 pj_status_t status = PJ_TRUE; 1181 1179 switch (*cmd) { … … 1225 1223 } 1226 1224 1227 /* 1228 * Send a message to a telnet session 1225 /* 1226 * Send a message to a telnet session 1229 1227 */ 1230 1228 static pj_status_t telnet_sess_send(cli_telnet_sess *sess, … … 1241 1239 1242 1240 if (sess->buf_len == 0) 1243 status = pj_activesock_send(sess->asock, &sess->op_key, 1241 status = pj_activesock_send(sess->asock, &sess->op_key, 1244 1242 str->ptr, &sz, 0); 1245 /* If we cannot send now, append it at the end of the buffer 1243 /* If we cannot send now, append it at the end of the buffer 1246 1244 * to be sent later. 1247 1245 */ 1248 if (sess->buf_len > 0 || 1246 if (sess->buf_len > 0 || 1249 1247 (status != PJ_SUCCESS && status != PJ_EPENDING)) 1250 1248 { … … 1273 1271 } 1274 1272 1275 /* 1276 * Send a message to a telnet session with formatted text 1273 /* 1274 * Send a message to a telnet session with formatted text 1277 1275 * (add single linefeed character with carriage return) 1278 1276 */ … … 1288 1286 PJ_USE_EXCEPTION; 1289 1287 1290 pj_scan_init(&scanner, str->ptr, str->slen, 1288 pj_scan_init(&scanner, str->ptr, str->slen, 1291 1289 PJ_SCAN_AUTOSKIP_WS, &on_syntax_error); 1292 1290 1293 1291 str_begin = scanner.begin; 1294 1292 1295 1293 PJ_TRY { 1296 while (!pj_scan_is_eof(&scanner)) { 1297 pj_scan_get_until_ch(&scanner, '\n', &out_str); 1294 while (!pj_scan_is_eof(&scanner)) { 1295 pj_scan_get_until_ch(&scanner, '\n', &out_str); 1298 1296 str_len = (int)(scanner.curptr - str_begin); 1299 if (*scanner.curptr == '\n') { 1300 if ((str_len > 1) && (out_str.ptr[str_len-2] == '\r')) 1301 { 1297 if (*scanner.curptr == '\n') { 1298 if ((str_len > 1) && (out_str.ptr[str_len-2] == '\r')) 1299 { 1302 1300 continue; 1303 } else { 1301 } else { 1304 1302 int str_pos = (int)(str_begin - scanner.begin); 1305 1303 … … 1314 1312 pj_scan_advance_n(&scanner, 1, PJ_TRUE); 1315 1313 str_begin = scanner.curptr; 1316 } 1314 } 1317 1315 } 1318 1316 } else { … … 1355 1353 pj_mutex_unlock(tsess->smutex); 1356 1354 pj_activesock_close(tsess->asock); 1357 pj_mutex_destroy(tsess->smutex); 1355 pj_mutex_destroy(tsess->smutex); 1358 1356 pj_pool_release(tsess->pool); 1359 1357 } … … 1363 1361 { 1364 1362 cli_telnet_fe *tfe = (cli_telnet_fe *)fe; 1365 pj_cli_sess *sess; 1363 pj_cli_sess *sess; 1366 1364 1367 1365 pj_mutex_lock(tfe->mutex); … … 1371 1369 cli_telnet_sess *tsess = (cli_telnet_sess *)sess; 1372 1370 1373 sess = sess->next; 1371 sess = sess->next; 1374 1372 if (tsess->base.log_level > level) { 1375 1373 pj_str_t s; … … 1379 1377 } 1380 1378 } 1381 1379 1382 1380 pj_mutex_unlock(tfe->mutex); 1383 1381 } … … 1436 1434 pj_activesock_get_user_data(asock); 1437 1435 1438 PJ_UNUSED_ARG(op_key); 1436 PJ_UNUSED_ARG(op_key); 1439 1437 1440 1438 if (sent <= 0) { … … 1471 1469 pj_activesock_get_user_data(asock); 1472 1470 cli_telnet_fe *tfe = (cli_telnet_fe *)sess->base.fe; 1473 unsigned char *cdata = (unsigned char*)data; 1471 unsigned char *cdata = (unsigned char*)data; 1474 1472 pj_status_t is_valid = PJ_TRUE; 1475 1473 … … 1483 1481 TRACE_((THIS_FILE, "Error on data read %d", status)); 1484 1482 return PJ_FALSE; 1485 } 1483 } 1486 1484 1487 1485 pj_mutex_lock(sess->smutex); … … 1490 1488 case ST_CR: 1491 1489 sess->parse_state = ST_NORMAL; 1492 if (*cdata == 0 || *cdata == '\n') 1490 if (*cdata == 0 || *cdata == '\n') 1493 1491 pj_mutex_unlock(sess->smutex); 1494 1492 is_valid = handle_return(sess); 1495 if (!is_valid) 1493 if (!is_valid) 1496 1494 return PJ_FALSE; 1497 pj_mutex_lock(sess->smutex); 1495 pj_mutex_lock(sess->smutex); 1498 1496 break; 1499 1497 case ST_NORMAL: … … 1502 1500 } else if (*cdata == 127) { 1503 1501 is_valid = handle_backspace(sess, cdata); 1504 } else if (*cdata == 27) { 1502 } else if (*cdata == 27) { 1505 1503 sess->parse_state = ST_ESC; 1506 } else { 1504 } else { 1507 1505 if (recv_buf_insert(sess->rcmd, cdata)) { 1508 1506 if (*cdata == '\r') { … … 1519 1517 break; 1520 1518 case ST_ESC: 1521 if (*cdata == 91) { 1519 if (*cdata == 91) { 1522 1520 sess->parse_state = ST_VT100; 1523 1521 } else { … … 1598 1596 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 1599 1597 TRACE_((THIS_FILE, "Error on data accept %d", status)); 1600 if (status == PJ_ESOCKETSTOP) 1601 telnet_restart(fe); 1602 1598 if (status == PJ_ESOCKETSTOP) 1599 telnet_restart(fe); 1600 1603 1601 return PJ_FALSE; 1604 } 1602 } 1605 1603 1606 1604 /* An incoming connection is accepted, create a new session */ … … 1609 1607 NULL); 1610 1608 if (!pool) { 1611 TRACE_((THIS_FILE, 1609 TRACE_((THIS_FILE, 1612 1610 "Not enough memory to create a new telnet session")); 1613 1611 return PJ_TRUE; … … 1632 1630 if (sstatus != PJ_SUCCESS) 1633 1631 goto on_exit; 1634 1632 1635 1633 sstatus = pj_activesock_create(pool, newsock, pj_SOCK_STREAM(), 1636 1634 NULL, fe->cfg.ioqueue, … … 1657 1655 send_cmd_do(sess, SUPPRESS_GA); 1658 1656 send_cmd_will(sess, TERM_ECHO); 1659 send_cmd_will(sess, STATUS); 1657 send_cmd_will(sess, STATUS); 1660 1658 send_cmd_will(sess, SUPPRESS_GA); 1661 1659 … … 1682 1680 else 1683 1681 pj_sock_close(newsock); 1684 1682 1685 1683 if (sess->smutex) 1686 1684 pj_mutex_destroy(sess->smutex); … … 1697 1695 cli_telnet_fe *fe; 1698 1696 pj_pool_t *pool; 1699 pj_status_t status; 1697 pj_status_t status; 1700 1698 1701 1699 PJ_ASSERT_RETURN(cli, PJ_EINVAL); … … 1707 1705 if (!fe) 1708 1706 return PJ_ENOMEM; 1709 1707 1710 1708 fe->base.op = PJ_POOL_ZALLOC_T(pool, struct pj_cli_front_end_op); 1711 1709 … … 1714 1712 else 1715 1713 pj_memcpy(&fe->cfg, param, sizeof(*param)); 1716 1714 1717 1715 pj_list_init(&fe->sess_head); 1718 1716 fe->base.cli = cli; … … 1722 1720 fe->pool = pool; 1723 1721 1724 if (!fe->cfg.ioqueue) { 1722 if (!fe->cfg.ioqueue) { 1725 1723 /* Create own ioqueue if application doesn't supply one */ 1726 1724 status = pj_ioqueue_create(pool, 8, &fe->cfg.ioqueue); … … 1762 1760 pj_activesock_cb asock_cb; 1763 1761 pj_sockaddr_in addr; 1764 pj_status_t status; 1762 pj_status_t status; 1765 1763 int val; 1766 1764 int restart_retry; … … 1794 1792 PJ_LOG(4,(THIS_FILE, "Address is still in use, retrying..")); 1795 1793 pj_thread_sleep(msec); 1796 } 1797 1798 if (status == PJ_SUCCESS) { 1799 int addr_len = sizeof(addr); 1794 } 1795 1796 if (status == PJ_SUCCESS) { 1797 int addr_len = sizeof(addr); 1800 1798 1801 1799 status = pj_sock_getsockname(sock, &addr, &addr_len); 1802 1800 if (status != PJ_SUCCESS) 1803 1801 goto on_exit; 1804 1805 fe->cfg.port = pj_sockaddr_in_get_port(&addr); 1802 1803 fe->cfg.port = pj_sockaddr_in_get_port(&addr); 1806 1804 1807 1805 if (fe->cfg.prompt_str.slen == 0) { 1808 1806 pj_str_t prompt_sign = {"> ", 2}; 1809 char *prompt_data = pj_pool_alloc(fe->pool, 1807 char *prompt_data = pj_pool_alloc(fe->pool, 1810 1808 pj_gethostname()->slen+2); 1811 1809 fe->cfg.prompt_str.ptr = prompt_data; … … 1813 1811 pj_strcpy(&fe->cfg.prompt_str, pj_gethostname()); 1814 1812 pj_strcat(&fe->cfg.prompt_str, &prompt_sign); 1815 } 1813 } 1816 1814 } else { 1817 1815 PJ_LOG(3, (THIS_FILE, "Failed binding the socket")); … … 1869 1867 { 1870 1868 pj_status_t status; 1871 pj_cli_sess *sess; 1869 pj_cli_sess *sess; 1872 1870 1873 1871 fe->is_quitting = PJ_TRUE; 1874 if (fe->worker_thread) { 1872 if (fe->worker_thread) { 1875 1873 pj_thread_join(fe->worker_thread); 1876 1874 } … … 1911 1909 } 1912 1910 1913 PJ_DEF(pj_status_t) pj_cli_telnet_get_info(pj_cli_front_end *fe, 1911 PJ_DEF(pj_status_t) pj_cli_telnet_get_info(pj_cli_front_end *fe, 1914 1912 pj_cli_telnet_info *info) 1915 1913 { 1916 1914 pj_sockaddr hostip; 1917 1915 pj_status_t status; 1918 cli_telnet_fe *tfe = (cli_telnet_fe*) fe; 1919 1920 PJ_ASSERT_RETURN(fe && (fe->type == PJ_CLI_TELNET_FRONT_END) && info, 1916 cli_telnet_fe *tfe = (cli_telnet_fe*) fe; 1917 1918 PJ_ASSERT_RETURN(fe && (fe->type == PJ_CLI_TELNET_FRONT_END) && info, 1921 1919 PJ_EINVAL); 1922 1920 -
pjproject/trunk/pjlib/src/pj/os_core_unix.c
r4359 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 /* … … 165 165 pj_log_init(); 166 166 167 /* Initialize exception ID for the pool. 167 /* Initialize exception ID for the pool. 168 168 * Must do so after critical section is configured. 169 169 */ … … 171 171 if (rc != PJ_SUCCESS) 172 172 return rc; 173 173 174 174 /* Init random seed. */ 175 175 /* Or probably not. Let application in charge of this */ … … 188 188 } 189 189 } 190 #endif 190 #endif 191 191 192 192 /* Flag PJLIB as initialized */ … … 383 383 * Get native thread handle 384 384 */ 385 PJ_DEF(void*) pj_thread_get_os_handle(pj_thread_t *thread) 385 PJ_DEF(void*) pj_thread_get_os_handle(pj_thread_t *thread) 386 386 { 387 387 PJ_ASSERT_RETURN(thread, NULL); … … 441 441 442 442 if(cstr_thread_name && pj_strlen(&thread_name) < sizeof(thread->obj_name)-1) 443 pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name), 443 pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name), 444 444 cstr_thread_name, thread->thread); 445 445 else 446 pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name), 446 pj_ansi_snprintf(thread->obj_name, sizeof(thread->obj_name), 447 447 "thr%p", (void*)thread->thread); 448 448 449 449 rc = pj_thread_local_set(thread_tls_id, thread); 450 450 if (rc != PJ_SUCCESS) { … … 458 458 thread->stk_max_usage = 0; 459 459 #else 460 stack_ptr = '\0';460 PJ_UNUSED_ARG(stack_ptr); 461 461 #endif 462 462 … … 533 533 * pj_thread_create(...) 534 534 */ 535 PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool, 535 PJ_DEF(pj_status_t) pj_thread_create( pj_pool_t *pool, 536 536 const char *thread_name, 537 pj_thread_proc *proc, 537 pj_thread_proc *proc, 538 538 void *arg, 539 pj_size_t stack_size, 539 pj_size_t stack_size, 540 540 unsigned flags, 541 541 pj_thread_t **ptr_thread) … … 555 555 rec = (struct pj_thread_t*) pj_pool_zalloc(pool, sizeof(pj_thread_t)); 556 556 PJ_ASSERT_RETURN(rec, PJ_ENOMEM); 557 557 558 558 /* Set name. */ 559 if (!thread_name) 559 if (!thread_name) 560 560 thread_name = "thr%p"; 561 561 562 562 if (strchr(thread_name, '%')) { 563 563 pj_ansi_snprintf(rec->obj_name, PJ_MAX_OBJ_NAME, thread_name, rec); … … 587 587 pj_assert(rec->suspended_mutex == NULL); 588 588 } 589 589 590 590 591 591 /* Init thread attributes */ … … 668 668 #if PJ_HAS_THREADS 669 669 pj_thread_t *rec = (pj_thread_t*)pj_thread_local_get(thread_tls_id); 670 670 671 671 if (rec == NULL) { 672 672 pj_assert(!"Calling pjlib from unknown/external thread. You must " … … 706 706 return PJ_SUCCESS; 707 707 else { 708 /* Calling pthread_join() on a thread that no longer exists and 709 * getting back ESRCH isn't an error (in this context). 708 /* Calling pthread_join() on a thread that no longer exists and 709 * getting back ESRCH isn't an error (in this context). 710 710 * Thanks Phil Torre <ptorre@zetron.com>. 711 711 */ … … 762 762 /* MacOS X (reported on 10.5) seems to always set errno to ETIMEDOUT. 763 763 * It does so because usleep() is declared to return int, and we're 764 * supposed to check for errno only when usleep() returns non-zero. 764 * supposed to check for errno only when usleep() returns non-zero. 765 765 * Unfortunately, usleep() is declared to return void in other platforms 766 * so it's not possible to always check for the return value (unless 766 * so it's not possible to always check for the return value (unless 767 767 * we add a detection routine in autoconf). 768 768 * … … 832 832 * pj_atomic_create() 833 833 */ 834 PJ_DEF(pj_status_t) pj_atomic_create( pj_pool_t *pool, 834 PJ_DEF(pj_status_t) pj_atomic_create( pj_pool_t *pool, 835 835 pj_atomic_value_t initial, 836 836 pj_atomic_t **ptr_atomic) … … 842 842 843 843 PJ_ASSERT_RETURN(atomic_var, PJ_ENOMEM); 844 844 845 845 #if PJ_HAS_THREADS 846 846 rc = pj_mutex_create(pool, "atm%p", PJ_MUTEX_SIMPLE, &atomic_var->mutex); … … 880 880 #if PJ_HAS_THREADS 881 881 pj_mutex_unlock( atomic_var->mutex); 882 #endif 882 #endif 883 883 } 884 884 … … 889 889 { 890 890 pj_atomic_value_t oldval; 891 891 892 892 PJ_CHECK_STACK(); 893 893 … … 959 959 /* 960 960 * pj_atomic_add_and_get() 961 */ 962 PJ_DEF(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var, 961 */ 962 PJ_DEF(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var, 963 963 pj_atomic_value_t value ) 964 964 { … … 968 968 pj_mutex_lock(atomic_var->mutex); 969 969 #endif 970 970 971 971 atomic_var->value += value; 972 972 new_value = atomic_var->value; … … 981 981 /* 982 982 * pj_atomic_add() 983 */ 984 PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var, 983 */ 984 PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var, 985 985 pj_atomic_value_t value ) 986 986 { … … 1012 1012 break; 1013 1013 } 1014 if (i == MAX_THREADS) 1014 if (i == MAX_THREADS) 1015 1015 return PJ_ETOOMANY; 1016 1016 1017 1017 tls_flag[i] = 1; 1018 1018 tls[i] = NULL; … … 1119 1119 defined(PJ_PTHREAD_MUTEXATTR_T_HAS_RECURSIVE) 1120 1120 // Phil Torre <ptorre@zetron.com>: 1121 // The RTEMS implementation of POSIX mutexes doesn't include 1121 // The RTEMS implementation of POSIX mutexes doesn't include 1122 1122 // pthread_mutexattr_settype(), so what follows is a hack 1123 1123 // until I get RTEMS patched to support the set/get functions. … … 1132 1132 #endif 1133 1133 } 1134 1134 1135 1135 if (rc != 0) { 1136 1136 return PJ_RETURN_OS_ERROR(rc); … … 1141 1141 return PJ_RETURN_OS_ERROR(rc); 1142 1142 } 1143 1143 1144 1144 rc = pthread_mutexattr_destroy(&attr); 1145 1145 if (rc != 0) { … … 1176 1176 * pj_mutex_create() 1177 1177 */ 1178 PJ_DEF(pj_status_t) pj_mutex_create(pj_pool_t *pool, 1179 const char *name, 1178 PJ_DEF(pj_status_t) pj_mutex_create(pj_pool_t *pool, 1179 const char *name, 1180 1180 int type, 1181 1181 pj_mutex_t **ptr_mutex) … … 1192 1192 if ((rc=init_mutex(mutex, name, type)) != PJ_SUCCESS) 1193 1193 return rc; 1194 1194 1195 1195 *ptr_mutex = mutex; 1196 1196 return PJ_SUCCESS; … … 1204 1204 * pj_mutex_create_simple() 1205 1205 */ 1206 PJ_DEF(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool, 1206 PJ_DEF(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool, 1207 1207 const char *name, 1208 1208 pj_mutex_t **mutex ) … … 1233 1233 1234 1234 #if PJ_DEBUG 1235 PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s is waiting (mutex owner=%s)", 1235 PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s is waiting (mutex owner=%s)", 1236 1236 pj_thread_this()->obj_name, 1237 1237 mutex->owner_name)); 1238 1238 #else 1239 PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s is waiting", 1239 PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s is waiting", 1240 1240 pj_thread_this()->obj_name)); 1241 1241 #endif … … 1251 1251 } 1252 1252 1253 PJ_LOG(6,(mutex->obj_name, 1254 (status==0 ? 1255 "Mutex acquired by thread %s (level=%d)" : 1253 PJ_LOG(6,(mutex->obj_name, 1254 (status==0 ? 1255 "Mutex acquired by thread %s (level=%d)" : 1256 1256 "Mutex acquisition FAILED by %s (level=%d)"), 1257 1257 pj_thread_this()->obj_name, 1258 1258 mutex->nesting_level)); 1259 1259 #else 1260 PJ_LOG(6,(mutex->obj_name, 1260 PJ_LOG(6,(mutex->obj_name, 1261 1261 (status==0 ? "Mutex acquired by thread %s" : "FAILED by %s"), 1262 1262 pj_thread_this()->obj_name)); … … 1291 1291 } 1292 1292 1293 PJ_LOG(6,(mutex->obj_name, "Mutex released by thread %s (level=%d)", 1294 pj_thread_this()->obj_name, 1293 PJ_LOG(6,(mutex->obj_name, "Mutex released by thread %s (level=%d)", 1294 pj_thread_this()->obj_name, 1295 1295 mutex->nesting_level)); 1296 1296 #else 1297 PJ_LOG(6,(mutex->obj_name, "Mutex released by thread %s", 1297 PJ_LOG(6,(mutex->obj_name, "Mutex released by thread %s", 1298 1298 pj_thread_this()->obj_name)); 1299 1299 #endif … … 1322 1322 PJ_ASSERT_RETURN(mutex, PJ_EINVAL); 1323 1323 1324 PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s is trying", 1324 PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s is trying", 1325 1325 pj_thread_this()->obj_name)); 1326 1326 … … 1333 1333 ++mutex->nesting_level; 1334 1334 1335 PJ_LOG(6,(mutex->obj_name, "Mutex acquired by thread %s (level=%d)", 1335 PJ_LOG(6,(mutex->obj_name, "Mutex acquired by thread %s (level=%d)", 1336 1336 pj_thread_this()->obj_name, 1337 1337 mutex->nesting_level)); 1338 1338 #else 1339 PJ_LOG(6,(mutex->obj_name, "Mutex acquired by thread %s", 1339 PJ_LOG(6,(mutex->obj_name, "Mutex acquired by thread %s", 1340 1340 pj_thread_this()->obj_name)); 1341 1341 #endif 1342 1342 } else { 1343 PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s's trylock() failed", 1343 PJ_LOG(6,(mutex->obj_name, "Mutex: thread %s's trylock() failed", 1344 1344 pj_thread_this()->obj_name)); 1345 1345 } 1346 1346 1347 1347 if (status==0) 1348 1348 return PJ_SUCCESS; … … 1426 1426 1427 1427 PJ_UNUSED_ARG(name); 1428 1428 1429 1429 rwm = PJ_POOL_ALLOC_T(pool, pj_rwmutex_t); 1430 1430 PJ_ASSERT_RETURN(rwm, PJ_ENOMEM); … … 1516 1516 * pj_sem_create() 1517 1517 */ 1518 PJ_DEF(pj_status_t) pj_sem_create( pj_pool_t *pool, 1518 PJ_DEF(pj_status_t) pj_sem_create( pj_pool_t *pool, 1519 1519 const char *name, 1520 unsigned initial, 1520 unsigned initial, 1521 1521 unsigned max, 1522 1522 pj_sem_t **ptr_sem) … … 1537 1537 pj_str_t nam; 1538 1538 1539 /* We should use SEM_NAME_LEN, but this doesn't seem to be 1539 /* We should use SEM_NAME_LEN, but this doesn't seem to be 1540 1540 * declared anywhere? The value here is just from trial and error 1541 1541 * to get the longest name supported. … … 1554 1554 1555 1555 /* Create semaphore */ 1556 sem->sem = sem_open(sem_name, O_CREAT|O_EXCL, S_IRUSR|S_IWUSR, 1556 sem->sem = sem_open(sem_name, O_CREAT|O_EXCL, S_IRUSR|S_IWUSR, 1557 1557 initial); 1558 1558 if (sem->sem == SEM_FAILED) … … 1564 1564 #else 1565 1565 sem->sem = PJ_POOL_ALLOC_T(pool, sem_t); 1566 if (sem_init( sem->sem, 0, initial) != 0) 1566 if (sem_init( sem->sem, 0, initial) != 0) 1567 1567 return PJ_RETURN_OS_ERROR(pj_get_native_os_error()); 1568 1568 #endif 1569 1569 1570 1570 /* Set name. */ 1571 1571 if (!name) { … … 1600 1600 PJ_ASSERT_RETURN(sem, PJ_EINVAL); 1601 1601 1602 PJ_LOG(6, (sem->obj_name, "Semaphore: thread %s is waiting", 1602 PJ_LOG(6, (sem->obj_name, "Semaphore: thread %s is waiting", 1603 1603 pj_thread_this()->obj_name)); 1604 1604 1605 1605 result = sem_wait( sem->sem ); 1606 1606 1607 1607 if (result == 0) { 1608 PJ_LOG(6, (sem->obj_name, "Semaphore acquired by thread %s", 1608 PJ_LOG(6, (sem->obj_name, "Semaphore acquired by thread %s", 1609 1609 pj_thread_this()->obj_name)); 1610 1610 } else { 1611 PJ_LOG(6, (sem->obj_name, "Semaphore: thread %s FAILED to acquire", 1611 PJ_LOG(6, (sem->obj_name, "Semaphore: thread %s FAILED to acquire", 1612 1612 pj_thread_this()->obj_name)); 1613 1613 } … … 1635 1635 1636 1636 result = sem_trywait( sem->sem ); 1637 1637 1638 1638 if (result == 0) { 1639 PJ_LOG(6, (sem->obj_name, "Semaphore acquired by thread %s", 1639 PJ_LOG(6, (sem->obj_name, "Semaphore acquired by thread %s", 1640 1640 pj_thread_this()->obj_name)); 1641 } 1641 } 1642 1642 if (result == 0) 1643 1643 return PJ_SUCCESS; -
pjproject/trunk/pjlib/src/pjlib-test/test.c
r4712 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include "test.h" … … 39 39 const char *param_echo_server = ECHO_SERVER_ADDRESS; 40 40 int param_echo_port = ECHO_SERVER_START_PORT; 41 int param_log_decor = PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME | 41 int param_log_decor = PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME | 42 42 PJ_LOG_HAS_MICRO_SEC; 43 43 … … 64 64 return rc; 65 65 } 66 66 67 67 //pj_dump_config(); 68 68 pj_caching_pool_init( &caching_pool, NULL, 0 ); … … 99 99 DO_TEST( string_test() ); 100 100 #endif 101 101 102 102 #if INCLUDE_FIFOBUF_TEST 103 103 DO_TEST( fifobuf_test() ); … … 185 185 param_echo_sock_type = pj_SOCK_DGRAM(); 186 186 187 echo_client( param_echo_sock_type, 188 param_echo_server, 187 echo_client( param_echo_sock_type, 188 param_echo_server, 189 189 param_echo_port); 190 190 #endif … … 197 197 198 198 PJ_LOG(3,("test", "")); 199 199 200 200 pj_thread_get_stack_info(pj_thread_this(), &filename, &line); 201 PJ_LOG(3,("test", "Stack max usage: %u, deepest: %s:%u", 201 PJ_LOG(3,("test", "Stack max usage: %u, deepest: %s:%u", 202 202 pj_thread_get_stack_max_usage(pj_thread_this()), 203 203 filename, line)); … … 206 206 else 207 207 PJ_LOG(3,("test", "Test completed with error(s)")); 208 208 209 209 pj_shutdown(); 210 210 211 211 return 0; 212 212 } … … 217 217 { 218 218 PJ_USE_EXCEPTION; 219 220 pj_AF_INET();221 219 222 220 PJ_TRY { … … 225 223 PJ_CATCH_ANY { 226 224 int id = PJ_GET_EXCEPTION(); 227 PJ_LOG(3,("test", "FATAL: unhandled exception id %d (%s)", 225 PJ_LOG(3,("test", "FATAL: unhandled exception id %d (%s)", 228 226 id, pj_exception_id_name(id))); 229 227 } -
pjproject/trunk/pjlib/src/pjlib-test/thread.c
r3553 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include "test.h" … … 31 31 * - whether thread timeslicing works, and threads have equal 32 32 * time-slice proportion. 33 * 33 * 34 34 * APIs tested: 35 35 * - pj_thread_create() … … 78 78 79 79 id = *pcounter; 80 PJ_UNUSED_ARG(id); /* Warning about unused var if TRACE__ is disabled */ 80 81 TRACE__((THIS_FILE, " thread %d running..", id)); 81 82 … … 121 122 pj_status_t rc; 122 123 pj_uint32_t counter = 0; 123 124 124 125 PJ_LOG(3,(THIS_FILE, "..%s", title)); 125 126 126 127 pool = pj_pool_create(mem, NULL, 4000, 4000, NULL); 127 128 if (!pool) … … 153 154 return -1015; 154 155 } 155 156 156 157 rc = pj_thread_resume(thread); 157 158 if (rc != PJ_SUCCESS) { … … 160 161 } 161 162 } 162 163 163 164 PJ_LOG(3,(THIS_FILE, "..waiting for thread to quit..")); 164 165 … … 174 175 return -1025; 175 176 } 176 177 177 178 PJ_LOG(3,(THIS_FILE, "...%s success", title)); 178 179 return PJ_SUCCESS; … … 203 204 for (i=0; i<NUM_THREADS; ++i) { 204 205 counter[i] = i; 205 rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc, 206 &counter[i], 207 PJ_THREAD_DEFAULT_STACK_SIZE, 208 PJ_THREAD_SUSPENDED, 206 rc = pj_thread_create(pool, "thread", (pj_thread_proc*)&thread_proc, 207 &counter[i], 208 PJ_THREAD_DEFAULT_STACK_SIZE, 209 PJ_THREAD_SUSPENDED, 209 210 &thread[i]); 210 211 if (rc!=PJ_SUCCESS) { … … 224 225 for (i=0; i<NUM_THREADS; ++i) { 225 226 if (counter[i] > i) { 226 PJ_LOG(3,(THIS_FILE, "....ERROR! Thread %d-th is not suspended!", 227 PJ_LOG(3,(THIS_FILE, "....ERROR! Thread %d-th is not suspended!", 227 228 i)); 228 229 return -30; … … 240 241 } 241 242 242 /* Main thread sleeps for some time to allow threads to run. 243 /* Main thread sleeps for some time to allow threads to run. 243 244 * The longer we sleep, the more accurate the calculation will be, 244 245 * but it'll make user waits for longer for the test to finish. … … 253 254 /* Wait until all threads quit, then destroy. */ 254 255 for (i=0; i<NUM_THREADS; ++i) { 255 TRACE__((THIS_FILE, " Main thread joining thread %d [%p]..", 256 TRACE__((THIS_FILE, " Main thread joining thread %d [%p]..", 256 257 i, thread[i])); 257 258 rc = pj_thread_join(thread[i]); … … 292 293 diff = (highest-lowest)*100 / ((highest+lowest)/2); 293 294 if ( diff >= 50) { 294 PJ_LOG(3,(THIS_FILE, 295 PJ_LOG(3,(THIS_FILE, 295 296 "...ERROR: thread didn't have equal timeslice!")); 296 PJ_LOG(3,(THIS_FILE, 297 PJ_LOG(3,(THIS_FILE, 297 298 ".....lowest counter=%u, highest counter=%u, diff=%u%%", 298 299 lowest, highest, diff)); 299 300 return -80; 300 301 } else { 301 PJ_LOG(3,(THIS_FILE, 302 PJ_LOG(3,(THIS_FILE, 302 303 "...info: timeslice diff between lowest & highest=%u%%", 303 304 diff)); … … 315 316 if (rc != PJ_SUCCESS) 316 317 return rc; 317 318 318 319 rc = simple_thread("suspended thread test", PJ_THREAD_SUSPENDED); 319 320 if (rc != PJ_SUCCESS) 320 321 return rc; 321 322 322 323 rc = timeslice_test(); 323 324 if (rc != PJ_SUCCESS) … … 329 330 #else 330 331 /* To prevent warning about "translation unit is empty" 331 * when this test is disabled. 332 * when this test is disabled. 332 333 */ 333 334 int dummy_thread_test; -
pjproject/trunk/pjmedia/src/pjmedia-audiodev/bb10_dev.c
r4707 r4728 501 501 if (status.status == SND_PCM_STATUS_READY || 502 502 status.status == SND_PCM_STATUS_UNDERRUN || 503 status.status == SND_PCM_STATUS_ERROR ) 503 status.status == SND_PCM_STATUS_ERROR ) 504 504 { 505 505 if (snd_pcm_plugin_prepare (stream->pb_pcm, … … 778 778 TRACE_((THIS_FILE, "bb10_open_playback: pb_frames = %d clock = %d", 779 779 stream->pb_frames, param->clock_rate)); 780 780 781 781 return PJ_SUCCESS; 782 782 } … … 864 864 865 865 frame_size = setup.buf.block.frag_size; 866 PJ_UNUSED_ARG(frame_size); /* Warning about unused var */ 866 867 867 868 /* Set clock rate */ … … 962 963 963 964 964 /* 965 /* 965 966 * API: get running parameter 966 967 * based on ALSA template … … 981 982 /* 982 983 * API: get capability 983 * based on ALSA template 984 * based on ALSA template 984 985 */ 985 986 static pj_status_t bb10_stream_get_cap(pjmedia_aud_stream *s, … … 1043 1044 ret = bb10_initialize_playback_ctrl(stream,true); 1044 1045 } else { 1045 ret = bb10_initialize_playback_ctrl(stream,false); 1046 ret = bb10_initialize_playback_ctrl(stream,false); 1046 1047 } 1047 1048 return ret; -
pjproject/trunk/pjmedia/src/pjmedia/echo_suppress.c
r4713 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include <pjmedia/types.h> … … 78 78 #if 0 79 79 # define TRACE_(expr) PJ_LOG(5,expr) 80 81 static const char *state_names[] = 82 { 83 "Null", 84 "local talking", 85 "remote silent", 86 "doubletalk", 87 "remote talking" 88 }; 89 80 90 #else 81 91 # define TRACE_(expr) … … 126 136 } talk_state_t; 127 137 128 static const char *state_names[] =129 {130 "Null",131 "local talking",132 "remote silent",133 "doubletalk",134 "remote talking"135 };136 137 138 138 139 /* Description: 139 140 140 141 The echo suppressor tries to find the position of echoed signal by looking 141 at the correlation between signal played to the speaker (played signal) 142 at the correlation between signal played to the speaker (played signal) 142 143 and the signal captured from the microphone (recorded signal). 143 144 144 To do this, it first divides the frames (from mic and speaker) into 145 To do this, it first divides the frames (from mic and speaker) into 145 146 segments, calculate the audio level of the segment, and save the level 146 147 information in the playback and record history (play_hist and rec_hist … … 151 152 152 153 The record history size is as large as the template size (tmpl_cnt), since 153 we will use the record history as the template to find the best matching 154 we will use the record history as the template to find the best matching 154 155 position in the playback history. 155 156 … … 188 189 similar) the signal is. The correlation value is done over the template 189 190 duration. 190 - the gain scaling factor, that is the ratio between mic signal and 191 - the gain scaling factor, that is the ratio between mic signal and 191 192 speaker signal. The ES calculates both the minimum and average ratios. 192 193 … … 210 211 Processing: 211 212 212 Once learning is done, the ES will change the level of the mic signal 213 Once learning is done, the ES will change the level of the mic signal 213 214 depending on the state of the conversation and according to the ratio that 214 215 has been found in the learning phase above. … … 264 265 265 266 /* 266 * Create. 267 * Create. 267 268 */ 268 269 PJ_DEF(pj_status_t) echo_supp_create( pj_pool_t *pool, … … 293 294 ec->play_hist_cnt = (pj_uint16_t)(ec->tail_cnt+ec->templ_cnt); 294 295 295 ec->max_calc = (pj_uint16_t)(MAX_CALC_DURATION_SEC * clock_rate / 296 ec->max_calc = (pj_uint16_t)(MAX_CALC_DURATION_SEC * clock_rate / 296 297 ec->samples_per_segment); 297 298 298 ec->rec_hist = (pj_uint16_t*) 299 ec->rec_hist = (pj_uint16_t*) 299 300 pj_pool_alloc(pool, ec->templ_cnt * 300 301 sizeof(ec->rec_hist[0])); 301 302 302 303 /* Note: play history has twice number of elements */ 303 ec->play_hist = (pj_uint16_t*) 304 ec->play_hist = (pj_uint16_t*) 304 305 pj_pool_alloc(pool, ec->play_hist_cnt * 305 306 sizeof(ec->play_hist[0])); 306 307 307 308 ec->corr_sum = (float*) 308 pj_pool_alloc(pool, ec->tail_cnt * 309 pj_pool_alloc(pool, ec->tail_cnt * 309 310 sizeof(ec->corr_sum[0])); 310 311 ec->tmp_corr = (float*) 311 pj_pool_alloc(pool, ec->tail_cnt * 312 pj_pool_alloc(pool, ec->tail_cnt * 312 313 sizeof(ec->tmp_corr[0])); 313 314 ec->min_factor = (float*) 314 pj_pool_alloc(pool, ec->tail_cnt * 315 pj_pool_alloc(pool, ec->tail_cnt * 315 316 sizeof(ec->min_factor[0])); 316 317 ec->avg_factor = (float*) 317 pj_pool_alloc(pool, ec->tail_cnt * 318 pj_pool_alloc(pool, ec->tail_cnt * 318 319 sizeof(ec->avg_factor[0])); 319 320 ec->tmp_factor = (float*) 320 pj_pool_alloc(pool, ec->tail_cnt * 321 pj_pool_alloc(pool, ec->tail_cnt * 321 322 sizeof(ec->tmp_factor[0])); 322 323 echo_supp_reset(ec); … … 328 329 329 330 /* 330 * Destroy. 331 * Destroy. 331 332 */ 332 333 PJ_DEF(pj_status_t) echo_supp_destroy(void *state) … … 394 395 395 396 /* Set state */ 396 static void echo_supp_set_state(echo_supp *ec, talk_state_t state, 397 static void echo_supp_set_state(echo_supp *ec, talk_state_t state, 397 398 unsigned level) 398 399 { … … 400 401 401 402 if (state != ec->talk_state) { 402 TRACE_((THIS_FILE, "[%03d.%03d] %s --> %s, level=%u", 403 (ec->update_cnt * SEGMENT_PTIME / 1000), 403 TRACE_((THIS_FILE, "[%03d.%03d] %s --> %s, level=%u", 404 (ec->update_cnt * SEGMENT_PTIME / 1000), 404 405 ((ec->update_cnt * SEGMENT_PTIME) % 1000), 405 406 state_names[ec->talk_state], … … 470 471 } else { 471 472 /* Update from previous calculation */ 472 ec->sum_rec_level = ec->sum_rec_level - old_rec_frm_level + 473 ec->sum_rec_level = ec->sum_rec_level - old_rec_frm_level + 473 474 ec->rec_hist[ec->templ_cnt-1]; 474 ec->rec_corr = ec->rec_corr - ((float)ec->rec_hist[0] / 475 ec->rec_corr = ec->rec_corr - ((float)ec->rec_hist[0] / 475 476 old_rec_frm_level) + 476 477 ((float)ec->rec_hist[ec->templ_cnt-1] / … … 483 484 * to detect echo. 484 485 */ 485 /* 486 * First phase: do full calculation for the first position 486 /* 487 * First phase: do full calculation for the first position 487 488 */ 488 489 if (ec->sum_play_level0 == 0) { … … 501 502 } else { 502 503 /* Update from previous calculation */ 503 ec->sum_play_level0 = ec->sum_play_level0 - old_play_frm_level + 504 ec->sum_play_level0 = ec->sum_play_level0 - old_play_frm_level + 504 505 ec->play_hist[ec->templ_cnt-1]; 505 ec->play_corr0 = ec->play_corr0 - ((float)ec->play_hist[0] / 506 ec->play_corr0 = ec->play_corr0 - ((float)ec->play_hist[0] / 506 507 old_play_frm_level) + 507 508 ((float)ec->play_hist[ec->templ_cnt-1] / … … 585 586 if (ec->tmp_factor[i] < ec->min_factor[i]) 586 587 ec->min_factor[i] = ec->tmp_factor[i]; 587 ec->avg_factor[i] = ((ec->avg_factor[i] * ec->tail_cnt) + 588 ec->avg_factor[i] = ((ec->avg_factor[i] * ec->tail_cnt) + 588 589 ec->tmp_factor[i]) / 589 590 (ec->tail_cnt + 1); … … 610 611 iavg = (int)(ec->avg_factor[ec->tail_index] * 1000); 611 612 612 PJ_LOG(4,(THIS_FILE, 613 PJ_LOG(4,(THIS_FILE, 613 614 "Echo suppressor updated at t=%03d.%03ds, echo tail=%d msec" 614 615 ", factor min/avg=%d.%03d/%d.%03d", … … 634 635 iavg = (int)(ec->avg_factor[ec->tail_index] * 1000); 635 636 636 PJ_LOG(4,(THIS_FILE, 637 PJ_LOG(4,(THIS_FILE, 637 638 "Echo suppressor learning done at t=%03d.%03ds, tail=%d ms" 638 639 ", factor min/avg=%d.%03d/%d.%03d", … … 647 648 648 649 /* Amplify frame */ 649 static void amplify_frame(pj_int16_t *frm, unsigned length, 650 static void amplify_frame(pj_int16_t *frm, unsigned length, 650 651 pj_ufloat_t factor) 651 652 { … … 657 658 } 658 659 659 /* 660 /* 660 661 * Perform echo cancellation. 661 662 */ … … 710 711 * if remote user is currently talking 711 712 */ 712 for (i=ec->play_hist_cnt -lookup_cnt -tail_cnt; 713 i<ec->play_hist_cnt-tail_cnt; ++i) 713 for (i=ec->play_hist_cnt -lookup_cnt -tail_cnt; 714 i<ec->play_hist_cnt-tail_cnt; ++i) 714 715 { 715 716 if (ec->play_hist[i] > play_level) … … 733 734 } else { 734 735 /* Speaker is active, but we've picked up large signal in 735 * the microphone. Assume that this is an echo, so bring 736 * the microphone. Assume that this is an echo, so bring 736 737 * the level down to minimum too. 737 738 */ … … 763 764 764 765 /* Amplify frame */ 765 amplify_frame(rec_frm, ec->samples_per_frame, 766 amplify_frame(rec_frm, ec->samples_per_frame, 766 767 pj_ufloat_from_float(factor)); 767 768 ec->last_factor = factor; … … 775 776 776 777 /* Accumulate average echo residue to see the ES effectiveness */ 777 ec->residue = ((ec->residue * ec->running_cnt) + level) / 778 ec->residue = ((ec->residue * ec->running_cnt) + level) / 778 779 (ec->running_cnt + 1); 779 780 -
pjproject/trunk/pjmedia/src/pjmedia/jbuf.c
r4537 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 /* … … 36 36 #define INVALID_OFFSET -9999 37 37 38 /* Maximum burst length, whenever an operation is bursting longer than 38 /* Maximum burst length, whenever an operation is bursting longer than 39 39 * this value, JB will assume that the opposite operation was idle. 40 40 */ … … 47 47 48 48 49 /* Minimal difference between JB size and 2*burst-level to perform 50 * JB shrinking in static discard algorithm. 49 /* Minimal difference between JB size and 2*burst-level to perform 50 * JB shrinking in static discard algorithm. 51 51 */ 52 52 #define STA_DISC_SAFE_SHRINKING_DIFF 1 … … 68 68 pj_uint32_t *bit_info; /**< frame bit info array */ 69 69 pj_uint32_t *ts; /**< timestamp array */ 70 70 71 71 /* States */ 72 72 unsigned head; /**< index of head, pointed frame 73 73 will be returned by next GET */ 74 unsigned size; /**< current size of framelist, 74 unsigned size; /**< current size of framelist, 75 75 including discarded frames. */ 76 unsigned discarded_num; /**< current number of discarded 76 unsigned discarded_num; /**< current number of discarded 77 77 frames. */ 78 78 int origin; /**< original index of flist_head */ … … 92 92 pj_size_t jb_frame_size; /**< frame size */ 93 93 unsigned jb_frame_ptime; /**< frame duration. */ 94 pj_size_t jb_max_count; /**< capacity of jitter buffer, 94 pj_size_t jb_max_count; /**< capacity of jitter buffer, 95 95 in frames */ 96 96 int jb_init_prefetch; /**< Initial prefetch */ … … 98 98 int jb_max_prefetch; /**< Maximum allowable prefetch */ 99 99 int jb_max_burst; /**< maximum possible burst, whenever 100 burst exceeds this value, it 101 won't be included in level 100 burst exceeds this value, it 101 won't be included in level 102 102 calculation */ 103 103 int jb_min_shrink_gap; /**< How often can we shrink */ … … 108 108 109 109 /* States */ 110 int jb_level; /**< delay between source & 111 destination (calculated according 112 of the number of burst get/put 110 int jb_level; /**< delay between source & 111 destination (calculated according 112 of the number of burst get/put 113 113 operations) */ 114 int jb_max_hist_level; /**< max level during the last level 114 int jb_max_hist_level; /**< max level during the last level 115 115 calculations */ 116 int jb_stable_hist; /**< num of times the delay has been 116 int jb_stable_hist; /**< num of times the delay has been 117 117 lower then the prefetch num */ 118 int jb_last_op; /**< last operation executed 118 int jb_last_op; /**< last operation executed 119 119 (put/get) */ 120 120 int jb_eff_level; /**< effective burst level */ 121 int jb_prefetch; /**< no. of frame to insert before 122 removing some (at the beginning 123 of the framelist->content 121 int jb_prefetch; /**< no. of frame to insert before 122 removing some (at the beginning 123 of the framelist->content 124 124 operation), the value may be 125 125 continuously updated based on 126 126 current frame burst level. */ 127 127 pj_bool_t jb_prefetching; /**< flag if jbuf is prefetching. */ 128 int jb_status; /**< status is 'init' until the first 128 int jb_status; /**< status is 'init' until the first 129 129 'put' operation */ 130 int jb_init_cycle_cnt; /**< status is 'init' until the first 130 int jb_init_cycle_cnt; /**< status is 'init' until the first 131 131 'put' operation */ 132 132 … … 137 137 138 138 /* Statistics */ 139 pj_math_stat jb_delay; /**< Delay statistics of jitter buffer 139 pj_math_stat jb_delay; /**< Delay statistics of jitter buffer 140 140 (in ms) */ 141 141 pj_math_stat jb_burst; /**< Burst statistics (in frames) */ … … 165 165 166 166 167 /* Enabling this would log the jitter buffer state about once per 167 /* Enabling this would log the jitter buffer state about once per 168 168 * second. 169 169 */ … … 181 181 jb_framelist_t *framelist, 182 182 unsigned frame_size, 183 unsigned max_count) 183 unsigned max_count) 184 184 { 185 185 PJ_ASSERT_RETURN(pool && framelist, PJ_EINVAL); … … 189 189 framelist->frame_size = frame_size; 190 190 framelist->max_count = max_count; 191 framelist->content = (char*) 191 framelist->content = (char*) 192 192 pj_pool_alloc(pool, 193 framelist->frame_size* 193 framelist->frame_size* 194 194 framelist->max_count); 195 195 framelist->frame_type = (int*) 196 pj_pool_alloc(pool, 196 pj_pool_alloc(pool, 197 197 sizeof(framelist->frame_type[0])* 198 198 framelist->max_count); 199 199 framelist->content_len = (pj_size_t*) 200 pj_pool_alloc(pool, 200 pj_pool_alloc(pool, 201 201 sizeof(framelist->content_len[0])* 202 202 framelist->max_count); 203 203 framelist->bit_info = (pj_uint32_t*) 204 pj_pool_alloc(pool, 204 pj_pool_alloc(pool, 205 205 sizeof(framelist->bit_info[0])* 206 206 framelist->max_count); 207 207 framelist->ts = (pj_uint32_t*) 208 pj_pool_alloc(pool, 208 pj_pool_alloc(pool, 209 209 sizeof(framelist->ts[0])* 210 210 framelist->max_count); … … 214 214 } 215 215 216 static pj_status_t jb_framelist_destroy(jb_framelist_t *framelist) 216 static pj_status_t jb_framelist_destroy(jb_framelist_t *framelist) 217 217 { 218 218 PJ_UNUSED_ARG(framelist); … … 220 220 } 221 221 222 static pj_status_t jb_framelist_reset(jb_framelist_t *framelist) 222 static pj_status_t jb_framelist_reset(jb_framelist_t *framelist) 223 223 { 224 224 framelist->head = 0; … … 228 228 229 229 230 //pj_bzero(framelist->content, 231 // framelist->frame_size * 230 //pj_bzero(framelist->content, 231 // framelist->frame_size * 232 232 // framelist->max_count); 233 233 234 234 pj_memset(framelist->frame_type, 235 235 PJMEDIA_JB_MISSING_FRAME, 236 sizeof(framelist->frame_type[0]) * 236 sizeof(framelist->frame_type[0]) * 237 237 framelist->max_count); 238 238 239 pj_bzero(framelist->content_len, 240 sizeof(framelist->content_len[0]) * 239 pj_bzero(framelist->content_len, 240 sizeof(framelist->content_len[0]) * 241 241 framelist->max_count); 242 242 243 243 //pj_bzero(framelist->bit_info, 244 // sizeof(framelist->bit_info[0]) * 244 // sizeof(framelist->bit_info[0]) * 245 245 // framelist->max_count); 246 246 … … 249 249 250 250 251 static unsigned jb_framelist_size(const jb_framelist_t *framelist) 251 static unsigned jb_framelist_size(const jb_framelist_t *framelist) 252 252 { 253 253 return framelist->size; … … 255 255 256 256 257 static unsigned jb_framelist_eff_size(const jb_framelist_t *framelist) 257 static unsigned jb_framelist_eff_size(const jb_framelist_t *framelist) 258 258 { 259 259 return (framelist->size - framelist->discarded_num); 260 260 } 261 261 262 static int jb_framelist_origin(const jb_framelist_t *framelist) 262 static int jb_framelist_origin(const jb_framelist_t *framelist) 263 263 { 264 264 return framelist->origin; … … 271 271 pj_uint32_t *bit_info, 272 272 pj_uint32_t *ts, 273 int *seq) 273 int *seq) 274 274 { 275 275 if (framelist->size) { … … 296 296 *bit_info = 0; 297 297 } else { 298 pj_memcpy(frame, 299 framelist->content + 298 pj_memcpy(frame, 299 framelist->content + 300 300 framelist->head * framelist->frame_size, 301 301 framelist->frame_size); 302 *p_type = (pjmedia_jb_frame_type) 302 *p_type = (pjmedia_jb_frame_type) 303 303 framelist->frame_type[framelist->head]; 304 304 if (size) … … 312 312 *seq = framelist->origin; 313 313 314 //pj_bzero(framelist->content + 314 //pj_bzero(framelist->content + 315 315 // framelist->head * framelist->frame_size, 316 316 // framelist->frame_size); … … 323 323 framelist->head = (framelist->head + 1) % framelist->max_count; 324 324 framelist->size--; 325 325 326 326 return PJ_TRUE; 327 327 } … … 342 342 pj_uint32_t *bit_info, 343 343 pj_uint32_t *ts, 344 int *seq) 344 int *seq) 345 345 { 346 346 unsigned pos, idx; … … 367 367 *frame = framelist->content + pos*framelist->frame_size; 368 368 if (type) 369 *type = (pjmedia_jb_frame_type) 369 *type = (pjmedia_jb_frame_type) 370 370 framelist->frame_type[pos]; 371 371 if (size) … … 384 384 /* Remove oldest frames as many as param 'count' */ 385 385 static unsigned jb_framelist_remove_head(jb_framelist_t *framelist, 386 unsigned count) 387 { 388 if (count > framelist->size) 386 unsigned count) 387 { 388 if (count > framelist->size) 389 389 count = framelist->size; 390 390 … … 410 410 } 411 411 412 //pj_bzero(framelist->content + 412 //pj_bzero(framelist->content + 413 413 // framelist->head * framelist->frame_size, 414 414 // step1*framelist->frame_size); … … 440 440 framelist->size -= count; 441 441 } 442 442 443 443 return count; 444 444 } … … 549 549 550 550 551 PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool, 551 PJ_DEF(pj_status_t) pjmedia_jbuf_create(pj_pool_t *pool, 552 552 const pj_str_t *name, 553 unsigned frame_size, 553 unsigned frame_size, 554 554 unsigned ptime, 555 555 unsigned max_count, … … 597 597 PJ_ASSERT_RETURN(prefetch <= jb->jb_max_count, PJ_EINVAL); 598 598 599 jb->jb_min_prefetch = jb->jb_max_prefetch = 599 jb->jb_min_prefetch = jb->jb_max_prefetch = 600 600 jb->jb_prefetch = jb->jb_init_prefetch = prefetch; 601 601 … … 676 676 " burst (min/max/avg/dev)=%d/%d/%d/%d frames\n" 677 677 " lost=%d discard=%d empty=%d", 678 jb_framelist_size(&jb->jb_framelist), 679 jb_framelist_eff_size(&jb->jb_framelist), 678 jb_framelist_size(&jb->jb_framelist), 679 jb_framelist_eff_size(&jb->jb_framelist), 680 680 jb->jb_prefetch, jb->jb_eff_level, 681 jb->jb_delay.min, jb->jb_delay.max, jb->jb_delay.mean, 681 jb->jb_delay.min, jb->jb_delay.max, jb->jb_delay.mean, 682 682 pj_math_stat_get_stddev(&jb->jb_delay), 683 jb->jb_burst.min, jb->jb_burst.max, jb->jb_burst.mean, 683 jb->jb_burst.min, jb->jb_burst.max, jb->jb_burst.mean, 684 684 pj_math_stat_get_stddev(&jb->jb_burst), 685 685 jb->jb_lost, jb->jb_discard, jb->jb_empty)); … … 705 705 706 706 enum { STABLE_HISTORY_LIMIT = 20 }; 707 707 708 708 jb->jb_stable_hist++; 709 710 /* Only update the effective level (and prefetch) if 'stable' 709 710 /* Only update the effective level (and prefetch) if 'stable' 711 711 * condition is reached (not just short time impulse) 712 712 */ 713 713 if (jb->jb_stable_hist > STABLE_HISTORY_LIMIT) { 714 714 715 715 diff = (jb->jb_eff_level - jb->jb_max_hist_level) / 3; 716 716 … … 724 724 if (jb->jb_init_prefetch) { 725 725 jb->jb_prefetch = jb->jb_eff_level; 726 if (jb->jb_prefetch < jb->jb_min_prefetch) 726 if (jb->jb_prefetch < jb->jb_min_prefetch) 727 727 jb->jb_prefetch = jb->jb_min_prefetch; 728 728 if (jb->jb_prefetch > jb->jb_max_prefetch) … … 736 736 TRACE__((jb->jb_name.ptr,"jb updated(1), lvl=%d pre=%d, size=%d", 737 737 jb->jb_eff_level, jb->jb_prefetch, cur_size)); 738 PJ_UNUSED_ARG(cur_size); /* Warning about unused var */ 738 739 } 739 740 } … … 759 760 //jb->jb_max_hist_level = 0; 760 761 761 TRACE__((jb->jb_name.ptr,"jb updated(2), lvl=%d pre=%d, size=%d", 762 TRACE__((jb->jb_name.ptr,"jb updated(2), lvl=%d pre=%d, size=%d", 762 763 jb->jb_eff_level, jb->jb_prefetch, cur_size)); 763 764 } … … 778 779 * 779 780 * Moreover, normally drift level is quite low, so JB shouldn't need 780 * to shrink aggresively, it will shrink maximum one frame per 781 * PJMEDIA_JBUF_DISC_MIN_GAP ms. Theoritically, JB may handle drift level 781 * to shrink aggresively, it will shrink maximum one frame per 782 * PJMEDIA_JBUF_DISC_MIN_GAP ms. Theoritically, JB may handle drift level 782 783 * as much as = FRAME_PTIME/PJMEDIA_JBUF_DISC_MIN_GAP * 100% 783 784 * 784 * Whenever there is drift, where PUT > GET, this method will keep 785 * Whenever there is drift, where PUT > GET, this method will keep 785 786 * the latency (JB size) as much as twice of burst level. 786 787 */ … … 797 798 int seq_origin; 798 799 799 /* Check and adjust jb_discard_ref, in case there was 800 * seq restart 800 /* Check and adjust jb_discard_ref, in case there was 801 * seq restart 801 802 */ 802 803 seq_origin = jb_framelist_origin(&jb->jb_framelist); … … 814 815 jb->jb_discard += diff; 815 816 816 TRACE__((jb->jb_name.ptr, 817 TRACE__((jb->jb_name.ptr, 817 818 "JB shrinking %d frame(s), cur size=%d", diff, 818 819 jb_framelist_eff_size(&jb->jb_framelist))); … … 846 847 T = PJMEDIA_JBUF_PRO_DISC_T2; 847 848 else 848 T = PJMEDIA_JBUF_PRO_DISC_T1 + 849 T = PJMEDIA_JBUF_PRO_DISC_T1 + 849 850 (PJMEDIA_JBUF_PRO_DISC_T2 - PJMEDIA_JBUF_PRO_DISC_T1) * 850 851 (burst_level - PJMEDIA_JBUF_PRO_DISC_MIN_BURST) / … … 874 875 if (last_seq >= (jb->jb_discard_ref + (int)jb->jb_discard_dist)) { 875 876 int discard_seq; 876 877 877 878 discard_seq = jb->jb_discard_ref + jb->jb_discard_dist; 878 879 if (discard_seq < jb_framelist_origin(&jb->jb_framelist)) … … 881 882 jb_framelist_discard(&jb->jb_framelist, discard_seq); 882 883 883 TRACE__((jb->jb_name.ptr, 884 TRACE__((jb->jb_name.ptr, 884 885 "Discard #%d: ref=#%d dist=%d orig=%d size=%d/%d " 885 886 "burst=%d/%d", … … 897 898 } 898 899 } 899 900 900 901 901 902 PJ_INLINE(void) jbuf_update(pjmedia_jbuf *jb, int oper) … … 905 906 906 907 if (jb->jb_status == JB_STATUS_INITIALIZING) { 907 /* Switch status 'initializing' -> 'processing' after some OP 908 * switch cycles and current OP is GET (burst level is calculated 908 /* Switch status 'initializing' -> 'processing' after some OP 909 * switch cycles and current OP is GET (burst level is calculated 909 910 * based on PUT burst), so burst calculation is guaranted to be 910 911 * performed right after the status switching. … … 922 923 } 923 924 924 /* Perform jitter calculation based on PUT burst-level only, since 925 /* Perform jitter calculation based on PUT burst-level only, since 925 926 * GET burst-level may not be accurate, e.g: when VAD is active. 926 927 * Note that when burst-level is too big, i.e: exceeds jb_max_burst, 927 * the GET op may be idle, in this case, we better skip the jitter 928 * the GET op may be idle, in this case, we better skip the jitter 928 929 * calculation. 929 930 */ … … 940 941 } 941 942 942 PJ_DEF(void) pjmedia_jbuf_put_frame( pjmedia_jbuf *jb, 943 const void *frame, 944 pj_size_t frame_size, 943 PJ_DEF(void) pjmedia_jbuf_put_frame( pjmedia_jbuf *jb, 944 const void *frame, 945 pj_size_t frame_size, 945 946 int frame_seq) 946 947 { … … 948 949 } 949 950 950 PJ_DEF(void) pjmedia_jbuf_put_frame2(pjmedia_jbuf *jb, 951 const void *frame, 952 pj_size_t frame_size, 951 PJ_DEF(void) pjmedia_jbuf_put_frame2(pjmedia_jbuf *jb, 952 const void *frame, 953 pj_size_t frame_size, 953 954 pj_uint32_t bit_info, 954 955 int frame_seq, 955 956 pj_bool_t *discarded) 956 957 { 957 pjmedia_jbuf_put_frame3(jb, frame, frame_size, bit_info, frame_seq, 0, 958 pjmedia_jbuf_put_frame3(jb, frame, frame_size, bit_info, frame_seq, 0, 958 959 discarded); 959 960 } 960 961 961 PJ_DEF(void) pjmedia_jbuf_put_frame3(pjmedia_jbuf *jb, 962 const void *frame, 963 pj_size_t frame_size, 962 PJ_DEF(void) pjmedia_jbuf_put_frame3(pjmedia_jbuf *jb, 963 const void *frame, 964 pj_size_t frame_size, 964 965 pj_uint32_t bit_info, 965 966 int frame_seq, … … 978 979 (unsigned)min_frame_size, bit_info, ts, 979 980 PJMEDIA_JB_NORMAL_FRAME); 980 981 981 982 /* Jitter buffer is full, remove some older frames */ 982 983 while (status == PJ_ETOOMANY) { … … 1010 1011 if (status == PJ_SUCCESS) { 1011 1012 if (jb->jb_prefetching) { 1012 TRACE__((jb->jb_name.ptr, "PUT prefetch_cnt=%d/%d", 1013 TRACE__((jb->jb_name.ptr, "PUT prefetch_cnt=%d/%d", 1013 1014 new_size, jb->jb_prefetch)); 1014 1015 if (new_size >= jb->jb_prefetch) … … 1024 1025 * Get frame from jitter buffer. 1025 1026 */ 1026 PJ_DEF(void) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb, 1027 void *frame, 1027 PJ_DEF(void) pjmedia_jbuf_get_frame( pjmedia_jbuf *jb, 1028 void *frame, 1028 1029 char *p_frame_type) 1029 1030 { … … 1035 1036 * Get frame from jitter buffer. 1036 1037 */ 1037 PJ_DEF(void) pjmedia_jbuf_get_frame2(pjmedia_jbuf *jb, 1038 void *frame, 1038 PJ_DEF(void) pjmedia_jbuf_get_frame2(pjmedia_jbuf *jb, 1039 void *frame, 1039 1040 pj_size_t *size, 1040 1041 char *p_frame_type, … … 1048 1049 * Get frame from jitter buffer. 1049 1050 */ 1050 PJ_DEF(void) pjmedia_jbuf_get_frame3(pjmedia_jbuf *jb, 1051 void *frame, 1051 PJ_DEF(void) pjmedia_jbuf_get_frame3(pjmedia_jbuf *jb, 1052 void *frame, 1052 1053 pj_size_t *size, 1053 1054 char *p_frame_type, … … 1078 1079 1079 1080 /* Try to retrieve a frame from frame list */ 1080 res = jb_framelist_get(&jb->jb_framelist, frame, size, &ftype, 1081 res = jb_framelist_get(&jb->jb_framelist, frame, size, &ftype, 1081 1082 bit_info, ts, seq); 1082 1083 if (res) { … … 1097 1098 /* We've just retrieved one frame, so add one to cur_size */ 1098 1099 cur_size = jb_framelist_eff_size(&jb->jb_framelist) + 1; 1099 pj_math_stat_update(&jb->jb_delay, 1100 pj_math_stat_update(&jb->jb_delay, 1100 1101 cur_size*jb->jb_frame_ptime); 1101 1102 } … … 1129 1130 state->min_prefetch = jb->jb_min_prefetch; 1130 1131 state->max_prefetch = jb->jb_max_prefetch; 1131 1132 1132 1133 state->burst = jb->jb_eff_level; 1133 1134 state->prefetch = jb->jb_prefetch; 1134 1135 state->size = jb_framelist_eff_size(&jb->jb_framelist); 1135 1136 1136 1137 state->avg_delay = jb->jb_delay.mean; 1137 1138 state->min_delay = jb->jb_delay.min; 1138 1139 state->max_delay = jb->jb_delay.max; 1139 1140 state->dev_delay = pj_math_stat_get_stddev(&jb->jb_delay); 1140 1141 1141 1142 state->avg_burst = jb->jb_burst.mean; 1142 1143 state->empty = jb->jb_empty; … … 1150 1151 PJ_DEF(void) pjmedia_jbuf_peek_frame( pjmedia_jbuf *jb, 1151 1152 unsigned offset, 1152 const void **frame, 1153 pj_size_t *size, 1153 const void **frame, 1154 pj_size_t *size, 1154 1155 char *p_frm_type, 1155 1156 pj_uint32_t *bit_info, … … 1171 1172 1172 1173 1173 PJ_DEF(unsigned) pjmedia_jbuf_remove_frame(pjmedia_jbuf *jb, 1174 PJ_DEF(unsigned) pjmedia_jbuf_remove_frame(pjmedia_jbuf *jb, 1174 1175 unsigned frame_cnt) 1175 1176 { -
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r4613 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include <pjmedia/stream.h> … … 185 185 */ 186 186 pj_bool_t has_g722_mpeg_bug; 187 /**< Flag to specify whether 188 normalization process 187 /**< Flag to specify whether 188 normalization process 189 189 is needed */ 190 190 unsigned rtp_tx_ts_len_per_pkt; 191 191 /**< Normalized ts length per packet 192 transmitted according to 192 transmitted according to 193 193 'erroneous' definition */ 194 194 unsigned rtp_rx_ts_len_per_frame; 195 195 /**< Normalized ts length per frame 196 received according to 196 received according to 197 197 'erroneous' definition */ 198 198 unsigned rtp_rx_last_cnt;/**< Nb of frames in last pkt */ … … 203 203 204 204 #if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0) 205 pj_uint32_t rtcp_xr_last_tx; /**< RTCP XR tx time 205 pj_uint32_t rtcp_xr_last_tx; /**< RTCP XR tx time 206 206 in timestamp. */ 207 207 pj_uint32_t rtcp_xr_interval; /**< Interval, in timestamp. */ 208 pj_sockaddr rtcp_xr_dest; /**< Additional remote RTCP XR 209 dest. If sin_family is 208 pj_sockaddr rtcp_xr_dest; /**< Additional remote RTCP XR 209 dest. If sin_family is 210 210 zero, it will be ignored*/ 211 211 unsigned rtcp_xr_dest_len; /**< Length of RTCP XR dest … … 231 231 232 232 /* RFC 2833 digit */ 233 static const char digitmap[16] = { '0', '1', '2', '3', 234 '4', '5', '6', '7', 233 static const char digitmap[16] = { '0', '1', '2', '3', 234 '4', '5', '6', '7', 235 235 '8', '9', '*', '#', 236 236 'A', 'B', 'C', 'D'}; … … 285 285 } 286 286 287 PJ_INLINE(int) trace_jb_print_state(pjmedia_stream *stream, 287 PJ_INLINE(int) trace_jb_print_state(pjmedia_stream *stream, 288 288 char **buf, pj_ssize_t len) 289 289 { … … 460 460 461 461 #else 462 462 463 463 PJ_UNUSED_ARG(stream); 464 464 … … 498 498 samples_per_frame = stream->codec_param.info.frm_ptime * 499 499 stream->codec_param.info.clock_rate * 500 stream->codec_param.info.channel_cnt / 500 stream->codec_param.info.channel_cnt / 501 501 1000; 502 502 p_out_samp = (pj_int16_t*) frame->buf; 503 503 504 for (samples_count=0; samples_count < samples_required; 505 samples_count += samples_per_frame) 504 for (samples_count=0; samples_count < samples_required; 505 samples_count += samples_per_frame) 506 506 { 507 507 char frame_type; … … 518 518 519 519 if (frame_type == PJMEDIA_JB_MISSING_FRAME) { 520 520 521 521 /* Activate PLC */ 522 if (stream->codec->op->recover && 522 if (stream->codec->op->recover && 523 523 stream->codec_param.setting.plc && 524 stream->plc_cnt < stream->max_plc_cnt) 524 stream->plc_cnt < stream->max_plc_cnt) 525 525 { 526 526 pjmedia_frame frame_out; … … 561 561 /* Jitter buffer is empty. If this is the first "empty" state, 562 562 * activate PLC to smoothen the fade-out, otherwise zero 563 * the frame. 563 * the frame. 564 564 */ 565 565 //Using this "if" will only invoke PLC for the first packet … … 568 568 if (1) { 569 569 /* Activate PLC to smoothen the missing frame */ 570 if (stream->codec->op->recover && 570 if (stream->codec->op->recover && 571 571 stream->codec_param.setting.plc && 572 stream->plc_cnt < stream->max_plc_cnt) 572 stream->plc_cnt < stream->max_plc_cnt) 573 573 { 574 574 pjmedia_frame frame_out; … … 590 590 591 591 with_plc = ", plc invoked"; 592 } 592 } 593 593 } 594 594 … … 604 604 /* Report changing frame type event */ 605 605 pjmedia_jbuf_get_state(stream->jb, &jb_state); 606 PJ_LOG(5,(stream->port.info.name.ptr, 607 "Jitter buffer empty (prefetch=%d)%s", 606 PJ_LOG(5,(stream->port.info.name.ptr, 607 "Jitter buffer empty (prefetch=%d)%s", 608 608 jb_state.prefetch, with_plc)); 609 609 … … 623 623 624 624 /* Always activate PLC when it's available.. */ 625 if (stream->codec->op->recover && 625 if (stream->codec->op->recover && 626 626 stream->codec_param.setting.plc && 627 stream->plc_cnt < stream->max_plc_cnt) 627 stream->plc_cnt < stream->max_plc_cnt) 628 628 { 629 629 pjmedia_frame frame_out; … … 645 645 646 646 with_plc = ", plc invoked"; 647 } 647 } 648 648 649 649 if (samples_count < samples_required) { … … 658 658 /* Report changing frame type event */ 659 659 pjmedia_jbuf_get_state(stream->jb, &jb_state); 660 PJ_LOG(5,(stream->port.info.name.ptr, 661 "Jitter buffer is bufferring (prefetch=%d)%s", 660 PJ_LOG(5,(stream->port.info.name.ptr, 661 "Jitter buffer is bufferring (prefetch=%d)%s", 662 662 jb_state.prefetch, with_plc)); 663 663 … … 684 684 frame_out.size = frame->size - samples_count*BYTES_PER_SAMPLE; 685 685 status = pjmedia_codec_decode( stream->codec, &frame_in, 686 (unsigned)frame_out.size, 686 (unsigned)frame_out.size, 687 687 &frame_out); 688 688 if (status != 0) { 689 LOGERR_((port->info.name.ptr, "codec decode() error", 689 LOGERR_((port->info.name.ptr, "codec decode() error", 690 690 status)); 691 691 692 pjmedia_zero_samples(p_out_samp + samples_count, 692 pjmedia_zero_samples(p_out_samp + samples_count, 693 693 samples_per_frame); 694 694 } … … 696 696 if (stream->jb_last_frm != frame_type) { 697 697 /* Report changing frame type event */ 698 PJ_LOG(5,(stream->port.info.name.ptr, 698 PJ_LOG(5,(stream->port.info.name.ptr, 699 699 "Jitter buffer starts returning normal frames " 700 700 "(after %d empty/lost)", … … 753 753 samples_per_frame = stream->codec_param.info.frm_ptime * 754 754 stream->codec_param.info.clock_rate * 755 stream->codec_param.info.channel_cnt / 755 stream->codec_param.info.channel_cnt / 756 756 1000; 757 757 … … 774 774 trace_jb_get(stream, frame_type, frame_size); 775 775 #endif 776 776 777 777 /* Unlock jitter buffer mutex. */ 778 778 pj_mutex_unlock( stream->jb_mutex ); … … 791 791 0, frame); 792 792 if (status != PJ_SUCCESS) { 793 LOGERR_((port->info.name.ptr, "codec decode() error", 793 LOGERR_((port->info.name.ptr, "codec decode() error", 794 794 status)); 795 795 pjmedia_frame_ext_append_subframe(f, NULL, 0, … … 799 799 if (stream->jb_last_frm != frame_type) { 800 800 /* Report changing frame type event */ 801 PJ_LOG(5,(stream->port.info.name.ptr, 801 PJ_LOG(5,(stream->port.info.name.ptr, 802 802 "Jitter buffer starts returning normal frames " 803 803 "(after %d empty/lost)", … … 817 817 status = pjmedia_codec_recover(stream->codec, 0, frame); 818 818 } 819 819 820 820 /* No PLC or PLC failed */ 821 821 if (!stream->codec->op->recover || status != PJ_SUCCESS) { … … 840 840 /* Report changing frame type event */ 841 841 pjmedia_jbuf_get_state(stream->jb, &jb_state); 842 PJ_LOG(5,(stream->port.info.name.ptr, 843 "Jitter buffer empty (prefetch=%d)", 842 PJ_LOG(5,(stream->port.info.name.ptr, 843 "Jitter buffer empty (prefetch=%d)", 844 844 jb_state.prefetch)); 845 845 … … 859 859 /* Report changing frame type event */ 860 860 pjmedia_jbuf_get_state(stream->jb, &jb_state); 861 PJ_LOG(5,(stream->port.info.name.ptr, 861 PJ_LOG(5,(stream->port.info.name.ptr, 862 862 "Jitter buffer is bufferring (prefetch=%d)", 863 863 jb_state.prefetch)); … … 879 879 * Transmit DTMF 880 880 */ 881 static void create_dtmf_payload(pjmedia_stream *stream, 881 static void create_dtmf_payload(pjmedia_stream *stream, 882 882 struct pjmedia_frame *frame_out, 883 883 int forced_last, int *first, int *last) … … 885 885 pjmedia_rtp_dtmf_event *event; 886 886 struct dtmf *digit = &stream->tx_dtmf_buf[0]; 887 pj_uint32_t cur_ts;888 887 889 888 pj_assert(sizeof(pjmedia_rtp_dtmf_event) == 4); … … 892 891 893 892 event = (pjmedia_rtp_dtmf_event*) frame_out->buf; 894 cur_ts = pj_ntohl(stream->enc->rtp.out_hdr.ts);895 893 896 894 if (digit->duration == 0) { 897 PJ_LOG(5,(stream->port.info.name.ptr, "Sending DTMF digit id %c", 895 PJ_LOG(5,(stream->port.info.name.ptr, "Sending DTMF digit id %c", 898 896 digitmap[digit->event])); 899 897 *first = 1; … … 988 986 /* Update RTCP XR with current JB states */ 989 987 pjmedia_jbuf_get_state(stream->jb, &jb_state); 990 988 991 989 i = jb_state.avg_delay; 992 status = pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 990 status = pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 993 991 PJMEDIA_RTCP_XR_INFO_JB_NOM, i); 994 992 pj_assert(status == PJ_SUCCESS); 995 993 996 994 i = jb_state.max_delay; 997 status = pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 995 status = pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 998 996 PJMEDIA_RTCP_XR_INFO_JB_MAX, i); 999 997 pj_assert(status == PJ_SUCCESS); … … 1008 1006 /* Send the RTCP XR to third-party destination if specified */ 1009 1007 if (stream->rtcp_xr_dest_len) { 1010 pjmedia_transport_send_rtcp2(stream->transport, 1008 pjmedia_transport_send_rtcp2(stream->transport, 1011 1009 &stream->rtcp_xr_dest, 1012 stream->rtcp_xr_dest_len, 1010 stream->rtcp_xr_dest_len, 1013 1011 xr_pkt, xr_len); 1014 1012 } … … 1050 1048 static void check_tx_rtcp(pjmedia_stream *stream, pj_uint32_t timestamp) 1051 1049 { 1052 /* Note that timestamp may represent local or remote timestamp, 1050 /* Note that timestamp may represent local or remote timestamp, 1053 1051 * depending on whether this function is called from put_frame() 1054 1052 * or get_frame(). … … 1056 1054 1057 1055 if (stream->rtcp_last_tx == 0) { 1058 1056 1059 1057 stream->rtcp_last_tx = timestamp; 1060 1058 … … 1067 1065 if (stream->rtcp_xr_last_tx == 0) { 1068 1066 stream->rtcp_xr_last_tx = timestamp; 1069 } else if (timestamp - stream->rtcp_xr_last_tx >= 1067 } else if (timestamp - stream->rtcp_xr_last_tx >= 1070 1068 stream->rtcp_xr_interval) 1071 1069 { … … 1131 1129 1132 1130 /* How many samples are needed */ 1133 count = stream->codec_param.info.enc_ptime * 1131 count = stream->codec_param.info.enc_ptime * 1134 1132 PJMEDIA_PIA_SRATE(&stream->port.info) / 1000; 1135 1133 … … 1154 1152 * put_frame_imp() 1155 1153 */ 1156 static pj_status_t put_frame_imp( pjmedia_port *port, 1154 static pj_status_t put_frame_imp( pjmedia_port *port, 1157 1155 pjmedia_frame *frame ) 1158 1156 { … … 1175 1173 pj_uint32_t dtx_duration; 1176 1174 1177 dtx_duration = pj_timestamp_diff32(&stream->last_frm_ts_sent, 1175 dtx_duration = pj_timestamp_diff32(&stream->last_frm_ts_sent, 1178 1176 &frame->timestamp); 1179 1177 if (dtx_duration > … … 1194 1192 /* Number of samples in the frame */ 1195 1193 if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO) 1196 ts_len = ((unsigned)frame->size >> 1) / 1194 ts_len = ((unsigned)frame->size >> 1) / 1197 1195 stream->codec_param.info.channel_cnt; 1198 1196 else if (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED) … … 1206 1204 1207 1205 #if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0) 1208 /* Handle special case for audio codec with RTP timestamp inconsistence 1206 /* Handle special case for audio codec with RTP timestamp inconsistence 1209 1207 * e.g: G722, MPEG audio. 1210 1208 */ … … 1225 1223 1226 1224 1227 /* If we have DTMF digits in the queue, transmit the digits. 1225 /* If we have DTMF digits in the queue, transmit the digits. 1228 1226 * Otherwise encode the PCM buffer. 1229 1227 */ … … 1235 1233 /* Encapsulate into RTP packet. Note that: 1236 1234 * - RTP marker should be set on the beginning of a new event 1237 * - RTP timestamp is constant for the same packet. 1235 * - RTP timestamp is constant for the same packet. 1238 1236 */ 1239 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1240 stream->tx_event_pt, first, 1237 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1238 stream->tx_event_pt, first, 1241 1239 (int)frame_out.size, 1242 (first ? rtp_ts_len : 0), 1243 (const void**)&rtphdr, 1240 (first ? rtp_ts_len : 0), 1241 (const void**)&rtphdr, 1244 1242 &rtphdrlen); 1245 1243 1246 1244 if (last) { 1247 /* This is the last packet for the event. 1245 /* This is the last packet for the event. 1248 1246 * Increment the RTP timestamp of the RTP session, for next 1249 1247 * RTP packets. … … 1272 1270 stream->codec_param.info.channel_cnt * 1273 1271 stream->codec_param.info.clock_rate/1000 < 1274 PJ_ARRAY_SIZE(zero_frame)) 1272 PJ_ARRAY_SIZE(zero_frame)) 1275 1273 { 1276 1274 pjmedia_frame silence_frame; … … 1283 1281 silence_frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 1284 1282 silence_frame.timestamp.u32.lo = pj_ntohl(stream->enc->rtp.out_hdr.ts); 1285 1283 1286 1284 /* Encode! */ 1287 1285 status = pjmedia_codec_encode( stream->codec, &silence_frame, 1288 channel->out_pkt_size - 1286 channel->out_pkt_size - 1289 1287 sizeof(pjmedia_rtp_hdr), 1290 1288 &frame_out); 1291 1289 if (status != PJ_SUCCESS) { 1292 LOGERR_((stream->port.info.name.ptr, 1290 LOGERR_((stream->port.info.name.ptr, 1293 1291 "Codec encode() error", status)); 1294 1292 return status; … … 1296 1294 1297 1295 /* Encapsulate. */ 1298 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1299 channel->pt, 0, 1300 (int)frame_out.size, rtp_ts_len, 1301 (const void**)&rtphdr, 1296 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1297 channel->pt, 0, 1298 (int)frame_out.size, rtp_ts_len, 1299 (const void**)&rtphdr, 1302 1300 &rtphdrlen); 1303 1301 … … 1309 1307 { 1310 1308 /* Encode! */ 1311 status = pjmedia_codec_encode( stream->codec, frame, 1312 channel->out_pkt_size - 1309 status = pjmedia_codec_encode( stream->codec, frame, 1310 channel->out_pkt_size - 1313 1311 sizeof(pjmedia_rtp_hdr), 1314 1312 &frame_out); 1315 1313 if (status != PJ_SUCCESS) { 1316 LOGERR_((stream->port.info.name.ptr, 1314 LOGERR_((stream->port.info.name.ptr, 1317 1315 "Codec encode() error", status)); 1318 1316 return status; … … 1320 1318 1321 1319 /* Encapsulate. */ 1322 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1323 channel->pt, 0, 1324 (int)frame_out.size, rtp_ts_len, 1325 (const void**)&rtphdr, 1320 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1321 channel->pt, 0, 1322 (int)frame_out.size, rtp_ts_len, 1323 (const void**)&rtphdr, 1326 1324 &rtphdrlen); 1327 1325 … … 1329 1327 1330 1328 /* Just update RTP session's timestamp. */ 1331 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1332 0, 0, 1333 0, rtp_ts_len, 1334 (const void**)&rtphdr, 1329 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1330 0, 0, 1331 0, rtp_ts_len, 1332 (const void**)&rtphdr, 1335 1333 &rtphdrlen); 1336 1334 … … 1338 1336 1339 1337 if (status != PJ_SUCCESS) { 1340 LOGERR_((stream->port.info.name.ptr, 1338 LOGERR_((stream->port.info.name.ptr, 1341 1339 "RTP encode_rtp() error", status)); 1342 1340 return status; 1343 1341 } 1344 1342 1345 /* Check if now is the time to transmit RTCP SR/RR report. 1343 /* Check if now is the time to transmit RTCP SR/RR report. 1346 1344 * We only do this when stream direction is not "decoding only", because 1347 1345 * when it is, check_tx_rtcp() will be handled by get_frame(). … … 1414 1412 * RTP packet, and transmit to peer. 1415 1413 */ 1416 static pj_status_t put_frame( pjmedia_port *port, 1414 static pj_status_t put_frame( pjmedia_port *port, 1417 1415 pjmedia_frame *frame ) 1418 1416 { … … 1462 1460 */ 1463 1461 if (stream->vad_enabled != stream->codec_param.setting.vad && 1464 (stream->tx_duration - stream->ts_vad_disabled) > 1462 (stream->tx_duration - stream->ts_vad_disabled) > 1465 1463 PJMEDIA_PIA_SRATE(&stream->port.info) * 1466 1464 PJMEDIA_STREAM_VAD_SUSPEND_MSEC / 1000) … … 1479 1477 pj_status_t status = PJ_SUCCESS; 1480 1478 1481 /* Copy original frame to temporary frame since we need 1479 /* Copy original frame to temporary frame since we need 1482 1480 * to modify it. 1483 1481 */ … … 1546 1544 * Handle incoming DTMF digits. 1547 1545 */ 1548 static void handle_incoming_dtmf( pjmedia_stream *stream, 1546 static void handle_incoming_dtmf( pjmedia_stream *stream, 1549 1547 const void *payload, unsigned payloadlen) 1550 1548 { … … 1572 1570 /* Ignore unknown event. */ 1573 1571 if (event->event > 15) { 1574 PJ_LOG(5,(stream->port.info.name.ptr, 1572 PJ_LOG(5,(stream->port.info.name.ptr, 1575 1573 "Ignored RTP pkt with bad DTMF event %d", 1576 1574 event->event)); … … 1591 1589 if (stream->dtmf_cb) { 1592 1590 1593 stream->dtmf_cb(stream, stream->dtmf_cb_user_data, 1591 stream->dtmf_cb(stream, stream->dtmf_cb_user_data, 1594 1592 digitmap[event->event]); 1595 1593 … … 1601 1599 if (stream->rx_dtmf_count >= PJ_ARRAY_SIZE(stream->rx_dtmf_buf)) { 1602 1600 /* DTMF digits overflow. Discard the oldest digit. */ 1603 pj_array_erase(stream->rx_dtmf_buf, 1601 pj_array_erase(stream->rx_dtmf_buf, 1604 1602 sizeof(stream->rx_dtmf_buf[0]), 1605 1603 stream->rx_dtmf_count, 0); … … 1614 1612 /* 1615 1613 * This callback is called by stream transport on receipt of packets 1616 * in the RTP socket. 1617 */ 1618 static void on_rx_rtp( void *data, 1614 * in the RTP socket. 1615 */ 1616 static void on_rx_rtp( void *data, 1619 1617 void *pkt, 1620 1618 pj_ssize_t bytes_read) … … 1632 1630 /* Check for errors */ 1633 1631 if (bytes_read < 0) { 1634 LOGERR_((stream->port.info.name.ptr, "RTP recv() error", 1632 LOGERR_((stream->port.info.name.ptr, "RTP recv() error", 1635 1633 (pj_status_t)-bytes_read)); 1636 1634 return; … … 1660 1658 hdr->pt != stream->rx_event_pt); 1661 1659 if (seq_st.status.value) { 1662 TRC_ ((stream->port.info.name.ptr, 1660 TRC_ ((stream->port.info.name.ptr, 1663 1661 "RTP status: badpt=%d, badssrc=%d, dup=%d, " 1664 "outorder=%d, probation=%d, restart=%d", 1662 "outorder=%d, probation=%d, restart=%d", 1665 1663 seq_st.status.flag.badpt, 1666 1664 seq_st.status.flag.badssrc, … … 1737 1735 payloadlen, &ts, &count, frames); 1738 1736 if (status != PJ_SUCCESS) { 1739 LOGERR_((stream->port.info.name.ptr, 1740 "Codec parse() error", 1737 LOGERR_((stream->port.info.name.ptr, 1738 "Codec parse() error", 1741 1739 status)); 1742 1740 count = 0; … … 1746 1744 /* This code is used to learn the samples per frame value that is put 1747 1745 * by remote endpoint, for codecs with inconsistent clock rate such 1748 * as G.722 or MPEG audio. We need to learn the samples per frame 1746 * as G.722 or MPEG audio. We need to learn the samples per frame 1749 1747 * value as it is used as divider when inserting frames into the 1750 1748 * jitter buffer. … … 1752 1750 if (stream->has_g722_mpeg_bug) { 1753 1751 if (stream->rtp_rx_check_cnt) { 1754 /* Make sure the detection performed only on two consecutive 1752 /* Make sure the detection performed only on two consecutive 1755 1753 * packets with valid RTP sequence and no wrapped timestamp. 1756 1754 */ 1757 if (seq_st.diff == 1 && stream->rtp_rx_last_ts && 1758 ts.u64 > stream->rtp_rx_last_ts && 1755 if (seq_st.diff == 1 && stream->rtp_rx_last_ts && 1756 ts.u64 > stream->rtp_rx_last_ts && 1759 1757 stream->rtp_rx_last_cnt > 0) 1760 1758 { … … 1768 1766 1769 1767 /* Get remote frame timestamp span */ 1770 peer_frm_ts_diff = 1771 ((pj_uint32_t)ts.u64-stream->rtp_rx_last_ts) / 1768 peer_frm_ts_diff = 1769 ((pj_uint32_t)ts.u64-stream->rtp_rx_last_ts) / 1772 1770 stream->rtp_rx_last_cnt; 1773 1771 … … 1778 1776 */ 1779 1777 if (stream->codec_param.info.pt == PJMEDIA_RTP_PT_G722 && 1780 (peer_frm_ts_diff == frm_ts_span || 1778 (peer_frm_ts_diff == frm_ts_span || 1781 1779 peer_frm_ts_diff == (frm_ts_span>>1))) 1782 1780 { … … 1790 1788 if (--stream->rtp_rx_check_cnt == 0) { 1791 1789 PJ_LOG(4, (THIS_FILE, "G722 codec used, remote" 1792 " samples per frame detected = %d", 1790 " samples per frame detected = %d", 1793 1791 stream->rtp_rx_ts_len_per_frame)); 1794 1792 1795 1793 /* Reset jitter buffer once detection done */ 1796 1794 pjmedia_jbuf_reset(stream->jb); … … 1811 1809 1812 1810 } else { 1813 ts_span = stream->codec_param.info.frm_ptime * 1811 ts_span = stream->codec_param.info.frm_ptime * 1814 1812 stream->codec_param.info.clock_rate / 1815 1813 1000; 1816 1814 } 1817 1815 #else 1818 ts_span = stream->codec_param.info.frm_ptime * 1816 ts_span = stream->codec_param.info.frm_ptime * 1819 1817 stream->codec_param.info.clock_rate / 1820 1818 1000; … … 1842 1840 1843 1841 /* Check if now is the time to transmit RTCP SR/RR report. 1844 * We only do this when stream direction is "decoding only", 1842 * We only do this when stream direction is "decoding only", 1845 1843 * because otherwise check_tx_rtcp() will be handled by put_frame() 1846 1844 */ … … 1850 1848 1851 1849 if (status != 0) { 1852 LOGERR_((stream->port.info.name.ptr, "Jitter buffer put() error", 1850 LOGERR_((stream->port.info.name.ptr, "Jitter buffer put() error", 1853 1851 status)); 1854 1852 pkt_discarded = PJ_TRUE; … … 1880 1878 /* 1881 1879 * This callback is called by stream transport on receipt of packets 1882 * in the RTCP socket. 1880 * in the RTCP socket. 1883 1881 */ 1884 1882 static void on_rx_rtcp( void *data, 1885 void *pkt, 1883 void *pkt, 1886 1884 pj_ssize_t bytes_read) 1887 1885 { … … 1890 1888 /* Check for errors */ 1891 1889 if (bytes_read < 0) { 1892 LOGERR_((stream->port.info.name.ptr, "RTCP recv() error", 1890 LOGERR_((stream->port.info.name.ptr, "RTCP recv() error", 1893 1891 (pj_status_t)-bytes_read)); 1894 1892 return; … … 1911 1909 pjmedia_channel *channel; 1912 1910 pj_status_t status; 1913 1911 1914 1912 /* Allocate memory for channel descriptor */ 1915 1913 … … 1924 1922 channel->pt = pt; 1925 1923 1926 1924 1927 1925 /* Allocate buffer for outgoing packet. */ 1928 1926 1929 1927 if (param->type == PJMEDIA_TYPE_AUDIO) { 1930 channel->out_pkt_size = sizeof(pjmedia_rtp_hdr) + 1931 stream->codec_param.info.max_bps * 1932 PJMEDIA_MAX_FRAME_DURATION_MS / 1928 channel->out_pkt_size = sizeof(pjmedia_rtp_hdr) + 1929 stream->codec_param.info.max_bps * 1930 PJMEDIA_MAX_FRAME_DURATION_MS / 1933 1931 8 / 1000; 1934 1932 if (channel->out_pkt_size > PJMEDIA_MAX_MTU - … … 2078 2076 stream->codec_param = *info->param; 2079 2077 else { 2080 status = pjmedia_codec_mgr_get_default_param(stream->codec_mgr, 2081 &info->fmt, 2078 status = pjmedia_codec_mgr_get_default_param(stream->codec_mgr, 2079 &info->fmt, 2082 2080 &stream->codec_param); 2083 2081 if (status != PJ_SUCCESS) … … 2137 2135 /* If encoder and decoder's ptime are asymmetric, then we need to 2138 2136 * create buffer on the encoder side. This could happen for example 2139 * with iLBC 2137 * with iLBC 2140 2138 */ 2141 2139 if (stream->codec_param.info.enc_ptime!=0 && … … 2185 2183 stream->frame_size = stream->codec_param.info.max_rx_frame_size; 2186 2184 } else { 2187 stream->frame_size = stream->codec_param.info.max_bps * 2185 stream->frame_size = stream->codec_param.info.max_bps * 2188 2186 stream->codec_param.info.frm_ptime / 8 / 1000; 2189 2187 if ((stream->codec_param.info.max_bps * … … 2218 2216 /* Init jitter buffer parameters: */ 2219 2217 if (info->jb_max >= stream->codec_param.info.frm_ptime) 2220 jb_max = (info->jb_max + stream->codec_param.info.frm_ptime - 1) / 2218 jb_max = (info->jb_max + stream->codec_param.info.frm_ptime - 1) / 2221 2219 stream->codec_param.info.frm_ptime; 2222 2220 else … … 2243 2241 /* Create jitter buffer */ 2244 2242 status = pjmedia_jbuf_create(pool, &stream->port.info.name, 2245 stream->frame_size, 2243 stream->frame_size, 2246 2244 stream->codec_param.info.frm_ptime, 2247 2245 jb_max, &stream->jb); … … 2255 2253 /* Create decoder channel: */ 2256 2254 2257 status = create_channel( pool, stream, PJMEDIA_DIR_DECODING, 2255 status = create_channel( pool, stream, PJMEDIA_DIR_DECODING, 2258 2256 info->rx_pt, info, &stream->dec); 2259 2257 if (status != PJ_SUCCESS) … … 2263 2261 /* Create encoder channel: */ 2264 2262 2265 status = create_channel( pool, stream, PJMEDIA_DIR_ENCODING, 2263 status = create_channel( pool, stream, PJMEDIA_DIR_ENCODING, 2266 2264 info->tx_pt, info, &stream->enc); 2267 2265 if (status != PJ_SUCCESS) … … 2316 2314 2317 2315 /* Only attach transport when stream is ready. */ 2318 status = pjmedia_transport_attach(tp, stream, &info->rem_addr, 2319 &info->rem_rtcp, 2320 pj_sockaddr_get_len(&info->rem_addr), 2316 status = pjmedia_transport_attach(tp, stream, &info->rem_addr, 2317 &info->rem_rtcp, 2318 pj_sockaddr_get_len(&info->rem_addr), 2321 2319 &on_rx_rtp, &on_rx_rtcp); 2322 2320 if (status != PJ_SUCCESS) … … 2336 2334 stream->rtcp_xr_interval = info->rtcp_xr_interval; 2337 2335 else 2338 stream->rtcp_xr_interval = (PJMEDIA_RTCP_INTERVAL + 2339 (pj_rand() % 8000)) * 2336 stream->rtcp_xr_interval = (PJMEDIA_RTCP_INTERVAL + 2337 (pj_rand() % 8000)) * 2340 2338 info->fmt.clock_rate / 1000; 2341 2339 … … 2349 2347 /* jitter buffer adaptive info */ 2350 2348 i = PJMEDIA_RTCP_XR_JB_ADAPTIVE; 2351 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 2349 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 2352 2350 PJMEDIA_RTCP_XR_INFO_CONF_JBA, 2353 2351 i); … … 2355 2353 /* Jitter buffer aggressiveness info (estimated) */ 2356 2354 i = 7; 2357 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 2355 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 2358 2356 PJMEDIA_RTCP_XR_INFO_CONF_JBR, 2359 2357 i); … … 2361 2359 /* Jitter buffer absolute maximum delay */ 2362 2360 i = jb_max * stream->codec_param.info.frm_ptime; 2363 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 2361 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 2364 2362 PJMEDIA_RTCP_XR_INFO_JB_ABS_MAX, 2365 2363 i); … … 2374 2372 i = PJMEDIA_RTCP_XR_PLC_DIS; 2375 2373 #endif 2376 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 2374 pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session, 2377 2375 PJMEDIA_RTCP_XR_INFO_CONF_PLC, 2378 2376 i); … … 2396 2394 pj_ssize_t len; 2397 2395 2398 pj_ansi_snprintf(trace_name, sizeof(trace_name), 2396 pj_ansi_snprintf(trace_name, sizeof(trace_name), 2399 2397 TRACE_JB_PATH_PREFIX "%s.csv", 2400 2398 stream->port.info.name.ptr); … … 2402 2400 if (status != PJ_SUCCESS) { 2403 2401 stream->trace_jb_fd = TRACE_JB_INVALID_FD; 2404 PJ_LOG(3,(THIS_FILE, "Failed creating RTP trace file '%s'", 2402 PJ_LOG(3,(THIS_FILE, "Failed creating RTP trace file '%s'", 2405 2403 trace_name)); 2406 2404 } else { … … 2490 2488 } 2491 2489 2492 /* Detach from transport 2490 /* Detach from transport 2493 2491 * MUST NOT hold stream mutex while detaching from transport, as 2494 2492 * it may cause deadlock. See ticket #460 for the details. … … 2513 2511 2514 2512 /* Free mutex */ 2515 2513 2516 2514 if (stream->jb_mutex) { 2517 2515 pj_mutex_destroy(stream->jb_mutex); … … 2724 2722 return PJMEDIA_RTP_EREMNORFC2833; 2725 2723 } 2726 2724 2727 2725 pj_mutex_lock(stream->jb_mutex); 2728 2726 2729 2727 if (stream->tx_dtmf_count+digit_char->slen >= 2730 2728 (long)PJ_ARRAY_SIZE(stream->tx_dtmf_buf)) … … 2735 2733 2736 2734 /* convert ASCII digits into payload type first, to make sure 2737 * that all digits are valid. 2735 * that all digits are valid. 2738 2736 */ 2739 2737 for (i=0; i<digit_char->slen; ++i) { … … 2744 2742 { 2745 2743 pt = dig - '0'; 2746 } 2744 } 2747 2745 else if (dig >= 'a' && dig <= 'd') 2748 2746 { … … 2830 2828 */ 2831 2829 PJ_DEF(pj_status_t) pjmedia_stream_set_dtmf_callback(pjmedia_stream *stream, 2832 void (*cb)(pjmedia_stream*, 2833 void *user_data, 2834 int digit), 2830 void (*cb)(pjmedia_stream*, 2831 void *user_data, 2832 int digit), 2835 2833 void *user_data) 2836 2834 { -
pjproject/trunk/pjmedia/src/pjmedia/transport_srtp.c
r4723 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 … … 46 46 #define MAX_KEY_LEN 128 47 47 48 /* Initial value of probation counter. When probation counter > 0, 48 /* Initial value of probation counter. When probation counter > 0, 49 49 * it means SRTP is in probation state, and it may restart when 50 50 * srtp_unprotect() returns err_status_replay_* … … 77 77 78 78 /* cipher AES_CM, auth HMAC_SHA1, auth tag len = 10 octets */ 79 {"AES_CM_128_HMAC_SHA1_80", AES_128_ICM, 30, HMAC_SHA1, 20, 10, 10, 79 {"AES_CM_128_HMAC_SHA1_80", AES_128_ICM, 30, HMAC_SHA1, 20, 10, 10, 80 80 sec_serv_conf_and_auth}, 81 81 … … 84 84 sec_serv_conf_and_auth}, 85 85 86 /* 86 /* 87 87 * F8_128_HMAC_SHA1_8 not supported by libsrtp? 88 88 * {"F8_128_HMAC_SHA1_8", NULL_CIPHER, 0, NULL_AUTH, 0, 0, 0, sec_serv_none} … … 125 125 void *pkt, 126 126 pj_ssize_t size); 127 127 128 128 /* Transport information */ 129 129 pjmedia_transport *member_tp; /**< Underlying transport. */ … … 131 131 /* SRTP usage policy of peer. This field is updated when media is starting. 132 132 * This is useful when SRTP is in optional mode and peer is using mandatory 133 * mode, so when local is about to reinvite/update, it should offer 133 * mode, so when local is about to reinvite/update, it should offer 134 134 * RTP/SAVP instead of offering RTP/AVP. 135 135 */ 136 136 pjmedia_srtp_use peer_use; 137 137 138 /* When probation counter > 0, it means SRTP is in probation state, 138 /* When probation counter > 0, it means SRTP is in probation state, 139 139 * and it may restart when srtp_unprotect() returns err_status_replay_* 140 140 */ … … 206 206 207 207 208 static pjmedia_transport_op transport_srtp_op = 208 static pjmedia_transport_op transport_srtp_op = 209 209 { 210 210 &transport_get_info, … … 239 239 "couldn't deallocate properly", /* err_status_dealloc_fail = 4 */ 240 240 "couldn't initialize", /* err_status_init_fail = 5 */ 241 "can't process as much data as requested", 241 "can't process as much data as requested", 242 242 /* err_status_terminus = 6 */ 243 243 "authentication failure", /* err_status_auth_fail = 7 */ 244 244 "cipher failure", /* err_status_cipher_fail = 8 */ 245 245 "replay check failed (bad index)", /* err_status_replay_fail = 9 */ 246 "replay check failed (index too old)", 246 "replay check failed (index too old)", 247 247 /* err_status_replay_old = 10 */ 248 248 "algorithm failed test routine", /* err_status_algo_fail = 11 */ 249 249 "unsupported operation", /* err_status_no_such_op = 12 */ 250 250 "no appropriate context found", /* err_status_no_ctx = 13 */ 251 "unable to perform desired validation", 251 "unable to perform desired validation", 252 252 /* err_status_cant_check = 14 */ 253 253 "can't use key any more", /* err_status_key_expired = 15 */ … … 286 286 287 287 err = srtp_init(); 288 if (err != err_status_ok) { 289 PJ_LOG(4, (THIS_FILE, "Failed to initialize libsrtp: %s", 288 if (err != err_status_ok) { 289 PJ_LOG(4, (THIS_FILE, "Failed to initialize libsrtp: %s", 290 290 get_libsrtp_errstr(err))); 291 291 return PJMEDIA_ERRNO_FROM_LIBSRTP(err); … … 294 294 if (pjmedia_endpt_atexit(endpt, pjmedia_srtp_deinit_lib) != PJ_SUCCESS) 295 295 { 296 /* There will be memory leak when it fails to schedule libsrtp 296 /* There will be memory leak when it fails to schedule libsrtp 297 297 * deinitialization, however the memory leak could be harmless, 298 * since in modern OS's memory used by an application is released 298 * since in modern OS's memory used by an application is released 299 299 * when the application terminates. 300 300 */ … … 307 307 PJ_UNUSED_ARG(endpt); 308 308 #endif 309 309 310 310 return PJ_SUCCESS; 311 311 } … … 338 338 #endif 339 339 if (err != err_status_ok) { 340 PJ_LOG(4, (THIS_FILE, "Failed to deinitialize libsrtp: %s", 340 PJ_LOG(4, (THIS_FILE, "Failed to deinitialize libsrtp: %s", 341 341 get_libsrtp_errstr(err))); 342 342 } … … 350 350 int i; 351 351 int cs_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]); 352 352 353 353 /* treat unspecified crypto_name as crypto 'NULL' */ 354 354 if (crypto_name->slen == 0) … … 421 421 422 422 /* Check crypto availability */ 423 if (opt && opt->crypto_count == 0 && 423 if (opt && opt->crypto_count == 0 && 424 424 opt->use == PJMEDIA_SRTP_MANDATORY) 425 425 return PJMEDIA_SRTP_ESDPREQCRYPTO; … … 435 435 436 436 /* check key length */ 437 if (opt->crypto[i].key.slen && 438 opt->crypto[i].key.slen < 437 if (opt->crypto[i].key.slen && 438 opt->crypto[i].key.slen < 439 439 (pj_ssize_t)crypto_suites[cs_idx].cipher_key_len) 440 440 return PJMEDIA_SRTP_EINKEYLEN; … … 506 506 */ 507 507 PJ_DEF(pj_status_t) pjmedia_transport_srtp_start( 508 pjmedia_transport *tp, 508 pjmedia_transport *tp, 509 509 const pjmedia_srtp_crypto *tx, 510 510 const pjmedia_srtp_crypto *rx) … … 518 518 int cr_rx_idx = 0; 519 519 int au_rx_idx = 0; 520 int crypto_suites_cnt;521 520 pj_status_t status = PJ_SUCCESS; 522 521 … … 528 527 pjmedia_transport_srtp_stop(tp); 529 528 } 530 531 crypto_suites_cnt = sizeof(crypto_suites)/sizeof(crypto_suites[0]);532 529 533 530 /* Get encryption and authentication method */ … … 545 542 546 543 /* Check whether the crypto-suite requested is supported */ 547 if (cr_tx_idx == -1 || cr_rx_idx == -1 || au_tx_idx == -1 || 544 if (cr_tx_idx == -1 || cr_rx_idx == -1 || au_tx_idx == -1 || 548 545 au_rx_idx == -1) 549 546 { … … 648 645 else 649 646 b64[b64_len] = '\0'; 650 647 651 648 PJ_LOG(5, (srtp->pool->obj_name, "TX: %s key=%s", 652 649 srtp->tx_policy.name.ptr, b64)); … … 700 697 err = srtp_dealloc(p_srtp->srtp_rx_ctx); 701 698 if (err != err_status_ok) { 702 PJ_LOG(4, (p_srtp->pool->obj_name, 699 PJ_LOG(4, (p_srtp->pool->obj_name, 703 700 "Failed to dealloc RX SRTP context: %s", 704 701 get_libsrtp_errstr(err))); … … 706 703 err = srtp_dealloc(p_srtp->srtp_tx_ctx); 707 704 if (err != err_status_ok) { 708 PJ_LOG(4, (p_srtp->pool->obj_name, 705 PJ_LOG(4, (p_srtp->pool->obj_name, 709 706 "Failed to dealloc TX SRTP context: %s", 710 707 get_libsrtp_errstr(err))); … … 753 750 info->spc_info[spc_info_idx].type = PJMEDIA_TRANSPORT_TYPE_SRTP; 754 751 info->spc_info[spc_info_idx].cbsize = sizeof(srtp_info); 755 pj_memcpy(&info->spc_info[spc_info_idx].buffer, &srtp_info, 752 pj_memcpy(&info->spc_info[spc_info_idx].buffer, &srtp_info, 756 753 sizeof(srtp_info)); 757 754 … … 782 779 783 780 /* Attach itself to transport */ 784 status = pjmedia_transport_attach(srtp->member_tp, srtp, rem_addr, 781 status = pjmedia_transport_attach(srtp->member_tp, srtp, rem_addr, 785 782 rem_rtcp, addr_len, &srtp_rtp_cb, 786 783 &srtp_rtcp_cb); … … 842 839 843 840 if (err == err_status_ok) { 844 status = pjmedia_transport_send_rtp(srtp->member_tp, 841 status = pjmedia_transport_send_rtp(srtp->member_tp, 845 842 srtp->rtp_tx_buffer, len); 846 843 } else { 847 844 status = PJMEDIA_ERRNO_FROM_LIBSRTP(err); 848 845 } 849 846 850 847 return status; 851 848 } … … 870 867 871 868 if (srtp->bypass_srtp) { 872 return pjmedia_transport_send_rtcp2(srtp->member_tp, addr, addr_len, 869 return pjmedia_transport_send_rtcp2(srtp->member_tp, addr, addr_len, 873 870 pkt, size); 874 871 } … … 903 900 { 904 901 transport_srtp *srtp = (transport_srtp *) tp; 905 902 906 903 PJ_ASSERT_RETURN(tp, PJ_EINVAL); 907 904 … … 965 962 } 966 963 err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len); 967 if (srtp->probation_cnt > 0 && 968 (err == err_status_replay_old || err == err_status_replay_fail)) 964 if (srtp->probation_cnt > 0 && 965 (err == err_status_replay_old || err == err_status_replay_fail)) 969 966 { 970 967 /* Handle such condition that stream is updated (RTP seq is reinited 971 * & SRTP is restarted), but some old packets are still coming 968 * & SRTP is restarted), but some old packets are still coming 972 969 * so SRTP is learning wrong RTP seq. While the newly inited RTP seq 973 * comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect() 970 * comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect() 974 971 * will return err_status_replay_*. Restarting SRTP can resolve this. 975 972 */ … … 982 979 &tx, &rx); 983 980 if (status != PJ_SUCCESS) { 984 PJ_LOG(5,(srtp->pool->obj_name, "Failed to restart SRTP, err=%s", 981 PJ_LOG(5,(srtp->pool->obj_name, "Failed to restart SRTP, err=%s", 985 982 get_libsrtp_errstr(err))); 986 983 } else if (!srtp->bypass_srtp) { … … 990 987 991 988 if (err != err_status_ok) { 992 PJ_LOG(5,(srtp->pool->obj_name, 993 "Failed to unprotect SRTP, pkt size=%d, err=%s", 989 PJ_LOG(5,(srtp->pool->obj_name, 990 "Failed to unprotect SRTP, pkt size=%d, err=%s", 994 991 size, get_libsrtp_errstr(err))); 995 992 } else { … … 1036 1033 err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len); 1037 1034 if (err != err_status_ok) { 1038 PJ_LOG(5,(srtp->pool->obj_name, 1035 PJ_LOG(5,(srtp->pool->obj_name, 1039 1036 "Failed to unprotect SRTCP, pkt size=%d, err=%s", 1040 1037 size, get_libsrtp_errstr(err))); … … 1056 1053 */ 1057 1054 static pj_status_t generate_crypto_attr_value(pj_pool_t *pool, 1058 char *buffer, int *buffer_len, 1055 char *buffer, int *buffer_len, 1059 1056 pjmedia_srtp_crypto *crypto, 1060 1057 int tag) … … 1088 1085 key_ok = PJ_TRUE; 1089 1086 1090 err = crypto_get_random((unsigned char*)key, 1087 err = crypto_get_random((unsigned char*)key, 1091 1088 crypto_suites[cs_idx].cipher_key_len); 1092 1089 if (err != err_status_ok) { … … 1100 1097 } while (!key_ok); 1101 1098 crypto->key.ptr = (char*) 1102 pj_pool_zalloc(pool, 1099 pj_pool_zalloc(pool, 1103 1100 crypto_suites[cs_idx].cipher_key_len); 1104 1101 pj_memcpy(crypto->key.ptr, key, crypto_suites[cs_idx].cipher_key_len); … … 1118 1115 1119 1116 b64_key[b64_key_len] = '\0'; 1120 1117 1121 1118 PJ_ASSERT_RETURN(*buffer_len >= (crypto->name.slen + \ 1122 1119 b64_key_len + 16), PJ_ETOOSMALL); … … 1124 1121 /* Print the crypto attribute value. */ 1125 1122 print_len = pj_ansi_snprintf(buffer, *buffer_len, "%d %s inline:%s", 1126 tag, 1123 tag, 1127 1124 crypto_suites[cs_idx].name, 1128 1125 b64_key); … … 1206 1203 crypto->key.ptr = (char*) pj_pool_zalloc(pool, MAX_KEY_LEN); 1207 1204 itmp = MAX_KEY_LEN; 1208 status = pj_base64_decode(&tmp, (pj_uint8_t*)crypto->key.ptr, 1205 status = pj_base64_decode(&tmp, (pj_uint8_t*)crypto->key.ptr, 1209 1206 &itmp); 1210 1207 if (status != PJ_SUCCESS) { … … 1227 1224 1228 1225 PJ_ASSERT_RETURN(tp, PJ_EINVAL); 1229 1226 1230 1227 pj_bzero(&srtp->rx_policy_neg, sizeof(srtp->rx_policy_neg)); 1231 1228 pj_bzero(&srtp->tx_policy_neg, sizeof(srtp->tx_policy_neg)); … … 1275 1272 1276 1273 PROPAGATE_MEDIA_CREATE: 1277 return pjmedia_transport_media_create(srtp->member_tp, sdp_pool, 1274 return pjmedia_transport_media_create(srtp->member_tp, sdp_pool, 1278 1275 member_tp_option, sdp_remote, 1279 1276 media_index); … … 1297 1294 1298 1295 PJ_ASSERT_RETURN(tp && sdp_pool && sdp_local, PJ_EINVAL); 1299 1296 1300 1297 pj_bzero(&srtp->rx_policy_neg, sizeof(srtp->rx_policy_neg)); 1301 1298 pj_bzero(&srtp->tx_policy_neg, sizeof(srtp->tx_policy_neg)); … … 1307 1304 1308 1305 /* Bypass if media transport is not RTP/AVP or RTP/SAVP */ 1309 if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP) != 0 && 1306 if (pj_stricmp(&m_loc->desc.transport, &ID_RTP_AVP) != 0 && 1310 1307 pj_stricmp(&m_loc->desc.transport, &ID_RTP_SAVP) != 0) 1311 1308 goto BYPASS_SRTP; … … 1318 1315 */ 1319 1316 /* 1320 if (pjmedia_sdp_media_find_attr(m_loc, &ID_INACTIVE, NULL) || 1317 if (pjmedia_sdp_media_find_attr(m_loc, &ID_INACTIVE, NULL) || 1321 1318 (m_rem && pjmedia_sdp_media_find_attr(m_rem, &ID_INACTIVE, NULL))) 1322 1319 goto BYPASS_SRTP; 1323 1320 */ 1324 1321 1325 /* Check remote media transport & set local media transport 1322 /* Check remote media transport & set local media transport 1326 1323 * based on SRTP usage option. 1327 1324 */ … … 1333 1330 goto BYPASS_SRTP; 1334 1331 case PJMEDIA_SRTP_OPTIONAL: 1335 m_loc->desc.transport = 1332 m_loc->desc.transport = 1336 1333 (srtp->peer_use == PJMEDIA_SRTP_MANDATORY)? 1337 1334 ID_RTP_SAVP : ID_RTP_AVP; … … 1356 1353 if (buffer_len) { 1357 1354 pj_strset(&attr_value, buffer, buffer_len); 1358 attr = pjmedia_sdp_attr_create(srtp->pool, ID_CRYPTO.ptr, 1355 attr = pjmedia_sdp_attr_create(srtp->pool, ID_CRYPTO.ptr, 1359 1356 &attr_value); 1360 1357 m_loc->attr[m_loc->attr_count++] = attr; … … 1401 1398 has_crypto_attr = PJ_TRUE; 1402 1399 1403 status = parse_attr_crypto(srtp->pool, m_rem->attr[i], 1400 status = parse_attr_crypto(srtp->pool, m_rem->attr[i], 1404 1401 &tmp_rx_crypto, &tags[cr_attr_count]); 1405 1402 if (status != PJ_SUCCESS) 1406 1403 return status; 1407 1404 1408 1405 /* Check duplicated tag */ 1409 1406 for (j=0; j<cr_attr_count; ++j) { … … 1417 1414 /* lets see if the crypto-suite offered is supported */ 1418 1415 for (j=0; j<srtp->setting.crypto_count; ++j) 1419 if (pj_stricmp(&tmp_rx_crypto.name, 1416 if (pj_stricmp(&tmp_rx_crypto.name, 1420 1417 &srtp->setting.crypto[j].name) == 0) 1421 1418 { … … 1434 1431 // hex_test_key, 1435 1432 // strlen(hex_test_key)); 1436 //pj_strset(test_key, raw_test_key, 1433 //pj_strset(test_key, raw_test_key, 1437 1434 // crypto_suites[cs_idx].cipher_key_len); 1438 1435 /* EO Force to use test key */ 1439 1436 1440 if (tmp_rx_crypto.key.slen != 1437 if (tmp_rx_crypto.key.slen != 1441 1438 (int)crypto_suites[cs_idx].cipher_key_len) 1442 1439 return PJMEDIA_SRTP_EINKEYLEN; … … 1459 1456 case PJMEDIA_SRTP_OPTIONAL: 1460 1457 /* bypass SRTP when no crypto-attr and remote uses RTP/AVP */ 1461 if (!has_crypto_attr && 1458 if (!has_crypto_attr && 1462 1459 pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP) == 0) 1463 1460 goto BYPASS_SRTP; 1464 1461 /* bypass SRTP when nothing match and remote uses RTP/AVP */ 1465 else if (matched_idx == -1 && 1462 else if (matched_idx == -1 && 1466 1463 pj_stricmp(&m_rem->desc.transport, &ID_RTP_AVP) == 0) 1467 1464 goto BYPASS_SRTP; … … 1485 1482 } 1486 1483 1487 /* we have to generate crypto answer, 1484 /* we have to generate crypto answer, 1488 1485 * with srtp->tx_policy_neg matched the offer 1489 1486 * and rem_tag contains matched offer tag. … … 1497 1494 1498 1495 srtp->tx_policy_neg = srtp->setting.crypto[matched_idx]; 1499 1496 1500 1497 /* If buffer_len==0, just skip the crypto attribute. */ 1501 1498 if (buffer_len) { 1502 1499 pj_strset(&attr_value, buffer, buffer_len); 1503 attr = pjmedia_sdp_attr_create(sdp_pool, ID_CRYPTO.ptr, 1500 attr = pjmedia_sdp_attr_create(sdp_pool, ID_CRYPTO.ptr, 1504 1501 &attr_value); 1505 1502 m_loc->attr[m_loc->attr_count++] = attr; … … 1508 1505 /* At this point, we get valid rx_policy_neg & tx_policy_neg. */ 1509 1506 } 1510 1507 1511 1508 } 1512 1509 goto PROPAGATE_MEDIA_CREATE; … … 1519 1516 1520 1517 PROPAGATE_MEDIA_CREATE: 1521 return pjmedia_transport_encode_sdp(srtp->member_tp, sdp_pool, 1518 return pjmedia_transport_encode_sdp(srtp->member_tp, sdp_pool, 1522 1519 sdp_local, sdp_remote, media_index); 1523 1520 } … … 1548 1545 /* For answerer side, this function will just have to start SRTP */ 1549 1546 1550 /* Check remote media transport & set local media transport 1547 /* Check remote media transport & set local media transport 1551 1548 * based on SRTP usage option. 1552 1549 */ … … 1561 1558 // Regardless the answer's transport type (RTP/AVP or RTP/SAVP), 1562 1559 // the answer must be processed through in optional mode. 1563 // Please note that at this point transport type is ensured to be 1560 // Please note that at this point transport type is ensured to be 1564 1561 // RTP/AVP or RTP/SAVP, see transport_media_create() 1565 1562 //if (pj_stricmp(&m_rem->desc.transport, &m_loc->desc.transport)) { … … 1574 1571 } 1575 1572 } 1576 1573 1577 1574 if (srtp->offerer_side) { 1578 1575 /* find supported crypto-suite, get the tag, and assign policy_local */ … … 1593 1590 has_crypto_attr = PJ_TRUE; 1594 1591 1595 status = parse_attr_crypto(srtp->pool, m_rem->attr[i], 1592 status = parse_attr_crypto(srtp->pool, m_rem->attr[i], 1596 1593 &tmp_tx_crypto, &rem_tag); 1597 1594 if (status != PJ_SUCCESS) … … 1606 1603 1607 1604 /* match the crypto name */ 1608 if (pj_stricmp(&tmp_tx_crypto.name, 1605 if (pj_stricmp(&tmp_tx_crypto.name, 1609 1606 &srtp->setting.crypto[rem_tag-1].name) != 0) 1610 1607 { … … 1634 1631 1635 1632 /* Make sure we have the SRTP policies */ 1636 if (srtp_crypto_empty(&srtp->tx_policy_neg) || 1633 if (srtp_crypto_empty(&srtp->tx_policy_neg) || 1637 1634 srtp_crypto_empty(&srtp->rx_policy_neg)) 1638 1635 { … … 1671 1668 1672 1669 PROPAGATE_MEDIA_START: 1673 return pjmedia_transport_media_start(srtp->member_tp, pool, 1670 return pjmedia_transport_media_start(srtp->member_tp, pool, 1674 1671 sdp_local, sdp_remote, 1675 1672 media_index); … … 1685 1682 status = pjmedia_transport_media_stop(srtp->member_tp); 1686 1683 if (status != PJ_SUCCESS) 1687 PJ_LOG(4, (srtp->pool->obj_name, 1684 PJ_LOG(4, (srtp->pool->obj_name, 1688 1685 "SRTP failed stop underlying media transport.")); 1689 1686 … … 1720 1717 else 1721 1718 err = srtp_unprotect_rtcp(srtp->srtp_rx_ctx, pkt, pkt_len); 1722 1719 1723 1720 if (err != err_status_ok) { 1724 PJ_LOG(5,(srtp->pool->obj_name, 1725 "Failed to unprotect SRTP, pkt size=%d, err=%s", 1721 PJ_LOG(5,(srtp->pool->obj_name, 1722 "Failed to unprotect SRTP, pkt size=%d, err=%s", 1726 1723 *pkt_len, get_libsrtp_errstr(err))); 1727 1724 } -
pjproject/trunk/pjmedia/src/test/jbuf_test.c
r3841 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include <stdio.h> … … 48 48 } test_cond_t; 49 49 50 static pj_bool_t parse_test_headers(char *line, test_param_t *param, 50 static pj_bool_t parse_test_headers(char *line, test_param_t *param, 51 51 test_cond_t *cond) 52 52 { … … 57 57 char mode_st[16]; 58 58 59 sscanf(p+1, "%s %u %u %u", mode_st, ¶m->init_prefetch, 59 sscanf(p+1, "%s %u %u %u", mode_st, ¶m->init_prefetch, 60 60 ¶m->min_prefetch, ¶m->max_prefetch); 61 61 param->adaptive = (pj_ansi_stricmp(mode_st, "adaptive") == 0); … … 103 103 } 104 104 105 static pj_bool_t process_test_data(char data, pjmedia_jbuf *jb, 105 static pj_bool_t process_test_data(char data, pjmedia_jbuf *jb, 106 106 pj_uint16_t *seq, pj_uint16_t *last_seq) 107 107 { … … 156 156 157 157 pjmedia_jbuf_get_state(jb, &state); 158 printf("seq=%d\t%c\tsize=%d\tprefetch=%d\n", 158 printf("seq=%d\t%c\tsize=%d\tprefetch=%d\n", 159 159 *last_seq, toupper(data), state.size, state.prefetch); 160 160 } 161 #else 162 PJ_UNUSED_ARG(print_state); /* Warning about variable set but unused */ 161 163 #endif 162 164 … … 171 173 int rc = 0; 172 174 const char* input_filename = "Jbtest.dat"; 173 const char* input_search_path[] = { 175 const char* input_search_path[] = { 174 176 "../build", 175 177 "pjmedia/build", … … 192 194 } 193 195 } 194 196 195 197 /* Failed to open test data file. */ 196 198 if (input == NULL) { … … 245 247 246 248 if (param.adaptive) { 247 pjmedia_jbuf_set_adaptive(jb, 248 param.init_prefetch, 249 pjmedia_jbuf_set_adaptive(jb, 250 param.init_prefetch, 249 251 param.min_prefetch, 250 252 param.max_prefetch); … … 255 257 #ifdef REPORT 256 258 pjmedia_jbuf_get_state(jb, &state); 257 printf("Initial\tsize=%d\tprefetch=%d\tmin.pftch=%d\tmax.pftch=%d\n", 258 state.size, state.prefetch, state.min_prefetch, 259 printf("Initial\tsize=%d\tprefetch=%d\tmin.pftch=%d\tmax.pftch=%d\n", 260 state.size, state.prefetch, state.min_prefetch, 259 261 state.max_prefetch); 260 262 #endif … … 264 266 while (1) { 265 267 char c; 266 268 267 269 /* Get next line of test data */ 268 270 if (!p || *p == 0) { … … 302 304 printf(" size=%d prefetch=%d\n", state.size, state.prefetch); 303 305 printf(" delay (min/max/avg/dev)=%d/%d/%d/%d ms\n", 304 state.min_delay, state.max_delay, state.avg_delay, 306 state.min_delay, state.max_delay, state.avg_delay, 305 307 state.dev_delay); 306 printf(" lost=%d discard=%d empty=%d burst(avg)=%d\n", 308 printf(" lost=%d discard=%d empty=%d burst(avg)=%d\n", 307 309 state.lost, state.discard, state.empty, state.avg_burst); 308 310 309 311 /* Evaluate test session */ 310 312 if (cond.burst >= 0 && (int)state.avg_burst > cond.burst) { 311 printf("! 'Burst' should be %d, it is %d\n", 313 printf("! 'Burst' should be %d, it is %d\n", 312 314 cond.burst, state.avg_burst); 313 315 rc |= 1; 314 316 } 315 317 if (cond.delay >= 0 && (int)state.avg_delay/JB_PTIME > cond.delay) { 316 printf("! 'Delay' should be %d, it is %d\n", 318 printf("! 'Delay' should be %d, it is %d\n", 317 319 cond.delay, state.avg_delay/JB_PTIME); 318 320 rc |= 2; 319 321 } 320 322 if (cond.delay_min >= 0 && (int)state.min_delay/JB_PTIME > cond.delay_min) { 321 printf("! 'Minimum delay' should be %d, it is %d\n", 323 printf("! 'Minimum delay' should be %d, it is %d\n", 322 324 cond.delay_min, state.min_delay/JB_PTIME); 323 325 rc |= 32; … … 329 331 } 330 332 if (cond.empty >= 0 && (int)state.empty > cond.empty) { 331 printf("! 'Empty' should be %d, it is %d\n", 333 printf("! 'Empty' should be %d, it is %d\n", 332 334 cond.empty, state.empty); 333 335 rc |= 8; 334 336 } 335 337 if (cond.lost >= 0 && (int)state.lost > cond.lost) { 336 printf("! 'Lost' should be %d, it is %d\n", 338 printf("! 'Lost' should be %d, it is %d\n", 337 339 cond.lost, state.lost); 338 340 rc |= 16; -
pjproject/trunk/pjnath/src/pjnath-test/ice_test.c
r4412 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include "test.h" … … 113 113 114 114 static void ice_on_rx_data(pj_ice_strans *ice_st, 115 unsigned comp_id, 115 unsigned comp_id, 116 116 void *pkt, pj_size_t size, 117 117 const pj_sockaddr_t *src_addr, 118 118 unsigned src_addr_len); 119 static void ice_on_ice_complete(pj_ice_strans *ice_st, 119 static void ice_on_ice_complete(pj_ice_strans *ice_st, 120 120 pj_ice_strans_op op, 121 121 pj_status_t status); … … 202 202 return PJ_SUCCESS; 203 203 } 204 204 205 205 /* Create test session */ 206 206 static int create_sess(pj_stun_config *stun_cfg, … … 239 239 return -10; 240 240 } 241 sess->server->turn_respond_allocate = 241 sess->server->turn_respond_allocate = 242 242 sess->server->turn_respond_refresh = PJ_TRUE; 243 243 … … 319 319 320 320 static void ice_on_rx_data(pj_ice_strans *ice_st, 321 unsigned comp_id, 321 unsigned comp_id, 322 322 void *pkt, pj_size_t size, 323 323 const pj_sockaddr_t *src_addr, … … 336 336 337 337 338 static void ice_on_ice_complete(pj_ice_strans *ice_st, 338 static void ice_on_ice_complete(pj_ice_strans *ice_st, 339 339 pj_ice_strans_op op, 340 340 pj_status_t status) … … 437 437 for (; i<max_cnt; ++i) { 438 438 if (ept1->cfg.comp_cnt>i && 439 pj_ice_strans_get_valid_pair(ept1->ice, i+1) != NULL) 439 pj_ice_strans_get_valid_pair(ept1->ice, i+1) != NULL) 440 440 { 441 441 PJ_LOG(3,(THIS_FILE, INDENT "err: ice1 shouldn't have valid pair " … … 444 444 } 445 445 if (ept2->cfg.comp_cnt>i && 446 pj_ice_strans_get_valid_pair(ept2->ice, i+1) != NULL) 446 pj_ice_strans_get_valid_pair(ept2->ice, i+1) != NULL) 447 447 { 448 448 PJ_LOG(3,(THIS_FILE, INDENT "err: ice2 shouldn't have valid pair " … … 464 464 pj_gettimeofday(&t); \ 465 465 if (expr) { \ 466 rc= PJ_SUCCESS; \466 RC = PJ_SUCCESS; \ 467 467 break; \ 468 468 } \ … … 478 478 struct test_sess *sess = (struct test_sess *) data; 479 479 pj_stun_config *stun_cfg = sess->stun_cfg; 480 480 481 481 /* Wait until negotiation is complete on both endpoints */ 482 482 #define ALL_DONE (sess->param->worker_quit || \ … … 484 484 sess->callee.result.nego_status!=PJ_EPENDING)) 485 485 WAIT_UNTIL(sess->param->worker_timeout, ALL_DONE, rc); 486 486 PJ_UNUSED_ARG(rc); 487 487 return 0; 488 488 } … … 539 539 } 540 540 /* Init ICE on caller */ 541 rc = pj_ice_strans_init_ice(sess->caller.ice, sess->caller.cfg.role, 541 rc = pj_ice_strans_init_ice(sess->caller.ice, sess->caller.cfg.role, 542 542 &sess->caller.ufrag, &sess->caller.pass); 543 543 if (rc != PJ_SUCCESS) { … … 548 548 549 549 /* Init ICE on callee */ 550 rc = pj_ice_strans_init_ice(sess->callee.ice, sess->callee.cfg.role, 550 rc = pj_ice_strans_init_ice(sess->callee.ice, sess->callee.cfg.role, 551 551 &sess->callee.ufrag, &sess->callee.pass); 552 552 if (rc != PJ_SUCCESS) { … … 597 597 goto on_destroy; 598 598 } 599 599 600 600 WAIT_UNTIL(30000, ALL_DONE, rc); 601 601 if (!ALL_DONE) { … … 691 691 struct test_cfg ua1; 692 692 struct test_cfg ua2; 693 } sess_cfg[] = 693 } sess_cfg[] = 694 694 { 695 695 /* Role comp# host? stun? turn? flag? ans_del snd_del des_del */ … … 741 741 /* Simple test first with host candidate */ 742 742 if (1) { 743 struct sess_cfg_t cfg = 743 struct sess_cfg_t cfg = 744 744 { 745 745 "Basic with host candidates", … … 750 750 }; 751 751 752 rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag, 752 rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag, 753 753 &cfg.ua1, &cfg.ua2); 754 754 if (rc != 0) … … 757 757 cfg.ua1.comp_cnt = 2; 758 758 cfg.ua2.comp_cnt = 2; 759 rc = perform_test("Basic with host candidates, 2 components", 760 &stun_cfg, cfg.server_flag, 761 &cfg.ua1, &cfg.ua2); 762 if (rc != 0) 763 goto on_return; 764 } 765 759 rc = perform_test("Basic with host candidates, 2 components", 760 &stun_cfg, cfg.server_flag, 761 &cfg.ua1, &cfg.ua2); 762 if (rc != 0) 763 goto on_return; 764 } 765 766 766 /* Simple test first with srflx candidate */ 767 767 if (1) { 768 struct sess_cfg_t cfg = 768 struct sess_cfg_t cfg = 769 769 { 770 770 "Basic with srflx candidates", … … 775 775 }; 776 776 777 rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag, 777 rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag, 778 778 &cfg.ua1, &cfg.ua2); 779 779 if (rc != 0) … … 783 783 cfg.ua2.comp_cnt = 2; 784 784 785 rc = perform_test("Basic with srflx candidates, 2 components", 786 &stun_cfg, cfg.server_flag, 785 rc = perform_test("Basic with srflx candidates, 2 components", 786 &stun_cfg, cfg.server_flag, 787 787 &cfg.ua1, &cfg.ua2); 788 788 if (rc != 0) … … 792 792 /* Simple test with relay candidate */ 793 793 if (1) { 794 struct sess_cfg_t cfg = 794 struct sess_cfg_t cfg = 795 795 { 796 796 "Basic with relay candidates", … … 801 801 }; 802 802 803 rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag, 803 rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag, 804 804 &cfg.ua1, &cfg.ua2); 805 805 if (rc != 0) … … 809 809 cfg.ua2.comp_cnt = 2; 810 810 811 rc = perform_test("Basic with relay candidates, 2 components", 812 &stun_cfg, cfg.server_flag, 811 rc = perform_test("Basic with relay candidates, 2 components", 812 &stun_cfg, cfg.server_flag, 813 813 &cfg.ua1, &cfg.ua2); 814 814 if (rc != 0) … … 818 818 /* Failure test with STUN resolution */ 819 819 if (1) { 820 struct sess_cfg_t cfg = 820 struct sess_cfg_t cfg = 821 821 { 822 822 "STUN resolution failure", … … 835 835 cfg.ua2.client_flag |= DEL_ON_ERR; 836 836 837 rc = perform_test("STUN resolution failure with destroy on callback", 838 &stun_cfg, cfg.server_flag, 837 rc = perform_test("STUN resolution failure with destroy on callback", 838 &stun_cfg, cfg.server_flag, 839 839 &cfg.ua1, &cfg.ua2); 840 840 if (rc != 0) … … 844 844 /* Failure test with TURN resolution */ 845 845 if (1) { 846 struct sess_cfg_t cfg = 846 struct sess_cfg_t cfg = 847 847 { 848 848 "TURN allocation failure", … … 853 853 }; 854 854 855 rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag, 855 rc = perform_test(cfg.title, &stun_cfg, cfg.server_flag, 856 856 &cfg.ua1, &cfg.ua2); 857 857 if (rc != 0) … … 861 861 cfg.ua2.client_flag |= DEL_ON_ERR; 862 862 863 rc = perform_test("TURN allocation failure with destroy on callback", 864 &stun_cfg, cfg.server_flag, 863 rc = perform_test("TURN allocation failure with destroy on callback", 864 &stun_cfg, cfg.server_flag, 865 865 &cfg.ua1, &cfg.ua2); 866 866 if (rc != 0) … … 871 871 /* STUN failure, testing TURN deallocation */ 872 872 if (1) { 873 struct sess_cfg_t cfg = 873 struct sess_cfg_t cfg = 874 874 { 875 875 "STUN failure, testing TURN deallocation", … … 888 888 cfg.ua2.client_flag |= DEL_ON_ERR; 889 889 890 rc = perform_test("STUN failure, testing TURN deallocation (cb)", 891 &stun_cfg, cfg.server_flag, 890 rc = perform_test("STUN failure, testing TURN deallocation (cb)", 891 &stun_cfg, cfg.server_flag, 892 892 &cfg.ua1, &cfg.ua2); 893 893 if (rc != 0) … … 909 909 pj_ice_sess_role ua1; 910 910 pj_ice_sess_role ua2; 911 } role[] = 911 } role[] = 912 912 { 913 913 { ROLE1, ROLE2}, … … 937 937 char title[120]; 938 938 939 sprintf(title, 940 "%s/%s, %dms answer delay, %d vs %d components", 939 sprintf(title, 940 "%s/%s, %dms answer delay, %d vs %d components", 941 941 pj_ice_sess_role_name(role[j].ua1), 942 942 pj_ice_sess_role_name(role[j].ua2), … … 944 944 945 945 cfg->ua2.comp_cnt = k2; 946 rc = perform_test(title, &stun_cfg, cfg->server_flag, 946 rc = perform_test(title, &stun_cfg, cfg->server_flag, 947 947 &cfg->ua1, &cfg->ua2); 948 948 if (rc != 0) … … 1022 1022 unsigned i; 1023 1023 int rc; 1024 1024 1025 1025 pool = pj_pool_create(mem, NULL, 512, 512, NULL); 1026 1026 rc = create_stun_config(pool, &stun_cfg); … … 1029 1029 return -7; 1030 1030 } 1031 1031 1032 1032 for (i = 0; i < LOOP; i++) { 1033 1033 PJ_LOG(3,(THIS_FILE, INDENT "Test %d of %d", i+1, LOOP)); … … 1039 1039 /* Avoid compiler warning */ 1040 1040 goto on_return; 1041 1041 1042 1042 on_return: 1043 1043 destroy_stun_config(&stun_cfg); -
pjproject/trunk/pjnath/src/pjnath-test/test.c
r4537 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include "test.h" … … 109 109 110 110 st->timer_cnt = (unsigned)pj_timer_heap_count(cfg->timer_heap); 111 111 112 112 cp = (pj_caching_pool*)cfg->pf; 113 113 st->pool_used_cnt = (unsigned)cp->used_count; 114 114 } 115 115 116 int check_pjlib_state(pj_stun_config *cfg, 116 int check_pjlib_state(pj_stun_config *cfg, 117 117 const struct pjlib_state *initial_st) 118 118 { … … 154 154 pj_pool_factory *mem; 155 155 156 int param_log_decor = PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME | 156 int param_log_decor = PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_TIME | 157 157 PJ_LOG_HAS_MICRO_SEC; 158 158 … … 179 179 pj_log_set_level(3); 180 180 pj_log_set_decor(param_log_decor); 181 PJ_UNUSED_ARG(test_log_func); 181 182 #elif 1 182 183 log_file = fopen("pjnath-test.log", "wt"); … … 191 192 return rc; 192 193 } 193 194 194 195 pj_dump_config(); 195 196 pj_caching_pool_init( &caching_pool, &pj_pool_factory_default_policy, 0 ); … … 234 235 PJ_CATCH_ANY { 235 236 int id = PJ_GET_EXCEPTION(); 236 PJ_LOG(3,("test", "FATAL: unhandled exception id %d (%s)", 237 PJ_LOG(3,("test", "FATAL: unhandled exception id %d (%s)", 237 238 id, pj_exception_id_name(id))); 238 239 } -
pjproject/trunk/pjnath/src/pjnath/ice_strans.c
r4606 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include <pjnath/ice_strans.h> … … 66 66 67 67 /* The candidate type preference when STUN candidate is used */ 68 static pj_uint8_t srflx_pref_table[PJ_ICE_CAND_TYPE_MAX] = 68 static pj_uint8_t srflx_pref_table[PJ_ICE_CAND_TYPE_MAX] = 69 69 { 70 70 #if PJNATH_ICE_PRIO_STD … … 85 85 /* ICE callbacks */ 86 86 static void on_ice_complete(pj_ice_sess *ice, pj_status_t status); 87 static pj_status_t ice_tx_pkt(pj_ice_sess *ice, 87 static pj_status_t ice_tx_pkt(pj_ice_sess *ice, 88 88 unsigned comp_id, 89 89 unsigned transport_id, … … 91 91 const pj_sockaddr_t *dst_addr, 92 92 unsigned dst_addr_len); 93 static void ice_rx_data(pj_ice_sess *ice, 94 unsigned comp_id, 93 static void ice_rx_data(pj_ice_sess *ice, 94 unsigned comp_id, 95 95 unsigned transport_id, 96 96 void *pkt, pj_size_t size, … … 111 111 pj_ssize_t sent); 112 112 /* Notification when the status of the STUN transport has changed. */ 113 static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, 113 static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, 114 114 pj_stun_sock_op op, 115 115 pj_status_t status); … … 137 137 * in ICE stream transport typically corresponds to a single socket created 138 138 * for this component, and bound to a specific transport address. This 139 * component may have multiple alias addresses, for example one alias 139 * component may have multiple alias addresses, for example one alias 140 140 * address for each interfaces in multi-homed host, another for server 141 141 * reflexive alias, and another for relayed alias. For each transport … … 299 299 /* Override with component specific socket buffer size settings, if any */ 300 300 if (ice_st->cfg.comp[comp->comp_id-1].so_rcvbuf_size > 0) { 301 ice_st->cfg.turn.cfg.so_rcvbuf_size = 301 ice_st->cfg.turn.cfg.so_rcvbuf_size = 302 302 ice_st->cfg.comp[comp->comp_id-1].so_rcvbuf_size; 303 303 } 304 304 if (ice_st->cfg.comp[comp->comp_id-1].so_sndbuf_size > 0) { 305 ice_st->cfg.turn.cfg.so_sndbuf_size = 305 ice_st->cfg.turn.cfg.so_sndbuf_size = 306 306 ice_st->cfg.comp[comp->comp_id-1].so_sndbuf_size; 307 307 } … … 382 382 stun_sock_cb.on_status = &stun_on_status; 383 383 stun_sock_cb.on_data_sent = &stun_on_data_sent; 384 384 385 385 /* Override component specific QoS settings, if any */ 386 386 if (ice_st->cfg.comp[comp_id-1].qos_type) { 387 ice_st->cfg.stun.cfg.qos_type = 387 ice_st->cfg.stun.cfg.qos_type = 388 388 ice_st->cfg.comp[comp_id-1].qos_type; 389 389 } … … 396 396 /* Override component specific socket buffer size settings, if any */ 397 397 if (ice_st->cfg.comp[comp_id-1].so_rcvbuf_size > 0) { 398 ice_st->cfg.stun.cfg.so_rcvbuf_size = 398 ice_st->cfg.stun.cfg.so_rcvbuf_size = 399 399 ice_st->cfg.comp[comp_id-1].so_rcvbuf_size; 400 400 } 401 401 if (ice_st->cfg.comp[comp_id-1].so_sndbuf_size > 0) { 402 ice_st->cfg.stun.cfg.so_sndbuf_size = 402 ice_st->cfg.stun.cfg.so_sndbuf_size = 403 403 ice_st->cfg.comp[comp_id-1].so_sndbuf_size; 404 404 } … … 412 412 return status; 413 413 414 /* Start STUN Binding resolution and add srflx candidate 415 * only if server is set 414 /* Start STUN Binding resolution and add srflx candidate 415 * only if server is set 416 416 */ 417 417 if (ice_st->cfg.stun.server.slen) { … … 421 421 ///sess_add_ref(ice_st); 422 422 423 PJ_LOG(4,(ice_st->obj_name, 423 PJ_LOG(4,(ice_st->obj_name, 424 424 "Comp %d: srflx candidate starts Binding discovery", 425 425 comp_id)); … … 428 428 429 429 /* Start Binding resolution */ 430 status = pj_stun_sock_start(comp->stun_sock, 430 status = pj_stun_sock_start(comp->stun_sock, 431 431 &ice_st->cfg.stun.server, 432 ice_st->cfg.stun.port, 432 ice_st->cfg.stun.port, 433 433 ice_st->cfg.resolver); 434 434 if (status != PJ_SUCCESS) { … … 476 476 return status; 477 477 478 for (i=0; i<stun_sock_info.alias_cnt && 479 i<ice_st->cfg.stun.max_host_cands; ++i) 478 for (i=0; i<stun_sock_info.alias_cnt && 479 i<ice_st->cfg.stun.max_host_cands; ++i) 480 480 { 481 481 char addrinfo[PJ_INET6_ADDRSTRLEN+10]; … … 488 488 } 489 489 490 /* Ignore loopback addresses unless cfg->stun.loop_addr 491 * is set 490 /* Ignore loopback addresses unless cfg->stun.loop_addr 491 * is set 492 492 */ 493 493 if ((pj_ntohl(addr->ipv4.sin_addr.s_addr)>>24)==127) { … … 509 509 cand->type, &cand->base_addr); 510 510 511 PJ_LOG(4,(ice_st->obj_name, 511 PJ_LOG(4,(ice_st->obj_name, 512 512 "Comp %d: host candidate %s added", 513 513 comp_id, pj_sockaddr_print(&cand->addr, addrinfo, … … 533 533 534 534 535 /* 536 * Create ICE stream transport 535 /* 536 * Create ICE stream transport 537 537 */ 538 538 PJ_DEF(pj_status_t) pj_ice_strans_create( const char *name, … … 565 565 ice_st->user_data = user_data; 566 566 567 PJ_LOG(4,(ice_st->obj_name, 567 PJ_LOG(4,(ice_st->obj_name, 568 568 "Creating ICE stream transport with %d component(s)", 569 569 comp_cnt)); … … 587 587 588 588 ice_st->comp_cnt = comp_cnt; 589 ice_st->comp = (pj_ice_strans_comp**) 589 ice_st->comp = (pj_ice_strans_comp**) 590 590 pj_pool_calloc(pool, comp_cnt, sizeof(pj_ice_strans_comp*)); 591 591 … … 593 593 ice_st->state = PJ_ICE_STRANS_STATE_INIT; 594 594 595 /* Acquire initialization mutex to prevent callback to be 595 /* Acquire initialization mutex to prevent callback to be 596 596 * called before we finish initialization. 597 597 */ … … 750 750 ice_st->state = PJ_ICE_STRANS_STATE_READY; 751 751 if (ice_st->cb.on_ice_complete) 752 (*ice_st->cb.on_ice_complete)(ice_st, PJ_ICE_STRANS_OP_INIT, 752 (*ice_st->cb.on_ice_complete)(ice_st, PJ_ICE_STRANS_OP_INIT, 753 753 PJ_SUCCESS); 754 754 } … … 786 786 787 787 /* 788 * Specify various options for this ICE stream transport. 788 * Specify various options for this ICE stream transport. 789 789 */ 790 790 PJ_DEF(pj_status_t) pj_ice_strans_set_options(pj_ice_strans *ice_st, … … 835 835 /* Create! */ 836 836 status = pj_ice_sess_create(&ice_st->cfg.stun_cfg, ice_st->obj_name, role, 837 ice_st->comp_cnt, &ice_cb, 837 ice_st->comp_cnt, &ice_cb, 838 838 local_ufrag, local_passwd, 839 839 ice_st->grp_lock, … … 853 853 */ 854 854 if (ice_st->comp[0]->default_cand >= 0 && 855 ice_st->comp[0]->cand_list[ice_st->comp[0]->default_cand].type 855 ice_st->comp[0]->cand_list[ice_st->comp[0]->default_cand].type 856 856 == PJ_ICE_CAND_TYPE_SRFLX) 857 857 { … … 866 866 /* Re-enable logging for Send/Data indications */ 867 867 if (comp->turn_sock) { 868 PJ_LOG(5,(ice_st->obj_name, 868 PJ_LOG(5,(ice_st->obj_name, 869 869 "Disabling STUN Indication logging for " 870 870 "component %d", i+1)); … … 879 879 /* Skip if candidate is not ready */ 880 880 if (cand->status != PJ_SUCCESS) { 881 PJ_LOG(5,(ice_st->obj_name, 881 PJ_LOG(5,(ice_st->obj_name, 882 882 "Candidate %d of comp %d is not added (pending)", 883 883 j, i)); … … 889 889 890 890 /* Add the candidate */ 891 status = pj_ice_sess_add_cand(ice_st->ice, comp->comp_id, 892 cand->transport_id, cand->type, 893 cand->local_pref, 894 &cand->foundation, &cand->addr, 891 status = pj_ice_sess_add_cand(ice_st->ice, comp->comp_id, 892 cand->transport_id, cand->type, 893 cand->local_pref, 894 &cand->foundation, &cand->addr, 895 895 &cand->base_addr, &cand->rel_addr, 896 896 pj_sockaddr_get_len(&cand->addr), … … 912 912 913 913 /* 914 * Check if the ICE stream transport has the ICE session created. 914 * Check if the ICE stream transport has the ICE session created. 915 915 */ 916 916 PJ_DEF(pj_bool_t) pj_ice_strans_has_sess(pj_ice_strans *ice_st) … … 985 985 unsigned i, cnt; 986 986 987 PJ_ASSERT_RETURN(ice_st && ice_st->ice && comp_id && 987 PJ_ASSERT_RETURN(ice_st && ice_st->ice && comp_id && 988 988 comp_id <= ice_st->comp_cnt, 0); 989 989 … … 1008 1008 unsigned i, cnt; 1009 1009 1010 PJ_ASSERT_RETURN(ice_st && ice_st->ice && comp_id && 1010 PJ_ASSERT_RETURN(ice_st && ice_st->ice && comp_id && 1011 1011 comp_id <= ice_st->comp_cnt && count && cand, PJ_EINVAL); 1012 1012 … … 1042 1042 pj_ice_strans_comp *comp = ice_st->comp[comp_id - 1]; 1043 1043 pj_assert(comp->default_cand>=0 && comp->default_cand<comp->cand_cnt); 1044 pj_memcpy(cand, &comp->cand_list[comp->default_cand], 1044 pj_memcpy(cand, &comp->cand_list[comp->default_cand], 1045 1045 sizeof(pj_ice_sess_cand)); 1046 1046 } … … 1108 1108 1109 1109 if (count) { 1110 status = pj_turn_sock_set_perm(comp->turn_sock, count, 1110 status = pj_turn_sock_set_perm(comp->turn_sock, count, 1111 1111 addrs, 0); 1112 1112 if (status != PJ_SUCCESS) { … … 1132 1132 * Get valid pair. 1133 1133 */ 1134 PJ_DEF(const pj_ice_sess_check*) 1134 PJ_DEF(const pj_ice_sess_check*) 1135 1135 pj_ice_strans_get_valid_pair(const pj_ice_strans *ice_st, 1136 1136 unsigned comp_id) … … 1138 1138 PJ_ASSERT_RETURN(ice_st && comp_id && comp_id <= ice_st->comp_cnt, 1139 1139 NULL); 1140 1140 1141 1141 if (ice_st->ice == NULL) 1142 1142 return NULL; 1143 1143 1144 1144 return ice_st->ice->comp[comp_id-1].valid_check; 1145 1145 } … … 1171 1171 int dst_addr_len) 1172 1172 { 1173 pj_ssize_t pkt_size;1174 1173 pj_ice_strans_comp *comp; 1175 1174 unsigned def_cand; … … 1220 1219 if (!comp->turn_log_off) { 1221 1220 /* Disable logging for Send/Data indications */ 1222 PJ_LOG(5,(ice_st->obj_name, 1221 PJ_LOG(5,(ice_st->obj_name, 1223 1222 "Disabling STUN Indication logging for " 1224 1223 "component %d", comp->comp_id)); … … 1227 1226 } 1228 1227 1229 status = pj_turn_sock_sendto(comp->turn_sock, 1230 (const pj_uint8_t*)data, 1228 status = pj_turn_sock_sendto(comp->turn_sock, 1229 (const pj_uint8_t*)data, 1231 1230 (unsigned)data_len, 1232 1231 dst_addr, dst_addr_len); 1233 return (status==PJ_SUCCESS||status==PJ_EPENDING) ? 1232 return (status==PJ_SUCCESS||status==PJ_EPENDING) ? 1234 1233 PJ_SUCCESS : status; 1235 1234 } else { 1236 pkt_size = data_len; 1237 status = pj_stun_sock_sendto(comp->stun_sock, NULL, data, 1238 (unsigned)data_len, 0, dst_addr, 1235 status = pj_stun_sock_sendto(comp->stun_sock, NULL, data, 1236 (unsigned)data_len, 0, dst_addr, 1239 1237 dst_addr_len); 1240 return (status==PJ_SUCCESS||status==PJ_EPENDING) ? 1238 return (status==PJ_SUCCESS||status==PJ_EPENDING) ? 1241 1239 PJ_SUCCESS : status; 1242 1240 } … … 1266 1264 char errmsg[PJ_ERR_MSG_SIZE]; 1267 1265 pj_strerror(status, errmsg, sizeof(errmsg)); 1268 PJ_LOG(4,(ice_st->obj_name, 1269 "ICE negotiation failed after %ds:%03d: %s", 1266 PJ_LOG(4,(ice_st->obj_name, 1267 "ICE negotiation failed after %ds:%03d: %s", 1270 1268 msec/1000, msec%1000, errmsg)); 1271 1269 } else { … … 1277 1275 }; 1278 1276 1279 PJ_LOG(4,(ice_st->obj_name, 1277 PJ_LOG(4,(ice_st->obj_name, 1280 1278 "ICE negotiation success after %ds:%03d", 1281 1279 msec/1000, msec%1000)); … … 1289 1287 char rip[PJ_INET6_ADDRSTRLEN+10]; 1290 1288 1291 pj_sockaddr_print(&check->lcand->addr, lip, 1289 pj_sockaddr_print(&check->lcand->addr, lip, 1292 1290 sizeof(lip), 3); 1293 pj_sockaddr_print(&check->rcand->addr, rip, 1291 pj_sockaddr_print(&check->rcand->addr, rip, 1294 1292 sizeof(rip), 3); 1295 1293 … … 1304 1302 1305 1303 /* Disable logging for Send/Data indications */ 1306 PJ_LOG(5,(ice_st->obj_name, 1304 PJ_LOG(5,(ice_st->obj_name, 1307 1305 "Disabling STUN Indication logging for " 1308 1306 "component %d", i+1)); … … 1315 1313 "sending from %s candidate %s to " 1316 1314 "%s candidate %s", 1317 i+1, 1315 i+1, 1318 1316 pj_ice_get_cand_type_name(check->lcand->type), 1319 1317 lip, 1320 1318 pj_ice_get_cand_type_name(check->rcand->type), 1321 1319 rip)); 1322 1320 1323 1321 } else { 1324 PJ_LOG(4,(ice_st->obj_name, 1322 PJ_LOG(4,(ice_st->obj_name, 1325 1323 "Comp %d: disabled", i+1)); 1326 1324 } … … 1332 1330 1333 1331 pj_log_push_indent(); 1334 (*ice_st->cb.on_ice_complete)(ice_st, PJ_ICE_STRANS_OP_NEGOTIATION, 1332 (*ice_st->cb.on_ice_complete)(ice_st, PJ_ICE_STRANS_OP_NEGOTIATION, 1335 1333 status); 1336 1334 pj_log_pop_indent(); 1337 1335 1338 1336 } 1339 1337 … … 1344 1342 * Callback called by ICE session when it wants to send outgoing packet. 1345 1343 */ 1346 static pj_status_t ice_tx_pkt(pj_ice_sess *ice, 1347 unsigned comp_id, 1344 static pj_status_t ice_tx_pkt(pj_ice_sess *ice, 1345 unsigned comp_id, 1348 1346 unsigned transport_id, 1349 1347 const void *pkt, pj_size_t size, … … 1362 1360 comp = ice_st->comp[comp_id-1]; 1363 1361 1364 TRACE_PKT((comp->ice_st->obj_name, 1362 TRACE_PKT((comp->ice_st->obj_name, 1365 1363 "Component %d TX packet to %s:%d with transport %d", 1366 comp_id, 1364 comp_id, 1367 1365 pj_sockaddr_print(dst_addr, daddr, sizeof(addr), 0), 1368 1366 pj_sockaddr_get_port(dst_addr), … … 1371 1369 if (transport_id == TP_TURN) { 1372 1370 if (comp->turn_sock) { 1373 status = pj_turn_sock_sendto(comp->turn_sock, 1374 (const pj_uint8_t*)pkt, 1371 status = pj_turn_sock_sendto(comp->turn_sock, 1372 (const pj_uint8_t*)pkt, 1375 1373 (unsigned)size, 1376 1374 dst_addr, dst_addr_len); … … 1379 1377 } 1380 1378 } else if (transport_id == TP_STUN) { 1381 status = pj_stun_sock_sendto(comp->stun_sock, NULL, 1379 status = pj_stun_sock_sendto(comp->stun_sock, NULL, 1382 1380 pkt, (unsigned)size, 0, 1383 1381 dst_addr, dst_addr_len); … … 1386 1384 status = PJ_EINVALIDOP; 1387 1385 } 1388 1386 1389 1387 return (status==PJ_SUCCESS||status==PJ_EPENDING) ? PJ_SUCCESS : status; 1390 1388 } … … 1393 1391 * Callback called by ICE session when it receives application data. 1394 1392 */ 1395 static void ice_rx_data(pj_ice_sess *ice, 1396 unsigned comp_id, 1393 static void ice_rx_data(pj_ice_sess *ice, 1394 unsigned comp_id, 1397 1395 unsigned transport_id, 1398 1396 void *pkt, pj_size_t size, … … 1405 1403 1406 1404 if (ice_st->cb.on_rx_data) { 1407 (*ice_st->cb.on_rx_data)(ice_st, comp_id, pkt, size, 1405 (*ice_st->cb.on_rx_data)(ice_st, comp_id, pkt, size, 1408 1406 src_addr, src_addr_len); 1409 1407 } … … 1411 1409 1412 1410 /* Notification when incoming packet has been received from 1413 * the STUN socket. 1411 * the STUN socket. 1414 1412 */ 1415 1413 static pj_bool_t stun_on_rx_data(pj_stun_sock *stun_sock, … … 1439 1437 */ 1440 1438 if (ice_st->cb.on_rx_data) { 1441 (*ice_st->cb.on_rx_data)(ice_st, comp->comp_id, pkt, pkt_len, 1439 (*ice_st->cb.on_rx_data)(ice_st, comp->comp_id, pkt, pkt_len, 1442 1440 src_addr, addr_len); 1443 1441 } … … 1446 1444 1447 1445 /* Hand over the packet to ICE session */ 1448 status = pj_ice_sess_on_rx_pkt(comp->ice_st->ice, comp->comp_id, 1446 status = pj_ice_sess_on_rx_pkt(comp->ice_st->ice, comp->comp_id, 1449 1447 TP_STUN, pkt, pkt_len, 1450 1448 src_addr, addr_len); 1451 1449 1452 1450 if (status != PJ_SUCCESS) { 1453 ice_st_perror(comp->ice_st, "Error processing packet", 1451 ice_st_perror(comp->ice_st, "Error processing packet", 1454 1452 status); 1455 1453 } … … 1460 1458 1461 1459 /* Notifification when asynchronous send operation to the STUN socket 1462 * has completed. 1460 * has completed. 1463 1461 */ 1464 1462 static pj_bool_t stun_on_data_sent(pj_stun_sock *stun_sock, … … 1473 1471 1474 1472 /* Notification when the status of the STUN transport has changed. */ 1475 static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, 1473 static pj_bool_t stun_on_status(pj_stun_sock *stun_sock, 1476 1474 pj_stun_sock_op op, 1477 1475 pj_status_t status) … … 1573 1571 } 1574 1572 1575 PJ_LOG(4,(comp->ice_st->obj_name, 1573 PJ_LOG(4,(comp->ice_st->obj_name, 1576 1574 "Comp %d: %s, " 1577 1575 "srflx address is %s", 1578 comp->comp_id, op_name, 1579 pj_sockaddr_print(&info.mapped_addr, ipaddr, 1576 comp->comp_id, op_name, 1577 pj_sockaddr_print(&info.mapped_addr, ipaddr, 1580 1578 sizeof(ipaddr), 3))); 1581 1579 … … 1663 1661 1664 1662 if (status != PJ_SUCCESS) { 1665 ice_st_perror(comp->ice_st, 1666 "Error processing packet from TURN relay", 1663 ice_st_perror(comp->ice_st, 1664 "Error processing packet from TURN relay", 1667 1665 status); 1668 1666 } … … 1722 1720 pj_sockaddr_cp(&cand->base_addr, &rel_info.relay_addr); 1723 1721 pj_sockaddr_cp(&cand->rel_addr, &rel_info.mapped_addr); 1724 pj_ice_calc_foundation(comp->ice_st->pool, &cand->foundation, 1725 PJ_ICE_CAND_TYPE_RELAYED, 1722 pj_ice_calc_foundation(comp->ice_st->pool, &cand->foundation, 1723 PJ_ICE_CAND_TYPE_RELAYED, 1726 1724 &rel_info.relay_addr); 1727 1725 cand->status = PJ_SUCCESS; … … 1730 1728 comp->default_cand = (unsigned)(cand - comp->cand_list); 1731 1729 1732 PJ_LOG(4,(comp->ice_st->obj_name, 1730 PJ_LOG(4,(comp->ice_st->obj_name, 1733 1731 "Comp %d: TURN allocation complete, relay address is %s", 1734 comp->comp_id, 1735 pj_sockaddr_print(&rel_info.relay_addr, ipaddr, 1732 comp->comp_id, 1733 pj_sockaddr_print(&rel_info.relay_addr, ipaddr, 1736 1734 sizeof(ipaddr), 3))); 1737 1735 -
pjproject/trunk/pjnath/src/pjturn-srv/allocation.c
r4360 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include "turn.h" … … 63 63 pj_turn_relay_res *relay); 64 64 static void destroy_relay(pj_turn_relay_res *relay); 65 static void on_rx_from_peer(pj_ioqueue_key_t *key, 66 pj_ioqueue_op_key_t *op_key, 65 static void on_rx_from_peer(pj_ioqueue_key_t *key, 66 pj_ioqueue_op_key_t *op_key, 67 67 pj_ssize_t bytes_read); 68 68 static pj_status_t stun_on_send_msg(pj_stun_session *sess, … … 125 125 /* Check if we can satisfy the bandwidth */ 126 126 if (cfg->bandwidth > MAX_CLIENT_BANDWIDTH) { 127 pj_stun_session_respond(sess, rdata, 127 pj_stun_session_respond(sess, rdata, 128 128 PJ_STUN_SC_ALLOCATION_QUOTA_REACHED, 129 129 "Invalid bandwidth", NULL, PJ_TRUE, … … 137 137 if (attr_req_tp == NULL) { 138 138 pj_stun_session_respond(sess, rdata, PJ_STUN_SC_BAD_REQUEST, 139 "Missing REQUESTED-TRANSPORT attribute", 139 "Missing REQUESTED-TRANSPORT attribute", 140 140 NULL, PJ_TRUE, src_addr, src_addr_len); 141 141 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); … … 157 157 if (attr_res_token) { 158 158 /* We don't support RESERVATION-TOKEN for now */ 159 pj_stun_session_respond(sess, rdata, 159 pj_stun_session_respond(sess, rdata, 160 160 PJ_STUN_SC_BAD_REQUEST, 161 "RESERVATION-TOKEN is not supported", NULL, 161 "RESERVATION-TOKEN is not supported", NULL, 162 162 PJ_TRUE, src_addr, src_addr_len); 163 163 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); … … 171 171 if (cfg->lifetime < MIN_LIFETIME) { 172 172 pj_stun_session_respond(sess, rdata, PJ_STUN_SC_BAD_REQUEST, 173 "LIFETIME too short", NULL, 173 "LIFETIME too short", NULL, 174 174 PJ_TRUE, src_addr, src_addr_len); 175 175 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); … … 207 207 /* Add LIFETIME. */ 208 208 pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 209 PJ_STUN_ATTR_LIFETIME, 209 PJ_STUN_ATTR_LIFETIME, 210 210 (unsigned)alloc->relay.lifetime); 211 211 … … 223 223 &alloc->hkey.clt_addr, 224 224 pj_sockaddr_get_len(&alloc->hkey.clt_addr)); 225 225 226 226 /* Send the response */ 227 227 return pj_stun_session_send_msg(srv_sess, transport, PJ_TRUE, 228 PJ_FALSE, &alloc->hkey.clt_addr, 228 PJ_FALSE, &alloc->hkey.clt_addr, 229 229 pj_sockaddr_get_len(&alloc->hkey.clt_addr), 230 230 tdata); … … 256 256 257 257 /* Lookup the password */ 258 status = pj_turn_get_password(NULL, NULL, &realm->value, 259 &user->value, alloc->pool, 260 &alloc->cred.data.static_cred.data_type, 258 status = pj_turn_get_password(NULL, NULL, &realm->value, 259 &user->value, alloc->pool, 260 &alloc->cred.data.static_cred.data_type, 261 261 &alloc->cred.data.static_cred.data); 262 262 if (status != PJ_SUCCESS) … … 315 315 pj_memcpy(&alloc->hkey.clt_addr, src_addr, src_addr_len); 316 316 317 status = pj_lock_create_recursive_mutex(pool, alloc->obj_name, 317 status = pj_lock_create_recursive_mutex(pool, alloc->obj_name, 318 318 &alloc->lock); 319 319 if (status != PJ_SUCCESS) { … … 328 328 329 329 /* Print info */ 330 pj_ansi_strcpy(alloc->info, 330 pj_ansi_strcpy(alloc->info, 331 331 pj_turn_tp_type_name(transport->listener->tp_type)); 332 332 alloc->info[3] = ':'; … … 372 372 373 373 /* Done */ 374 pj_sockaddr_print(&alloc->relay.hkey.addr, str_tmp, 374 pj_sockaddr_print(&alloc->relay.hkey.addr, str_tmp, 375 375 sizeof(str_tmp), 3); 376 PJ_LOG(4,(alloc->obj_name, "Client %s created, relay addr=%s:%s", 376 PJ_LOG(4,(alloc->obj_name, "Client %s created, relay addr=%s:%s", 377 377 alloc->info, pj_turn_tp_type_name(req.tp_type), str_tmp)); 378 378 … … 384 384 /* Send reply to the ALLOCATE request */ 385 385 pj_strerror(status, str_tmp, sizeof(str_tmp)); 386 pj_stun_session_respond(srv_sess, rdata, PJ_STUN_SC_BAD_REQUEST, str_tmp, 386 pj_stun_session_respond(srv_sess, rdata, PJ_STUN_SC_BAD_REQUEST, str_tmp, 387 387 transport, PJ_TRUE, src_addr, src_addr_len); 388 388 … … 397 397 { 398 398 if (relay->timer.id) { 399 pj_timer_heap_cancel(relay->allocation->server->core.timer_heap, 399 pj_timer_heap_cancel(relay->allocation->server->core.timer_heap, 400 400 &relay->timer); 401 401 relay->timer.id = PJ_FALSE; … … 483 483 484 484 /* Initiate shutdown sequence for this allocation and start destroy timer. 485 * Once allocation is marked as shutting down, any packets will be 486 * rejected/discarded 485 * Once allocation is marked as shutting down, any packets will be 486 * rejected/discarded 487 487 */ 488 488 static void alloc_shutdown(pj_turn_allocation *alloc) … … 502 502 */ 503 503 return; 504 } 504 } 505 505 506 506 pj_assert(alloc->relay.timer.id == TIMER_ID_NONE); … … 531 531 pj_assert(alloc->relay.timer.id != TIMER_ID_DESTROY); 532 532 if (alloc->relay.timer.id != 0) { 533 pj_timer_heap_cancel(alloc->server->core.timer_heap, 533 pj_timer_heap_cancel(alloc->server->core.timer_heap, 534 534 &alloc->relay.timer); 535 535 alloc->relay.timer.id = TIMER_ID_NONE; … … 540 540 541 541 alloc->relay.timer.id = TIMER_ID_TIMEOUT; 542 status = pj_timer_heap_schedule(alloc->server->core.timer_heap, 542 status = pj_timer_heap_schedule(alloc->server->core.timer_heap, 543 543 &alloc->relay.timer, &delay); 544 544 if (status != PJ_SUCCESS) { … … 566 566 e->id = TIMER_ID_NONE; 567 567 568 PJ_LOG(4,(alloc->obj_name, 569 "Client %s refresh timed-out, shutting down..", 568 PJ_LOG(4,(alloc->obj_name, 569 "Client %s refresh timed-out, shutting down..", 570 570 alloc->info)); 571 571 … … 575 575 e->id = TIMER_ID_NONE; 576 576 577 PJ_LOG(4,(alloc->obj_name, "Client %s destroying..", 577 PJ_LOG(4,(alloc->obj_name, "Client %s destroying..", 578 578 alloc->info)); 579 579 … … 601 601 602 602 pj_bzero(relay, sizeof(*relay)); 603 603 604 604 relay->allocation = alloc; 605 605 relay->tp.sock = PJ_INVALID_SOCKET; 606 606 607 607 /* TODO: get the requested address family from somewhere */ 608 608 af = alloc->transport->listener->addr.addr.sa_family; … … 622 622 /* Lifetime and timeout */ 623 623 relay->lifetime = req->lifetime; 624 pj_timer_entry_init(&relay->timer, TIMER_ID_NONE, relay, 624 pj_timer_entry_init(&relay->timer, TIMER_ID_NONE, relay, 625 625 &relay_timeout_cb); 626 626 resched_timeout(alloc); 627 627 628 628 /* Transport type */ 629 629 relay->hkey.tp_type = req->tp_type; … … 677 677 pj_sockaddr_init(af, &bound_addr, NULL, port); 678 678 679 status = pj_sock_bind(relay->tp.sock, &bound_addr, 679 status = pj_sock_bind(relay->tp.sock, &bound_addr, 680 680 pj_sockaddr_get_len(&bound_addr)); 681 681 if (status == PJ_SUCCESS) … … 685 685 if (status != PJ_SUCCESS) { 686 686 /* Unable to allocate port */ 687 PJ_LOG(4,(THIS_FILE, "Unable to allocate relay, giving up: err %d", 687 PJ_LOG(4,(THIS_FILE, "Unable to allocate relay, giving up: err %d", 688 688 status)); 689 689 pj_sock_close(relay->tp.sock); … … 696 696 status = pj_sock_getsockname(relay->tp.sock, &relay->hkey.addr, &namelen); 697 697 if (status != PJ_SUCCESS) { 698 PJ_LOG(4,(THIS_FILE, "pj_sock_getsockname() failed: err %d", 698 PJ_LOG(4,(THIS_FILE, "pj_sock_getsockname() failed: err %d", 699 699 status)); 700 700 pj_sock_close(relay->tp.sock); … … 703 703 } 704 704 if (!pj_sockaddr_has_addr(&relay->hkey.addr)) { 705 pj_sockaddr_copy_addr(&relay->hkey.addr, 705 pj_sockaddr_copy_addr(&relay->hkey.addr, 706 706 &alloc->transport->listener->addr); 707 707 } … … 719 719 relay, &icb, &relay->tp.key); 720 720 if (status != PJ_SUCCESS) { 721 PJ_LOG(4,(THIS_FILE, "pj_ioqueue_register_sock() failed: err %d", 721 PJ_LOG(4,(THIS_FILE, "pj_ioqueue_register_sock() failed: err %d", 722 722 status)); 723 723 pj_sock_close(relay->tp.sock); … … 737 737 static void send_reply_err(pj_turn_allocation *alloc, 738 738 const pj_stun_rx_data *rdata, 739 pj_bool_t cache, 739 pj_bool_t cache, 740 740 int code, const char *errmsg) 741 741 { 742 742 pj_status_t status; 743 743 744 status = pj_stun_session_respond(alloc->sess, rdata, code, errmsg, NULL, 744 status = pj_stun_session_respond(alloc->sess, rdata, code, errmsg, NULL, 745 745 cache, &alloc->hkey.clt_addr, 746 746 pj_sockaddr_get_len(&alloc->hkey.clt_addr.addr)); … … 787 787 } 788 788 789 status = pj_stun_session_send_msg(alloc->sess, NULL, PJ_TRUE, 790 PJ_FALSE, &alloc->hkey.clt_addr, 791 pj_sockaddr_get_len(&alloc->hkey.clt_addr), 789 status = pj_stun_session_send_msg(alloc->sess, NULL, PJ_TRUE, 790 PJ_FALSE, &alloc->hkey.clt_addr, 791 pj_sockaddr_get_len(&alloc->hkey.clt_addr), 792 792 tdata); 793 793 if (status != PJ_SUCCESS) { … … 807 807 perm = PJ_POOL_ZALLOC_T(alloc->pool, pj_turn_permission); 808 808 pj_memcpy(&perm->hkey.peer_addr, peer_addr, addr_len); 809 809 810 810 perm->allocation = alloc; 811 811 perm->channel = PJ_TURN_INVALID_CHANNEL; … … 815 815 816 816 /* Register to hash table (only the address part!) */ 817 pj_hash_set(alloc->pool, alloc->peer_table, 818 pj_sockaddr_get_addr(&perm->hkey.peer_addr), 817 pj_hash_set(alloc->pool, alloc->peer_table, 818 pj_sockaddr_get_addr(&perm->hkey.peer_addr), 819 819 pj_sockaddr_get_addr_len(&perm->hkey.peer_addr), 0, perm); 820 820 … … 835 835 836 836 /* Remove from permission hash table */ 837 pj_hash_set(NULL, alloc->peer_table, 838 pj_sockaddr_get_addr(&perm->hkey.peer_addr), 837 pj_hash_set(NULL, alloc->peer_table, 838 pj_sockaddr_get_addr(&perm->hkey.peer_addr), 839 839 pj_sockaddr_get_addr_len(&perm->hkey.peer_addr), 0, NULL); 840 840 841 841 /* Remove from channel hash table, if assigned a channel number */ 842 842 if (perm->channel != PJ_TURN_INVALID_CHANNEL) { 843 pj_hash_set(NULL, alloc->ch_table, &perm->channel, 843 pj_hash_set(NULL, alloc->ch_table, &perm->channel, 844 844 sizeof(perm->channel), 0, NULL); 845 845 } … … 859 859 860 860 /* Lookup in peer hash table */ 861 perm = (pj_turn_permission*) 862 pj_hash_get(alloc->peer_table, 861 perm = (pj_turn_permission*) 862 pj_hash_get(alloc->peer_table, 863 863 pj_sockaddr_get_addr(peer_addr), 864 pj_sockaddr_get_addr_len(peer_addr), 864 pj_sockaddr_get_addr_len(peer_addr), 865 865 NULL); 866 866 return perm ? check_permission_expiry(perm) : NULL; … … 881 881 } 882 882 883 /* Update permission because of data from client to peer. 883 /* Update permission because of data from client to peer. 884 884 * Return PJ_TRUE is permission is found. 885 885 */ … … 917 917 * callbacks. 918 918 * 919 * Note: currently it is necessary to specify the 919 * Note: currently it is necessary to specify the 920 920 * PJ_STUN_NO_FINGERPRINT_CHECK otherwise the FINGERPRINT 921 921 * attribute inside STUN Send Indication message will mess up … … 930 930 status = pj_stun_session_on_rx_pkt(alloc->sess, pkt->pkt, pkt->len, 931 931 options, NULL, &parsed_len, 932 &pkt->src.clt_addr, 932 &pkt->src.clt_addr, 933 933 pkt->src_addr_len); 934 934 … … 963 963 if (alloc->transport->listener->tp_type == PJ_TURN_TP_UDP) { 964 964 if (pkt->len < pj_ntohs(cd->length)+sizeof(*cd)) { 965 PJ_LOG(4,(alloc->obj_name, 965 PJ_LOG(4,(alloc->obj_name, 966 966 "ChannelData from %s discarded: UDP size error", 967 967 alloc->info)); … … 976 976 if (!perm) { 977 977 /* Discard */ 978 PJ_LOG(4,(alloc->obj_name, 978 PJ_LOG(4,(alloc->obj_name, 979 979 "ChannelData from %s discarded: ch#0x%x not found", 980 980 alloc->info, pj_ntohs(cd->ch_number))); … … 999 999 1000 1000 /* 1001 * Handle incoming packet from peer. This function is called by 1001 * Handle incoming packet from peer. This function is called by 1002 1002 * on_rx_from_peer(). 1003 1003 */ … … 1010 1010 1011 1011 /* Lookup permission */ 1012 perm = lookup_permission_by_addr(alloc, src_addr, 1012 perm = lookup_permission_by_addr(alloc, src_addr, 1013 1013 pj_sockaddr_get_len(src_addr)); 1014 1014 if (perm == NULL) { … … 1050 1050 pj_status_t status; 1051 1051 1052 status = pj_stun_session_create_ind(alloc->sess, 1052 status = pj_stun_session_create_ind(alloc->sess, 1053 1053 PJ_STUN_DATA_INDICATION, &tdata); 1054 1054 if (status != PJ_SUCCESS) { … … 1057 1057 } 1058 1058 1059 pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 1059 pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 1060 1060 PJ_STUN_ATTR_XOR_PEER_ADDR, PJ_TRUE, 1061 1061 src_addr, pj_sockaddr_get_len(src_addr)); 1062 1062 pj_stun_msg_add_binary_attr(tdata->pool, tdata->msg, 1063 PJ_STUN_ATTR_DATA, 1063 PJ_STUN_ATTR_DATA, 1064 1064 (const pj_uint8_t*)pkt, len); 1065 1065 1066 pj_stun_session_send_msg(alloc->sess, NULL, PJ_FALSE, 1067 PJ_FALSE, &alloc->hkey.clt_addr, 1068 pj_sockaddr_get_len(&alloc->hkey.clt_addr), 1066 pj_stun_session_send_msg(alloc->sess, NULL, PJ_FALSE, 1067 PJ_FALSE, &alloc->hkey.clt_addr, 1068 pj_sockaddr_get_len(&alloc->hkey.clt_addr), 1069 1069 tdata); 1070 1070 } … … 1074 1074 * ioqueue notification on RX packets from the relay socket. 1075 1075 */ 1076 static void on_rx_from_peer(pj_ioqueue_key_t *key, 1077 pj_ioqueue_op_key_t *op_key, 1076 static void on_rx_from_peer(pj_ioqueue_key_t *key, 1077 pj_ioqueue_op_key_t *op_key, 1078 1078 pj_ssize_t bytes_read) 1079 1079 { … … 1097 1097 status = pj_ioqueue_recvfrom(key, op_key, 1098 1098 rel->tp.rx_pkt, &bytes_read, 0, 1099 &rel->tp.src_addr, 1099 &rel->tp.src_addr, 1100 1100 &rel->tp.src_addr_len); 1101 1101 … … 1157 1157 if (alloc->relay.lifetime == 0) { 1158 1158 /* Reject with 437 if we're shutting down */ 1159 send_reply_err(alloc, rdata, PJ_TRUE, 1159 send_reply_err(alloc, rdata, PJ_TRUE, 1160 1160 PJ_STUN_SC_ALLOCATION_MISMATCH, NULL); 1161 1161 return PJ_SUCCESS; … … 1163 1163 1164 1164 if (msg->hdr.type == PJ_STUN_REFRESH_REQUEST) { 1165 /* 1166 * Handle REFRESH request 1165 /* 1166 * Handle REFRESH request 1167 1167 */ 1168 1168 pj_stun_lifetime_attr *lifetime; … … 1176 1176 bandwidth = (pj_stun_bandwidth_attr*) 1177 1177 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_BANDWIDTH, 0); 1178 1179 /* TODO: process bandwidth */ 1180 PJ_UNUSED_ARG(bandwidth); 1178 1181 1179 1182 if (lifetime && lifetime->value==0) { … … 1187 1190 1188 1191 /* Shutdown allocation */ 1189 PJ_LOG(4,(alloc->obj_name, 1192 PJ_LOG(4,(alloc->obj_name, 1190 1193 "Client %s request to dealloc, shutting down", 1191 1194 alloc->info)); … … 1197 1200 * This is a refresh request. 1198 1201 */ 1199 1202 1200 1203 /* Update lifetime */ 1201 1204 if (lifetime) { … … 1227 1230 1228 1231 if (!ch_attr || !peer_attr) { 1229 send_reply_err(alloc, rdata, PJ_TRUE, 1232 send_reply_err(alloc, rdata, PJ_TRUE, 1230 1233 PJ_STUN_SC_BAD_REQUEST, NULL); 1231 1234 return PJ_SUCCESS; … … 1235 1238 p1 = lookup_permission_by_chnum(alloc, PJ_STUN_GET_CH_NB(ch_attr->value)); 1236 1239 1237 /* If permission is found, this is supposed to be a channel bind 1240 /* If permission is found, this is supposed to be a channel bind 1238 1241 * refresh. Make sure it's for the same peer. 1239 1242 */ … … 1241 1244 if (pj_sockaddr_cmp(&p1->hkey.peer_addr, &peer_attr->sockaddr)) { 1242 1245 /* Address mismatch. Send 400 */ 1243 send_reply_err(alloc, rdata, PJ_TRUE, 1244 PJ_STUN_SC_BAD_REQUEST, 1246 send_reply_err(alloc, rdata, PJ_TRUE, 1247 PJ_STUN_SC_BAD_REQUEST, 1245 1248 "Peer address mismatch"); 1246 1249 return PJ_SUCCESS; … … 1263 1266 pj_sockaddr_get_len(&peer_attr->sockaddr)); 1264 1267 if (p2 && p2->channel != PJ_TURN_INVALID_CHANNEL) { 1265 send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, 1268 send_reply_err(alloc, rdata, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, 1266 1269 "Peer address already assigned a channel number"); 1267 1270 return PJ_SUCCESS; … … 1281 1284 /* Register to hash table */ 1282 1285 pj_assert(sizeof(p2->channel==2)); 1283 pj_hash_set(alloc->pool, alloc->ch_table, &p2->channel, 1286 pj_hash_set(alloc->pool, alloc->ch_table, &p2->channel, 1284 1287 sizeof(p2->channel), 0, p2); 1285 1288 … … 1368 1371 /* Relay the data to peer */ 1369 1372 len = data_attr->length; 1370 pj_sock_sendto(alloc->relay.tp.sock, data_attr->data, 1373 pj_sock_sendto(alloc->relay.tp.sock, data_attr->data, 1371 1374 &len, 0, &peer_attr->sockaddr, 1372 1375 pj_sockaddr_get_len(&peer_attr->sockaddr)); -
pjproject/trunk/pjnath/src/pjturn-srv/server.c
r4360 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include "turn.h" … … 77 77 * Create server. 78 78 */ 79 PJ_DEF(pj_status_t) pj_turn_srv_create(pj_pool_factory *pf, 79 PJ_DEF(pj_status_t) pj_turn_srv_create(pj_pool_factory *pf, 80 80 pj_turn_srv **p_srv) 81 81 { … … 95 95 srv->core.pool = pool; 96 96 srv->core.tls_key = srv->core.tls_data = -1; 97 97 98 98 /* Create ioqueue */ 99 99 status = pj_ioqueue_create(pool, MAX_HANDLES, &srv->core.ioqueue); … … 102 102 103 103 /* Server mutex */ 104 status = pj_lock_create_recursive_mutex(pool, srv->obj_name, 104 status = pj_lock_create_recursive_mutex(pool, srv->obj_name, 105 105 &srv->core.lock); 106 106 if (status != PJ_SUCCESS) … … 115 115 if (status != PJ_SUCCESS) 116 116 goto on_error; 117 117 118 118 /* Create timer heap */ 119 119 status = pj_timer_heap_create(pool, MAX_TIMER, &srv->core.timer_heap); … … 126 126 /* Array of listeners */ 127 127 srv->core.listener = (pj_turn_listener**) 128 pj_pool_calloc(pool, MAX_LISTENERS, 128 pj_pool_calloc(pool, MAX_LISTENERS, 129 129 sizeof(srv->core.listener[0])); 130 130 … … 170 170 srv->core.thread_cnt = MAX_THREADS; 171 171 srv->core.thread = (pj_thread_t**) 172 pj_pool_calloc(pool, srv->core.thread_cnt, 172 pj_pool_calloc(pool, srv->core.thread_cnt, 173 173 sizeof(pj_thread_t*)); 174 174 175 175 /* Start the worker threads */ 176 176 for (i=0; i<srv->core.thread_cnt; ++i) { 177 status = pj_thread_create(pool, srv->obj_name, &server_thread_proc, 177 status = pj_thread_create(pool, srv->obj_name, &server_thread_proc, 178 178 srv, 0, 0, &srv->core.thread[i]); 179 179 if (status != PJ_SUCCESS) … … 182 182 183 183 /* We're done. Application should add listeners now */ 184 PJ_LOG(4,(srv->obj_name, "TURN server v%s is running", 184 PJ_LOG(4,(srv->obj_name, "TURN server v%s is running", 185 185 pj_get_version())); 186 186 … … 194 194 195 195 196 /* 197 * Handle timer and network events 196 /* 197 * Handle timer and network events 198 198 */ 199 199 static void srv_handle_events(pj_turn_srv *srv, const pj_time_val *max_timeout) … … 204 204 int c; 205 205 206 /* Poll the timer. The timer heap has its own mutex for better 207 * granularity, so we don't need to lock the server. 206 /* Poll the timer. The timer heap has its own mutex for better 207 * granularity, so we don't need to lock the server. 208 208 */ 209 209 timeout.sec = timeout.msec = 0; … … 223 223 } 224 224 225 /* Poll ioqueue. 225 /* Poll ioqueue. 226 226 * Repeat polling the ioqueue while we have immediate events, because 227 227 * timer heap may process more than one events, so if we only process … … 293 293 } 294 294 } 295 295 296 296 /* Destroy all listeners. */ 297 297 for (i=0; i<srv->core.lis_cnt; ++i) { … … 313 313 srv->tables.res = NULL; 314 314 } 315 315 316 316 /* Destroy timer heap */ 317 317 if (srv->core.timer_heap) { … … 461 461 462 462 463 /* Callback from our own STUN session whenever it needs to send 463 /* Callback from our own STUN session whenever it needs to send 464 464 * outgoing STUN packet. 465 465 */ … … 472 472 { 473 473 pj_turn_transport *transport = (pj_turn_transport*) token; 474 474 475 475 PJ_ASSERT_RETURN(transport!=NULL, PJ_EINVALIDOP); 476 476 477 477 PJ_UNUSED_ARG(sess); 478 478 479 return transport->sendto(transport, pdu, pdu_size, 0, 479 return transport->sendto(transport, pdu, pdu_size, 0, 480 480 dst_addr, addr_len); 481 481 } … … 483 483 484 484 /* Respond to STUN request */ 485 static pj_status_t stun_respond(pj_stun_session *sess, 485 static pj_status_t stun_respond(pj_stun_session *sess, 486 486 pj_turn_transport *transport, 487 487 const pj_stun_rx_data *rdata, 488 unsigned code, 488 unsigned code, 489 489 const char *errmsg, 490 pj_bool_t cache, 491 const pj_sockaddr_t *dst_addr, 490 pj_bool_t cache, 491 const pj_sockaddr_t *dst_addr, 492 492 unsigned addr_len) 493 493 { … … 497 497 498 498 /* Create response */ 499 status = pj_stun_session_create_res(sess, rdata, code, 499 status = pj_stun_session_create_res(sess, rdata, code, 500 500 (errmsg?pj_cstr(&reason,errmsg):NULL), 501 501 &tdata); … … 504 504 505 505 /* Send the response */ 506 return pj_stun_session_send_msg(sess, transport, cache, PJ_FALSE, 506 return pj_stun_session_send_msg(sess, transport, cache, PJ_FALSE, 507 507 dst_addr, addr_len, tdata); 508 508 } … … 523 523 pj_turn_transport *transport; 524 524 const pj_stun_msg *msg = rdata->msg; 525 pj_turn_srv *srv;526 525 pj_turn_allocation *alloc; 527 526 pj_status_t status; … … 531 530 532 531 transport = (pj_turn_transport*) token; 533 srv = transport->listener->server;534 532 535 533 /* Respond any requests other than ALLOCATE with 437 response */ … … 570 568 571 569 /* Create response */ 572 status = pj_stun_msg_create_response(pkt->pool, request, 0, NULL, 570 status = pj_stun_msg_create_response(pkt->pool, request, 0, NULL, 573 571 &response); 574 572 if (status != PJ_SUCCESS) … … 576 574 577 575 /* Add XOR-MAPPED-ADDRESS */ 578 pj_stun_msg_add_sockaddr_attr(pkt->pool, response, 576 pj_stun_msg_add_sockaddr_attr(pkt->pool, response, 579 577 PJ_STUN_ATTR_XOR_MAPPED_ADDR, 580 578 PJ_TRUE, … … 588 586 589 587 /* Send response */ 590 pkt->transport->sendto(pkt->transport, pdu, len, 0, 588 pkt->transport->sendto(pkt->transport, pdu, len, 0, 591 589 &pkt->src.clt_addr, pkt->src_addr_len); 592 590 } … … 599 597 * if an allocation is not found. 600 598 */ 601 PJ_DEF(void) pj_turn_srv_on_rx_pkt(pj_turn_srv *srv, 599 PJ_DEF(void) pj_turn_srv_on_rx_pkt(pj_turn_srv *srv, 602 600 pj_turn_pkt *pkt) 603 601 { … … 639 637 if ((*pkt->pkt != 0x00 && *pkt->pkt != 0x01) || 640 638 pkt->len > 1600 || 641 (options & PJ_STUN_IS_DATAGRAM)) 639 (options & PJ_STUN_IS_DATAGRAM)) 642 640 { 643 641 char errmsg[PJ_ERR_MSG_SIZE]; … … 647 645 648 646 pj_strerror(status, errmsg, sizeof(errmsg)); 649 PJ_LOG(5,(srv->obj_name, 647 PJ_LOG(5,(srv->obj_name, 650 648 "Non-STUN packet from %s is dropped: %s", 651 649 pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), … … 655 653 } 656 654 657 /* Special handling for Binding Request. We won't give it to the 655 /* Special handling for Binding Request. We won't give it to the 658 656 * STUN session since this request is not authenticated. 659 657 */ … … 669 667 options &= ~PJ_STUN_CHECK_PACKET; 670 668 parsed_len = 0; 671 status = pj_stun_session_on_rx_pkt(srv->core.stun_sess, pkt->pkt, 669 status = pj_stun_session_on_rx_pkt(srv->core.stun_sess, pkt->pkt, 672 670 pkt->len, options, pkt->transport, 673 &parsed_len, &pkt->src.clt_addr, 671 &parsed_len, &pkt->src.clt_addr, 674 672 pkt->src_addr_len); 675 673 if (status != PJ_SUCCESS) { … … 678 676 679 677 pj_strerror(status, errmsg, sizeof(errmsg)); 680 PJ_LOG(5,(srv->obj_name, 678 PJ_LOG(5,(srv->obj_name, 681 679 "Error processing STUN packet from %s: %s", 682 680 pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), -
pjproject/trunk/pjsip-apps/src/pjsystest/systest.c
r4537 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * … … 15 15 * You should have received a copy of the GNU General Public License 16 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 19 19 #include "systest.h" … … 57 57 static gui_menu menu_getsets = { "View Settings", &systest_display_settings }; 58 58 59 static gui_menu menu_tests = { 60 "Tests", NULL, 61 10, 59 static gui_menu menu_tests = { 60 "Tests", NULL, 61 10, 62 62 { 63 63 &menu_wizard, 64 &menu_audtest, 64 &menu_audtest, 65 65 &menu_playtn, 66 66 &menu_playwv1, … … 69 69 &menu_calclat, 70 70 &menu_sndaec, 71 NULL, 71 NULL, 72 72 &menu_exit 73 73 } 74 74 }; 75 75 76 static gui_menu menu_options = { 77 "Options", NULL, 78 2, 76 static gui_menu menu_options = { 77 "Options", NULL, 78 2, 79 79 { 80 80 &menu_listdev, … … 83 83 }; 84 84 85 static gui_menu root_menu = { 86 "Root", NULL, 2, {&menu_tests, &menu_options} 85 static gui_menu root_menu = { 86 "Root", NULL, 2, {&menu_tests, &menu_options} 87 87 }; 88 88 … … 134 134 else 135 135 errmsg[0] = '\0'; 136 136 137 137 strcpy(themsg, title); 138 138 strncat(themsg, errmsg, sizeof(themsg)-1); … … 159 159 160 160 /***************************************************************************** 161 * test: play simple ringback tone and hear it 161 * test: play simple ringback tone and hear it 162 162 */ 163 163 static void systest_play_tone(void) … … 202 202 203 203 pool = pjsua_pool_create("ringback", 512, 512); 204 samples_per_frame = systest.media_cfg.audio_frame_ptime * 204 samples_per_frame = systest.media_cfg.audio_frame_ptime * 205 205 systest.media_cfg.clock_rate * 206 206 systest.media_cfg.channel_count / 1000; … … 208 208 /* Ringback tone (call is ringing) */ 209 209 name = pj_str("ringback"); 210 status = pjmedia_tonegen_create2(pool, &name, 210 status = pjmedia_tonegen_create2(pool, &name, 211 211 systest.media_cfg.clock_rate, 212 systest.media_cfg.channel_count, 212 systest.media_cfg.channel_count, 213 213 samples_per_frame, 214 16, PJMEDIA_TONEGEN_LOOP, 214 16, PJMEDIA_TONEGEN_LOOP, 215 215 &ringback_port); 216 216 if (status != PJ_SUCCESS) … … 270 270 * the file. 271 271 */ 272 static pj_status_t create_player(unsigned path_cnt, const char *paths[], 272 static pj_status_t create_player(unsigned path_cnt, const char *paths[], 273 273 pjsua_player_id *p_id) 274 274 { … … 365 365 366 366 /***************************************************************************** 367 * test: record audio 367 * test: record audio 368 368 */ 369 369 static void systest_rec_audio(void) … … 388 388 "from the microphone, and playback the " 389 389 "audio to the speaker. Press OK to start recording, " 390 "CANCEL to skip.", 390 "CANCEL to skip.", 391 391 WITH_OKCANCEL); 392 392 if (key != KEY_OK) { … … 433 433 "The recorded audio is being played now to " 434 434 "the speaker device, in a loop. Listen for " 435 "any audio impairments. Press OK to stop.", 435 "any audio impairments. Press OK to stop.", 436 436 WITH_OK); 437 437 … … 526 526 param.clock_rate = systest.media_cfg.snd_clock_rate; 527 527 param.channel_count = systest.media_cfg.channel_count; 528 param.samples_per_frame = param.clock_rate * param.channel_count * 528 param.samples_per_frame = param.clock_rate * param.channel_count * 529 529 systest.media_cfg.audio_frame_ptime / 1000; 530 530 531 531 /* Latency settings */ 532 param.flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY | 532 param.flags |= (PJMEDIA_AUD_DEV_CAP_INPUT_LATENCY | 533 533 PJMEDIA_AUD_DEV_CAP_OUTPUT_LATENCY); 534 534 param.input_latency_ms = systest.media_cfg.snd_rec_latency; … … 554 554 555 555 if (result.rec.frame_cnt==0) { 556 problems[problem_count++] = 556 problems[problem_count++] = 557 557 "No audio frames were captured from the microphone. " 558 558 "This means the audio device is not working properly."; 559 559 } else { 560 pj_ansi_snprintf(textbuf+textbufpos, 560 pj_ansi_snprintf(textbuf+textbufpos, 561 561 sizeof(textbuf)-textbufpos, 562 562 "Rec : interval (min/max/avg/dev)=\r\n" … … 571 571 572 572 if (result.rec.max_burst > GOOD_MAX_INTERVAL) { 573 problems[problem_count++] = 573 problems[problem_count++] = 574 574 "Recording max burst is quite high"; 575 575 } … … 577 577 578 578 if (result.play.frame_cnt==0) { 579 problems[problem_count++] = 579 problems[problem_count++] = 580 580 "No audio frames were played to the speaker. " 581 581 "This means the audio device is not working properly."; 582 582 } else { 583 pj_ansi_snprintf(textbuf+textbufpos, 583 pj_ansi_snprintf(textbuf+textbufpos, 584 584 sizeof(textbuf)-textbufpos, 585 585 "Play: interval (min/max/avg/dev)=\r\n" … … 594 594 595 595 if (result.play.max_burst > GOOD_MAX_INTERVAL) { 596 problems[problem_count++] = 596 problems[problem_count++] = 597 597 "Playback max burst is quite high"; 598 598 } … … 601 601 if (result.rec_drift_per_sec) { 602 602 const char *which = result.rec_drift_per_sec>=0 ? "faster" : "slower"; 603 unsigned drift = result.rec_drift_per_sec>=0 ? 603 unsigned drift = result.rec_drift_per_sec>=0 ? 604 604 result.rec_drift_per_sec : 605 605 -result.rec_drift_per_sec; … … 614 614 615 615 if (problem_count == 0) { 616 pj_ansi_snprintf(textbuf+textbufpos, 616 pj_ansi_snprintf(textbuf+textbufpos, 617 617 sizeof(textbuf)-textbufpos, 618 618 "\r\nThe sound device seems to be okay!"); … … 624 624 625 625 pj_ansi_snprintf(textbuf+textbufpos, 626 sizeof(textbuf)-textbufpos, 626 sizeof(textbuf)-textbufpos, 627 627 "There could be %d problem(s) with the " 628 628 "sound device:\r\n", … … 632 632 for (i=0; i<problem_count; ++i) { 633 633 pj_ansi_snprintf(textbuf+textbufpos, 634 sizeof(textbuf)-textbufpos, 634 sizeof(textbuf)-textbufpos, 635 635 " %d: %s\r\n", i+1, problems[i]); 636 636 textbufpos = strlen(textbuf); … … 650 650 */ 651 651 static int calculate_latency(pj_pool_t *pool, pjmedia_port *wav, 652 unsigned *lat_sum, unsigned *lat_cnt, 652 unsigned *lat_sum, unsigned *lat_cnt, 653 653 unsigned *lat_min, unsigned *lat_max) 654 654 { … … 689 689 } 690 690 691 /* Zero the first 500ms to remove loud click noises 691 /* Zero the first 500ms to remove loud click noises 692 692 * (keypad press, etc.) 693 693 */ … … 784 784 return; 785 785 } 786 key = gui_msgbox(title, 786 key = gui_msgbox(title, 787 787 "For this test to work, we must be able to capture " 788 788 "the audio played in the speaker (the echo), and only" … … 798 798 PJ_LOG(3,(THIS_FILE, "Running %s", title)); 799 799 800 status = create_player(PJ_ARRAY_SIZE(ref_wav_paths), ref_wav_paths, 800 status = create_player(PJ_ARRAY_SIZE(ref_wav_paths), ref_wav_paths, 801 801 &play_id); 802 802 if (status != PJ_SUCCESS) … … 817 817 status = pjsua_conf_connect(0, rec_slot); 818 818 status = pjsua_conf_connect(play_slot, rec_slot); 819 819 820 820 821 821 /* We're running */ … … 870 870 goto on_return; 871 871 872 status = calculate_latency(pool, wav_port, &lat_sum, &lat_cnt, 872 status = calculate_latency(pool, wav_port, &lat_sum, &lat_cnt, 873 873 &lat_min, &lat_max); 874 874 if (status != PJ_SUCCESS) … … 913 913 msglen = strlen(msg); 914 914 } 915 915 916 916 key = gui_msgbox(title, msg, WITH_OK); 917 917 … … 965 965 * Create player and recorder 966 966 */ 967 status = create_player(PJ_ARRAY_SIZE(ref_wav_paths), ref_wav_paths, 967 status = create_player(PJ_ARRAY_SIZE(ref_wav_paths), ref_wav_paths, 968 968 &player_id); 969 969 if (status != PJ_SUCCESS) { … … 1018 1018 gui_msgbox(title, "We are now playing the captured audio from the mic. " 1019 1019 "Check if echo (of the audio played back previously) is " 1020 "present in the audio. The recording is stored in " 1020 "present in the audio. The recording is stored in " 1021 1021 AEC_REC_PATH " for offline analysis. " 1022 1022 "Press OK to stop.", … … 1074 1074 enum gui_key key; 1075 1075 const char *title = "Audio Device List"; 1076 1076 1077 1077 ti = systest_alloc_test_item(title); 1078 1078 if (!ti) … … 1083 1083 dev_count = pjmedia_aud_dev_count(); 1084 1084 if (dev_count == 0) { 1085 key = gui_msgbox(title, 1085 key = gui_msgbox(title, 1086 1086 "No audio devices are found", WITH_OK); 1087 1087 ti->success = PJ_FALSE; … … 1107 1107 pj_ansi_snprintf(ti->reason+len, sizeof(ti->reason)-len, 1108 1108 " %2d: %s [%s] (%d/%d)\r\n", 1109 i, info.driver, info.name, 1109 i, info.driver, info.name, 1110 1110 info.input_count, info.output_count); 1111 1111 len = strlen(ti->reason); … … 1114 1114 ti->reason[len] = '\0'; 1115 1115 key = gui_msgbox(title, ti->reason, WITH_OK); 1116 PJ_UNUSED_ARG(key); 1116 1117 1117 1118 ti->success = PJ_TRUE; … … 1205 1206 ti->reason[sizeof(ti->reason)-1] = '\0'; 1206 1207 key = gui_msgbox(title, textbuf, WITH_OK); 1207 1208 PJ_UNUSED_ARG(key); /* Warning about unused var */ 1208 1209 } 1209 1210 … … 1243 1244 systest.media_cfg.snd_rec_latency = OVERRIDE_AUDDEV_REC_LAT; 1244 1245 #endif 1245 1246 1246 1247 status = pjsua_init(&systest.ua_cfg, &log_cfg, &systest.media_cfg); 1247 1248 if (status != PJ_SUCCESS) { -
pjproject/trunk/pjsip/src/pjsip/sip_auth_client.c
r4537 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 … … 138 138 /* 139 139 * Create response digest based on the parameters and store the 140 * digest ASCII in 'result'. 140 * digest ASCII in 'result'. 141 141 */ 142 142 PJ_DEF(void) pjsip_auth_create_digest( pj_str_t *result, … … 160 160 161 161 if ((cred_info->data_type & PASSWD_MASK) == PJSIP_CRED_DATA_PLAIN_PASSWD) { 162 /*** 163 *** ha1 = MD5(username ":" realm ":" password) 162 /*** 163 *** ha1 = MD5(username ":" realm ":" password) 164 164 ***/ 165 165 pj_md5_init(&pms); … … 183 183 184 184 /*** 185 *** ha2 = MD5(method ":" req_uri) 185 *** ha2 = MD5(method ":" req_uri) 186 186 ***/ 187 187 pj_md5_init(&pms); … … 196 196 /*** 197 197 *** When qop is not used: 198 *** response = MD5(ha1 ":" nonce ":" ha2) 198 *** response = MD5(ha1 ":" nonce ":" ha2) 199 199 *** 200 200 *** When qop=auth is used: … … 218 218 /* This is the final response digest. */ 219 219 pj_md5_final(&pms, digest); 220 220 221 221 /* Convert digest to string and store in chal->response. */ 222 222 result->slen = PJSIP_MD5STRLEN; … … 259 259 260 260 /* 261 * Generate response digest. 261 * Generate response digest. 262 262 * Most of the parameters to generate the digest (i.e. username, realm, uri, 263 263 * and nonce) are expected to be in the credential. Additional parameters (i.e. … … 308 308 if ((cred_info->data_type & EXT_MASK) == PJSIP_CRED_DATA_EXT_AKA) { 309 309 /* Call application callback to create the response digest */ 310 return (*cred_info->ext.aka.cb)(pool, chal, cred_info, 310 return (*cred_info->ext.aka.cb)(pool, chal, cred_info, 311 311 method, cred); 312 } 312 } 313 313 else { 314 314 /* Convert digest to string and store in chal->response. */ 315 pjsip_auth_create_digest( &cred->response, &cred->nonce, NULL, 316 NULL, NULL, uri, &chal->realm, 315 pjsip_auth_create_digest( &cred->response, &cred->nonce, NULL, 316 NULL, NULL, uri, &chal->realm, 317 317 cred_info, method); 318 318 } 319 319 320 320 } else if (has_auth_qop(pool, &chal->qop)) { 321 /* Server requires quality of protection. 321 /* Server requires quality of protection. 322 322 * We respond with selecting "qop=auth" protection. 323 323 */ … … 335 335 if ((cred_info->data_type & EXT_MASK) == PJSIP_CRED_DATA_EXT_AKA) { 336 336 /* Call application callback to create the response digest */ 337 return (*cred_info->ext.aka.cb)(pool, chal, cred_info, 337 return (*cred_info->ext.aka.cb)(pool, chal, cred_info, 338 338 method, cred); 339 339 } 340 340 else { 341 pjsip_auth_create_digest( &cred->response, &cred->nonce, 342 &cred->nc, cnonce, &pjsip_AUTH_STR, 341 pjsip_auth_create_digest( &cred->response, &cred->nonce, 342 &cred->nc, cnonce, &pjsip_AUTH_STR, 343 343 uri, &chal->realm, cred_info, method ); 344 344 } … … 346 346 } else { 347 347 /* Server requires quality protection that we don't support. */ 348 PJ_LOG(4,(THIS_FILE, "Unsupported qop offer %.*s", 348 PJ_LOG(4,(THIS_FILE, "Unsupported qop offer %.*s", 349 349 chal->qop.slen, chal->qop.ptr)); 350 350 return PJSIP_EINVALIDQOP; … … 358 358 * Update authentication session with a challenge. 359 359 */ 360 static void update_digest_session( pj_pool_t *ses_pool, 360 static void update_digest_session( pj_pool_t *ses_pool, 361 361 pjsip_cached_auth *cached_auth, 362 362 const pjsip_www_authenticate_hdr *hdr ) … … 371 371 * than the one in the cache, to reduce memory usage. 372 372 */ 373 const pjsip_digest_challenge *d1 = 373 const pjsip_digest_challenge *d1 = 374 374 &cached_auth->last_chal->challenge.digest; 375 375 const pjsip_digest_challenge *d2 = &hdr->challenge.digest; … … 407 407 */ 408 408 if (cached_auth->realm.slen == 0) { 409 pj_strdup(ses_pool, &cached_auth->realm, 409 pj_strdup(ses_pool, &cached_auth->realm, 410 410 &hdr->challenge.digest.realm); 411 411 } … … 413 413 } else { 414 414 /* Update last_nonce and nonce-count */ 415 if (!pj_strcmp(&hdr->challenge.digest.nonce, 416 &cached_auth->last_chal->challenge.digest.nonce)) 415 if (!pj_strcmp(&hdr->challenge.digest.nonce, 416 &cached_auth->last_chal->challenge.digest.nonce)) 417 417 { 418 418 /* Same nonce, increment nonce-count */ … … 424 424 /* Has the opaque changed? */ 425 425 if (pj_strcmp(&cached_auth->last_chal->challenge.digest.opaque, 426 &hdr->challenge.digest.opaque)) 426 &hdr->challenge.digest.opaque)) 427 427 { 428 pj_strdup(ses_pool, 428 pj_strdup(ses_pool, 429 429 &cached_auth->last_chal->challenge.digest.opaque, 430 430 &hdr->challenge.digest.opaque); … … 485 485 PJ_DEF(pj_status_t) pjsip_auth_clt_init( pjsip_auth_clt_sess *sess, 486 486 pjsip_endpoint *endpt, 487 pj_pool_t *pool, 487 pj_pool_t *pool, 488 488 unsigned options) 489 489 { … … 510 510 511 511 pjsip_auth_clt_init(sess, (pjsip_endpoint*)rhs->endpt, pool, 0); 512 512 513 513 sess->cred_cnt = rhs->cred_cnt; 514 514 sess->cred_info = (pjsip_cred_info*) 515 pj_pool_alloc(pool, 515 pj_pool_alloc(pool, 516 516 sess->cred_cnt*sizeof(pjsip_cred_info)); 517 517 for (i=0; i<rhs->cred_cnt; ++i) { 518 518 pj_strdup(pool, &sess->cred_info[i].realm, &rhs->cred_info[i].realm); 519 519 pj_strdup(pool, &sess->cred_info[i].scheme, &rhs->cred_info[i].scheme); 520 pj_strdup(pool, &sess->cred_info[i].username, 520 pj_strdup(pool, &sess->cred_info[i].username, 521 521 &rhs->cred_info[i].username); 522 522 sess->cred_info[i].data_type = rhs->cred_info[i].data_type; … … 553 553 sess->cred_info[i].data_type = c[i].data_type; 554 554 555 /* When data_type is PJSIP_CRED_DATA_EXT_AKA, 555 /* When data_type is PJSIP_CRED_DATA_EXT_AKA, 556 556 * callback must be specified. 557 557 */ … … 569 569 570 570 /* Verify K len */ 571 PJ_ASSERT_RETURN(c[i].ext.aka.k.slen <= PJSIP_AKA_KLEN, 571 PJ_ASSERT_RETURN(c[i].ext.aka.k.slen <= PJSIP_AKA_KLEN, 572 572 PJSIP_EAUTHINAKACRED); 573 573 574 574 /* Verify OP len */ 575 PJ_ASSERT_RETURN(c[i].ext.aka.op.slen <= PJSIP_AKA_OPLEN, 575 PJ_ASSERT_RETURN(c[i].ext.aka.op.slen <= PJSIP_AKA_OPLEN, 576 576 PJSIP_EAUTHINAKACRED); 577 577 … … 631 631 632 632 633 /* 633 /* 634 634 * Create Authorization/Proxy-Authorization response header based on the challege 635 635 * in WWW-Authenticate/Proxy-Authenticate header. … … 786 786 if (status != PJ_SUCCESS) 787 787 return status; 788 788 789 789 pjsip_msg_add_hdr( tdata->msg, (pjsip_hdr*)hauth); 790 790 … … 832 832 /* Get the method. */ 833 833 method = &tdata->msg->line.req.method; 834 PJ_UNUSED_ARG(method); /* Warning about unused var caused by #if below */ 834 835 835 836 auth = sess->cached_auth.next; … … 870 871 # endif 871 872 872 } 873 } 873 874 # if defined(PJSIP_AUTH_QOP_SUPPORT) && \ 874 875 defined(PJSIP_AUTH_AUTO_SEND_NEXT) && \ 875 876 (PJSIP_AUTH_QOP_SUPPORT && PJSIP_AUTH_AUTO_SEND_NEXT) 876 877 else if (auth->qop_value == PJSIP_AUTH_QOP_AUTH) { 877 /* For qop="auth", we have to re-create the authorization header. 878 /* For qop="auth", we have to re-create the authorization header. 878 879 */ 879 880 const pjsip_cred_info *cred; … … 881 882 pj_status_t status; 882 883 883 cred = auth_find_cred(sess, &auth->realm, 884 cred = auth_find_cred(sess, &auth->realm, 884 885 &auth->last_chal->scheme); 885 886 if (!cred) { … … 888 889 } 889 890 890 status = auth_respond( tdata->pool, auth->last_chal, 891 tdata->msg->line.req.uri, 891 status = auth_respond( tdata->pool, auth->last_chal, 892 tdata->msg->line.req.uri, 892 893 cred, 893 894 &tdata->msg->line.req.method, … … 895 896 if (status != PJ_SUCCESS) 896 897 return status; 897 898 898 899 //pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hauth); 899 900 pj_list_push_back(&added, hauth); … … 984 985 { 985 986 sent_auth = (pjsip_authorization_hdr*) hdr; 986 if (pj_stricmp(&hchal->challenge.common.realm, 987 if (pj_stricmp(&hchal->challenge.common.realm, 987 988 &sent_auth->credential.common.realm )==0) 988 989 { … … 1055 1056 1056 1057 /* Find credential to be used for the challenge. */ 1057 cred = auth_find_cred( sess, &hchal->challenge.common.realm, 1058 cred = auth_find_cred( sess, &hchal->challenge.common.realm, 1058 1059 &hchal->scheme); 1059 1060 if (!cred) { 1060 1061 const pj_str_t *realm = &hchal->challenge.common.realm; 1061 PJ_LOG(4,(THIS_FILE, 1062 PJ_LOG(4,(THIS_FILE, 1062 1063 "Unable to set auth for %s: can not find credential for %.*s/%.*s", 1063 tdata->obj_name, 1064 tdata->obj_name, 1064 1065 realm->slen, realm->ptr, 1065 1066 hchal->scheme.slen, hchal->scheme.ptr)); … … 1068 1069 1069 1070 /* Respond to authorization challenge. */ 1070 status = auth_respond( req_pool, hchal, uri, cred, 1071 &tdata->msg->line.req.method, 1071 status = auth_respond( req_pool, hchal, uri, cred, 1072 &tdata->msg->line.req.method, 1072 1073 sess->pool, cached_auth, h_auth); 1073 1074 return status; … … 1148 1149 * authorization session. 1149 1150 */ 1150 status = process_auth( tdata->pool, hchal, tdata->msg->line.req.uri, 1151 status = process_auth( tdata->pool, hchal, tdata->msg->line.req.uri, 1151 1152 tdata, sess, cached_auth, &hauth); 1152 1153 if (status != PJ_SUCCESS) -
pjproject/trunk/pjsip/src/pjsip/sip_dialog.c
r4208 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include <pjsip/sip_dialog.h> … … 74 74 return PJ_EINVALIDOP; 75 75 76 pool = pjsip_endpt_create_pool(endpt, "dlg%p", 77 PJSIP_POOL_LEN_DIALOG, 76 pool = pjsip_endpt_create_pool(endpt, "dlg%p", 77 PJSIP_POOL_LEN_DIALOG, 78 78 PJSIP_POOL_INC_DIALOG); 79 79 if (!pool) … … 195 195 dlg->local.info = pjsip_from_hdr_create(dlg->pool); 196 196 pj_strdup_with_null(dlg->pool, &dlg->local.info_str, local_uri); 197 dlg->local.info->uri = pjsip_parse_uri(dlg->pool, 198 dlg->local.info_str.ptr, 197 dlg->local.info->uri = pjsip_parse_uri(dlg->pool, 198 dlg->local.info_str.ptr, 199 199 dlg->local.info_str.slen, 0); 200 200 if (!dlg->local.info->uri) { … … 215 215 216 216 /* Init local contact. */ 217 pj_strdup_with_null(dlg->pool, &tmp, 217 pj_strdup_with_null(dlg->pool, &tmp, 218 218 local_contact ? local_contact : local_uri); 219 219 dlg->local.contact = (pjsip_contact_hdr*) 220 pjsip_parse_hdr(dlg->pool, &HCONTACT, tmp.ptr, 220 pjsip_parse_hdr(dlg->pool, &HCONTACT, tmp.ptr, 221 221 tmp.slen, NULL); 222 222 if (!dlg->local.contact) { … … 228 228 dlg->remote.info = pjsip_to_hdr_create(dlg->pool); 229 229 pj_strdup_with_null(dlg->pool, &dlg->remote.info_str, remote_uri); 230 dlg->remote.info->uri = pjsip_parse_uri(dlg->pool, 231 dlg->remote.info_str.ptr, 230 dlg->remote.info->uri = pjsip_parse_uri(dlg->pool, 231 dlg->remote.info_str.ptr, 232 232 dlg->remote.info_str.slen, 0); 233 233 if (!dlg->remote.info->uri) { … … 240 240 PJSIP_URI_SCHEME_IS_SIPS(dlg->remote.info->uri)) 241 241 { 242 pjsip_sip_uri *sip_uri = (pjsip_sip_uri *) 242 pjsip_sip_uri *sip_uri = (pjsip_sip_uri *) 243 243 pjsip_uri_get_uri(dlg->remote.info->uri); 244 244 if (!pj_list_empty(&sip_uri->header_param)) { … … 249 249 250 250 /* Print URI */ 251 tmp.ptr = (char*) pj_pool_alloc(dlg->pool, 251 tmp.ptr = (char*) pj_pool_alloc(dlg->pool, 252 252 dlg->remote.info_str.slen); 253 253 tmp.slen = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, 254 sip_uri, tmp.ptr, 254 sip_uri, tmp.ptr, 255 255 dlg->remote.info_str.slen); 256 256 … … 283 283 284 284 /* Init client authentication session. */ 285 status = pjsip_auth_clt_init(&dlg->auth_sess, dlg->endpt, 285 status = pjsip_auth_clt_init(&dlg->auth_sess, dlg->endpt, 286 286 dlg->pool, 0); 287 287 if (status != PJ_SUCCESS) … … 333 333 PJSIP_ENOTREQUESTMSG); 334 334 335 /* Request must not have To tag. 335 /* Request must not have To tag. 336 336 * This should have been checked in the user agent (or application?). 337 337 */ 338 338 PJ_ASSERT_RETURN(rdata->msg_info.to->tag.slen == 0, PJ_EINVALIDOP); 339 339 340 340 /* The request must be a dialog establishing request. */ 341 341 PJ_ASSERT_RETURN( … … 385 385 /* TODO: 386 386 * Section 12.1.1, paragraph about using SIPS URI in Contact. 387 * If the request that initiated the dialog contained a SIPS URI 388 * in the Request-URI or in the top Record-Route header field value, 389 * if there was any, or the Contact header field if there was no 387 * If the request that initiated the dialog contained a SIPS URI 388 * in the Request-URI or in the top Record-Route header field value, 389 * if there was any, or the Contact header field if there was no 390 390 * Record-Route header field, the Contact header field in the response 391 391 * MUST be a SIPS URI. … … 396 396 pj_strdup_with_null(dlg->pool, &tmp, contact); 397 397 dlg->local.contact = (pjsip_contact_hdr*) 398 pjsip_parse_hdr(dlg->pool, &HCONTACT, tmp.ptr, 398 pjsip_parse_hdr(dlg->pool, &HCONTACT, tmp.ptr, 399 399 tmp.slen, NULL); 400 400 if (!dlg->local.contact) { … … 409 409 410 410 /* Init remote info from the From header. */ 411 dlg->remote.info = (pjsip_fromto_hdr*) 411 dlg->remote.info = (pjsip_fromto_hdr*) 412 412 pjsip_hdr_clone(dlg->pool, rdata->msg_info.from); 413 413 pjsip_fromto_hdr_set_to(dlg->remote.info); … … 426 426 427 427 428 /* Init remote's contact from Contact header. 428 /* Init remote's contact from Contact header. 429 429 * Iterate the Contact URI until we find sip: or sips: scheme. 430 430 */ … … 452 452 } 453 453 454 dlg->remote.contact = (pjsip_contact_hdr*) 454 dlg->remote.contact = (pjsip_contact_hdr*) 455 455 pjsip_hdr_clone(dlg->pool, (pjsip_hdr*)contact_hdr); 456 456 … … 464 464 dlg->role = PJSIP_ROLE_UAS; 465 465 466 /* Secure? 466 /* Secure? 467 467 * RFC 3261 Section 12.1.1: 468 * If the request arrived over TLS, and the Request-URI contained a 468 * If the request arrived over TLS, and the Request-URI contained a 469 469 * SIPS URI, the 'secure' flag is set to TRUE. 470 470 */ … … 473 473 474 474 /* Call-ID */ 475 dlg->call_id = (pjsip_cid_hdr*) 475 dlg->call_id = (pjsip_cid_hdr*) 476 476 pjsip_hdr_clone(dlg->pool, rdata->msg_info.cid); 477 477 478 /* Route set. 478 /* Route set. 479 479 * RFC 3261 Section 12.1.1: 480 * The route set MUST be set to the list of URIs in the Record-Route 481 * header field from the request, taken in order and preserving all URI 480 * The route set MUST be set to the list of URIs in the Record-Route 481 * header field from the request, taken in order and preserving all URI 482 482 * parameters. If no Record-Route header field is present in the request, 483 483 * the route set MUST be set to the empty set. … … 499 499 if (rr == (void*)&rdata->msg_info.msg->hdr) 500 500 break; 501 rr = (pjsip_route_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, 501 rr = (pjsip_route_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, 502 502 PJSIP_H_RECORD_ROUTE, rr); 503 503 } … … 621 621 /* Check arguments. */ 622 622 PJ_ASSERT_RETURN(first_dlg && rdata && new_dlg, PJ_EINVAL); 623 623 624 624 /* rdata must be response message. */ 625 625 PJ_ASSERT_RETURN(msg->type == PJSIP_RESPONSE_MSG, … … 649 649 650 650 /* Clone local info. */ 651 dlg->local.info = (pjsip_fromto_hdr*) 651 dlg->local.info = (pjsip_fromto_hdr*) 652 652 pjsip_hdr_clone(dlg->pool, first_dlg->local.info); 653 653 … … 661 661 662 662 /* Clone local Contact. */ 663 dlg->local.contact = (pjsip_contact_hdr*) 663 dlg->local.contact = (pjsip_contact_hdr*) 664 664 pjsip_hdr_clone(dlg->pool, first_dlg->local.contact); 665 665 666 666 /* Clone remote info. */ 667 dlg->remote.info = (pjsip_fromto_hdr*) 667 dlg->remote.info = (pjsip_fromto_hdr*) 668 668 pjsip_hdr_clone(dlg->pool, first_dlg->remote.info); 669 669 … … 690 690 691 691 /* Clone Call-ID header. */ 692 dlg->call_id = (pjsip_cid_hdr*) 692 dlg->call_id = (pjsip_cid_hdr*) 693 693 pjsip_hdr_clone(dlg->pool, first_dlg->call_id); 694 694 … … 708 708 709 709 /* Clone client authentication session. */ 710 status = pjsip_auth_clt_clone(dlg->pool, &dlg->auth_sess, 710 status = pjsip_auth_clt_clone(dlg->pool, &dlg->auth_sess, 711 711 &first_dlg->auth_sess); 712 712 if (status != PJ_SUCCESS) … … 842 842 PJ_DEF(void) pjsip_dlg_inc_lock(pjsip_dialog *dlg) 843 843 { 844 PJ_LOG(6,(dlg->obj_name, "Entering pjsip_dlg_inc_lock(), sess_count=%d", 844 PJ_LOG(6,(dlg->obj_name, "Entering pjsip_dlg_inc_lock(), sess_count=%d", 845 845 dlg->sess_count)); 846 846 … … 848 848 dlg->sess_count++; 849 849 850 PJ_LOG(6,(dlg->obj_name, "Leaving pjsip_dlg_inc_lock(), sess_count=%d", 850 PJ_LOG(6,(dlg->obj_name, "Leaving pjsip_dlg_inc_lock(), sess_count=%d", 851 851 dlg->sess_count)); 852 852 } … … 859 859 pj_status_t status; 860 860 861 PJ_LOG(6,(dlg->obj_name,"Entering pjsip_dlg_try_inc_lock(), sess_count=%d", 861 PJ_LOG(6,(dlg->obj_name,"Entering pjsip_dlg_try_inc_lock(), sess_count=%d", 862 862 dlg->sess_count)); 863 863 … … 870 870 dlg->sess_count++; 871 871 872 PJ_LOG(6,(dlg->obj_name, "Leaving pjsip_dlg_try_inc_lock(), sess_count=%d", 872 PJ_LOG(6,(dlg->obj_name, "Leaving pjsip_dlg_try_inc_lock(), sess_count=%d", 873 873 dlg->sess_count)); 874 874 … … 885 885 PJ_ASSERT_ON_FAIL(dlg!=NULL, return); 886 886 887 PJ_LOG(6,(dlg->obj_name, "Entering pjsip_dlg_dec_lock(), sess_count=%d", 887 PJ_LOG(6,(dlg->obj_name, "Entering pjsip_dlg_dec_lock(), sess_count=%d", 888 888 dlg->sess_count)); 889 889 … … 960 960 PJ_ASSERT_RETURN(dlg->usage_cnt < PJSIP_MAX_MODULE, PJ_EBUG); 961 961 962 PJ_LOG(5,(dlg->obj_name, 962 PJ_LOG(5,(dlg->obj_name, 963 963 "Module %.*s added as dialog usage, data=%p", 964 964 (int)mod->name.slen, mod->name.ptr, mod_data)); … … 977 977 * So return PJ_SUCCESS here. 978 978 */ 979 PJ_LOG(4,(dlg->obj_name, 979 PJ_LOG(4,(dlg->obj_name, 980 980 "Module %.*s already registered as dialog usage, " 981 981 "updating the data %p", … … 1000 1000 pj_array_insert(dlg->usage, sizeof(dlg->usage[0]), dlg->usage_cnt, 1001 1001 index, &mod); 1002 1002 1003 1003 /* Set module data. */ 1004 1004 dlg->mod_data[mod->id] = mod_data; … … 1014 1014 1015 1015 /* 1016 * Attach module specific data to the dialog. Application can also set 1016 * Attach module specific data to the dialog. Application can also set 1017 1017 * the value directly by accessing dlg->mod_data[module_id]. 1018 1018 */ … … 1044 1044 /* 1045 1045 * Create a new request within dialog (i.e. after the dialog session has been 1046 * established). The construction of such requests follows the rule in 1046 * established). The construction of such requests follows the rule in 1047 1047 * RFC3261 section 12.2.1. 1048 1048 */ … … 1058 1058 1059 1059 /* Contact Header field. 1060 * Contact can only be present in requests that establish dialog (in the 1060 * Contact can only be present in requests that establish dialog (in the 1061 1061 * core SIP spec, only INVITE). 1062 1062 */ … … 1083 1083 return status; 1084 1084 1085 /* Just copy dialog route-set to Route header. 1085 /* Just copy dialog route-set to Route header. 1086 1086 * The transaction will do the processing as specified in Section 12.2.1 1087 1087 * of RFC 3261 in function tsx_process_route() in sip_transaction.c. … … 1193 1193 */ 1194 1194 if (msg->line.req.method.id != PJSIP_CANCEL_METHOD && 1195 msg->line.req.method.id != PJSIP_ACK_METHOD) 1195 msg->line.req.method.id != PJSIP_ACK_METHOD) 1196 1196 { 1197 1197 pjsip_cseq_hdr *ch; 1198 1198 1199 1199 ch = PJSIP_MSG_CSEQ_HDR(msg); 1200 1200 PJ_ASSERT_RETURN(ch!=NULL, PJ_EBUG); … … 1245 1245 1246 1246 /* Send request */ 1247 status = pjsip_endpt_send_request_stateless(dlg->endpt, tdata, 1247 status = pjsip_endpt_send_request_stateless(dlg->endpt, tdata, 1248 1248 NULL, NULL); 1249 1249 if (status != PJ_SUCCESS) … … 1260 1260 /* Unlock dialog, may destroy dialog. */ 1261 1261 pjsip_dlg_dec_lock(dlg); 1262 1262 1263 1263 /* Whatever happen delete the message. */ 1264 1264 pjsip_tx_data_dec_ref( tdata ); … … 1287 1287 /* Add Contact header for 1xx, 2xx, 3xx and 485 response. */ 1288 1288 if (st_class==2 || st_class==3 || (st_class==1 && st_code != 100) || 1289 st_code==485) 1289 st_code==485) 1290 1290 { 1291 1291 /* Add contact header only if one is not present. */ 1292 1292 if (pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL) == 0 && 1293 pjsip_msg_find_hdr_by_name(tdata->msg, &HCONTACT, NULL) == 0) 1293 pjsip_msg_find_hdr_by_name(tdata->msg, &HCONTACT, NULL) == 0) 1294 1294 { 1295 hdr = (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, 1295 hdr = (pjsip_hdr*) pjsip_hdr_clone(tdata->pool, 1296 1296 dlg->local.contact); 1297 1297 pjsip_msg_add_hdr(tdata->msg, hdr); … … 1302 1302 if ((((st_code/10==18 || st_class==2) && dlg->add_allow) 1303 1303 || st_code==405) && 1304 pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ALLOW, NULL)==NULL) 1304 pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ALLOW, NULL)==NULL) 1305 1305 { 1306 1306 c_hdr = pjsip_endpt_get_capability(dlg->endpt, … … 1313 1313 1314 1314 /* Add Supported header in 2xx response. */ 1315 if (st_class==2 && 1316 pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL)==NULL) 1315 if (st_class==2 && 1316 pjsip_msg_find_hdr(tdata->msg, PJSIP_H_SUPPORTED, NULL)==NULL) 1317 1317 { 1318 1318 c_hdr = pjsip_endpt_get_capability(dlg->endpt, … … 1401 1401 } 1402 1402 1403 /* Remove existing Contact header (without this, when dialog sent 1403 /* Remove existing Contact header (without this, when dialog sent 1404 1404 * 180 and then 302, the Contact in 302 will not get updated). 1405 1405 */ … … 1446 1446 pjsip_tx_data_get_info(tdata))); 1447 1447 1448 /* Check that transaction method and cseq match the response. 1448 /* Check that transaction method and cseq match the response. 1449 1449 * This operation is sloooww (search CSeq header twice), that's why 1450 1450 * we only do it in debug mode. … … 1452 1452 #if defined(PJ_DEBUG) && PJ_DEBUG!=0 1453 1453 PJ_ASSERT_RETURN( PJSIP_MSG_CSEQ_HDR(tdata->msg)->cseq == tsx->cseq && 1454 pjsip_method_cmp(&PJSIP_MSG_CSEQ_HDR(tdata->msg)->method, 1454 pjsip_method_cmp(&PJSIP_MSG_CSEQ_HDR(tdata->msg)->method, 1455 1455 &tsx->method)==0, 1456 1456 PJ_EINVALIDOP); … … 1478 1478 status = pjsip_tsx_send_msg(tsx, tdata); 1479 1479 1480 /* This function must decrement transmit data request counter 1480 /* This function must decrement transmit data request counter 1481 1481 * regardless of the operation status. The transaction only 1482 1482 * decrements the counter if the operation is successful. … … 1563 1563 if (rdata->msg_info.cseq->cseq <= dlg->remote.cseq && 1564 1564 rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD && 1565 rdata->msg_info.msg->line.req.method.id != PJSIP_CANCEL_METHOD) 1565 rdata->msg_info.msg->line.req.method.id != PJSIP_CANCEL_METHOD) 1566 1566 { 1567 1567 /* Invalid CSeq. … … 1595 1595 1596 1596 /* Create UAS transaction for this request. */ 1597 if (pjsip_rdata_get_tsx(rdata) == NULL && 1598 rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) 1597 if (pjsip_rdata_get_tsx(rdata) == NULL && 1598 rdata->msg_info.msg->line.req.method.id != PJSIP_ACK_METHOD) 1599 1599 { 1600 1600 status = pjsip_tsx_create_uas(dlg->ua, rdata, &tsx); … … 1630 1630 1631 1631 contact = (pjsip_contact_hdr*) 1632 pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, 1632 pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, 1633 1633 NULL); 1634 1634 if (contact && contact->uri && … … 1638 1638 contact->uri))) 1639 1639 { 1640 dlg->remote.contact = (pjsip_contact_hdr*) 1640 dlg->remote.contact = (pjsip_contact_hdr*) 1641 1641 pjsip_hdr_clone(dlg->pool, contact); 1642 1642 dlg->target = dlg->remote.contact->uri; … … 1688 1688 { 1689 1689 const pjsip_hdr *hdr, *end_hdr; 1690 pj_int32_t msg_cseq;1690 //pj_int32_t msg_cseq; 1691 1691 const pjsip_msg *msg; 1692 1692 1693 1693 msg = rdata->msg_info.msg; 1694 msg_cseq = rdata->msg_info.cseq->cseq;1694 //msg_cseq = rdata->msg_info.cseq->cseq; 1695 1695 1696 1696 /* Ignore if route set has been frozen */ … … 1708 1708 1709 1709 /* Ignore subsequent responses with higher CSeq than initial CSeq. 1710 * Unfortunately this would be broken when the first request is 1710 * Unfortunately this would be broken when the first request is 1711 1711 * challenged! 1712 1712 */ … … 1747 1747 PJ_LOG(5,(dlg->obj_name, "Route-set updated")); 1748 1748 1749 /* Freeze the route set only when the route set comes in 2xx response. 1750 * If it is in 1xx response, prepare to recompute the route set when 1749 /* Freeze the route set only when the route set comes in 2xx response. 1750 * If it is in 1xx response, prepare to recompute the route set when 1751 1751 * the 2xx response comes in. 1752 1752 * … … 1756 1756 * upon receiving 2xx response). Also RFC 3261 says so in 13.2.2.4. 1757 1757 * 1758 * The pjsip_method_creates_dialog() check protects from wrongly 1758 * The pjsip_method_creates_dialog() check protects from wrongly 1759 1759 * freezing the route set upon receiving 200/OK response for PRACK. 1760 1760 */ 1761 1761 if (pjsip_method_creates_dialog(&rdata->msg_info.cseq->method) && 1762 PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200)) 1762 PJSIP_IS_STATUS_IN_CLASS(msg->line.status.code, 200)) 1763 1763 { 1764 1764 dlg->route_set_frozen = PJ_TRUE; … … 1789 1789 res_code = rdata->msg_info.msg->line.status.code; 1790 1790 1791 /* When we receive response that establishes dialog, update To tag, 1791 /* When we receive response that establishes dialog, update To tag, 1792 1792 * route set and dialog target. 1793 1793 * … … 1803 1803 * New update: 1804 1804 * We also need to update the dialog for 1xx responses, to handle the 1805 * case when 100rel is used, otherwise PRACK will be sent to the 1805 * case when 100rel is used, otherwise PRACK will be sent to the 1806 1806 * wrong target. 1807 1807 */ 1808 if ((dlg->state == PJSIP_DIALOG_STATE_NULL && 1808 if ((dlg->state == PJSIP_DIALOG_STATE_NULL && 1809 1809 pjsip_method_creates_dialog(&rdata->msg_info.cseq->method) && 1810 1810 (res_code > 100 && res_code < 300) && 1811 rdata->msg_info.to->tag.slen) 1811 rdata->msg_info.to->tag.slen) 1812 1812 || 1813 1813 (dlg->role==PJSIP_ROLE_UAC && … … 1820 1820 pjsip_contact_hdr *contact; 1821 1821 1822 /* Update remote capability info, when To tags in the dialog remote 1822 /* Update remote capability info, when To tags in the dialog remote 1823 1823 * info and the incoming response are different, e.g: first response 1824 1824 * with To-tag or forking, apply strict update. … … 1834 1834 /* RFC 3271 Section 12.1.2: 1835 1835 * The route set MUST be set to the list of URIs in the Record-Route 1836 * header field from the response, taken in reverse order and 1837 * preserving all URI parameters. If no Record-Route header field 1838 * is present in the response, the route set MUST be set to the 1836 * header field from the response, taken in reverse order and 1837 * preserving all URI parameters. If no Record-Route header field 1838 * is present in the response, the route set MUST be set to the 1839 1839 * empty set. This route set, even if empty, overrides any pre-existing 1840 1840 * route set for future requests in this dialog. … … 1842 1842 dlg_update_routeset(dlg, rdata); 1843 1843 1844 /* The remote target MUST be set to the URI from the Contact header 1844 /* The remote target MUST be set to the URI from the Contact header 1845 1845 * field of the response. 1846 1846 */ 1847 1847 contact = (pjsip_contact_hdr*) 1848 pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, 1848 pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, 1849 1849 NULL); 1850 1850 if (contact && contact->uri && … … 1854 1854 contact->uri))) 1855 1855 { 1856 dlg->remote.contact = (pjsip_contact_hdr*) 1856 dlg->remote.contact = (pjsip_contact_hdr*) 1857 1857 pjsip_hdr_clone(dlg->pool, contact); 1858 1858 dlg->target = dlg->remote.contact->uri; … … 1864 1864 * gets through this dialog (it shouldn't happen). 1865 1865 */ 1866 if (dlg->role==PJSIP_ROLE_UAC && !dlg->uac_has_2xx && 1867 res_code/100==2) 1866 if (dlg->role==PJSIP_ROLE_UAC && !dlg->uac_has_2xx && 1867 res_code/100==2) 1868 1868 { 1869 1869 dlg->uac_has_2xx = PJ_TRUE; … … 1872 1872 1873 1873 /* Update remote target (again) when receiving 2xx response messages 1874 * that's defined as target refresh. 1874 * that's defined as target refresh. 1875 1875 * 1876 1876 * Also upon receiving 2xx response, recheck again the route set. … … 1882 1882 the "confirmed" state, and the route set for the dialog MUST be 1883 1883 recomputed based on the 2xx response using the procedures of Section 1884 12.2.1.2. 1884 12.2.1.2. 1885 1885 1886 1886 Note that the only piece of state that is recomputed is the route … … 1897 1897 1898 1898 contact = (pjsip_contact_hdr*) pjsip_msg_find_hdr(rdata->msg_info.msg, 1899 PJSIP_H_CONTACT, 1899 PJSIP_H_CONTACT, 1900 1900 NULL); 1901 1901 if (contact && contact->uri && … … 1905 1905 contact->uri))) 1906 1906 { 1907 dlg->remote.contact = (pjsip_contact_hdr*) 1907 dlg->remote.contact = (pjsip_contact_hdr*) 1908 1908 pjsip_hdr_clone(dlg->pool, contact); 1909 1909 dlg->target = dlg->remote.contact->uri; … … 1943 1943 pj_status_t status; 1944 1944 1945 if (rdata->msg_info.cseq->method.id==PJSIP_INVITE_METHOD && 1946 rdata->msg_info.msg->line.status.code/100 == 2) 1945 if (rdata->msg_info.cseq->method.id==PJSIP_INVITE_METHOD && 1946 rdata->msg_info.msg->line.status.code/100 == 2) 1947 1947 { 1948 1948 pjsip_tx_data *ack; … … 1958 1958 pjsip_transaction *tsx = pjsip_rdata_get_tsx(rdata); 1959 1959 pjsip_tx_data *tdata; 1960 1961 status = pjsip_auth_clt_reinit_req( &dlg->auth_sess, 1960 1961 status = pjsip_auth_clt_reinit_req( &dlg->auth_sess, 1962 1962 rdata, tsx->last_tx, 1963 1963 &tdata); 1964 1964 1965 1965 if (status == PJ_SUCCESS) { 1966 1966 /* Re-send request. */ … … 2015 2015 */ 2016 2016 if (tsx->state == PJSIP_TSX_STATE_TERMINATED && 2017 tsx->mod_data[dlg->ua->id] == dlg) 2017 tsx->mod_data[dlg->ua->id] == dlg) 2018 2018 { 2019 2019 pj_assert(dlg->tsx_count>0); … … 2045 2045 pjsip_dlg_inc_lock(dlg); 2046 2046 2047 hdr = (const pjsip_generic_array_hdr*) 2047 hdr = (const pjsip_generic_array_hdr*) 2048 2048 pjsip_dlg_get_remote_cap_hdr(dlg, htype, hname); 2049 2049 if (!hdr) { … … 2072 2072 pj_bool_t strict) 2073 2073 { 2074 pjsip_hdr_e htypes[] = 2074 pjsip_hdr_e htypes[] = 2075 2075 { PJSIP_H_ACCEPT, PJSIP_H_ALLOW, PJSIP_H_SUPPORTED }; 2076 2076 unsigned i; -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r4724 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include <pjsua-lib/pjsua.h> … … 39 39 * The INFO method. 40 40 */ 41 const pjsip_method pjsip_info_method = 41 const pjsip_method pjsip_info_method = 42 42 { 43 43 PJSIP_OTHER_METHOD, … … 49 49 * session state has changed. 50 50 */ 51 static void pjsua_call_on_state_changed(pjsip_inv_session *inv, 51 static void pjsua_call_on_state_changed(pjsip_inv_session *inv, 52 52 pjsip_event *e); 53 53 … … 55 55 * has forked. 56 56 */ 57 static void pjsua_call_on_forked( pjsip_inv_session *inv, 57 static void pjsua_call_on_forked( pjsip_inv_session *inv, 58 58 pjsip_event *e); 59 59 … … 164 164 /* Check the route URI's and force loose route if required */ 165 165 for (i=0; i<pjsua_var.ua_cfg.outbound_proxy_cnt; ++i) { 166 status = normalize_route_uri(pjsua_var.pool, 166 status = normalize_route_uri(pjsua_var.pool, 167 167 &pjsua_var.ua_cfg.outbound_proxy[i]); 168 168 if (status != PJ_SUCCESS) … … 258 258 #if 1 259 259 /* New algorithm: round-robin */ 260 if (pjsua_var.next_call_id >= (int)pjsua_var.ua_cfg.max_calls || 260 if (pjsua_var.next_call_id >= (int)pjsua_var.ua_cfg.max_calls || 261 261 pjsua_var.next_call_id < 0) 262 262 { … … 264 264 } 265 265 266 for (cid=pjsua_var.next_call_id; 267 cid<(int)pjsua_var.ua_cfg.max_calls; 268 ++cid) 266 for (cid=pjsua_var.next_call_id; 267 cid<(int)pjsua_var.ua_cfg.max_calls; 268 ++cid) 269 269 { 270 270 if (pjsua_var.calls[cid].inv == NULL && … … 310 310 if (pj_stristr(dst_uri, &sips)) 311 311 return 2; 312 312 313 313 if (!pj_list_empty(&acc->route_set)) { 314 314 pjsip_route_hdr *r = acc->route_set.next; 315 315 pjsip_uri *uri = r->name_addr.uri; 316 316 pjsip_sip_uri *sip_uri; 317 317 318 318 sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri); 319 319 if (pj_stricmp2(&sip_uri->transport_param, "tls")==0) … … 338 338 pjsip_uri *uri = r->name_addr.uri; 339 339 pjsip_sip_uri *sip_uri; 340 340 341 341 sip_uri = (pjsip_sip_uri*)pjsip_uri_get_uri(uri); 342 342 if (pj_stricmp2(&sip_uri->transport_param, "tls")==0) … … 468 468 /* Set credentials: */ 469 469 if (acc->cred_cnt) { 470 pjsip_auth_clt_set_credentials( &dlg->auth_sess, 470 pjsip_auth_clt_set_credentials( &dlg->auth_sess, 471 471 acc->cred_cnt, acc->cred); 472 472 } … … 479 479 status = pjsip_inv_invite(inv, &tdata); 480 480 if (status != PJ_SUCCESS) { 481 pjsua_perror(THIS_FILE, "Unable to create initial INVITE request", 481 pjsua_perror(THIS_FILE, "Unable to create initial INVITE request", 482 482 status); 483 483 goto on_error; … … 499 499 cb_called = PJ_TRUE; 500 500 501 /* Upon failure to send first request, the invite 501 /* Upon failure to send first request, the invite 502 502 * session would have been cleared. 503 503 */ … … 617 617 618 618 /* Check that account is valid */ 619 PJ_ASSERT_RETURN(acc_id>=0 || acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc), 619 PJ_ASSERT_RETURN(acc_id>=0 || acc_id<(int)PJ_ARRAY_SIZE(pjsua_var.acc), 620 620 PJ_EINVAL); 621 621 … … 631 631 632 632 /* Create sound port if none is instantiated, to check if sound device 633 * can be used. But only do this with the conference bridge, as with 634 * audio switchboard (i.e. APS-Direct), we can only open the sound 633 * can be used. But only do this with the conference bridge, as with 634 * audio switchboard (i.e. APS-Direct), we can only open the sound 635 635 * device once the correct format has been known 636 636 */ 637 if (!pjsua_var.is_mswitch && pjsua_var.snd_port==NULL && 638 pjsua_var.null_snd==NULL && !pjsua_var.no_snd) 637 if (!pjsua_var.is_mswitch && pjsua_var.snd_port==NULL && 638 pjsua_var.null_snd==NULL && !pjsua_var.no_snd) 639 639 { 640 640 status = pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev); … … 679 679 tmp_pool = pjsua_pool_create("tmpcall10", 512, 256); 680 680 681 /* Verify that destination URI is valid before calling 682 * pjsua_acc_create_uac_contact, or otherwise there 681 /* Verify that destination URI is valid before calling 682 * pjsua_acc_create_uac_contact, or otherwise there 683 683 * a misleading "Invalid Contact URI" error will be printed 684 684 * when pjsua_acc_create_uac_contact() fails. … … 692 692 693 693 if (uri == NULL) { 694 pjsua_perror(THIS_FILE, "Unable to make call", 694 pjsua_perror(THIS_FILE, "Unable to make call", 695 695 PJSIP_EINVALIDREQURI); 696 696 status = PJSIP_EINVALIDREQURI; … … 714 714 acc_id, dest_uri); 715 715 if (status != PJ_SUCCESS) { 716 pjsua_perror(THIS_FILE, "Unable to generate Contact header", 716 pjsua_perror(THIS_FILE, "Unable to generate Contact header", 717 717 status); 718 718 goto on_error; … … 721 721 722 722 /* Create outgoing dialog: */ 723 status = pjsip_dlg_create_uac( pjsip_ua_instance(), 723 status = pjsip_dlg_create_uac( pjsip_ua_instance(), 724 724 &acc->cfg.id, &contact, 725 725 dest_uri, … … 745 745 /* Attach user data */ 746 746 call->user_data = user_data; 747 747 748 748 /* Store variables required for the callback after the async 749 749 * media transport creation is completed. … … 762 762 763 763 /* Init media channel */ 764 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC, 764 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAC, 765 765 call->secure_level, dlg->pool, 766 766 NULL, NULL, PJ_TRUE, … … 813 813 814 814 /* Get the NAT type information in remote's SDP */ 815 static void update_remote_nat_type(pjsua_call *call, 815 static void update_remote_nat_type(pjsua_call *call, 816 816 const pjmedia_sdp_session *sdp) 817 817 { … … 900 900 { 901 901 struct call_answer *answer, *next; 902 902 903 903 answer = call->async_call.call_var.inc_call.answers.next; 904 904 while (answer != &call->async_call.call_var.inc_call.answers) { … … 906 906 pjsua_call_answer2(call->index, answer->opt, answer->code, 907 907 answer->reason, answer->msg_data); 908 908 909 909 /* Call might have been disconnected if application is answering 910 910 * with 200/OK and the media failed to start. … … 953 953 954 954 status = pjsua_media_channel_create_sdp(call_id, 955 call->async_call.dlg->pool, 955 call->async_call.dlg->pool, 956 956 offer, &answer, &sip_err_code); 957 957 if (status != PJ_SUCCESS) { … … 977 977 sip_err_code = PJSIP_ERRNO_TO_SIP_STATUS(status); 978 978 goto on_return; 979 } 979 } 980 980 981 981 on_return: … … 1007 1007 if (call->async_call.call_var.inc_call.replaced_dlg) { 1008 1008 /* Process pending call replace */ 1009 pjsip_dialog *replaced_dlg = 1009 pjsip_dialog *replaced_dlg = 1010 1010 call->async_call.call_var.inc_call.replaced_dlg; 1011 1011 process_incoming_call_replace(call, replaced_dlg); … … 1054 1054 /* Don't want to accept the call if shutdown is in progress */ 1055 1055 if (pjsua_var.thread_quit_flag) { 1056 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 1056 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 1057 1057 PJSIP_SC_TEMPORARILY_UNAVAILABLE, NULL, 1058 1058 NULL, NULL); … … 1069 1069 1070 1070 if (call_id == PJSUA_INVALID_ID) { 1071 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 1071 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 1072 1072 PJSIP_SC_BUSY_HERE, NULL, 1073 1073 NULL, NULL); 1074 PJ_LOG(2,(THIS_FILE, 1074 PJ_LOG(2,(THIS_FILE, 1075 1075 "Unable to accept incoming call (too many calls)")); 1076 1076 goto on_return; … … 1098 1098 1099 1099 pjsip_get_response_addr(response->pool, rdata, &res_addr); 1100 pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, response, 1100 pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, response, 1101 1101 NULL, NULL); 1102 1102 … … 1152 1152 st_text = *pjsip_get_status_text(st_code); 1153 1153 1154 pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 1154 pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 1155 1155 st_code, &st_text, NULL, NULL, NULL); 1156 1156 goto on_return; … … 1158 1158 } 1159 1159 1160 /* 1160 /* 1161 1161 * Get which account is most likely to be associated with this incoming 1162 1162 * call. We need the account to find which contact URI to put for … … 1190 1190 pjsip_warning_hdr *w; 1191 1191 1192 pjsua_perror(THIS_FILE, "Bad SDP in incoming INVITE", 1192 pjsua_perror(THIS_FILE, "Bad SDP in incoming INVITE", 1193 1193 status); 1194 1194 1195 w = pjsip_warning_hdr_create_from_status(rdata->tp_info.pool, 1195 w = pjsip_warning_hdr_create_from_status(rdata->tp_info.pool, 1196 1196 pjsip_endpt_name(pjsua_var.endpt), 1197 1197 status); … … 1199 1199 pj_list_push_back(&hdr_list, w); 1200 1200 1201 pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 400, 1201 pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 400, 1202 1202 &reason, &hdr_list, NULL, NULL); 1203 1203 goto on_return; 1204 1204 } 1205 1205 1206 /* Do quick checks on SDP before passing it to transports. More elabore 1206 /* Do quick checks on SDP before passing it to transports. More elabore 1207 1207 * checks will be done in pjsip_inv_verify_request2() below. 1208 1208 */ 1209 1209 if (offer->media_count==0) { 1210 1210 const pj_str_t reason = pj_str("Missing media in SDP"); 1211 pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 400, &reason, 1211 pjsip_endpt_respond(pjsua_var.endpt, NULL, rdata, 400, &reason, 1212 1212 NULL, NULL, NULL); 1213 1213 goto on_return; … … 1241 1241 1242 1242 pjsip_get_response_addr(response->pool, rdata, &res_addr); 1243 pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, response, 1243 pjsip_endpt_send_response(pjsua_var.endpt, &res_addr, response, 1244 1244 NULL, NULL); 1245 1245 … … 1251 1251 1252 1252 goto on_return; 1253 } 1253 } 1254 1254 1255 1255 /* Get suitable Contact header */ … … 1260 1260 acc_id, rdata); 1261 1261 if (status != PJ_SUCCESS) { 1262 pjsua_perror(THIS_FILE, "Unable to generate Contact header", 1262 pjsua_perror(THIS_FILE, "Unable to generate Contact header", 1263 1263 status); 1264 1264 pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL, … … 1286 1286 /* Set credentials */ 1287 1287 if (pjsua_var.acc[acc_id].cred_cnt) { 1288 pjsip_auth_clt_set_credentials(&dlg->auth_sess, 1288 pjsip_auth_clt_set_credentials(&dlg->auth_sess, 1289 1289 pjsua_var.acc[acc_id].cred_cnt, 1290 1290 pjsua_var.acc[acc_id].cred); … … 1292 1292 1293 1293 /* Set preference */ 1294 pjsip_auth_clt_set_prefs(&dlg->auth_sess, 1294 pjsip_auth_clt_set_prefs(&dlg->auth_sess, 1295 1295 &pjsua_var.acc[acc_id].cfg.auth_pref); 1296 1296 … … 1298 1298 * did not require it. 1299 1299 */ 1300 if (pjsua_var.acc[acc_id].cfg.use_timer == PJSUA_SIP_TIMER_INACTIVE && 1300 if (pjsua_var.acc[acc_id].cfg.use_timer == PJSUA_SIP_TIMER_INACTIVE && 1301 1301 (options & PJSIP_INV_REQUIRE_TIMER) == 0) 1302 1302 { … … 1323 1323 pjsip_warning_hdr *w; 1324 1324 1325 w = pjsip_warning_hdr_create_from_status(dlg->pool, 1325 w = pjsip_warning_hdr_create_from_status(dlg->pool, 1326 1326 pjsip_endpt_name(pjsua_var.endpt), 1327 1327 status); … … 1361 1361 */ 1362 1362 if (offer || replaced_dlg) { 1363 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS, 1364 call->secure_level, 1363 status = pjsua_media_channel_init(call->index, PJSIP_ROLE_UAS, 1364 call->secure_level, 1365 1365 rdata->tp_info.pool, 1366 1366 offer, … … 1377 1377 */ 1378 1378 pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL); 1379 pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE); 1379 pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE); 1380 1380 call->inv = NULL; 1381 1381 call->async_call.dlg = NULL; … … 1385 1385 pjsua_perror(THIS_FILE, "Error initializing media channel", status); 1386 1386 pjsip_dlg_respond(dlg, rdata, sip_err_code, NULL, NULL, NULL); 1387 pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE); 1388 call->inv = NULL; 1387 pjsip_inv_terminate(call->inv, sip_err_code, PJ_FALSE); 1388 call->inv = NULL; 1389 1389 call->async_call.dlg = NULL; 1390 1390 goto on_return; … … 1393 1393 1394 1394 /* Create answer */ 1395 /* 1396 status = pjsua_media_channel_create_sdp(call->index, rdata->tp_info.pool, 1395 /* 1396 status = pjsua_media_channel_create_sdp(call->index, rdata->tp_info.pool, 1397 1397 offer, &answer, &sip_err_code); 1398 1398 if (status != PJ_SUCCESS) { … … 1405 1405 1406 1406 /* Init Session Timers */ 1407 status = pjsip_timer_init_session(inv, 1407 status = pjsip_timer_init_session(inv, 1408 1408 &pjsua_var.acc[acc_id].cfg.timer_setting); 1409 1409 if (status != PJ_SUCCESS) { … … 1420 1420 1421 1421 /* Update NAT type of remote endpoint, only when there is SDP in 1422 * incoming INVITE! 1422 * incoming INVITE! 1423 1423 */ 1424 1424 if (pjsua_var.ua_cfg.nat_type_in_sdp && inv->neg && 1425 pjmedia_sdp_neg_get_state(inv->neg) > PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) 1425 pjmedia_sdp_neg_get_state(inv->neg) > PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER) 1426 1426 { 1427 1427 const pjmedia_sdp_session *remote_sdp; … … 1489 1489 } 1490 1490 } else { 1491 /* Notify application if on_incoming_call() is overriden, 1491 /* Notify application if on_incoming_call() is overriden, 1492 1492 * otherwise hangup the call with 480 1493 1493 */ … … 1495 1495 pjsua_var.ua_cfg.cb.on_incoming_call(acc_id, call_id, rdata); 1496 1496 } else { 1497 pjsua_call_hangup(call_id, PJSIP_SC_TEMPORARILY_UNAVAILABLE, 1497 pjsua_call_hangup(call_id, PJSIP_SC_TEMPORARILY_UNAVAILABLE, 1498 1498 NULL, NULL); 1499 1499 } … … 1551 1551 break; 1552 1552 } 1553 1553 1554 1554 has_pjsua_lock = PJ_FALSE; 1555 1555 … … 1596 1596 return PJ_ETIMEDOUT; 1597 1597 } 1598 1598 1599 1599 *p_call = call; 1600 1600 *p_dlg = dlg; … … 1701 1701 sizeof(info->buf_.last_status_text)); 1702 1702 } 1703 1703 1704 1704 /* Audio & video count offered by remote */ 1705 1705 info->rem_offerer = call->rem_offerer; … … 1727 1727 pjmedia_vid_dev_index cap_dev = PJMEDIA_VID_INVALID_DEV; 1728 1728 1729 info->media[info->media_cnt].stream.vid.win_in = 1729 info->media[info->media_cnt].stream.vid.win_in = 1730 1730 call_med->strm.v.rdr_win_id; 1731 1731 … … 1763 1763 pjmedia_vid_dev_index cap_dev = PJMEDIA_VID_INVALID_DEV; 1764 1764 1765 info->prov_media[info->prov_media_cnt].stream.vid.win_in = 1765 info->prov_media[info->prov_media_cnt].stream.vid.win_in = 1766 1766 call_med->strm.v.rdr_win_id; 1767 1767 … … 1874 1874 * Get media transport info for the specified media index. 1875 1875 */ 1876 PJ_DEF(pj_status_t) 1876 PJ_DEF(pj_status_t) 1877 1877 pjsua_call_get_med_transport_info(pjsua_call_id call_id, 1878 1878 unsigned med_idx, … … 1890 1890 1891 1891 call = &pjsua_var.calls[call_id]; 1892 1892 1893 1893 if (med_idx >= call->med_cnt) { 1894 1894 PJSUA_UNLOCK(); … … 1900 1900 pjmedia_transport_info_init(t); 1901 1901 status = pjmedia_transport_get_info(call_med->tp, t); 1902 1902 1903 1903 PJSUA_UNLOCK(); 1904 1904 return status; … … 1932 1932 1933 1933 status = pjsua_media_channel_create_sdp(call_id, 1934 call->async_call.dlg->pool, 1934 call->async_call.dlg->pool, 1935 1935 NULL, &sdp, &sip_err_code); 1936 1936 if (status != PJ_SUCCESS) { … … 1984 1984 * Send response to incoming INVITE request. 1985 1985 */ 1986 PJ_DEF(pj_status_t) pjsua_call_answer( pjsua_call_id call_id, 1986 PJ_DEF(pj_status_t) pjsua_call_answer( pjsua_call_id call_id, 1987 1987 unsigned code, 1988 1988 const pj_str_t *reason, … … 2042 2042 * answer code 183 or 2xx is issued 2043 2043 */ 2044 if (!call->med_ch_cb && 2044 if (!call->med_ch_cb && 2045 2045 (call->opt_inited || (code==183 || code/100==2)) && 2046 2046 (!call->inv->neg || 2047 pjmedia_sdp_neg_get_state(call->inv->neg) == 2047 pjmedia_sdp_neg_get_state(call->inv->neg) == 2048 2048 PJMEDIA_SDP_NEG_STATE_NULL)) 2049 2049 { … … 2076 2076 if (call->med_ch_cb) { 2077 2077 struct call_answer *answer; 2078 2078 2079 2079 PJ_LOG(4,(THIS_FILE, "Pending answering call %d upon completion " 2080 2080 "of media transport", call_id)); … … 2114 2114 status = pjsip_inv_answer(call->inv, code, reason, NULL, &tdata); 2115 2115 if (status != PJ_SUCCESS) { 2116 pjsua_perror(THIS_FILE, "Error creating response", 2116 pjsua_perror(THIS_FILE, "Error creating response", 2117 2117 status); 2118 2118 goto on_return; … … 2131 2131 status = pjsip_inv_send_msg(call->inv, tdata); 2132 2132 if (status != PJ_SUCCESS) 2133 pjsua_perror(THIS_FILE, "Error sending response", 2133 pjsua_perror(THIS_FILE, "Error sending response", 2134 2134 status); 2135 2135 … … 2160 2160 call_id)); 2161 2161 } 2162 2162 2163 2163 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 2164 2164 PJ_EINVAL); … … 2186 2186 sizeof(call->last_text_buf_)); 2187 2187 } 2188 2188 2189 2189 goto on_return; 2190 2190 } … … 2201 2201 status = pjsip_inv_end_session(call->inv, code, reason, &tdata); 2202 2202 if (status != PJ_SUCCESS) { 2203 pjsua_perror(THIS_FILE, 2204 "Failed to create end session message", 2203 pjsua_perror(THIS_FILE, 2204 "Failed to create end session message", 2205 2205 status); 2206 2206 goto on_return; 2207 2207 } 2208 2208 2209 /* pjsip_inv_end_session may return PJ_SUCCESS with NULL 2209 /* pjsip_inv_end_session may return PJ_SUCCESS with NULL 2210 2210 * as p_tdata when INVITE transaction has not been answered 2211 2211 * with any provisional responses. … … 2220 2220 status = pjsip_inv_send_msg(call->inv, tdata); 2221 2221 if (status != PJ_SUCCESS) { 2222 pjsua_perror(THIS_FILE, 2223 "Failed to send end session message", 2222 pjsua_perror(THIS_FILE, 2223 "Failed to send end session message", 2224 2224 status); 2225 2225 goto on_return; … … 2252 2252 PJ_EINVAL); 2253 2253 2254 status = acquire_call("pjsua_call_process_redirect()", call_id, 2254 status = acquire_call("pjsua_call_process_redirect()", call_id, 2255 2255 &call, &dlg); 2256 2256 if (status != PJ_SUCCESS) … … 2398 2398 goto on_return; 2399 2399 } 2400 2401 status = apply_call_setting(call, opt, NULL);2402 if (status != PJ_SUCCESS) {2403 pjsua_perror(THIS_FILE, "Failed to apply call setting", status);2404 goto on_return;2405 }2406 2407 /* Create SDP */2408 if (call->local_hold && (call->opt.flag & PJSUA_CALL_UNHOLD)==0) {2409 status = create_sdp_of_call_hold(call, &sdp);2410 } else {2411 status = pjsua_media_channel_create_sdp(call->index,2412 call->inv->pool_prov,2413 NULL, &sdp, NULL);2414 call->local_hold = PJ_FALSE;2415 }2416 if (status != PJ_SUCCESS) {2417 pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint",2418 status);2419 goto on_return;2420 }2421 2422 if ((call->opt.flag & PJSUA_CALL_UPDATE_CONTACT) &&2423 pjsua_acc_is_valid(call->acc_id))2424 {2425 new_contact = &pjsua_var.acc[call->acc_id].contact;2426 }2427 2428 /* Create re-INVITE with new offer */2429 status = pjsip_inv_reinvite( call->inv, new_contact, sdp, &tdata);2430 if (status != PJ_SUCCESS) {2431 pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status);2432 goto on_return;2433 }2434 2435 /* Add additional headers etc */2436 pjsua_process_msg_data( tdata, msg_data);2437 2438 /* Send the request */2439 status = pjsip_inv_send_msg( call->inv, tdata);2440 if (status != PJ_SUCCESS) {2441 pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status);2442 goto on_return;2443 }2444 2445 on_return:2446 if (dlg) pjsip_dlg_dec_lock(dlg);2447 pj_log_pop_indent();2448 return status;2449 }2450 2451 2452 /*2453 * Send UPDATE request.2454 */2455 PJ_DEF(pj_status_t) pjsua_call_update( pjsua_call_id call_id,2456 unsigned options,2457 const pjsua_msg_data *msg_data)2458 {2459 pjsua_call *call;2460 pjsip_dialog *dlg = NULL;2461 pj_status_t status;2462 2463 status = acquire_call("pjsua_call_update()", call_id, &call, &dlg);2464 if (status != PJ_SUCCESS)2465 goto on_return;2466 2467 if (options != call->opt.flag)2468 call->opt.flag = options;2469 2470 status = pjsua_call_update2(call_id, NULL, msg_data);2471 2472 on_return:2473 if (dlg) pjsip_dlg_dec_lock(dlg);2474 return status;2475 }2476 2477 2478 /*2479 * Send UPDATE request.2480 */2481 PJ_DEF(pj_status_t) pjsua_call_update2(pjsua_call_id call_id,2482 const pjsua_call_setting *opt,2483 const pjsua_msg_data *msg_data)2484 {2485 pjmedia_sdp_session *sdp;2486 pj_str_t *new_contact = NULL;2487 pjsip_tx_data *tdata;2488 pjsua_call *call;2489 pjsip_dialog *dlg = NULL;2490 pj_status_t status;2491 2492 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls,2493 PJ_EINVAL);2494 2495 PJ_LOG(4,(THIS_FILE, "Sending UPDATE on call %d", call_id));2496 pj_log_push_indent();2497 2498 status = acquire_call("pjsua_call_update2()", call_id, &call, &dlg);2499 if (status != PJ_SUCCESS)2500 goto on_return;2501 2400 2502 2401 status = apply_call_setting(call, opt, NULL); … … 2515 2414 call->local_hold = PJ_FALSE; 2516 2415 } 2517 2518 2416 if (status != PJ_SUCCESS) { 2519 2417 pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint", … … 2528 2426 } 2529 2427 2530 /* Create UPDATE with new offer */2531 status = pjsip_inv_ update(call->inv, new_contact, sdp, &tdata);2532 if (status != PJ_SUCCESS) { 2533 pjsua_perror(THIS_FILE, "Unable to create UPDATE request", status);2428 /* Create re-INVITE with new offer */ 2429 status = pjsip_inv_reinvite( call->inv, new_contact, sdp, &tdata); 2430 if (status != PJ_SUCCESS) { 2431 pjsua_perror(THIS_FILE, "Unable to create re-INVITE", status); 2534 2432 goto on_return; 2535 2433 } … … 2541 2439 status = pjsip_inv_send_msg( call->inv, tdata); 2542 2440 if (status != PJ_SUCCESS) { 2543 pjsua_perror(THIS_FILE, "Unable to send UPDATE request", status);2441 pjsua_perror(THIS_FILE, "Unable to send re-INVITE", status); 2544 2442 goto on_return; 2545 2443 } … … 2553 2451 2554 2452 /* 2453 * Send UPDATE request. 2454 */ 2455 PJ_DEF(pj_status_t) pjsua_call_update( pjsua_call_id call_id, 2456 unsigned options, 2457 const pjsua_msg_data *msg_data) 2458 { 2459 pjsua_call *call; 2460 pjsip_dialog *dlg = NULL; 2461 pj_status_t status; 2462 2463 status = acquire_call("pjsua_call_update()", call_id, &call, &dlg); 2464 if (status != PJ_SUCCESS) 2465 goto on_return; 2466 2467 if (options != call->opt.flag) 2468 call->opt.flag = options; 2469 2470 status = pjsua_call_update2(call_id, NULL, msg_data); 2471 2472 on_return: 2473 if (dlg) pjsip_dlg_dec_lock(dlg); 2474 return status; 2475 } 2476 2477 2478 /* 2479 * Send UPDATE request. 2480 */ 2481 PJ_DEF(pj_status_t) pjsua_call_update2(pjsua_call_id call_id, 2482 const pjsua_call_setting *opt, 2483 const pjsua_msg_data *msg_data) 2484 { 2485 pjmedia_sdp_session *sdp; 2486 pj_str_t *new_contact = NULL; 2487 pjsip_tx_data *tdata; 2488 pjsua_call *call; 2489 pjsip_dialog *dlg = NULL; 2490 pj_status_t status; 2491 2492 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 2493 PJ_EINVAL); 2494 2495 PJ_LOG(4,(THIS_FILE, "Sending UPDATE on call %d", call_id)); 2496 pj_log_push_indent(); 2497 2498 status = acquire_call("pjsua_call_update2()", call_id, &call, &dlg); 2499 if (status != PJ_SUCCESS) 2500 goto on_return; 2501 2502 status = apply_call_setting(call, opt, NULL); 2503 if (status != PJ_SUCCESS) { 2504 pjsua_perror(THIS_FILE, "Failed to apply call setting", status); 2505 goto on_return; 2506 } 2507 2508 /* Create SDP */ 2509 if (call->local_hold && (call->opt.flag & PJSUA_CALL_UNHOLD)==0) { 2510 status = create_sdp_of_call_hold(call, &sdp); 2511 } else { 2512 status = pjsua_media_channel_create_sdp(call->index, 2513 call->inv->pool_prov, 2514 NULL, &sdp, NULL); 2515 call->local_hold = PJ_FALSE; 2516 } 2517 2518 if (status != PJ_SUCCESS) { 2519 pjsua_perror(THIS_FILE, "Unable to get SDP from media endpoint", 2520 status); 2521 goto on_return; 2522 } 2523 2524 if ((call->opt.flag & PJSUA_CALL_UPDATE_CONTACT) && 2525 pjsua_acc_is_valid(call->acc_id)) 2526 { 2527 new_contact = &pjsua_var.acc[call->acc_id].contact; 2528 } 2529 2530 /* Create UPDATE with new offer */ 2531 status = pjsip_inv_update(call->inv, new_contact, sdp, &tdata); 2532 if (status != PJ_SUCCESS) { 2533 pjsua_perror(THIS_FILE, "Unable to create UPDATE request", status); 2534 goto on_return; 2535 } 2536 2537 /* Add additional headers etc */ 2538 pjsua_process_msg_data( tdata, msg_data); 2539 2540 /* Send the request */ 2541 status = pjsip_inv_send_msg( call->inv, tdata); 2542 if (status != PJ_SUCCESS) { 2543 pjsua_perror(THIS_FILE, "Unable to send UPDATE request", status); 2544 goto on_return; 2545 } 2546 2547 on_return: 2548 if (dlg) pjsip_dlg_dec_lock(dlg); 2549 pj_log_pop_indent(); 2550 return status; 2551 } 2552 2553 2554 /* 2555 2555 * Initiate call transfer to the specified address. 2556 2556 */ 2557 PJ_DEF(pj_status_t) pjsua_call_xfer( pjsua_call_id call_id, 2557 PJ_DEF(pj_status_t) pjsua_call_xfer( pjsua_call_id call_id, 2558 2558 const pj_str_t *dest, 2559 2559 const pjsua_msg_data *msg_data) … … 2571 2571 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls && 2572 2572 dest, PJ_EINVAL); 2573 2573 2574 2574 PJ_LOG(4,(THIS_FILE, "Transferring call %d to %.*s", call_id, 2575 2575 (int)dest->slen, dest->ptr)); … … 2579 2579 if (status != PJ_SUCCESS) 2580 2580 goto on_return; 2581 2581 2582 2582 /* Create xfer client subscription. */ 2583 2583 pj_bzero(&xfer_cb, sizeof(xfer_cb)); … … 2618 2618 } 2619 2619 2620 /* For simplicity (that's what this program is intended to be!), 2620 /* For simplicity (that's what this program is intended to be!), 2621 2621 * leave the original invite session as it is. More advanced application 2622 2622 * may want to hold the INVITE, or terminate the invite, or whatever. … … 2633 2633 * Initiate attended call transfer to the specified address. 2634 2634 */ 2635 PJ_DEF(pj_status_t) pjsua_call_xfer_replaces( pjsua_call_id call_id, 2635 PJ_DEF(pj_status_t) pjsua_call_xfer_replaces( pjsua_call_id call_id, 2636 2636 pjsua_call_id dest_call_id, 2637 2637 unsigned options, … … 2645 2645 pjsip_uri *uri; 2646 2646 pj_status_t status; 2647 2647 2648 2648 2649 2649 PJ_ASSERT_RETURN(call_id>=0 && call_id<(int)pjsua_var.ua_cfg.max_calls, 2650 2650 PJ_EINVAL); 2651 PJ_ASSERT_RETURN(dest_call_id>=0 && 2651 PJ_ASSERT_RETURN(dest_call_id>=0 && 2652 2652 dest_call_id<(int)pjsua_var.ua_cfg.max_calls, 2653 2653 PJ_EINVAL); 2654 2654 2655 2655 PJ_LOG(4,(THIS_FILE, "Transferring call %d replacing with call %d", 2656 2656 call_id, dest_call_id)); 2657 2657 pj_log_push_indent(); 2658 2658 2659 status = acquire_call("pjsua_call_xfer_replaces()", dest_call_id, 2659 status = acquire_call("pjsua_call_xfer_replaces()", dest_call_id, 2660 2660 &dest_call, &dest_dlg); 2661 2661 if (status != PJ_SUCCESS) { … … 2663 2663 return status; 2664 2664 } 2665 2666 /* 2665 2666 /* 2667 2667 * Create REFER destination URI with Replaces field. 2668 2668 */ … … 2672 2672 dest_dlg->call_id->id.slen + 2673 2673 dest_dlg->remote.info->tag.slen + 2674 dest_dlg->local.info->tag.slen + 32 2674 dest_dlg->local.info->tag.slen + 32 2675 2675 < (long)sizeof(str_dest_buf), 2676 2676 { status=PJSIP_EURITOOLONG; goto on_error; }); … … 2681 2681 2682 2682 uri = (pjsip_uri*) pjsip_uri_get_uri(dest_dlg->remote.info->uri); 2683 len = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri, 2683 len = pjsip_uri_print(PJSIP_URI_IN_REQ_URI, uri, 2684 2684 str_dest_buf+1, sizeof(str_dest_buf)-1); 2685 2685 if (len < 0) { … … 2692 2692 2693 2693 /* Build the URI */ 2694 len = pj_ansi_snprintf(str_dest_buf + str_dest.slen, 2694 len = pj_ansi_snprintf(str_dest_buf + str_dest.slen, 2695 2695 sizeof(str_dest_buf) - str_dest.slen, 2696 2696 "?%s" … … 2709 2709 PJ_ASSERT_ON_FAIL(len > 0 && len <= (int)sizeof(str_dest_buf)-str_dest.slen, 2710 2710 { status=PJSIP_EURITOOLONG; goto on_error; }); 2711 2711 2712 2712 str_dest.ptr = str_dest_buf; 2713 2713 str_dest.slen += len; 2714 2714 2715 2715 pjsip_dlg_dec_lock(dest_dlg); 2716 2716 2717 2717 status = pjsua_call_xfer(call_id, &str_dest, msg_data); 2718 2718 … … 2730 2730 * Send instant messaging inside INVITE session. 2731 2731 */ 2732 PJ_DEF(pj_status_t) pjsua_call_send_im( pjsua_call_id call_id, 2732 PJ_DEF(pj_status_t) pjsua_call_send_im( pjsua_call_id call_id, 2733 2733 const pj_str_t *mime_type, 2734 2734 const pj_str_t *content, … … 2754 2754 if (status != PJ_SUCCESS) 2755 2755 goto on_return; 2756 2756 2757 2757 /* Set default media type if none is specified */ 2758 2758 if (mime_type == NULL) { … … 2769 2769 2770 2770 /* Add accept header. */ 2771 pjsip_msg_add_hdr( tdata->msg, 2771 pjsip_msg_add_hdr( tdata->msg, 2772 2772 (pjsip_hdr*)pjsua_im_create_accept(tdata->pool)); 2773 2773 … … 2797 2797 2798 2798 /* Send the request. */ 2799 status = pjsip_dlg_send_request( call->inv->dlg, tdata, 2799 status = pjsip_dlg_send_request( call->inv->dlg, tdata, 2800 2800 pjsua_var.mod.id, im_data); 2801 2801 if (status != PJ_SUCCESS) { … … 2814 2814 * Send IM typing indication inside INVITE session. 2815 2815 */ 2816 PJ_DEF(pj_status_t) pjsua_call_send_typing_ind( pjsua_call_id call_id, 2816 PJ_DEF(pj_status_t) pjsua_call_send_typing_ind( pjsua_call_id call_id, 2817 2817 pj_bool_t is_typing, 2818 2818 const pjsua_msg_data*msg_data) … … 3099 3099 pjmedia_transport_info tpinfo; 3100 3100 pjmedia_ice_transport_info *ice_info; 3101 3101 3102 3102 if (call_med->tp_st == PJSUA_MED_TP_NULL || 3103 3103 call_med->tp_st == PJSUA_MED_TP_DISABLED || … … 3106 3106 continue; 3107 3107 } 3108 3108 3109 3109 pjmedia_transport_info_init(&tpinfo); 3110 3110 pjmedia_transport_get_info(call_med->tp, &tpinfo); … … 3122 3122 break; 3123 3123 } 3124 3124 3125 3125 /* Check if ICE needs to send reinvite */ 3126 3126 if (!ice_need_reinv && … … 3137 3137 } 3138 3138 } 3139 3139 3140 3140 if (ice_complete && need_reinv) 3141 3141 *need_reinv = ice_need_reinv; 3142 3142 3143 3143 return ice_complete; 3144 3144 } … … 3177 3177 * remote does not support UPDATE method. 3178 3178 */ 3179 if (inv->state == PJSIP_INV_STATE_EARLY && 3179 if (inv->state == PJSIP_INV_STATE_EARLY && 3180 3180 pjsip_dlg_remote_has_cap(inv->dlg, PJSIP_H_ALLOW, NULL, &ST_UPDATE)!= 3181 3181 PJSIP_DIALOG_CAP_SUPPORTED) … … 3197 3197 return PJ_SUCCESS; 3198 3198 3199 3199 3200 3200 /* Okay! So we need to send re-INVITE/UPDATE */ 3201 3201 … … 3218 3218 )); 3219 3219 } 3220 3220 3221 3221 /* Generate SDP re-offer */ 3222 3222 status = pjsua_media_channel_create_sdp(call->index, pool, NULL, … … 3235 3235 if (need_lock_codec) { 3236 3236 const pjmedia_sdp_session *ref_sdp; 3237 3237 3238 3238 /* Get local active SDP as reference */ 3239 3239 status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &ref_sdp); 3240 3240 if (status != PJ_SUCCESS) 3241 3241 return status; 3242 3242 3243 3243 /* Verify media count. Note that remote may add/remove media line 3244 3244 * in the answer. When answer has less media, it must have been … … 3262 3262 pjmedia_sdp_media *m = new_offer->media[i]; 3263 3263 pjsua_call_media *call_med = &call->media[i]; 3264 3264 3265 3265 /* Verify if media is deactivated */ 3266 3266 if (call_med->state == PJSUA_CALL_MEDIA_NONE || … … 3270 3270 continue; 3271 3271 } 3272 3272 3273 3273 /* Reset formats */ 3274 3274 m->desc.fmt_count = 0; 3275 3275 pjmedia_sdp_attr_remove_all(&m->attr_count, m->attr, "rtpmap"); 3276 3276 pjmedia_sdp_attr_remove_all(&m->attr_count, m->attr, "fmtp"); 3277 3277 3278 3278 /* Copy only the first format + any non-AV formats from 3279 3279 * the active local SDP. … … 3284 3284 if (is_non_av_fmt(ref_m, fmt) || (++codec_cnt == 1)) { 3285 3285 pjmedia_sdp_attr *a; 3286 3286 3287 3287 m->desc.fmt[m->desc.fmt_count++] = *fmt; 3288 3288 a = pjmedia_sdp_attr_find2(ref_m->attr_count, ref_m->attr, … … 3300 3300 { 3301 3301 const pjmedia_sdp_session *cur_sdp; 3302 3302 3303 3303 /* Get local active SDP */ 3304 3304 status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &cur_sdp); … … 3356 3356 } 3357 3357 3358 3358 3359 3359 if (rem_can_update) { 3360 3360 status = pjsip_inv_update(inv, NULL, new_offer, &tdata); … … 3388 3388 if (need_lock_codec) 3389 3389 ++call->lock_codec.retry_cnt; 3390 3390 3391 3391 return PJ_SUCCESS; 3392 3392 } … … 3397 3397 * session state has changed. 3398 3398 */ 3399 static void pjsua_call_on_state_changed(pjsip_inv_session *inv, 3399 static void pjsua_call_on_state_changed(pjsip_inv_session *inv, 3400 3400 pjsip_event *e) 3401 3401 { … … 3418 3418 if (call->res_time.sec == 0) 3419 3419 pj_gettimeofday(&call->res_time); 3420 call->last_code = (pjsip_status_code) 3420 call->last_code = (pjsip_status_code) 3421 3421 e->body.tsx_state.tsx->status_code; 3422 pj_strncpy(&call->last_text, 3422 pj_strncpy(&call->last_text, 3423 3423 &e->body.tsx_state.tsx->status_text, 3424 3424 sizeof(call->last_text_buf_)); … … 3439 3439 if (call->res_time.sec == 0) 3440 3440 pj_gettimeofday(&call->res_time); 3441 if (e->type == PJSIP_EVENT_TSX_STATE && 3442 e->body.tsx_state.tsx->status_code > call->last_code) 3441 if (e->type == PJSIP_EVENT_TSX_STATE && 3442 e->body.tsx_state.tsx->status_code > call->last_code) 3443 3443 { 3444 call->last_code = (pjsip_status_code) 3444 call->last_code = (pjsip_status_code) 3445 3445 e->body.tsx_state.tsx->status_code; 3446 pj_strncpy(&call->last_text, 3446 pj_strncpy(&call->last_text, 3447 3447 &e->body.tsx_state.tsx->status_text, 3448 3448 sizeof(call->last_text_buf_)); … … 3461 3461 break; 3462 3462 default: 3463 call->last_code = (pjsip_status_code) 3463 call->last_code = (pjsip_status_code) 3464 3464 e->body.tsx_state.tsx->status_code; 3465 pj_strncpy(&call->last_text, 3465 pj_strncpy(&call->last_text, 3466 3466 &e->body.tsx_state.tsx->status_text, 3467 3467 sizeof(call->last_text_buf_)); … … 3475 3475 int st_code = -1; 3476 3476 pjsip_evsub_state ev_state = PJSIP_EVSUB_STATE_ACTIVE; 3477 3477 3478 3478 3479 3479 switch (call->inv->state) { … … 3554 3554 3555 3555 PJSUA_LOCK(); 3556 3556 3557 3557 pjsua_media_channel_deinit(call->index); 3558 3558 … … 3577 3577 * has forked. 3578 3578 */ 3579 static void pjsua_call_on_forked( pjsip_inv_session *inv, 3579 static void pjsua_call_on_forked( pjsip_inv_session *inv, 3580 3580 pjsip_event *e) 3581 3581 { … … 3592 3592 pjsip_dialog* on_dlg_forked(pjsip_dialog *dlg, pjsip_rx_data *res) 3593 3593 { 3594 if (dlg->uac_has_2xx && 3594 if (dlg->uac_has_2xx && 3595 3595 res->msg_info.cseq->method.id == PJSIP_INVITE_METHOD && 3596 3596 pjsip_rdata_get_tsx(res) == NULL && 3597 res->msg_info.msg->line.status.code/100 == 2) 3597 res->msg_info.msg->line.status.code/100 == 2) 3598 3598 { 3599 3599 pjsip_dialog *forked_dlg; … … 3631 3631 * Disconnect call upon error. 3632 3632 */ 3633 static void call_disconnect( pjsip_inv_session *inv, 3633 static void call_disconnect( pjsip_inv_session *inv, 3634 3634 int code ) 3635 3635 { 3636 pjsua_call *call;3637 3636 pjsip_tx_data *tdata; 3638 3637 pj_status_t status; 3639 3640 call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];3641 3638 3642 3639 status = pjsip_inv_end_session(inv, code, NULL, &tdata); … … 3644 3641 return; 3645 3642 3643 #if DISABLED_FOR_TICKET_1185 3644 pjsua_call *call; 3645 3646 3646 /* Add SDP in 488 status */ 3647 #if DISABLED_FOR_TICKET_1185 3647 call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id]; 3648 3648 3649 if (call && call->tp && tdata->msg->type==PJSIP_RESPONSE_MSG && 3649 code==PJSIP_SC_NOT_ACCEPTABLE_HERE) 3650 code==PJSIP_SC_NOT_ACCEPTABLE_HERE) 3650 3651 { 3651 3652 pjmedia_sdp_session *local_sdp; … … 3654 3655 pjmedia_transport_info_init(&ti); 3655 3656 pjmedia_transport_get_info(call->med_tp, &ti); 3656 status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, tdata->pool, 3657 status = pjmedia_endpt_create_sdp(pjsua_var.med_endpt, tdata->pool, 3657 3658 1, &ti.sock_info, &local_sdp); 3658 3659 if (status == PJ_SUCCESS) { … … 3699 3700 3700 3701 /* Disconnect call if we're not in the middle of initializing an 3701 * UAS dialog and if this is not a re-INVITE 3702 * UAS dialog and if this is not a re-INVITE 3702 3703 */ 3703 3704 if (inv->state != PJSIP_INV_STATE_NULL && 3704 inv->state != PJSIP_INV_STATE_CONFIRMED) 3705 inv->state != PJSIP_INV_STATE_CONFIRMED) 3705 3706 { 3706 3707 call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); … … 3714 3715 status = pjmedia_sdp_neg_get_active_local(call->inv->neg, &local_sdp); 3715 3716 if (status != PJ_SUCCESS) { 3716 pjsua_perror(THIS_FILE, 3717 "Unable to retrieve currently active local SDP", 3717 pjsua_perror(THIS_FILE, 3718 "Unable to retrieve currently active local SDP", 3718 3719 status); 3719 3720 //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); … … 3723 3724 status = pjmedia_sdp_neg_get_active_remote(call->inv->neg, &remote_sdp); 3724 3725 if (status != PJ_SUCCESS) { 3725 pjsua_perror(THIS_FILE, 3726 "Unable to retrieve currently active remote SDP", 3726 pjsua_perror(THIS_FILE, 3727 "Unable to retrieve currently active remote SDP", 3727 3728 status); 3728 3729 //call_disconnect(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE); … … 3738 3739 status = pjsua_media_channel_update(call->index, local_sdp, remote_sdp); 3739 3740 if (status != PJ_SUCCESS) { 3740 pjsua_perror(THIS_FILE, "Unable to create media session", 3741 pjsua_perror(THIS_FILE, "Unable to create media session", 3741 3742 status); 3742 3743 call_disconnect(inv, PJSIP_SC_NOT_ACCEPTABLE_HERE); … … 3768 3769 unsigned mi; 3769 3770 3770 /* Call-hold is done by set the media direction to 'sendonly' 3771 * (PJMEDIA_DIR_ENCODING), except when current media direction is 3771 /* Call-hold is done by set the media direction to 'sendonly' 3772 * (PJMEDIA_DIR_ENCODING), except when current media direction is 3772 3773 * 'inactive' (PJMEDIA_DIR_NONE). 3773 3774 * (See RFC 3264 Section 8.4 and RFC 4317 Section 3.1) 3774 3775 */ 3775 /* http://trac.pjsip.org/repos/ticket/880 3776 /* http://trac.pjsip.org/repos/ticket/880 3776 3777 if (call->dir != PJMEDIA_DIR_ENCODING) { 3777 3778 */ … … 3883 3884 pjsip_status_code code = PJSIP_SC_OK; 3884 3885 pjsua_call_setting opt = call->opt; 3885 3886 3886 3887 (*pjsua_var.ua_cfg.cb.on_call_rx_offer)(call->index, offer, NULL, 3887 3888 &code, &opt); … … 3895 3896 call->opt = opt; 3896 3897 } 3897 3898 3898 3899 /* Re-init media for the new remote offer before creating SDP */ 3899 3900 status = apply_call_setting(call, &call->opt, offer); … … 3901 3902 goto on_return; 3902 3903 3903 status = pjsua_media_channel_create_sdp(call->index, 3904 call->inv->pool_prov, 3904 status = pjsua_media_channel_create_sdp(call->index, 3905 call->inv->pool_prov, 3905 3906 offer, &answer, NULL); 3906 3907 if (status != PJ_SUCCESS) { … … 3972 3973 /* See if we've put call on hold. */ 3973 3974 if (call->local_hold) { 3974 PJ_LOG(4,(THIS_FILE, 3975 PJ_LOG(4,(THIS_FILE, 3975 3976 "Call %d: call is on-hold locally, creating call-hold SDP ", 3976 3977 call->index)); … … 3980 3981 call->index)); 3981 3982 3982 status = pjsua_media_channel_create_sdp(call->index, 3983 call->inv->pool_prov, 3983 status = pjsua_media_channel_create_sdp(call->index, 3984 call->inv->pool_prov, 3984 3985 NULL, offer, NULL); 3985 3986 } … … 4001 4002 static void xfer_client_on_evsub_state( pjsip_evsub *sub, pjsip_event *event) 4002 4003 { 4003 4004 4004 4005 PJ_UNUSED_ARG(event); 4005 4006 … … 4007 4008 4008 4009 /* 4009 * When subscription is accepted (got 200/OK to REFER), check if 4010 * When subscription is accepted (got 200/OK to REFER), check if 4010 4011 * subscription suppressed. 4011 4012 */ … … 4020 4021 4021 4022 /* Must be receipt of response message */ 4022 pj_assert(event->type == PJSIP_EVENT_TSX_STATE && 4023 pj_assert(event->type == PJSIP_EVENT_TSX_STATE && 4023 4024 event->body.tsx_state.type == PJSIP_EVENT_RX_MSG); 4024 4025 rdata = event->body.tsx_state.src.rdata; … … 4026 4027 /* Find Refer-Sub header */ 4027 4028 refer_sub = (pjsip_generic_string_hdr*) 4028 pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, 4029 pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, 4029 4030 &REFER_SUB, NULL); 4030 4031 … … 4037 4038 const pj_str_t ACCEPTED = { "Accepted", 8 }; 4038 4039 pj_bool_t cont = PJ_FALSE; 4039 (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index, 4040 (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index, 4040 4041 200, 4041 4042 &ACCEPTED, … … 4052 4053 4053 4054 } else { 4054 /* Notify application about call transfer progress. 4055 /* Notify application about call transfer progress. 4055 4056 * Initially notify with 100/Accepted status. 4056 4057 */ … … 4058 4059 const pj_str_t ACCEPTED = { "Accepted", 8 }; 4059 4060 pj_bool_t cont = PJ_FALSE; 4060 (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index, 4061 (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index, 4061 4062 100, 4062 4063 &ACCEPTED, … … 4070 4071 */ 4071 4072 else if (pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_ACTIVE || 4072 pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) 4073 pjsip_evsub_get_state(sub) == PJSIP_EVSUB_STATE_TERMINATED) 4073 4074 { 4074 4075 pjsua_call *call; … … 4082 4083 call = (pjsua_call*) pjsip_evsub_get_mod_data(sub, pjsua_var.mod.id); 4083 4084 4084 /* When subscription is terminated, clear the xfer_sub member of 4085 /* When subscription is terminated, clear the xfer_sub member of 4085 4086 * the inv_data. 4086 4087 */ … … 4108 4109 body = msg->body; 4109 4110 if (!body) { 4110 PJ_LOG(2,(THIS_FILE, 4111 PJ_LOG(2,(THIS_FILE, 4111 4112 "Warning: received NOTIFY without message body")); 4112 4113 goto on_return; … … 4117 4118 pj_stricmp2(&body->content_type.subtype, "sipfrag") != 0) 4118 4119 { 4119 PJ_LOG(2,(THIS_FILE, 4120 PJ_LOG(2,(THIS_FILE, 4120 4121 "Warning: received NOTIFY with non message/sipfrag " 4121 4122 "content")); … … 4124 4125 4125 4126 /* Try to parse the content */ 4126 status = pjsip_parse_status_line((char*)body->data, body->len, 4127 status = pjsip_parse_status_line((char*)body->data, body->len, 4127 4128 &status_line); 4128 4129 if (status != PJ_SUCCESS) { 4129 PJ_LOG(2,(THIS_FILE, 4130 PJ_LOG(2,(THIS_FILE, 4130 4131 "Warning: received NOTIFY with invalid " 4131 4132 "message/sipfrag content")); … … 4141 4142 is_last = (pjsip_evsub_get_state(sub)==PJSIP_EVSUB_STATE_TERMINATED); 4142 4143 cont = !is_last; 4143 (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index, 4144 (*pjsua_var.ua_cfg.cb.on_call_transfer_status)(call->index, 4144 4145 status_line.code, 4145 4146 &status_line.reason, … … 4156 4157 pjsip_tx_data *tdata; 4157 4158 4158 status = pjsip_evsub_initiate(sub, &pjsip_subscribe_method, 4159 status = pjsip_evsub_initiate(sub, &pjsip_subscribe_method, 4159 4160 0, &tdata); 4160 4161 if (status == PJ_SUCCESS) … … 4179 4180 4180 4181 /* 4181 * When subscription is terminated, clear the xfer_sub member of 4182 * When subscription is terminated, clear the xfer_sub member of 4182 4183 * the inv_data. 4183 4184 */ … … 4254 4255 */ 4255 4256 ref_by_hdr = (pjsip_hdr*) 4256 pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_ref_by, 4257 pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_ref_by, 4257 4258 NULL); 4258 4259 … … 4261 4262 if (pjsua_var.ua_cfg.cb.on_call_transfer_request) { 4262 4263 (*pjsua_var.ua_cfg.cb.on_call_transfer_request)(existing_call->index, 4263 &refer_to->hvalue, 4264 &refer_to->hvalue, 4264 4265 &code); 4265 4266 } … … 4268 4269 if (pjsua_var.ua_cfg.cb.on_call_transfer_request2) { 4269 4270 (*pjsua_var.ua_cfg.cb.on_call_transfer_request2)(existing_call->index, 4270 &refer_to->hvalue, 4271 &refer_to->hvalue, 4271 4272 &code, 4272 4273 &call_opt); … … 4284 4285 (int)inv->dlg->remote.info_str.slen, 4285 4286 inv->dlg->remote.info_str.ptr, 4286 (int)refer_to->hvalue.slen, 4287 (int)refer_to->hvalue.slen, 4287 4288 refer_to->hvalue.ptr)); 4288 4289 … … 4295 4296 pjsip_hdr *hdr; 4296 4297 4297 status = pjsip_dlg_create_response(inv->dlg, rdata, code, NULL, 4298 status = pjsip_dlg_create_response(inv->dlg, rdata, code, NULL, 4298 4299 &tdata); 4299 4300 if (status != PJ_SUCCESS) { … … 4304 4305 4305 4306 /* Add Refer-Sub header */ 4306 hdr = (pjsip_hdr*) 4307 hdr = (pjsip_hdr*) 4307 4308 pjsip_generic_string_hdr_create(tdata->pool, &str_refer_sub, 4308 4309 &str_false); … … 4348 4349 pjsip_hdr *hdr; 4349 4350 4350 hdr = (pjsip_hdr*) 4351 pjsip_generic_string_hdr_create(inv->dlg->pool, 4351 hdr = (pjsip_hdr*) 4352 pjsip_generic_string_hdr_create(inv->dlg->pool, 4352 4353 &str_refer_sub, 4353 4354 &str_true); … … 4363 4364 100, NULL, &tdata); 4364 4365 if (status != PJ_SUCCESS) { 4365 pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER", 4366 pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER", 4366 4367 status); 4367 4368 goto on_return; … … 4379 4380 * We need to get a null terminated string from a pj_str_t. 4380 4381 * So grab the pointer from the hvalue and NULL terminate it, knowing 4381 * that the NULL position will be occupied by a newline. 4382 * that the NULL position will be occupied by a newline. 4382 4383 */ 4383 4384 uri = refer_to->hvalue.ptr; … … 4399 4400 tmp = pj_str(uri); 4400 4401 status = pjsua_call_make_call(existing_call->acc_id, &tmp, &call_opt, 4401 existing_call->user_data, &msg_data, 4402 existing_call->user_data, &msg_data, 4402 4403 &new_call); 4403 4404 if (status != PJ_SUCCESS) { … … 4408 4409 500, NULL, &tdata); 4409 4410 if (status != PJ_SUCCESS) { 4410 pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER", 4411 pjsua_perror(THIS_FILE, "Unable to create NOTIFY to REFER", 4411 4412 status); 4412 4413 goto on_return; … … 4414 4415 status = pjsip_xfer_send_request(sub, tdata); 4415 4416 if (status != PJ_SUCCESS) { 4416 pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER", 4417 pjsua_perror(THIS_FILE, "Unable to send NOTIFY to REFER", 4417 4418 status); 4418 4419 goto on_return; … … 4430 4431 4431 4432 /* Put the invite_data in the subscription. */ 4432 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, 4433 pjsip_evsub_set_mod_data(sub, pjsua_var.mod.id, 4433 4434 &pjsua_var.calls[new_call]); 4434 4435 } … … 4512 4513 pj_list_push_back(&hdr_list, accept_hdr); 4513 4514 4514 pjsip_dlg_respond( inv->dlg, rdata, PJSIP_SC_NOT_ACCEPTABLE_HERE, 4515 pjsip_dlg_respond( inv->dlg, rdata, PJSIP_SC_NOT_ACCEPTABLE_HERE, 4515 4516 NULL, &hdr_list, NULL ); 4516 4517 goto on_return; … … 4518 4519 4519 4520 /* Respond with 200 first, so that remote doesn't retransmit in case 4520 * the UI takes too long to process the message. 4521 * the UI takes too long to process the message. 4521 4522 */ 4522 4523 pjsip_dlg_respond( inv->dlg, rdata, 200, NULL, NULL, NULL); … … 4626 4627 4627 4628 if (pjsua_var.ua_cfg.cb.on_call_redirected) { 4628 op = (*pjsua_var.ua_cfg.cb.on_call_redirected)(call->index, 4629 op = (*pjsua_var.ua_cfg.cb.on_call_redirected)(call->index, 4629 4630 target, e); 4630 4631 } else { -
pjproject/trunk/pjsip/src/test/tsx_uas_test.c
r4420 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 … … 31 31 ** 32 32 ** This file performs various tests for UAC transactions. Each test will have 33 ** a different Via branch param so that message receiver module and 33 ** a different Via branch param so that message receiver module and 34 34 ** transaction user module can identify which test is being carried out. 35 35 ** … … 48 48 ** 49 49 ** TEST4_BRANCH_ID 50 ** Transaction retransmits last response (if any) without notifying 50 ** Transaction retransmits last response (if any) without notifying 51 51 ** transaction user upon receiving request retransmissions on TRYING 52 52 ** state … … 67 67 ** TEST9_BRANCH_ID 68 68 ** INVITE transaction MUST cease retransmission of final response when 69 ** ACK is received. (Note: PJSIP also retransmit 2xx final response 69 ** ACK is received. (Note: PJSIP also retransmit 2xx final response 70 70 ** until it's terminated by user). 71 71 ** Transaction also MUST terminate in T4 seconds. … … 117 117 #define TEST4_REQUEST_COUNT 2 118 118 #define TEST5_PROVISIONAL_CODE 100 119 #define TEST5_STATUS_CODE 200 119 #define TEST5_STATUS_CODE 200 120 120 #define TEST5_REQUEST_COUNT 2 121 121 #define TEST5_RESPONSE_COUNT 2 … … 147 147 148 148 /* UAC transaction user module. */ 149 static pjsip_module tsx_user = 149 static pjsip_module tsx_user = 150 150 { 151 151 NULL, NULL, /* prev and next */ … … 165 165 166 166 /* Module to send request. */ 167 static pjsip_module msg_sender = 167 static pjsip_module msg_sender = 168 168 { 169 169 NULL, NULL, /* prev and next */ … … 242 242 pjsip_tx_data *tdata; 243 243 244 status = pjsip_endpt_create_response( endpt, rdata, status_code, NULL, 244 status = pjsip_endpt_create_response( endpt, rdata, status_code, NULL, 245 245 &tdata); 246 246 if (status != PJ_SUCCESS) { … … 272 272 pj_time_val delay; 273 273 274 status = pjsip_endpt_create_response( endpt, rdata, status_code, NULL, 274 status = pjsip_endpt_create_response( endpt, rdata, status_code, NULL, 275 275 &tdata); 276 276 if (status != PJ_SUCCESS) { … … 354 354 { 355 355 if (pj_stricmp2(&tsx->branch, TEST1_BRANCH_ID)==0 || 356 pj_stricmp2(&tsx->branch, TEST2_BRANCH_ID)==0) 356 pj_stricmp2(&tsx->branch, TEST2_BRANCH_ID)==0) 357 357 { 358 358 /* … … 375 375 test_complete = -100; 376 376 } 377 377 378 378 /* Previous state must be completed. */ 379 379 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) { … … 406 406 test_complete = -110; 407 407 } 408 408 409 409 /* Previous state must be completed. */ 410 410 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) { … … 466 466 /* Check that status code is status_code. */ 467 467 if (tsx->status_code != TEST4_STATUS_CODE) { 468 PJ_LOG(3,(THIS_FILE, 468 PJ_LOG(3,(THIS_FILE, 469 469 " error: incorrect status code %d " 470 470 "(expecting %d)", tsx->status_code, … … 472 472 test_complete = -120; 473 473 } 474 474 475 475 /* Previous state. */ 476 476 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) { … … 479 479 } 480 480 481 } else if (tsx->state != PJSIP_TSX_STATE_DESTROYED) 481 } else if (tsx->state != PJSIP_TSX_STATE_DESTROYED) 482 482 { 483 483 PJ_LOG(3,(THIS_FILE, " error: unexpected state %s (122)", … … 503 503 test_complete = -130; 504 504 } 505 505 506 506 /* Previous state. */ 507 507 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_PROCEEDING) { … … 538 538 if (tsx->status_code != TEST6_STATUS_CODE) { 539 539 PJ_LOG(3,(THIS_FILE, " error: incorrect status code %d " 540 "(expecting %d)", tsx->status_code, 540 "(expecting %d)", tsx->status_code, 541 541 TEST6_STATUS_CODE)); 542 542 test_complete = -140; 543 543 } 544 544 545 545 /* Previous state. */ 546 546 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) { … … 551 551 } else if (tsx->state != PJSIP_TSX_STATE_PROCEEDING && 552 552 tsx->state != PJSIP_TSX_STATE_COMPLETED && 553 tsx->state != PJSIP_TSX_STATE_DESTROYED) 553 tsx->state != PJSIP_TSX_STATE_DESTROYED) 554 554 { 555 555 PJ_LOG(3,(THIS_FILE, " error: unexpected state %s (142)", … … 562 562 } else 563 563 if (pj_stricmp2(&tsx->branch, TEST7_BRANCH_ID)==0 || 564 pj_stricmp2(&tsx->branch, TEST8_BRANCH_ID)==0) 564 pj_stricmp2(&tsx->branch, TEST8_BRANCH_ID)==0) 565 565 { 566 566 /* … … 588 588 test_complete = -150; 589 589 } 590 590 591 591 /* Previous state. */ 592 592 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) { … … 606 606 607 607 if (tsx->retransmit_count != 10) { 608 PJ_LOG(3,(THIS_FILE, 608 PJ_LOG(3,(THIS_FILE, 609 609 " error: incorrect retransmit count %d " 610 610 "(expecting 10)", … … 622 622 test_complete = -152; 623 623 } 624 624 625 625 /* Previous state. */ 626 626 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) { … … 657 657 test_complete = -160; 658 658 } 659 659 660 660 /* Previous state. */ 661 661 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_CONFIRMED) { … … 671 671 test_complete = -162; 672 672 } 673 673 674 674 /* Previous state. */ 675 675 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_TRYING) { … … 686 686 test_complete = -164; 687 687 } 688 688 689 689 /* Previous state. */ 690 690 if (e->body.tsx_state.prev_state != PJSIP_TSX_STATE_COMPLETED) { … … 704 704 if (pj_stricmp2(&tsx->branch, TEST10_BRANCH_ID)==0 || 705 705 pj_stricmp2(&tsx->branch, TEST11_BRANCH_ID)==0 || 706 pj_stricmp2(&tsx->branch, TEST12_BRANCH_ID)==0) 706 pj_stricmp2(&tsx->branch, TEST12_BRANCH_ID)==0) 707 707 { 708 708 if (tsx->state == PJSIP_TSX_STATE_TERMINATED) { 709 709 710 710 if (!test_complete) 711 711 test_complete = 1; … … 741 741 742 742 if (pj_stricmp2(&branch_param, TEST1_BRANCH_ID) == 0 || 743 pj_stricmp2(&branch_param, TEST2_BRANCH_ID) == 0) 743 pj_stricmp2(&branch_param, TEST2_BRANCH_ID) == 0) 744 744 { 745 745 /* 746 * TEST1_BRANCH_ID tests that non-INVITE transaction transmits 2xx 747 * final response using correct transport and terminates transaction 746 * TEST1_BRANCH_ID tests that non-INVITE transaction transmits 2xx 747 * final response using correct transport and terminates transaction 748 748 * after 32 seconds. 749 749 * … … 754 754 755 755 if (msg->type == PJSIP_REQUEST_MSG) { 756 /* On received request, create UAS and respond with final 757 * response. 756 /* On received request, create UAS and respond with final 757 * response. 758 758 */ 759 759 pjsip_transaction *tsx; … … 811 811 812 812 send_response(rdata, tsx, TEST3_PROVISIONAL_CODE); 813 schedule_send_response(rdata, &tsx->transaction_key, 813 schedule_send_response(rdata, &tsx->transaction_key, 814 814 TEST3_STATUS_CODE, 2000); 815 815 … … 841 841 } else if (pj_stricmp2(&branch_param, TEST4_BRANCH_ID) == 0 || 842 842 pj_stricmp2(&branch_param, TEST5_BRANCH_ID) == 0 || 843 pj_stricmp2(&branch_param, TEST6_BRANCH_ID) == 0) 843 pj_stricmp2(&branch_param, TEST6_BRANCH_ID) == 0) 844 844 { 845 845 … … 878 878 } else { 879 879 /* Verify the response received. */ 880 880 881 881 PJ_LOG(4,(THIS_FILE, " received response number %d", recv_count)); 882 882 … … 893 893 test_complete = -133; 894 894 895 } 895 } 896 896 if (recv_count > TEST5_RESPONSE_COUNT) { 897 897 PJ_LOG(3,(THIS_FILE, " error: not expecting response!")); … … 929 929 930 930 } else if (pj_stricmp2(&branch_param, TEST7_BRANCH_ID) == 0 || 931 pj_stricmp2(&branch_param, TEST8_BRANCH_ID) == 0) 931 pj_stricmp2(&branch_param, TEST8_BRANCH_ID) == 0) 932 932 { 933 933 … … 972 972 973 973 if (recv_count==1) { 974 974 975 975 if (rdata->msg_info.msg->line.status.code != code) { 976 976 PJ_LOG(3,(THIS_FILE," error: invalid status code")); … … 988 988 989 989 PJ_TIME_VAL_SUB(now, recv_last); 990 990 991 991 msec = now.sec*1000 + now.msec; 992 992 msec_expected = (1 << (recv_count-2)) * pjsip_cfg()->tsx.t1; … … 1017 1017 1018 1018 /* 1019 * TEST9_BRANCH_ID tests that the retransmission of INVITE final 1019 * TEST9_BRANCH_ID tests that the retransmission of INVITE final 1020 1020 * response should cease when ACK is received. Transaction also MUST 1021 1021 * terminate in T4 seconds. … … 1060 1060 1061 1061 PJ_TIME_VAL_SUB(now, recv_last); 1062 1062 1063 1063 msec = now.sec*1000 + now.msec; 1064 1064 msec_expected = (1 << (recv_count-2)) * pjsip_cfg()->tsx.t1; … … 1082 1082 1083 1083 status = pjsip_endpt_create_request_from_hdr( 1084 endpt, &pjsip_ack_method, 1084 endpt, &pjsip_ack_method, 1085 1085 rdata->msg_info.to->uri, 1086 1086 rdata->msg_info.from, 1087 1087 rdata->msg_info.to, 1088 NULL, 1088 NULL, 1089 1089 rdata->msg_info.cid, 1090 1090 rdata->msg_info.cseq->cseq, … … 1121 1121 } else if (pj_stricmp2(&branch_param, TEST10_BRANCH_ID) == 0 || 1122 1122 pj_stricmp2(&branch_param, TEST11_BRANCH_ID) == 0 || 1123 pj_stricmp2(&branch_param, TEST12_BRANCH_ID) == 0) 1123 pj_stricmp2(&branch_param, TEST12_BRANCH_ID) == 0) 1124 1124 { 1125 1125 int test_num, code1, code2; … … 1132 1132 test_num=12, code1 = 200, code2 = 0; 1133 1133 1134 PJ_UNUSED_ARG(test_num); 1135 1134 1136 if (rdata->msg_info.msg->type == PJSIP_REQUEST_MSG) { 1135 1137 … … 1146 1148 pjsip_tsx_recv_msg(tsx, rdata); 1147 1149 save_key(tsx); 1148 1150 1149 1151 schedule_send_response(rdata, &tsx_key, code1, 1000); 1150 1152 … … 1162 1164 } 1163 1165 1164 /* 1165 * The generic test framework, used by most of the tests. 1166 /* 1167 * The generic test framework, used by most of the tests. 1166 1168 */ 1167 static int perform_test( char *target_uri, char *from_uri, 1168 char *branch_param, int test_time, 1169 static int perform_test( char *target_uri, char *from_uri, 1170 char *branch_param, int test_time, 1169 1171 const pjsip_method *method, 1170 1172 int request_cnt, int request_interval_msec, … … 1178 1180 pj_status_t status; 1179 1181 1180 PJ_LOG(3,(THIS_FILE, 1182 PJ_LOG(3,(THIS_FILE, 1181 1183 " please standby, this will take at most %d seconds..", 1182 1184 test_time)); … … 1193 1195 /* Create request. */ 1194 1196 status = pjsip_endpt_create_request( endpt, method, &target, 1195 &from, &target, NULL, NULL, -1, 1197 &from, &target, NULL, NULL, -1, 1196 1198 NULL, &tdata); 1197 1199 if (status != PJ_SUCCESS) { … … 1369 1371 1370 1372 status = perform_test(TARGET_URI, FROM_URI, branch_id, 5, 1371 &pjsip_options_method, 1373 &pjsip_options_method, 1372 1374 request_cnt, 1000, 1); 1373 1375 if (status && status != TEST_TIMEOUT_ERROR) … … 1423 1425 /***************************************************************************** 1424 1426 ** 1425 ** TEST9_BRANCH_ID: retransmission of non-2xx INVITE final response must 1427 ** TEST9_BRANCH_ID: retransmission of non-2xx INVITE final response must 1426 1428 ** cease when ACK is received 1427 1429 ** … … 1464 1466 char *branch_id; 1465 1467 char *title; 1466 } tests[] = 1468 } tests[] = 1467 1469 { 1468 1470 { 0, 10, TEST10_BRANCH_ID, "test10: failed transport in TRYING state (no delay)" }, … … 1538 1540 tp_flag = pjsip_transport_get_flag_from_type((pjsip_transport_type_e)param->type); 1539 1541 1540 pj_ansi_sprintf(TARGET_URI, "sip:bob@127.0.0.1:%d;transport=%s", 1542 pj_ansi_sprintf(TARGET_URI, "sip:bob@127.0.0.1:%d;transport=%s", 1541 1543 param->port, param->tp_type); 1542 pj_ansi_sprintf(FROM_URI, "sip:alice@127.0.0.1:%d;transport=%s", 1544 pj_ansi_sprintf(FROM_URI, "sip:alice@127.0.0.1:%d;transport=%s", 1543 1545 param->port, param->tp_type); 1544 1546 1545 1547 /* Check if loop transport is configured. */ 1546 status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM, 1548 status = pjsip_endpt_acquire_transport(endpt, PJSIP_TRANSPORT_LOOP_DGRAM, 1547 1549 &addr, sizeof(addr), NULL, &loop); 1548 1550 if (status != PJ_SUCCESS) { … … 1562 1564 } 1563 1565 1564 /* TEST1_BRANCH_ID: Basic 2xx final response. 1565 * TEST2_BRANCH_ID: Basic non-2xx final response. 1566 /* TEST1_BRANCH_ID: Basic 2xx final response. 1567 * TEST2_BRANCH_ID: Basic non-2xx final response. 1566 1568 */ 1567 1569 status = tsx_basic_final_response_test(); … … 1578 1580 */ 1579 1581 status = tsx_retransmit_last_response_test(TEST4_TITLE, 1580 TEST4_BRANCH_ID, 1582 TEST4_BRANCH_ID, 1581 1583 TEST4_REQUEST_COUNT, 1582 1584 TEST4_STATUS_CODE); … … 1587 1589 */ 1588 1590 status = tsx_retransmit_last_response_test(TEST5_TITLE, 1589 TEST5_BRANCH_ID, 1591 TEST5_BRANCH_ID, 1590 1592 TEST5_REQUEST_COUNT, 1591 1593 TEST5_STATUS_CODE); … … 1600 1602 if ((tp_flag & PJSIP_TRANSPORT_RELIABLE) == 0) { 1601 1603 status = tsx_retransmit_last_response_test(TEST6_TITLE, 1602 TEST6_BRANCH_ID, 1604 TEST6_BRANCH_ID, 1603 1605 TEST6_REQUEST_COUNT, 1604 1606 TEST6_STATUS_CODE); … … 1614 1616 return status; 1615 1617 1616 /* TEST9_BRANCH_ID: retransmission of non-2xx INVITE final response must 1618 /* TEST9_BRANCH_ID: retransmission of non-2xx INVITE final response must 1617 1619 * cease when ACK is received 1618 1620 * Only applicable for non-reliable transports. -
pjproject/trunk/pjsip/src/test/uri_test.c
r4641 r4728 1 1 /* $Id$ */ 2 /* 2 /* 3 3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) 4 4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 19 */ 20 20 #include "test.h" … … 68 68 static pjsip_uri *create_uri16( pj_pool_t *pool ); 69 69 static pjsip_uri *create_uri17( pj_pool_t *pool ); 70 static pjsip_uri *create_uri18( pj_pool_t *pool );71 70 static pjsip_uri *create_uri25( pj_pool_t *pool ); 72 71 static pjsip_uri *create_uri26( pj_pool_t *pool ); … … 97 96 const char *printed; 98 97 pj_size_t len; 99 } uri_test_array[] = 98 } uri_test_array[] = 100 99 { 101 100 { … … 184 183 { 185 184 /* Excercise strange character sets allowed in display, user, password, 186 * host, and port. 185 * host, and port. 187 186 */ 188 187 PJ_SUCCESS, … … 198 197 }, 199 198 { 200 /* Another excercise to the allowed character sets to the username 199 /* Another excercise to the allowed character sets to the username 201 200 * and password. 202 201 */ … … 439 438 { 440 439 /* "sip:localhost;pickup=hurry;user=phone;message=I%20am%20sorry" 441 "?Subject=Hello%20There&Server=SIP%20Server" 440 "?Subject=Hello%20There&Server=SIP%20Server" 442 441 */ 443 442 pjsip_sip_uri *url = pjsip_sip_uri_create(pool, 0); … … 659 658 660 659 uri->number = pj_str("(44).1234-*#+Deaf"); 661 return (pjsip_uri*)uri; 660 return (pjsip_uri*)uri; 662 661 } 663 662 … … 669 668 uri->number = pj_str("+1"); 670 669 uri->isub_param = pj_str("/:@&$,-_.!~*'()[]/:&$aA1!+="); 671 return (pjsip_uri*)uri; 670 return (pjsip_uri*)uri; 672 671 } 673 672 … … 679 678 uri->number = pj_str("+1"); 680 679 uri->ext_param = pj_str("+123"); 681 return (pjsip_uri*)uri; 680 return (pjsip_uri*)uri; 682 681 } 683 682 … … 689 688 uri->number = pj_str("911"); 690 689 uri->context = pj_str("+1-911"); 691 return (pjsip_uri*)uri; 690 return (pjsip_uri*)uri; 692 691 } 693 692 … … 699 698 uri->number = pj_str("911"); 700 699 uri->context = pj_str("EMERGENCY.EXAMPLE.COM"); 701 return (pjsip_uri*)uri; 700 return (pjsip_uri*)uri; 702 701 } 703 702 … … 709 708 710 709 uri->number = pj_str("911"); 711 710 712 711 p = PJ_POOL_ALLOC_T(pool, pjsip_param); 713 712 p->name = p->value = pj_str("p1"); 714 713 pj_list_insert_before(&uri->other_param, p); 715 714 716 return (pjsip_uri*)uri; 715 return (pjsip_uri*)uri; 717 716 } 718 717 … … 750 749 url = pjsip_sip_uri_create(pool, 0); 751 750 url->host = pj_str("localhost"); 752 751 753 752 name->uri = (pjsip_uri*)url; 754 753 … … 768 767 url = pjsip_sip_uri_create(pool, 0); 769 768 url->host = pj_str("localhost"); 770 769 771 770 name->uri = (pjsip_uri*)url; 772 771 … … 1000 999 avg_parse = 1000000 / avg_parse; 1001 1000 1002 PJ_LOG(3,(THIS_FILE, 1003 " %u.%u MB of urls parsed in %d.%03ds (avg=%d urls/sec)", 1001 PJ_LOG(3,(THIS_FILE, 1002 " %u.%u MB of urls parsed in %d.%03ds (avg=%d urls/sec)", 1004 1003 (unsigned)(var.parse_len/1000000), (unsigned)kbytes, 1005 1004 elapsed.sec, elapsed.msec, … … 1019 1018 avg_print = 1000000 / avg_print; 1020 1019 1021 PJ_LOG(3,(THIS_FILE, 1022 " %u.%u MB of urls printed in %d.%03ds (avg=%d urls/sec)", 1020 PJ_LOG(3,(THIS_FILE, 1021 " %u.%u MB of urls printed in %d.%03ds (avg=%d urls/sec)", 1023 1022 (unsigned)(var.print_len/1000000), (unsigned)kbytes, 1024 1023 elapsed.sec, elapsed.msec, … … 1038 1037 avg_cmp = 1000000 / avg_cmp; 1039 1038 1040 PJ_LOG(3,(THIS_FILE, 1041 " %u.%u MB of urls compared in %d.%03ds (avg=%d urls/sec)", 1039 PJ_LOG(3,(THIS_FILE, 1040 " %u.%u MB of urls compared in %d.%03ds (avg=%d urls/sec)", 1042 1041 (unsigned)(var.cmp_len/1000000), (unsigned)kbytes, 1043 1042 elapsed.sec, elapsed.msec, … … 1085 1084 1086 1085 1087 /* 1088 * Print maximum parse/sec 1086 /* 1087 * Print maximum parse/sec 1089 1088 */ 1090 1089 for (i=0, max=0; i<COUNT; ++i) -
pjproject/trunk/third_party/ilbc/LPCencode.c
r638 r4728 225 225 float lsf[LPC_FILTERORDER * LPC_N_MAX]; 226 226 float lsfdeq[LPC_FILTERORDER * LPC_N_MAX]; 227 int change=0;228 227 229 228 SimpleAnalysis(lsf, data, iLBCenc_inst); … … 234 233 235 234 236 change=LSF_check(lsfdeq, LPC_FILTERORDER, iLBCenc_inst->lpc_n);235 LSF_check(lsfdeq, LPC_FILTERORDER, iLBCenc_inst->lpc_n); 237 236 SimpleInterpolateLSF(syntdenum, weightdenum, 238 237 lsf, lsfdeq, iLBCenc_inst->lsfold, -
pjproject/trunk/third_party/ilbc/helpfun.c
r638 r4728 278 278 ){ 279 279 int k,n,m, Nit=2, change=0,pos; 280 float tmp;280 //float tmp; 281 281 static float eps=(float)0.039; /* 50 Hz */ 282 282 static float eps2=(float)0.0195; … … 294 294 295 295 if (lsf[pos+1]<lsf[pos]) { 296 tmp=lsf[pos+1];296 //tmp=lsf[pos+1]; 297 297 lsf[pos+1]= lsf[pos]+eps2; 298 298 lsf[pos]= lsf[pos+1]-eps2; -
pjproject/trunk/third_party/ilbc/iLBC_decode.c
r638 r4728 340 340 float cc, maxcc; 341 341 int idxVec[STATE_LEN]; 342 int check;343 342 int gain_index[NASUB_MAX*CB_NSTAGES], 344 343 extra_gain_index[CB_NSTAGES]; … … 501 500 502 501 SimplelsfDEQ(lsfdeq, lsf_i, iLBCdec_inst->lpc_n); 503 check=LSF_check(lsfdeq, LPC_FILTERORDER,502 LSF_check(lsfdeq, LPC_FILTERORDER, 504 503 iLBCdec_inst->lpc_n); 505 504 DecoderInterpolateLSF(syntdenum, weightdenum, -
pjproject/trunk/third_party/resample/src/resamplesubs.c
r3085 r4728 7 7 * 8 8 * Snippet from the resample.1 man page: 9 * 9 * 10 10 * HISTORY 11 11 * … … 14 14 * 1981. It was called SRCONV and was written in SAIL for PDP-10 15 15 * compatible machines. The algorithm was first published in 16 * 16 * 17 17 * Smith, Julius O. and Phil Gossett. ``A Flexible Sampling-Rate 18 18 * Conversion Method,'' Proceedings (2): 19.4.1-19.4.4, IEEE Conference 19 19 * on Acoustics, Speech, and Signal Processing, San Diego, March 1984. 20 * 20 * 21 21 * An expanded tutorial based on this paper is available at the Digital 22 22 * Audio Resampling Home Page given above. 23 * 23 * 24 24 * Circa 1988, the SRCONV program was translated from SAIL to C by 25 25 * Christopher Lee Fraley working with Roger Dannenberg at CMU. 26 * 26 * 27 27 * Since then, the C version has been maintained by jos. 28 * 28 * 29 29 * Sndlib support was added 6/99 by John Gibson <jgg9c@virginia.edu>. 30 * 30 * 31 31 * The resample program is free software distributed in accordance 32 32 * with the Lesser GNU Public License (LGPL). There is NO warranty; not … … 78 78 #undef INLINE 79 79 #define INLINE 80 #define HAVE_FILTER 0 80 #define HAVE_FILTER 0 81 81 82 82 #ifndef NULL … … 95 95 } else if (v < MIN_HWORD) { 96 96 v = MIN_HWORD; 97 } 97 } 98 98 out = (RES_HWORD) v; 99 99 return out; … … 102 102 /* Sampling rate conversion using linear interpolation for maximum speed. 103 103 */ 104 static int 104 static int 105 105 SrcLinear(const RES_HWORD X[], RES_HWORD Y[], double pFactor, RES_UHWORD nx) 106 106 { … … 110 110 RES_HWORD *Ystart, *Yend; 111 111 RES_WORD v,x1,x2; 112 113 double dt; /* Step through input signal */ 112 113 double dt; /* Step through input signal */ 114 114 RES_UWORD dtb; /* Fixed-point version of Dt */ 115 RES_UWORD endTime; /* When time reaches EndTime, return to user */116 115 //RES_UWORD endTime; /* When time reaches EndTime, return to user */ 116 117 117 dt = 1.0/pFactor; /* Output sampling period */ 118 118 dtb = dt*(1<<Np) + 0.5; /* Fixed-point representation */ 119 119 120 120 Ystart = Y; 121 121 Yend = Ystart + (unsigned)(nx * pFactor + 0.5); 122 endTime = time + (1<<Np)*(RES_WORD)nx;123 124 // Integer round down in dtb calculation may cause (endTime % dtb > 0), 122 //endTime = time + (1<<Np)*(RES_WORD)nx; 123 124 // Integer round down in dtb calculation may cause (endTime % dtb > 0), 125 125 // so it may cause resample write pass the output buffer (Y >= Yend). 126 126 // while (time < endTime) … … 140 140 } 141 141 142 static RES_WORD FilterUp(const RES_HWORD Imp[], const RES_HWORD ImpD[], 142 static RES_WORD FilterUp(const RES_HWORD Imp[], const RES_HWORD ImpD[], 143 143 RES_UHWORD Nwing, RES_BOOL Interp, 144 144 const RES_HWORD *Xp, RES_HWORD Ph, RES_HWORD Inc) … … 149 149 RES_HWORD a = 0; 150 150 RES_WORD v, t; 151 151 152 152 v=0; 153 153 Hp = &Imp[Ph>>Na]; … … 179 179 180 180 Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ 181 } 182 else 181 } 182 else 183 183 while (Hp < End) { 184 184 t = *Hp; /* Get filter coeff */ … … 203 203 RES_WORD v, t; 204 204 RES_UWORD Ho; 205 205 206 206 v=0; 207 207 Ho = (Ph*(RES_UWORD)dhb)>>Np; … … 228 228 Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ 229 229 } 230 else 230 else 231 231 while ((Hp = &Imp[Ho>>Na]) < End) { 232 232 t = *Hp; /* Get IR sample */ … … 245 245 * Slightly faster than down-conversion; 246 246 */ 247 static int SrcUp(const RES_HWORD X[], RES_HWORD Y[], double pFactor, 247 static int SrcUp(const RES_HWORD X[], RES_HWORD Y[], double pFactor, 248 248 RES_UHWORD nx, RES_UHWORD pNwing, RES_UHWORD pLpScl, 249 249 const RES_HWORD pImp[], const RES_HWORD pImpD[], RES_BOOL Interp) … … 252 252 RES_HWORD *Ystart, *Yend; 253 253 RES_WORD v; 254 255 double dt; /* Step through input signal */ 254 255 double dt; /* Step through input signal */ 256 256 RES_UWORD dtb; /* Fixed-point version of Dt */ 257 257 RES_UWORD time = 0; 258 RES_UWORD endTime; /* When time reaches EndTime, return to user */259 258 //RES_UWORD endTime; /* When time reaches EndTime, return to user */ 259 260 260 dt = 1.0/pFactor; /* Output sampling period */ 261 261 dtb = dt*(1<<Np) + 0.5; /* Fixed-point representation */ 262 262 263 263 Ystart = Y; 264 264 Yend = Ystart + (unsigned)(nx * pFactor + 0.5); 265 endTime = time + (1<<Np)*(RES_WORD)nx;266 267 // Integer round down in dtb calculation may cause (endTime % dtb > 0), 265 //endTime = time + (1<<Np)*(RES_WORD)nx; 266 267 // Integer round down in dtb calculation may cause (endTime % dtb > 0), 268 268 // so it may cause resample write pass the output buffer (Y >= Yend). 269 269 // while (time < endTime) … … 289 289 /* Sampling rate conversion subroutine */ 290 290 291 static int SrcUD(const RES_HWORD X[], RES_HWORD Y[], double pFactor, 291 static int SrcUD(const RES_HWORD X[], RES_HWORD Y[], double pFactor, 292 292 RES_UHWORD nx, RES_UHWORD pNwing, RES_UHWORD pLpScl, 293 293 const RES_HWORD pImp[], const RES_HWORD pImpD[], RES_BOOL Interp) … … 296 296 RES_HWORD *Ystart, *Yend; 297 297 RES_WORD v; 298 298 299 299 double dh; /* Step through filter impulse response */ 300 300 double dt; /* Step through input signal */ 301 301 RES_UWORD time = 0; 302 RES_UWORD endTime; /* When time reaches EndTime, return to user */302 //RES_UWORD endTime; /* When time reaches EndTime, return to user */ 303 303 RES_UWORD dhb, dtb; /* Fixed-point versions of Dh,Dt */ 304 304 305 305 dt = 1.0/pFactor; /* Output sampling period */ 306 306 dtb = dt*(1<<Np) + 0.5; /* Fixed-point representation */ 307 307 308 308 dh = MIN(Npc, pFactor*Npc); /* Filter sampling period */ 309 309 dhb = dh*(1<<Na) + 0.5; /* Fixed-point representation */ 310 310 311 311 Ystart = Y; 312 312 Yend = Ystart + (unsigned)(nx * pFactor + 0.5); 313 endTime = time + (1<<Np)*(RES_WORD)nx;314 315 // Integer round down in dtb calculation may cause (endTime % dtb > 0), 313 //endTime = time + (1<<Np)*(RES_WORD)nx; 314 315 // Integer round down in dtb calculation may cause (endTime % dtb > 0), 316 316 // so it may cause resample write pass the output buffer (Y >= Yend). 317 317 // while (time < endTime) … … 332 332 333 333 334 DECL(int) res_SrcLinear(const RES_HWORD X[], RES_HWORD Y[], 334 DECL(int) res_SrcLinear(const RES_HWORD X[], RES_HWORD Y[], 335 335 double pFactor, RES_UHWORD nx) 336 336 { … … 338 338 } 339 339 340 DECL(int) res_Resample(const RES_HWORD X[], RES_HWORD Y[], double pFactor, 340 DECL(int) res_Resample(const RES_HWORD X[], RES_HWORD Y[], double pFactor, 341 341 RES_UHWORD nx, RES_BOOL LargeF, RES_BOOL Interp) 342 342 { … … 355 355 356 356 if (LargeF) 357 return SrcUD(X, Y, pFactor, nx, 357 return SrcUD(X, Y, pFactor, nx, 358 358 LARGE_FILTER_NWING, LARGE_FILTER_SCALE * pFactor + 0.5, 359 359 LARGE_FILTER_IMP, LARGE_FILTER_IMPD, Interp); 360 360 else 361 return SrcUD(X, Y, pFactor, nx, 361 return SrcUD(X, Y, pFactor, nx, 362 362 SMALL_FILTER_NWING, SMALL_FILTER_SCALE * pFactor + 0.5, 363 363 SMALL_FILTER_IMP, SMALL_FILTER_IMPD, Interp); … … 369 369 { 370 370 if (LargeF) 371 return (LARGE_FILTER_NMULT + 1) / 2.0 * 371 return (LARGE_FILTER_NMULT + 1) / 2.0 * 372 372 MAX(1.0, 1.0/pFactor); 373 373 else 374 return (SMALL_FILTER_NMULT + 1) / 2.0 * 374 return (SMALL_FILTER_NMULT + 1) / 2.0 * 375 375 MAX(1.0, 1.0/pFactor); 376 376 }
Note: See TracChangeset
for help on using the changeset viewer.