Changeset 1382
- Timestamp:
- Jun 22, 2007 11:32:49 AM (17 years ago)
- Location:
- pjproject/trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip-apps/build/samples.dsp
r1127 r1382 103 103 # Begin Source File 104 104 105 SOURCE=..\src\samples\invtester.c 106 # End Source File 107 # Begin Source File 108 105 109 SOURCE=..\src\samples\level.c 106 110 # End Source File … … 168 172 169 173 SOURCE=..\src\samples\tonegen.c 174 # End Source File 175 # Begin Source File 176 177 SOURCE=..\src\samples\transportpausetest.c 170 178 # End Source File 171 179 # End Group -
pjproject/trunk/pjsip/include/pjsip/sip_errno.h
r974 r1382 223 223 */ 224 224 #define PJSIP_ETPNOTSUITABLE (PJSIP_ERRNO_START_PJSIP + 64) /* 171064 */ 225 225 /** 226 * @hideinitializer 227 * Transport not available. This error occurs for example when the SIP stack 228 * is trying to use a SIP transport while the transport is being paused by 229 * application. 230 */ 231 #define PJSIP_ETPNOTAVAIL (PJSIP_ERRNO_START_PJSIP + 65) /* 171065 */ 226 232 227 233 /************************************************************ -
pjproject/trunk/pjsip/include/pjsip/sip_transport_udp.h
r974 r1382 37 37 * the transport to the framework. 38 38 */ 39 40 /** 41 * Flag that can be specified when calling #pjsip_udp_transport_pause() or 42 * #pjsip_udp_transport_restart(). 43 */ 44 enum 45 { 46 /** 47 * This flag tells the transport to keep the existing/internal socket 48 * handle. 49 */ 50 PJSIP_UDP_TRANSPORT_KEEP_SOCKET = 1, 51 52 /** 53 * This flag tells the transport to destroy the existing/internal socket 54 * handle. Naturally this flag and PJSIP_UDP_TRANSPORT_KEEP_SOCKET are 55 * mutually exclusive. 56 */ 57 PJSIP_UDP_TRANSPORT_DESTROY_SOCKET = 2 58 }; 59 39 60 40 61 /** … … 82 103 83 104 105 /** 106 * Retrieve the internal socket handle used by the UDP transport. Note 107 * that this socket normally is registered to ioqueue, so if application 108 * wants to make use of this socket, it should temporarily pause the 109 * transport. 110 * 111 * @param transport The UDP transport. 112 * 113 * @return The socket handle, or PJ_INVALID_SOCKET if no socket 114 * is currently being used (for example, when transport 115 * is being paused). 116 */ 117 PJ_DECL(pj_sock_t) pjsip_udp_transport_get_socket(pjsip_transport *transport); 118 119 120 /** 121 * Temporarily pause or shutdown the transport. When transport is being 122 * paused, it cannot be used by the SIP stack to send or receive SIP 123 * messages. 124 * 125 * Two types of operations are supported by this function: 126 * - to temporarily make this transport unavailable for SIP uses, but 127 * otherwise keep the socket handle intact. Application then can 128 * retrieve the socket handle with #pjsip_udp_transport_get_socket() 129 * and use it to send/receive application data (for example, STUN 130 * messages). In this case, application should specify 131 * PJSIP_UDP_TRANSPORT_KEEP_SOCKET when calling this function, and 132 * also to specify this flag when calling #pjsip_udp_transport_restart() 133 * later. 134 * - to temporarily shutdown the transport, including closing down 135 * the internal socket handle. This is useful for example to 136 * temporarily suspend the application for an indefinite period. In 137 * this case, application should specify PJSIP_UDP_TRANSPORT_DESTROY_SOCKET 138 * flag when calling this function, and specify a new socket when 139 * calling #pjsip_udp_transport_restart(). 140 * 141 * @param transport The UDP transport. 142 * @param option Pause option. 143 * 144 * @return PJ_SUCCESS if transport is paused successfully, 145 * or the appropriate error code. 146 */ 147 PJ_DECL(pj_status_t) pjsip_udp_transport_pause(pjsip_transport *transport, 148 unsigned option); 149 150 /** 151 * Restart the transport. Several operations are supported by this function: 152 * - if transport was made temporarily unavailable to SIP stack with 153 * pjsip_udp_transport_pause() and PJSIP_UDP_TRANSPORT_KEEP_SOCKET, 154 * application can make the transport available to the SIP stack 155 * again, by specifying PJSIP_UDP_TRANSPORT_KEEP_SOCKET flag here. 156 * - if application wants to replace the internal socket with a new 157 * socket, it must specify PJSIP_UDP_TRANSPORT_DESTROY_SOCKET when 158 * calling this function, so that the internal socket will be destroyed 159 * if it hasn't been closed. In this case, application has two choices 160 * on how to create the new socket: 1) to let the transport create 161 * the new socket, in this case the \a sock option should be set 162 * to \a PJ_INVALID_SOCKET and optionally the \a local parameter can be 163 * filled with the desired address and port where the new socket 164 * should be bound to, or 2) to specify its own socket to be used 165 * by this transport, by specifying a valid socket in \a sock argument 166 * and set the \a local argument to NULL. In both cases, application 167 * may specify the published address of the socket in \a a_name 168 * argument. 169 * 170 * @param transport The UDP transport. 171 * @param option Restart option. 172 * @param sock Optional socket to be used by the transport. 173 * @param local The address where the socket should be bound to. 174 * If this argument is NULL, socket will be bound 175 * to any available port. 176 * @param a_name Optionally specify the published address for 177 * this transport. If the socket is not replaced 178 * (PJSIP_UDP_TRANSPORT_KEEP_SOCKET flag is 179 * specified), then if this argument is NULL, the 180 * previous value will be used. If the socket is 181 * replaced and this argument is NULL, the bound 182 * address will be used as the published address 183 * of the transport. 184 * 185 * @return PJ_SUCCESS if transport can be restarted, or 186 * the appropriate error code. 187 */ 188 PJ_DECL(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport, 189 unsigned option, 190 pj_sock_t sock, 191 const pj_sockaddr_in *local, 192 const pjsip_host_port *a_name); 193 194 84 195 PJ_END_DECL 85 196 -
pjproject/trunk/pjsip/src/pjsip/sip_errno.c
r974 r1382 69 69 PJ_BUILD_ERR( PJSIP_EBUFDESTROYED, "Buffer destroyed"), 70 70 PJ_BUILD_ERR( PJSIP_ETPNOTSUITABLE, "Unsuitable transport selected"), 71 PJ_BUILD_ERR( PJSIP_ETPNOTAVAIL, "Transport not available for use"), 71 72 72 73 /* Transaction errors */ -
pjproject/trunk/pjsip/src/pjsip/sip_transport_udp.c
r1269 r1382 68 68 pjsip_rx_data **rdata; 69 69 int is_closing; 70 pj_bool_t is_paused; 70 71 }; 71 72 … … 122 123 return; 123 124 } 125 126 /* Don't do anything if transport is being paused. */ 127 if (tp->is_paused) 128 return; 124 129 125 130 /* … … 205 210 op_key = &rdata->tp_info.op_key.op_key; 206 211 } 212 213 /* Only read next packet if transport is not being paused. This 214 * check handles the case where transport is paused while endpoint 215 * is still processing a SIP message. 216 */ 217 if (tp->is_paused) 218 return; 207 219 208 220 /* Read next packet. */ … … 296 308 PJ_ASSERT_RETURN(tdata->op_key.tdata == NULL, PJSIP_EPENDINGTX); 297 309 310 /* Return error if transport is paused */ 311 if (tp->is_paused) 312 return PJSIP_ETPNOTAVAIL; 313 298 314 /* Init op key. */ 299 315 tdata->op_key.tdata = tdata; … … 396 412 397 413 398 /* 399 * pjsip_udp_transport_attach() 400 * 401 * Attach UDP socket and start transport. 402 */ 403 PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt, 404 pj_sock_t sock, 405 const pjsip_host_port *a_name, 406 unsigned async_cnt, 407 pjsip_transport **p_transport) 408 { 409 enum { M = 80 }; 410 pj_pool_t *pool; 411 struct udp_transport *tp; 412 pj_ioqueue_t *ioqueue; 413 pj_ioqueue_callback ioqueue_cb; 414 /* Create socket */ 415 static pj_status_t create_socket(const pj_sockaddr_in *local_a, 416 pj_sock_t *p_sock) 417 { 418 pj_sock_t sock; 419 pj_sockaddr_in tmp_addr; 420 pj_status_t status; 421 422 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock); 423 if (status != PJ_SUCCESS) 424 return status; 425 426 if (local_a == NULL) { 427 pj_sockaddr_in_init(&tmp_addr, NULL, 0); 428 local_a = &tmp_addr; 429 } 430 431 status = pj_sock_bind(sock, local_a, sizeof(*local_a)); 432 if (status != PJ_SUCCESS) { 433 pj_sock_close(sock); 434 return status; 435 } 436 437 *p_sock = sock; 438 return PJ_SUCCESS; 439 } 440 441 442 /* Generate transport's published address */ 443 static pj_status_t get_published_name(pj_sock_t sock, 444 char hostbuf[], 445 pjsip_host_port *bound_name) 446 { 447 pj_sockaddr_in tmp_addr; 448 int addr_len; 449 pj_status_t status; 450 451 addr_len = sizeof(tmp_addr); 452 status = pj_sock_getsockname(sock, &tmp_addr, &addr_len); 453 if (status != PJ_SUCCESS) 454 return status; 455 456 bound_name->host.ptr = hostbuf; 457 bound_name->port = pj_ntohs(tmp_addr.sin_port); 458 459 /* If bound address specifies "0.0.0.0", get the IP address 460 * of local hostname. 461 */ 462 if (tmp_addr.sin_addr.s_addr == PJ_INADDR_ANY) { 463 pj_in_addr hostip; 464 465 status = pj_gethostip(&hostip); 466 if (status != PJ_SUCCESS) 467 return status; 468 469 pj_strcpy2(&bound_name->host, pj_inet_ntoa(hostip)); 470 } else { 471 /* Otherwise use bound address. */ 472 pj_strcpy2(&bound_name->host, pj_inet_ntoa(tmp_addr.sin_addr)); 473 } 474 475 return PJ_SUCCESS; 476 } 477 478 /* Set the published address of the transport */ 479 static void udp_set_pub_name(struct udp_transport *tp, 480 const pjsip_host_port *a_name) 481 { 482 enum { INFO_LEN = 80 }; 483 484 pj_assert(a_name->host.slen != 0); 485 pj_strdup_with_null(tp->base.pool, &tp->base.local_name.host, 486 &a_name->host); 487 tp->base.local_name.port = a_name->port; 488 489 /* Update transport info. */ 490 if (tp->base.info == NULL) { 491 tp->base.info = (char*) pj_pool_alloc(tp->base.pool, INFO_LEN); 492 } 493 pj_ansi_snprintf( 494 tp->base.info, INFO_LEN, "udp %s:%d [published as %s:%d]", 495 pj_inet_ntoa(((pj_sockaddr_in*)&tp->base.local_addr)->sin_addr), 496 pj_ntohs(((pj_sockaddr_in*)&tp->base.local_addr)->sin_port), 497 tp->base.local_name.host.ptr, 498 tp->base.local_name.port); 499 } 500 501 /* Set the socket handle of the transport */ 502 static void udp_set_socket(struct udp_transport *tp, 503 pj_sock_t sock, 504 const pjsip_host_port *a_name) 505 { 414 506 long sobuf_size; 415 unsigned i;416 507 pj_status_t status; 417 418 PJ_ASSERT_RETURN(endpt && sock!=PJ_INVALID_SOCKET && a_name && async_cnt>0,419 PJ_EINVAL);420 421 508 422 509 /* Adjust socket rcvbuf size */ … … 442 529 } 443 530 444 /* Create pool. */ 445 pool = pjsip_endpt_create_pool(endpt, "udp%p", PJSIP_POOL_LEN_TRANSPORT, 446 PJSIP_POOL_INC_TRANSPORT); 447 if (!pool) 448 return PJ_ENOMEM; 449 450 /* Create the UDP transport object. */ 451 tp = PJ_POOL_ZALLOC_T(pool, struct udp_transport); 452 453 /* Save pool. */ 454 tp->base.pool = pool; 455 456 /* Object name. */ 457 pj_ansi_snprintf(tp->base.obj_name, sizeof(tp->base.obj_name), 458 "udp%p", tp); 459 460 /* Init reference counter. */ 461 status = pj_atomic_create(pool, 0, &tp->base.ref_cnt); 462 if (status != PJ_SUCCESS) 463 goto on_error; 464 465 /* Init lock. */ 466 status = pj_lock_create_recursive_mutex(pool, "udp%p", &tp->base.lock); 467 if (status != PJ_SUCCESS) 468 goto on_error; 469 470 /* Set type. */ 471 tp->base.key.type = PJSIP_TRANSPORT_UDP; 472 473 /* Remote address is left zero (except the family) */ 474 tp->base.key.rem_addr.addr.sa_family = PJ_AF_INET; 475 476 /* Type name. */ 477 tp->base.type_name = "UDP"; 478 479 /* Transport flag */ 480 tp->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP); 481 482 483 /* Length of addressess. */ 484 tp->base.addr_len = sizeof(pj_sockaddr_in); 485 486 /* Init local address. */ 487 status = pj_sock_getsockname(sock, &tp->base.local_addr, 488 &tp->base.addr_len); 489 if (status != PJ_SUCCESS) 490 goto on_error; 531 /* Set the socket. */ 532 tp->sock = sock; 491 533 492 534 /* Init address name (published address) */ 493 pj_strdup_with_null(pool, &tp->base.local_name.host, &a_name->host); 494 tp->base.local_name.port = a_name->port; 495 496 /* Init remote name. */ 497 tp->base.remote_name.host = pj_str("0.0.0.0"); 498 tp->base.remote_name.port = 0; 499 500 /* Transport info. */ 501 tp->base.info = (char*) pj_pool_alloc(pool, M); 502 pj_ansi_snprintf( 503 tp->base.info, M, "udp %s:%d [published as %s:%d]", 504 pj_inet_ntoa(((pj_sockaddr_in*)&tp->base.local_addr)->sin_addr), 505 pj_ntohs(((pj_sockaddr_in*)&tp->base.local_addr)->sin_port), 506 tp->base.local_name.host.ptr, 507 tp->base.local_name.port); 508 509 /* Set endpoint. */ 510 tp->base.endpt = endpt; 511 512 /* Transport manager and timer will be initialized by tpmgr */ 513 514 /* Attach socket. */ 515 tp->sock = sock; 535 udp_set_pub_name(tp, a_name); 536 } 537 538 /* Register socket to ioqueue */ 539 static pj_status_t register_to_ioqueue(struct udp_transport *tp) 540 { 541 pj_ioqueue_t *ioqueue; 542 pj_ioqueue_callback ioqueue_cb; 516 543 517 544 /* Register to ioqueue. */ 518 ioqueue = pjsip_endpt_get_ioqueue( endpt);545 ioqueue = pjsip_endpt_get_ioqueue(tp->base.endpt); 519 546 pj_memset(&ioqueue_cb, 0, sizeof(ioqueue_cb)); 520 547 ioqueue_cb.on_read_complete = &udp_on_read_complete; 521 548 ioqueue_cb.on_write_complete = &udp_on_write_complete; 522 status = pj_ioqueue_register_sock(pool, ioqueue, tp->sock, tp, 523 &ioqueue_cb, &tp->key); 524 if (status != PJ_SUCCESS) 525 goto on_error; 526 527 /* Set functions. */ 528 tp->base.send_msg = &udp_send_msg; 529 tp->base.do_shutdown = &udp_shutdown; 530 tp->base.destroy = &udp_destroy; 531 532 /* This is a permanent transport, so we initialize the ref count 533 * to one so that transport manager don't destroy this transport 534 * when there's no user! 535 */ 536 pj_atomic_inc(tp->base.ref_cnt); 537 538 /* Register to transport manager. */ 539 tp->base.tpmgr = pjsip_endpt_get_tpmgr(endpt); 540 status = pjsip_transport_register( tp->base.tpmgr, (pjsip_transport*)tp); 541 if (status != PJ_SUCCESS) 542 goto on_error; 543 544 545 /* Create rdata and put it in the array. */ 546 tp->rdata_cnt = 0; 547 tp->rdata = (pjsip_rx_data**) 548 pj_pool_calloc(tp->base.pool, async_cnt, 549 sizeof(pjsip_rx_data*)); 550 for (i=0; i<async_cnt; ++i) { 551 pj_pool_t *rdata_pool = pjsip_endpt_create_pool(endpt, "rtd%p", 552 PJSIP_POOL_RDATA_LEN, 553 PJSIP_POOL_RDATA_INC); 554 if (!rdata_pool) { 555 pj_atomic_set(tp->base.ref_cnt, 0); 556 pjsip_transport_destroy(&tp->base); 557 return PJ_ENOMEM; 558 } 559 560 init_rdata(tp, i, rdata_pool, NULL); 561 tp->rdata_cnt++; 562 } 549 550 return pj_ioqueue_register_sock(tp->base.pool, ioqueue, tp->sock, tp, 551 &ioqueue_cb, &tp->key); 552 } 553 554 /* Start ioqueue asynchronous reading to all rdata */ 555 static pj_status_t start_async_read(struct udp_transport *tp) 556 { 557 pj_ioqueue_t *ioqueue; 558 int i; 559 pj_status_t status; 560 561 ioqueue = pjsip_endpt_get_ioqueue(tp->base.endpt); 563 562 564 563 /* Start reading the ioqueue. */ 565 for (i=0; i< async_cnt; ++i) {564 for (i=0; i<tp->rdata_cnt; ++i) { 566 565 pj_ssize_t size; 567 566 … … 580 579 } else if (status != PJ_EPENDING) { 581 580 /* Error! */ 581 return status; 582 } 583 } 584 585 return PJ_SUCCESS; 586 } 587 588 589 /* 590 * pjsip_udp_transport_attach() 591 * 592 * Attach UDP socket and start transport. 593 */ 594 PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt, 595 pj_sock_t sock, 596 const pjsip_host_port *a_name, 597 unsigned async_cnt, 598 pjsip_transport **p_transport) 599 { 600 pj_pool_t *pool; 601 struct udp_transport *tp; 602 unsigned i; 603 pj_status_t status; 604 605 PJ_ASSERT_RETURN(endpt && sock!=PJ_INVALID_SOCKET && a_name && async_cnt>0, 606 PJ_EINVAL); 607 608 /* Create pool. */ 609 pool = pjsip_endpt_create_pool(endpt, "udp%p", PJSIP_POOL_LEN_TRANSPORT, 610 PJSIP_POOL_INC_TRANSPORT); 611 if (!pool) 612 return PJ_ENOMEM; 613 614 /* Create the UDP transport object. */ 615 tp = PJ_POOL_ZALLOC_T(pool, struct udp_transport); 616 617 /* Save pool. */ 618 tp->base.pool = pool; 619 620 /* Object name. */ 621 pj_ansi_snprintf(tp->base.obj_name, sizeof(tp->base.obj_name), 622 "udp%p", tp); 623 624 /* Init reference counter. */ 625 status = pj_atomic_create(pool, 0, &tp->base.ref_cnt); 626 if (status != PJ_SUCCESS) 627 goto on_error; 628 629 /* Init lock. */ 630 status = pj_lock_create_recursive_mutex(pool, "udp%p", &tp->base.lock); 631 if (status != PJ_SUCCESS) 632 goto on_error; 633 634 /* Set type. */ 635 tp->base.key.type = PJSIP_TRANSPORT_UDP; 636 637 /* Remote address is left zero (except the family) */ 638 tp->base.key.rem_addr.addr.sa_family = PJ_AF_INET; 639 640 /* Type name. */ 641 tp->base.type_name = "UDP"; 642 643 /* Transport flag */ 644 tp->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP); 645 646 647 /* Length of addressess. */ 648 tp->base.addr_len = sizeof(pj_sockaddr_in); 649 650 /* Init local address. */ 651 status = pj_sock_getsockname(sock, &tp->base.local_addr, 652 &tp->base.addr_len); 653 if (status != PJ_SUCCESS) 654 goto on_error; 655 656 /* Init remote name. */ 657 tp->base.remote_name.host = pj_str("0.0.0.0"); 658 tp->base.remote_name.port = 0; 659 660 /* Set endpoint. */ 661 tp->base.endpt = endpt; 662 663 /* Transport manager and timer will be initialized by tpmgr */ 664 665 /* Attach socket and assign name. */ 666 udp_set_socket(tp, sock, a_name); 667 668 /* Register to ioqueue */ 669 status = register_to_ioqueue(tp); 670 if (status != PJ_SUCCESS) 671 goto on_error; 672 673 /* Set functions. */ 674 tp->base.send_msg = &udp_send_msg; 675 tp->base.do_shutdown = &udp_shutdown; 676 tp->base.destroy = &udp_destroy; 677 678 /* This is a permanent transport, so we initialize the ref count 679 * to one so that transport manager don't destroy this transport 680 * when there's no user! 681 */ 682 pj_atomic_inc(tp->base.ref_cnt); 683 684 /* Register to transport manager. */ 685 tp->base.tpmgr = pjsip_endpt_get_tpmgr(endpt); 686 status = pjsip_transport_register( tp->base.tpmgr, (pjsip_transport*)tp); 687 if (status != PJ_SUCCESS) 688 goto on_error; 689 690 691 /* Create rdata and put it in the array. */ 692 tp->rdata_cnt = 0; 693 tp->rdata = (pjsip_rx_data**) 694 pj_pool_calloc(tp->base.pool, async_cnt, 695 sizeof(pjsip_rx_data*)); 696 for (i=0; i<async_cnt; ++i) { 697 pj_pool_t *rdata_pool = pjsip_endpt_create_pool(endpt, "rtd%p", 698 PJSIP_POOL_RDATA_LEN, 699 PJSIP_POOL_RDATA_INC); 700 if (!rdata_pool) { 701 pj_atomic_set(tp->base.ref_cnt, 0); 582 702 pjsip_transport_destroy(&tp->base); 583 return status; 584 } 703 return PJ_ENOMEM; 704 } 705 706 init_rdata(tp, i, rdata_pool, NULL); 707 tp->rdata_cnt++; 708 } 709 710 /* Start reading the ioqueue. */ 711 status = start_async_read(tp); 712 if (status != PJ_SUCCESS) { 713 pjsip_transport_destroy(&tp->base); 714 return status; 585 715 } 586 716 … … 616 746 pj_status_t status; 617 747 char addr_buf[16]; 618 pj_sockaddr_in tmp_addr;619 748 pjsip_host_port bound_name; 620 749 621 750 PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL); 622 751 623 status = pj_sock_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, &sock);752 status = create_socket(local_a, &sock); 624 753 if (status != PJ_SUCCESS) 625 754 return status; 626 627 if (local_a == NULL) {628 pj_sockaddr_in_init(&tmp_addr, NULL, 0);629 local_a = &tmp_addr;630 }631 632 status = pj_sock_bind(sock, local_a, sizeof(*local_a));633 if (status != PJ_SUCCESS) {634 pj_sock_close(sock);635 return status;636 }637 755 638 756 if (a_name == NULL) { … … 640 758 * Build a name based on bound address. 641 759 */ 642 int addr_len; 643 644 addr_len = sizeof(tmp_addr); 645 status = pj_sock_getsockname(sock, &tmp_addr, &addr_len); 760 status = get_published_name(sock, addr_buf, &bound_name); 646 761 if (status != PJ_SUCCESS) { 647 762 pj_sock_close(sock); … … 650 765 651 766 a_name = &bound_name; 652 bound_name.host.ptr = addr_buf; 653 bound_name.port = pj_ntohs(tmp_addr.sin_port); 654 655 /* If bound address specifies "0.0.0.0", get the IP address 656 * of local hostname. 657 */ 658 if (tmp_addr.sin_addr.s_addr == PJ_INADDR_ANY) { 659 pj_in_addr hostip; 660 661 status = pj_gethostip(&hostip); 767 } 768 769 return pjsip_udp_transport_attach( endpt, sock, a_name, async_cnt, 770 p_transport ); 771 } 772 773 774 /* 775 * Retrieve the internal socket handle used by the UDP transport. 776 */ 777 PJ_DEF(pj_sock_t) pjsip_udp_transport_get_socket(pjsip_transport *transport) 778 { 779 struct udp_transport *tp; 780 781 PJ_ASSERT_RETURN(transport != NULL, PJ_INVALID_SOCKET); 782 783 tp = (struct udp_transport*) transport; 784 785 return tp->sock; 786 } 787 788 789 /* 790 * Temporarily pause or shutdown the transport. 791 */ 792 PJ_DEF(pj_status_t) pjsip_udp_transport_pause(pjsip_transport *transport, 793 unsigned option) 794 { 795 struct udp_transport *tp; 796 unsigned i; 797 798 PJ_ASSERT_RETURN(transport != NULL, PJ_EINVAL); 799 800 /* Flag must be specified */ 801 PJ_ASSERT_RETURN((option & 0x03) != 0, PJ_EINVAL); 802 803 tp = (struct udp_transport*) transport; 804 805 /* Transport must not have been paused */ 806 PJ_ASSERT_RETURN(tp->is_paused==0, PJ_EINVALIDOP); 807 808 /* Set transport to paused first, so that when the read callback is 809 * called by pj_ioqueue_post_completion() it will not try to 810 * re-register the rdata. 811 */ 812 tp->is_paused = PJ_TRUE; 813 814 /* Cancel the ioqueue operation. */ 815 for (i=0; i<(unsigned)tp->rdata_cnt; ++i) { 816 pj_ioqueue_post_completion(tp->key, 817 &tp->rdata[i]->tp_info.op_key.op_key, -1); 818 } 819 820 /* Destroy the socket? */ 821 if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) { 822 if (tp->key) { 823 /* This implicitly closes the socket */ 824 pj_ioqueue_unregister(tp->key); 825 tp->key = NULL; 826 } else { 827 /* Close socket. */ 828 if (tp->sock && tp->sock != PJ_INVALID_SOCKET) { 829 pj_sock_close(tp->sock); 830 tp->sock = PJ_INVALID_SOCKET; 831 } 832 } 833 tp->sock = PJ_INVALID_SOCKET; 834 } 835 836 PJ_LOG(4,(tp->base.obj_name, "SIP UDP transport paused")); 837 838 return PJ_SUCCESS; 839 } 840 841 842 /* 843 * Restart transport. 844 * 845 * If option is KEEP_SOCKET, just re-activate ioqueue operation. 846 * 847 * If option is DESTROY_SOCKET: 848 * - if socket is specified, replace. 849 * - if socket is not specified, create and replace. 850 */ 851 PJ_DEF(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport, 852 unsigned option, 853 pj_sock_t sock, 854 const pj_sockaddr_in *local, 855 const pjsip_host_port *a_name) 856 { 857 struct udp_transport *tp; 858 pj_status_t status; 859 860 PJ_ASSERT_RETURN(transport != NULL, PJ_EINVAL); 861 /* Flag must be specified */ 862 PJ_ASSERT_RETURN((option & 0x03) != 0, PJ_EINVAL); 863 864 tp = (struct udp_transport*) transport; 865 866 if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) { 867 char addr_buf[16]; 868 pjsip_host_port bound_name; 869 870 /* Request to recreate transport */ 871 872 /* Destroy existing socket, if any. */ 873 if (tp->key) { 874 /* This implicitly closes the socket */ 875 pj_ioqueue_unregister(tp->key); 876 tp->key = NULL; 877 } else { 878 /* Close socket. */ 879 if (tp->sock && tp->sock != PJ_INVALID_SOCKET) { 880 pj_sock_close(tp->sock); 881 tp->sock = PJ_INVALID_SOCKET; 882 } 883 } 884 tp->sock = PJ_INVALID_SOCKET; 885 886 /* Create the socket if it's not specified */ 887 if (sock == PJ_INVALID_SOCKET) { 888 status = create_socket(local, &sock); 662 889 if (status != PJ_SUCCESS) 663 890 return status; 664 665 pj_strcpy2(&bound_name.host, pj_inet_ntoa(hostip)); 666 } else { 667 /* Otherwise use bound address. */ 668 pj_strcpy2(&bound_name.host, pj_inet_ntoa(tmp_addr.sin_addr)); 669 } 670 671 } 672 673 return pjsip_udp_transport_attach( endpt, sock, a_name, async_cnt, 674 p_transport ); 675 } 676 677 891 } 892 893 /* If transport published name is not specified, calculate it 894 * from the bound address. 895 */ 896 if (a_name == NULL) { 897 status = get_published_name(sock, addr_buf, &bound_name); 898 if (status != PJ_SUCCESS) { 899 pj_sock_close(sock); 900 return status; 901 } 902 903 a_name = &bound_name; 904 } 905 906 /* Assign the socket and published address to transport. */ 907 udp_set_socket(tp, sock, a_name); 908 909 } else { 910 911 /* For KEEP_SOCKET, transport must have been paused before */ 912 PJ_ASSERT_RETURN(tp->is_paused, PJ_EINVALIDOP); 913 914 /* If address name is specified, update it */ 915 if (a_name != NULL) 916 udp_set_pub_name(tp, a_name); 917 } 918 919 /* Re-register new or existing socket to ioqueue. */ 920 status = register_to_ioqueue(tp); 921 if (status != PJ_SUCCESS) { 922 return status; 923 } 924 925 /* Restart async read operation. */ 926 status = start_async_read(tp); 927 if (status != PJ_SUCCESS) 928 return status; 929 930 /* Everything has been set up */ 931 tp->is_paused = PJ_FALSE; 932 933 PJ_LOG(4,(tp->base.obj_name, 934 "SIP UDP transport restarted, published address is %.*s:%d", 935 (int)tp->base.local_name.host.slen, 936 tp->base.local_name.host.ptr, 937 tp->base.local_name.port)); 938 939 return PJ_SUCCESS; 940 } 941
Note: See TracChangeset
for help on using the changeset viewer.