summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2013-06-19 09:06:55 +0000
committerNanang Izzuddin <nanang@teluu.com>2013-06-19 09:06:55 +0000
commit1229122bc17bb86b6a10e043aa3505715b797347 (patch)
treeae8a72fe1f020f77c31514b05fbd98af2fdcd434
parentd7aa4332dae06ae890053dd13239ddabee46b86c (diff)
Close #1681:
- Added compile-time settings PJMEDIA_TRANSPORT_SO_RCVBUF_SIZE and PJMEDIA_TRANSPORT_SO_SNDBUF_SIZE. The default values are both 64 KB when PJMEDIA_HAS_VIDEO is set, otherwise just zero (socket buffer size uses OS default). The settings will be applied to media transport UDP and ICE. - Also added run-time settings so_sndbuf_size and so_rcvbuf_size into ICE stream transport, STUN socket, and TURN socket. Default values are all zero. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4538 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjlib/include/pj/sock.h21
-rw-r--r--pjlib/src/pj/sock_common.c63
-rw-r--r--pjmedia/include/pjmedia/config.h40
-rw-r--r--pjmedia/src/pjmedia/transport_ice.c14
-rw-r--r--pjmedia/src/pjmedia/transport_udp.c42
-rw-r--r--pjnath/include/pjnath/ice_strans.h34
-rw-r--r--pjnath/include/pjnath/stun_sock.h20
-rw-r--r--pjnath/include/pjnath/turn_sock.h20
-rw-r--r--pjnath/src/pjnath/ice_strans.c20
-rw-r--r--pjnath/src/pjnath/stun_sock.c40
-rw-r--r--pjnath/src/pjnath/turn_sock.c40
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;