diff options
-rw-r--r-- | pjlib/include/pj/sock.h | 21 | ||||
-rw-r--r-- | pjlib/src/pj/sock_common.c | 63 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/config.h | 40 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/transport_ice.c | 14 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/transport_udp.c | 42 | ||||
-rw-r--r-- | pjnath/include/pjnath/ice_strans.h | 34 | ||||
-rw-r--r-- | pjnath/include/pjnath/stun_sock.h | 20 | ||||
-rw-r--r-- | pjnath/include/pjnath/turn_sock.h | 20 | ||||
-rw-r--r-- | pjnath/src/pjnath/ice_strans.c | 20 | ||||
-rw-r--r-- | pjnath/src/pjnath/stun_sock.c | 40 | ||||
-rw-r--r-- | pjnath/src/pjnath/turn_sock.c | 40 |
11 files changed, 353 insertions, 1 deletions
diff --git a/pjlib/include/pj/sock.h b/pjlib/include/pj/sock.h index 4011f21a..b7d1cb05 100644 --- a/pjlib/include/pj/sock.h +++ b/pjlib/include/pj/sock.h @@ -1307,6 +1307,27 @@ PJ_DECL(pj_status_t) pj_sock_setsockopt( pj_sock_t sockfd, /** + * Helper function to set socket buffer size using #pj_sock_setsockopt() + * with capability to auto retry with lower buffer setting value until + * the highest possible value is successfully set. + * + * @param sockfd The socket descriptor. + * @param optname The option name, valid values are pj_SO_RCVBUF() + * and pj_SO_SNDBUF(). + * @param auto_retry Option whether auto retry with lower value is + * enabled. + * @param buf_size On input, specify the prefered buffer size setting, + * on output, the buffer size setting applied. + * + * @return PJ_SUCCESS or the status code. + */ +PJ_DECL(pj_status_t) pj_sock_setsockopt_sobuf( pj_sock_t sockfd, + pj_uint16_t optname, + pj_bool_t auto_retry, + unsigned *buf_size); + + +/** * Receives data stream or message coming to the specified socket. * * @param sockfd The socket descriptor. diff --git a/pjlib/src/pj/sock_common.c b/pjlib/src/pj/sock_common.c index eb338e73..94fa52e4 100644 --- a/pjlib/src/pj/sock_common.c +++ b/pjlib/src/pj/sock_common.c @@ -1079,6 +1079,69 @@ PJ_DEF(pj_status_t) pj_sock_bind_random( pj_sock_t sockfd, } +/* + * Adjust socket send/receive buffer size. + */ +PJ_DEF(pj_status_t) pj_sock_setsockopt_sobuf( pj_sock_t sockfd, + pj_uint16_t optname, + pj_bool_t auto_retry, + unsigned *buf_size) +{ + pj_status_t status; + int try_size, cur_size, i, step, size_len; + enum { MAX_TRY = 20 }; + + PJ_CHECK_STACK(); + + PJ_ASSERT_RETURN(sockfd != PJ_INVALID_SOCKET && + buf_size && + *buf_size > 0 && + (optname == pj_SO_RCVBUF() || + optname == pj_SO_SNDBUF()), + PJ_EINVAL); + + size_len = sizeof(cur_size); + status = pj_sock_getsockopt(sockfd, pj_SOL_SOCKET(), optname, + &cur_size, &size_len); + if (status != PJ_SUCCESS) + return status; + + try_size = *buf_size; + step = (try_size - cur_size) / MAX_TRY; + if (step < 4096) + step = 4096; + + for (i = 0; i < (MAX_TRY-1); ++i) { + if (try_size <= cur_size) { + /* Done, return current size */ + *buf_size = cur_size; + break; + } + + status = pj_sock_setsockopt(sockfd, pj_SOL_SOCKET(), optname, + &try_size, sizeof(try_size)); + if (status == PJ_SUCCESS) { + status = pj_sock_getsockopt(sockfd, pj_SOL_SOCKET(), optname, + &cur_size, &size_len); + if (status != PJ_SUCCESS) { + /* Ops! No info about current size, just return last try size + * and quit. + */ + *buf_size = try_size; + break; + } + } + + if (!auto_retry) + break; + + try_size -= step; + } + + return status; +} + + /* Only need to implement these in DLL build */ #if defined(PJ_DLL) diff --git a/pjmedia/include/pjmedia/config.h b/pjmedia/include/pjmedia/config.h index b3becbc7..d718b659 100644 --- a/pjmedia/include/pjmedia/config.h +++ b/pjmedia/include/pjmedia/config.h @@ -1217,6 +1217,46 @@ /** + * Specify target value for socket receive buffer size. It will be + * applied to RTP socket of media transport using setsockopt(). When + * transport failed to set the specified size, it will try with lower + * value until the highest possible is successfully set. + * + * Setting this to zero will leave the socket receive buffer size to + * OS default (e.g: usually 8 KB on desktop platforms). + * + * Default: 64 KB when video is enabled, otherwise zero (OS default) + */ +#ifndef PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE +# if PJMEDIA_HAS_VIDEO +# define PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE (64*1024) +# else +# define PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE 0 +# endif +#endif + + +/** + * Specify target value for socket send buffer size. It will be + * applied to RTP socket of media transport using setsockopt(). When + * transport failed to set the specified size, it will try with lower + * value until the highest possible is successfully set. + * + * Setting this to zero will leave the socket send buffer size to + * OS default (e.g: usually 8 KB on desktop platforms). + * + * Default: 64 KB when video is enabled, otherwise zero (OS default) + */ +#ifndef PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE +# if PJMEDIA_HAS_VIDEO +# define PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE (64*1024) +# else +# define PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE 0 +# endif +#endif + + +/** * @} */ diff --git a/pjmedia/src/pjmedia/transport_ice.c b/pjmedia/src/pjmedia/transport_ice.c index abd872ae..06eef516 100644 --- a/pjmedia/src/pjmedia/transport_ice.c +++ b/pjmedia/src/pjmedia/transport_ice.c @@ -225,6 +225,7 @@ PJ_DEF(pj_status_t) pjmedia_ice_create3(pjmedia_endpt *endpt, { pj_pool_t *pool; pj_ice_strans_cb ice_st_cb; + pj_ice_strans_cfg ice_st_cfg; struct transport_ice *tp_ice; pj_status_t status; @@ -245,6 +246,7 @@ PJ_DEF(pj_status_t) pjmedia_ice_create3(pjmedia_endpt *endpt, tp_ice->oa_role = ROLE_NONE; tp_ice->use_ice = PJ_FALSE; + pj_memcpy(&ice_st_cfg, cfg, sizeof(pj_ice_strans_cfg)); if (cb) pj_memcpy(&tp_ice->cb, cb, sizeof(pjmedia_ice_cb)); @@ -258,8 +260,18 @@ PJ_DEF(pj_status_t) pjmedia_ice_create3(pjmedia_endpt *endpt, ice_st_cb.on_ice_complete = &ice_on_ice_complete; ice_st_cb.on_rx_data = &ice_on_rx_data; + /* Configure RTP socket buffer settings, if not set */ + if (ice_st_cfg.comp[COMP_RTP-1].so_rcvbuf_size == 0) { + ice_st_cfg.comp[COMP_RTP-1].so_rcvbuf_size = + PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE; + } + if (ice_st_cfg.comp[COMP_RTP-1].so_sndbuf_size == 0) { + ice_st_cfg.comp[COMP_RTP-1].so_sndbuf_size = + PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE; + } + /* Create ICE */ - status = pj_ice_strans_create(name, cfg, comp_cnt, tp_ice, + status = pj_ice_strans_create(name, &ice_st_cfg, comp_cnt, tp_ice, &ice_st_cb, &tp_ice->ice_st); if (status != PJ_SUCCESS) { pj_pool_release(pool); diff --git a/pjmedia/src/pjmedia/transport_udp.c b/pjmedia/src/pjmedia/transport_udp.c index 3e288c74..70f16d6d 100644 --- a/pjmedia/src/pjmedia/transport_udp.c +++ b/pjmedia/src/pjmedia/transport_udp.c @@ -693,6 +693,48 @@ static pj_status_t transport_attach( pjmedia_transport *tp, udp->rtp_src_cnt = 0; udp->rtcp_src_cnt = 0; + /* Set buffer size for RTP socket */ +#if PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE + { + unsigned sobuf_size = PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE; + pj_status_t status; + status = pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_RCVBUF(), + PJ_TRUE, &sobuf_size); + if (status != PJ_SUCCESS) { + pj_perror(3, tp->name, status, "Failed setting SO_RCVBUF"); + } else { + if (sobuf_size < PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE) { + PJ_LOG(4, (tp->name, + "Warning! Cannot set SO_RCVBUF as configured, " + "now=%d, configured=%d", + sobuf_size, PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE)); + } else { + PJ_LOG(5, (tp->name, "SO_RCVBUF set to %d", sobuf_size)); + } + } + } +#endif +#if PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE + { + unsigned sobuf_size = PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE; + pj_status_t status; + status = pj_sock_setsockopt_sobuf(udp->rtp_sock, pj_SO_SNDBUF(), + PJ_TRUE, &sobuf_size); + if (status != PJ_SUCCESS) { + pj_perror(3, tp->name, status, "Failed setting SO_SNDBUF"); + } else { + if (sobuf_size < PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE) { + PJ_LOG(4, (tp->name, + "Warning! Cannot set SO_SNDBUF as configured, " + "now=%d, configured=%d", + sobuf_size, PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE)); + } else { + PJ_LOG(5, (tp->name, "SO_SNDBUF set to %d", sobuf_size)); + } + } + } +#endif + /* Unlock keys */ pj_ioqueue_unlock_key(udp->rtcp_key); pj_ioqueue_unlock_key(udp->rtp_key); diff --git a/pjnath/include/pjnath/ice_strans.h b/pjnath/include/pjnath/ice_strans.h index 11cfc5db..fe38ff58 100644 --- a/pjnath/include/pjnath/ice_strans.h +++ b/pjnath/include/pjnath/ice_strans.h @@ -370,6 +370,40 @@ typedef struct pj_ice_strans_cfg */ pj_qos_params qos_params; + /** + * Specify target value for socket receive buffer size. It will be + * applied using setsockopt(). When it fails to set the specified + * size, it will try with lower value until the highest possible is + * successfully set. + * + * When this is set to zero, this component will apply socket receive + * buffer size settings specified in STUN and TURN socket config + * above, i.e: \a stun::cfg::so_rcvbuf_size and + * \a turn::cfg::so_rcvbuf_size. Otherwise, this setting will be + * applied to STUN and TURN sockets for this component, overriding + * the setting specified in STUN/TURN socket config. + * + * Default: 0 + */ + unsigned so_rcvbuf_size; + + /** + * Specify target value for socket send buffer size. It will be + * applied using setsockopt(). When it fails to set the specified + * size, it will try with lower value until the highest possible is + * successfully set. + * + * When this is set to zero, this component will apply socket send + * buffer size settings specified in STUN and TURN socket config + * above, i.e: \a stun::cfg::so_sndbuf_size and + * \a turn::cfg::so_sndbuf_size. Otherwise, this setting will be + * applied to STUN and TURN sockets for this component, overriding + * the setting specified in STUN/TURN socket config. + * + * Default: 0 + */ + unsigned so_sndbuf_size; + } comp[PJ_ICE_MAX_COMP]; } pj_ice_strans_cfg; diff --git a/pjnath/include/pjnath/stun_sock.h b/pjnath/include/pjnath/stun_sock.h index 30e94a2d..081f36d5 100644 --- a/pjnath/include/pjnath/stun_sock.h +++ b/pjnath/include/pjnath/stun_sock.h @@ -295,6 +295,26 @@ typedef struct pj_stun_sock_cfg */ pj_bool_t qos_ignore_error; + /** + * Specify target value for socket receive buffer size. It will be + * applied using setsockopt(). When it fails to set the specified size, + * it will try with lower value until the highest possible is + * successfully set. + * + * Default: 0 (OS default) + */ + unsigned so_rcvbuf_size; + + /** + * Specify target value for socket send buffer size. It will be + * applied using setsockopt(). When it fails to set the specified size, + * it will try with lower value until the highest possible is + * successfully set. + * + * Default: 0 (OS default) + */ + unsigned so_sndbuf_size; + } pj_stun_sock_cfg; diff --git a/pjnath/include/pjnath/turn_sock.h b/pjnath/include/pjnath/turn_sock.h index 96990baa..eddac515 100644 --- a/pjnath/include/pjnath/turn_sock.h +++ b/pjnath/include/pjnath/turn_sock.h @@ -166,6 +166,26 @@ typedef struct pj_turn_sock_cfg */ pj_uint16_t port_range; + /** + * Specify target value for socket receive buffer size. It will be + * applied using setsockopt(). When it fails to set the specified size, + * it will try with lower value until the highest possible has been + * successfully set. + * + * Default: 0 (OS default) + */ + unsigned so_rcvbuf_size; + + /** + * Specify target value for socket send buffer size. It will be + * applied using setsockopt(). When it fails to set the specified size, + * it will try with lower value until the highest possible has been + * successfully set. + * + * Default: 0 (OS default) + */ + unsigned so_sndbuf_size; + } pj_turn_sock_cfg; diff --git a/pjnath/src/pjnath/ice_strans.c b/pjnath/src/pjnath/ice_strans.c index 84dc2bb4..95ca9571 100644 --- a/pjnath/src/pjnath/ice_strans.c +++ b/pjnath/src/pjnath/ice_strans.c @@ -296,6 +296,16 @@ static pj_status_t add_update_turn(pj_ice_strans *ice_st, sizeof(ice_st->cfg.turn.cfg.qos_params)); } + /* Override with component specific socket buffer size settings, if any */ + if (ice_st->cfg.comp[comp->comp_id-1].so_rcvbuf_size > 0) { + ice_st->cfg.turn.cfg.so_rcvbuf_size = + ice_st->cfg.comp[comp->comp_id-1].so_rcvbuf_size; + } + if (ice_st->cfg.comp[comp->comp_id-1].so_sndbuf_size > 0) { + ice_st->cfg.turn.cfg.so_sndbuf_size = + ice_st->cfg.comp[comp->comp_id-1].so_sndbuf_size; + } + /* Create the TURN transport */ status = pj_turn_sock_create(&ice_st->cfg.stun_cfg, ice_st->cfg.af, ice_st->cfg.turn.conn_type, @@ -383,6 +393,16 @@ static pj_status_t create_comp(pj_ice_strans *ice_st, unsigned comp_id) sizeof(ice_st->cfg.stun.cfg.qos_params)); } + /* Override component specific socket buffer size settings, if any */ + if (ice_st->cfg.comp[comp_id-1].so_rcvbuf_size > 0) { + ice_st->cfg.stun.cfg.so_rcvbuf_size = + ice_st->cfg.comp[comp_id-1].so_rcvbuf_size; + } + if (ice_st->cfg.comp[comp_id-1].so_sndbuf_size > 0) { + ice_st->cfg.stun.cfg.so_sndbuf_size = + ice_st->cfg.comp[comp_id-1].so_sndbuf_size; + } + /* Create the STUN transport */ status = pj_stun_sock_create(&ice_st->cfg.stun_cfg, NULL, ice_st->cfg.af, &stun_sock_cb, diff --git a/pjnath/src/pjnath/stun_sock.c b/pjnath/src/pjnath/stun_sock.c index b0bad9e3..eadec9cb 100644 --- a/pjnath/src/pjnath/stun_sock.c +++ b/pjnath/src/pjnath/stun_sock.c @@ -237,6 +237,46 @@ PJ_DEF(pj_status_t) pj_stun_sock_create( pj_stun_config *stun_cfg, if (status != PJ_SUCCESS && !cfg->qos_ignore_error) goto on_error; + /* Apply socket buffer size */ + if (cfg->so_rcvbuf_size > 0) { + unsigned sobuf_size = cfg->so_rcvbuf_size; + status = pj_sock_setsockopt_sobuf(stun_sock->sock_fd, pj_SO_RCVBUF(), + PJ_TRUE, &sobuf_size); + if (status != PJ_SUCCESS) { + pj_perror(3, stun_sock->obj_name, status, + "Failed setting SO_RCVBUF"); + } else { + if (sobuf_size < cfg->so_rcvbuf_size) { + PJ_LOG(4, (stun_sock->obj_name, + "Warning! Cannot set SO_RCVBUF as configured, " + "now=%d, configured=%d", + sobuf_size, cfg->so_rcvbuf_size)); + } else { + PJ_LOG(5, (stun_sock->obj_name, "SO_RCVBUF set to %d", + sobuf_size)); + } + } + } + if (cfg->so_sndbuf_size > 0) { + unsigned sobuf_size = cfg->so_sndbuf_size; + status = pj_sock_setsockopt_sobuf(stun_sock->sock_fd, pj_SO_SNDBUF(), + PJ_TRUE, &sobuf_size); + if (status != PJ_SUCCESS) { + pj_perror(3, stun_sock->obj_name, status, + "Failed setting SO_SNDBUF"); + } else { + if (sobuf_size < cfg->so_sndbuf_size) { + PJ_LOG(4, (stun_sock->obj_name, + "Warning! Cannot set SO_SNDBUF as configured, " + "now=%d, configured=%d", + sobuf_size, cfg->so_sndbuf_size)); + } else { + PJ_LOG(5, (stun_sock->obj_name, "SO_SNDBUF set to %d", + sobuf_size)); + } + } + } + /* Bind socket */ max_bind_retry = MAX_BIND_RETRY; if (cfg->port_range && cfg->port_range < max_bind_retry) diff --git a/pjnath/src/pjnath/turn_sock.c b/pjnath/src/pjnath/turn_sock.c index 7dde5a5e..42beb225 100644 --- a/pjnath/src/pjnath/turn_sock.c +++ b/pjnath/src/pjnath/turn_sock.c @@ -810,6 +810,46 @@ static void turn_on_state(pj_turn_session *sess, return; } + /* Apply socket buffer size */ + if (turn_sock->setting.so_rcvbuf_size > 0) { + unsigned sobuf_size = turn_sock->setting.so_rcvbuf_size; + status = pj_sock_setsockopt_sobuf(sock, pj_SO_RCVBUF(), + PJ_TRUE, &sobuf_size); + if (status != PJ_SUCCESS) { + pj_perror(3, turn_sock->obj_name, status, + "Failed setting SO_RCVBUF"); + } else { + if (sobuf_size < turn_sock->setting.so_rcvbuf_size) { + PJ_LOG(4, (turn_sock->obj_name, + "Warning! Cannot set SO_RCVBUF as configured," + " now=%d, configured=%d", sobuf_size, + turn_sock->setting.so_rcvbuf_size)); + } else { + PJ_LOG(5, (turn_sock->obj_name, "SO_RCVBUF set to %d", + sobuf_size)); + } + } + } + if (turn_sock->setting.so_sndbuf_size > 0) { + unsigned sobuf_size = turn_sock->setting.so_sndbuf_size; + status = pj_sock_setsockopt_sobuf(sock, pj_SO_SNDBUF(), + PJ_TRUE, &sobuf_size); + if (status != PJ_SUCCESS) { + pj_perror(3, turn_sock->obj_name, status, + "Failed setting SO_SNDBUF"); + } else { + if (sobuf_size < turn_sock->setting.so_sndbuf_size) { + PJ_LOG(4, (turn_sock->obj_name, + "Warning! Cannot set SO_SNDBUF as configured," + " now=%d, configured=%d", sobuf_size, + turn_sock->setting.so_sndbuf_size)); + } else { + PJ_LOG(5, (turn_sock->obj_name, "SO_SNDBUF set to %d", + sobuf_size)); + } + } + } + /* Create active socket */ pj_activesock_cfg_default(&asock_cfg); asock_cfg.grp_lock = turn_sock->grp_lock; |