Changeset 5649 for pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c
- Timestamp:
- Sep 15, 2017 5:32:08 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c
r5534 r5649 62 62 pj_qos_params qos_params; 63 63 pj_sockopt_params sockopt_params; 64 pj_bool_t reuse_addr; 65 unsigned async_cnt; 64 66 65 67 /* Group lock to be used by TCP listener and ioqueue key */ … … 242 244 */ 243 245 246 static void update_bound_addr(struct tcp_listener *listener, 247 const pj_sockaddr *local) 248 { 249 pj_sockaddr *listener_addr = &listener->factory.local_addr; 250 int af = pjsip_transport_type_get_af(listener->factory.type); 251 252 /* Bind address may be different than factory.local_addr because 253 * factory.local_addr will be resolved. 254 */ 255 if (local) { 256 pj_sockaddr_cp(&listener->bound_addr, local); 257 } 258 else { 259 pj_sockaddr_init(af, &listener->bound_addr, NULL, 0); 260 } 261 pj_sockaddr_cp(listener_addr, &listener->bound_addr); 262 } 263 264 static pj_status_t update_factory_addr(struct tcp_listener *listener, 265 const pjsip_host_port *addr_name) 266 { 267 pj_status_t status = PJ_SUCCESS; 268 pj_sockaddr *listener_addr = &listener->factory.local_addr; 269 270 /* If published host/IP is specified, then use that address as the 271 * listener advertised address. 272 */ 273 if (addr_name && addr_name->host.slen) { 274 pj_sockaddr tmp; 275 int af = pjsip_transport_type_get_af(listener->factory.type); 276 277 /* Verify that address given in a_name (if any) is valid */ 278 status = pj_sockaddr_init(af, &tmp, &addr_name->host, 279 (pj_uint16_t)addr_name->port); 280 if (status != PJ_SUCCESS || !pj_sockaddr_has_addr(&tmp) || 281 (af == pj_AF_INET() && tmp.ipv4.sin_addr.s_addr == PJ_INADDR_NONE)) 282 { 283 /* Invalid address */ 284 return PJ_EINVAL; 285 } 286 287 /* Copy the address */ 288 listener->factory.addr_name = *addr_name; 289 pj_strdup(listener->factory.pool, &listener->factory.addr_name.host, 290 &addr_name->host); 291 listener->factory.addr_name.port = addr_name->port; 292 293 } else { 294 /* No published address is given, use the bound address */ 295 296 /* If the address returns 0.0.0.0, use the default 297 * interface address as the transport's address. 298 */ 299 if (!pj_sockaddr_has_addr(listener_addr)) { 300 pj_sockaddr hostip; 301 302 status = pj_gethostip(listener->bound_addr.addr.sa_family, 303 &hostip); 304 if (status != PJ_SUCCESS) 305 return status; 306 307 pj_sockaddr_copy_addr(listener_addr, &hostip); 308 } 309 310 /* Save the address name */ 311 sockaddr_to_host_port(listener->factory.pool, 312 &listener->factory.addr_name, 313 listener_addr); 314 } 315 316 /* If port is zero, get the bound port */ 317 if (listener->factory.addr_name.port == 0) { 318 listener->factory.addr_name.port = pj_sockaddr_get_port(listener_addr); 319 } 320 321 pj_ansi_snprintf(listener->factory.obj_name, 322 sizeof(listener->factory.obj_name), 323 "tcptp:%d", listener->factory.addr_name.port); 324 return status; 325 } 326 327 static void update_transport_info(struct tcp_listener *listener) 328 { 329 enum { INFO_LEN = 100 }; 330 char local_addr[PJ_INET6_ADDRSTRLEN + 10]; 331 pj_sockaddr *listener_addr = &listener->factory.local_addr; 332 333 /* Set transport info. */ 334 if (listener->factory.info == NULL) { 335 listener->factory.info = (char*)pj_pool_alloc(listener->factory.pool, 336 INFO_LEN); 337 } 338 pj_sockaddr_print(listener_addr, local_addr, sizeof(local_addr), 3); 339 pj_ansi_snprintf( 340 listener->factory.info, INFO_LEN, "tcp %s [published as %.*s:%d]", 341 local_addr, 342 (int)listener->factory.addr_name.host.slen, 343 listener->factory.addr_name.host.ptr, 344 listener->factory.addr_name.port); 345 346 if (listener->asock) { 347 PJ_LOG(4, (listener->factory.obj_name, 348 "SIP TCP listener ready for incoming connections at %.*s:%d", 349 (int)listener->factory.addr_name.host.slen, 350 listener->factory.addr_name.host.ptr, 351 listener->factory.addr_name.port)); 352 } else { 353 PJ_LOG(4, (listener->factory.obj_name, "SIP TCP is ready " 354 "(client only)")); 355 } 356 } 357 244 358 /* 245 359 * This is the public API to create, initialize, register, and start the … … 251 365 pjsip_tpfactory **p_factory 252 366 ) 253 { 254 enum { INFO_LEN = 100 }; 255 char local_addr[PJ_INET6_ADDRSTRLEN+10]; 256 pj_pool_t *pool; 257 pj_sock_t sock = PJ_INVALID_SOCKET; 258 struct tcp_listener *listener; 259 pj_activesock_cfg asock_cfg; 260 pj_activesock_cb listener_cb; 261 pj_sockaddr *listener_addr; 262 int addr_len; 263 pj_bool_t has_listener = PJ_FALSE; 367 { 368 pj_pool_t *pool; 369 struct tcp_listener *listener; 264 370 pj_status_t status; 265 371 266 372 /* Sanity check */ 267 373 PJ_ASSERT_RETURN(endpt && cfg->async_cnt, PJ_EINVAL); 268 269 /* Verify that address given in a_name (if any) is valid */270 if (cfg->addr_name.host.slen) {271 pj_sockaddr tmp;272 273 status = pj_sockaddr_init(cfg->af, &tmp, &cfg->addr_name.host,274 (pj_uint16_t)cfg->addr_name.port);275 if (status != PJ_SUCCESS || !pj_sockaddr_has_addr(&tmp) ||276 (cfg->af==pj_AF_INET() &&277 tmp.ipv4.sin_addr.s_addr==PJ_INADDR_NONE))278 {279 /* Invalid address */280 return PJ_EINVAL;281 }282 }283 374 284 375 pool = pjsip_endpt_create_pool(endpt, "tcptp", POOL_LIS_INIT, … … 292 383 PJSIP_TRANSPORT_TCP6; 293 384 listener->factory.type_name = (char*) 294 pjsip_transport_get_type_name(listener->factory.type);385 pjsip_transport_get_type_name(listener->factory.type); 295 386 listener->factory.flag = 296 pjsip_transport_get_flag_from_type(listener->factory.type);387 pjsip_transport_get_flag_from_type(listener->factory.type); 297 388 listener->qos_type = cfg->qos_type; 389 listener->reuse_addr = cfg->reuse_addr; 390 listener->async_cnt = cfg->async_cnt; 298 391 pj_memcpy(&listener->qos_params, &cfg->qos_params, 299 392 sizeof(cfg->qos_params)); … … 308 401 &listener->factory.lock); 309 402 if (status != PJ_SUCCESS) 310 goto on_error; 311 312 #if !(defined(PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER) && \ 313 PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER != 0) 314 315 /* Create socket */ 316 status = pj_sock_socket(cfg->af, pj_SOCK_STREAM(), 0, &sock); 317 if (status != PJ_SUCCESS) 318 goto on_error; 319 320 /* Apply QoS, if specified */ 321 status = pj_sock_apply_qos2(sock, cfg->qos_type, &cfg->qos_params, 322 2, listener->factory.obj_name, 323 "SIP TCP listener socket"); 324 325 /* Apply SO_REUSEADDR */ 326 if (cfg->reuse_addr) { 327 int enabled = 1; 328 status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), 329 &enabled, sizeof(enabled)); 330 if (status != PJ_SUCCESS) { 331 PJ_PERROR(4,(listener->factory.obj_name, status, 332 "Warning: error applying SO_REUSEADDR")); 333 } 334 } 335 336 /* Apply socket options, if specified */ 337 if (cfg->sockopt_params.cnt) 338 status = pj_sock_setsockopt_params(sock, &cfg->sockopt_params); 339 340 #else 341 PJ_UNUSED_ARG(addr_len); 342 #endif 343 344 /* Bind address may be different than factory.local_addr because 345 * factory.local_addr will be resolved below. 346 */ 347 pj_sockaddr_cp(&listener->bound_addr, &cfg->bind_addr); 348 349 /* Bind socket */ 350 listener_addr = &listener->factory.local_addr; 351 pj_sockaddr_cp(listener_addr, &cfg->bind_addr); 352 353 #if !(defined(PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER) && \ 354 PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER != 0) 355 356 status = pj_sock_bind(sock, listener_addr, 357 pj_sockaddr_get_len(listener_addr)); 358 if (status != PJ_SUCCESS) 359 goto on_error; 360 361 /* Retrieve the bound address */ 362 addr_len = pj_sockaddr_get_len(listener_addr); 363 status = pj_sock_getsockname(sock, listener_addr, &addr_len); 364 if (status != PJ_SUCCESS) 365 goto on_error; 366 367 #endif 368 369 /* If published host/IP is specified, then use that address as the 370 * listener advertised address. 371 */ 372 if (cfg->addr_name.host.slen) { 373 /* Copy the address */ 374 listener->factory.addr_name = cfg->addr_name; 375 pj_strdup(listener->factory.pool, &listener->factory.addr_name.host, 376 &cfg->addr_name.host); 377 listener->factory.addr_name.port = cfg->addr_name.port; 378 379 } else { 380 /* No published address is given, use the bound address */ 381 382 /* If the address returns 0.0.0.0, use the default 383 * interface address as the transport's address. 384 */ 385 if (!pj_sockaddr_has_addr(listener_addr)) { 386 pj_sockaddr hostip; 387 388 status = pj_gethostip(listener->bound_addr.addr.sa_family, 389 &hostip); 390 if (status != PJ_SUCCESS) 391 goto on_error; 392 393 pj_sockaddr_copy_addr(listener_addr, &hostip); 394 } 395 396 /* Save the address name */ 397 sockaddr_to_host_port(listener->factory.pool, 398 &listener->factory.addr_name, 399 listener_addr); 400 } 401 402 /* If port is zero, get the bound port */ 403 if (listener->factory.addr_name.port == 0) { 404 listener->factory.addr_name.port = pj_sockaddr_get_port(listener_addr); 405 } 406 407 pj_ansi_snprintf(listener->factory.obj_name, 408 sizeof(listener->factory.obj_name), 409 "tcptp:%d", listener->factory.addr_name.port); 410 411 412 #if !(defined(PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER) && \ 413 PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER != 0) 414 415 /* Start listening to the address */ 416 status = pj_sock_listen(sock, PJSIP_TCP_TRANSPORT_BACKLOG); 417 if (status != PJ_SUCCESS) 418 goto on_error; 419 420 421 /* Create active socket */ 422 pj_activesock_cfg_default(&asock_cfg); 423 if (cfg->async_cnt > MAX_ASYNC_CNT) 424 asock_cfg.async_cnt = MAX_ASYNC_CNT; 425 else 426 asock_cfg.async_cnt = cfg->async_cnt; 427 428 #endif 403 goto on_error; 429 404 430 405 /* Create group lock */ 431 406 status = pj_grp_lock_create(pool, NULL, &listener->grp_lock); 432 407 if (status != PJ_SUCCESS) 433 return status;408 goto on_error; 434 409 435 410 pj_grp_lock_add_ref(listener->grp_lock); 436 411 pj_grp_lock_add_handler(listener->grp_lock, pool, listener, 437 412 &lis_on_destroy); 438 439 asock_cfg.grp_lock = listener->grp_lock;440 441 pj_bzero(&listener_cb, sizeof(listener_cb));442 listener_cb.on_accept_complete = &on_accept_complete;443 444 #if !(defined(PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER) && \445 PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER != 0)446 447 status = pj_activesock_create(pool, sock, pj_SOCK_STREAM(), &asock_cfg,448 pjsip_endpt_get_ioqueue(endpt),449 &listener_cb, listener,450 &listener->asock);451 452 #endif453 413 454 414 /* Register to transport manager */ … … 456 416 listener->tpmgr = pjsip_endpt_get_tpmgr(endpt); 457 417 listener->factory.create_transport = lis_create_transport; 458 listener->factory.destroy = lis_destroy; 418 listener->factory.destroy = lis_destroy; 419 420 #if !(defined(PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER) && \ 421 PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER != 0) 422 /* Start listener. */ 423 status = pjsip_tcp_transport_lis_start(&listener->factory, &cfg->bind_addr, 424 &cfg->addr_name); 425 if (status != PJ_SUCCESS) 426 goto on_error; 427 428 #else 429 update_bound_addr(listener, &cfg->bind_addr); 430 status = update_factory_addr(listener, &cfg->addr_name); 431 if (status != PJ_SUCCESS) 432 goto on_error; 433 434 /* Set transport info. */ 435 update_transport_info(listener); 436 #endif 437 459 438 listener->is_registered = PJ_TRUE; 460 439 status = pjsip_tpmgr_register_tpfactory(listener->tpmgr, … … 465 444 } 466 445 467 #if !(defined(PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER) && \468 PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER != 0)469 470 /* Start pending accept() operations */471 status = pj_activesock_start_accept(listener->asock, pool);472 if (status != PJ_SUCCESS)473 goto on_error;474 475 has_listener = PJ_TRUE;476 477 #endif478 479 /* Set transport info. */480 if (listener->factory.info == NULL) {481 listener->factory.info = (char*) pj_pool_alloc(listener->factory.pool,482 INFO_LEN);483 }484 pj_sockaddr_print(listener_addr, local_addr, sizeof(local_addr), 3);485 pj_ansi_snprintf(486 listener->factory.info, INFO_LEN, "tcp %s [published as %.*s:%d]",487 local_addr,488 (int)listener->factory.addr_name.host.slen,489 listener->factory.addr_name.host.ptr,490 listener->factory.addr_name.port);491 492 if (has_listener) {493 PJ_LOG(4,(listener->factory.obj_name,494 "SIP TCP listener ready for incoming connections at %.*s:%d",495 (int)listener->factory.addr_name.host.slen,496 listener->factory.addr_name.host.ptr,497 listener->factory.addr_name.port));498 } else {499 PJ_LOG(4,(listener->factory.obj_name, "SIP TCP is ready "500 "(client only)"));501 }502 503 446 /* Return the pointer to user */ 504 447 if (p_factory) *p_factory = &listener->factory; … … 507 450 508 451 on_error: 509 if (listener->asock==NULL && sock!=PJ_INVALID_SOCKET)510 pj_sock_close(sock);511 452 lis_destroy(&listener->factory); 512 453 return status; … … 572 513 } 573 514 574 575 /* This callback is called by transport manager to destroy listener */ 576 static pj_status_t lis_destroy(pjsip_tpfactory *factory) 577 { 578 struct tcp_listener *listener = (struct tcp_listener *)factory; 579 515 /* This will close the listener. */ 516 static void lis_close(struct tcp_listener *listener) 517 { 580 518 if (listener->is_registered) { 581 519 pjsip_tpmgr_unregister_tpfactory(listener->tpmgr, &listener->factory); … … 587 525 listener->asock = NULL; 588 526 } 527 } 528 529 /* This callback is called by transport manager to destroy listener */ 530 static pj_status_t lis_destroy(pjsip_tpfactory *factory) 531 { 532 struct tcp_listener *listener = (struct tcp_listener *)factory; 533 534 lis_close(listener); 589 535 590 536 if (listener->grp_lock) { … … 1638 1584 1639 1585 1586 PJ_DEF(pj_status_t) pjsip_tcp_transport_lis_start(pjsip_tpfactory *factory, 1587 const pj_sockaddr *local, 1588 const pjsip_host_port *a_name) 1589 { 1590 pj_activesock_cfg asock_cfg; 1591 pj_activesock_cb listener_cb; 1592 pj_sock_t sock = PJ_INVALID_SOCKET; 1593 int addr_len, af; 1594 struct tcp_listener *listener = (struct tcp_listener *)factory; 1595 pj_sockaddr *listener_addr = &factory->local_addr; 1596 pj_status_t status = PJ_SUCCESS; 1597 1598 /* Nothing to be done, if listener already started. */ 1599 if (listener->asock) 1600 return PJ_SUCCESS; 1601 1602 update_bound_addr(listener, local); 1603 1604 addr_len = pj_sockaddr_get_len(listener_addr); 1605 af = pjsip_transport_type_get_af(listener->factory.type); 1606 1607 /* Create socket */ 1608 status = pj_sock_socket(af, pj_SOCK_STREAM(), 0, &sock); 1609 if (status != PJ_SUCCESS) 1610 goto on_error; 1611 1612 /* Apply QoS, if specified */ 1613 status = pj_sock_apply_qos2(sock, listener->qos_type, 1614 &listener->qos_params, 2, 1615 listener->factory.obj_name, 1616 "SIP TCP listener socket"); 1617 1618 /* Apply SO_REUSEADDR */ 1619 if (listener->reuse_addr) { 1620 int enabled = 1; 1621 status = pj_sock_setsockopt(sock, pj_SOL_SOCKET(), pj_SO_REUSEADDR(), 1622 &enabled, sizeof(enabled)); 1623 if (status != PJ_SUCCESS) { 1624 PJ_LOG(1, ("TRACE", "fail set reuseaddr")); 1625 PJ_PERROR(4, (listener->factory.obj_name, status, 1626 "Warning: error applying SO_REUSEADDR")); 1627 } 1628 } 1629 1630 /* Apply socket options, if specified */ 1631 if (listener->sockopt_params.cnt) 1632 status = pj_sock_setsockopt_params(sock, &listener->sockopt_params); 1633 1634 status = pj_sock_bind(sock, listener_addr, addr_len); 1635 if (status != PJ_SUCCESS) 1636 goto on_error; 1637 1638 /* Retrieve the bound address */ 1639 status = pj_sock_getsockname(sock, &listener->factory.local_addr, 1640 &addr_len); 1641 if (status != PJ_SUCCESS) 1642 goto on_error; 1643 1644 status = update_factory_addr(listener, a_name); 1645 if (status != PJ_SUCCESS) 1646 goto on_error; 1647 1648 /* Start listening to the address */ 1649 status = pj_sock_listen(sock, PJSIP_TCP_TRANSPORT_BACKLOG); 1650 if (status != PJ_SUCCESS) 1651 goto on_error; 1652 1653 1654 /* Create active socket */ 1655 pj_activesock_cfg_default(&asock_cfg); 1656 if (listener->async_cnt > MAX_ASYNC_CNT) 1657 asock_cfg.async_cnt = MAX_ASYNC_CNT; 1658 else 1659 asock_cfg.async_cnt = listener->async_cnt; 1660 1661 asock_cfg.grp_lock = listener->grp_lock; 1662 pj_bzero(&listener_cb, sizeof(listener_cb)); 1663 listener_cb.on_accept_complete = &on_accept_complete; 1664 1665 status = pj_activesock_create(listener->factory.pool, sock, 1666 pj_SOCK_STREAM(), &asock_cfg, 1667 pjsip_endpt_get_ioqueue(listener->endpt), 1668 &listener_cb, listener, 1669 &listener->asock); 1670 1671 /* Start pending accept() operations */ 1672 status = pj_activesock_start_accept(listener->asock, 1673 listener->factory.pool); 1674 1675 update_transport_info(listener); 1676 1677 return status; 1678 1679 on_error: 1680 if (listener->asock == NULL && sock != PJ_INVALID_SOCKET) 1681 pj_sock_close(sock); 1682 1683 return status; 1684 } 1685 1686 1687 PJ_DEF(pj_status_t) pjsip_tcp_transport_restart(pjsip_tpfactory *factory, 1688 const pj_sockaddr *local, 1689 const pjsip_host_port *a_name) 1690 { 1691 pj_status_t status = PJ_SUCCESS; 1692 struct tcp_listener *listener = (struct tcp_listener *)factory; 1693 1694 lis_close(listener); 1695 1696 status = pjsip_tcp_transport_lis_start(factory, local, a_name); 1697 if (status != PJ_SUCCESS) { 1698 tcp_perror(listener->factory.obj_name, 1699 "Unable to start listener after closing it", status); 1700 1701 return status; 1702 } 1703 1704 status = pjsip_tpmgr_register_tpfactory(listener->tpmgr, 1705 &listener->factory); 1706 if (status != PJ_SUCCESS) { 1707 tcp_perror(listener->factory.obj_name, 1708 "Unable to register the transport listener", status); 1709 } else { 1710 listener->is_registered = PJ_TRUE; 1711 } 1712 1713 return status; 1714 } 1715 1640 1716 #endif /* PJ_HAS_TCP */ 1641 1717
Note: See TracChangeset
for help on using the changeset viewer.