- 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; \