Add TLS initial receive timeout for server connection (#3744)
This commit is contained in:
parent
f2da44b720
commit
33f64ba933
|
@ -676,6 +676,25 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
|
|||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* The initial timeout interval for incoming TCP/TLS transports
|
||||
* (i.e. server side) in the event that no valid SIP message is received
|
||||
* following a successful connection. The value is in seconds.
|
||||
* Disable the timeout by setting it to 0.
|
||||
*
|
||||
* Note that even if this is disabled, the connection might still get closed
|
||||
* when it is idle or not referred anymore. Have a look at \a
|
||||
* PJSIP_TRANSPORT_SERVER_IDLE_TIME.
|
||||
*
|
||||
* Notes:
|
||||
* - keep-alive packet is not considered as a valid message.
|
||||
*
|
||||
* Default: 0
|
||||
*/
|
||||
#ifndef PJSIP_TRANSPORT_SERVER_IDLE_TIME_FIRST
|
||||
# define PJSIP_TRANSPORT_SERVER_IDLE_TIME_FIRST 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Maximum number of usages for a transport before a new transport is
|
||||
* created. This only applies for ephemeral transports such as TCP.
|
||||
|
@ -786,14 +805,20 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
|
|||
|
||||
|
||||
/**
|
||||
* Initial timeout interval to be applied to incoming transports (i.e. server
|
||||
* side) when no data received after a successful connection. Value is in
|
||||
* seconds. Disable the timeout by setting it to 0.
|
||||
* The initial timeout interval for incoming TCP transports
|
||||
* (i.e. server side) in the event that no valid SIP message is received
|
||||
* following a successful connection. The value is in seconds.
|
||||
* Disable the timeout by setting it to 0.
|
||||
*
|
||||
* Note that even when this is disable, the connection might still get closed
|
||||
* Note that even if this is disabled, the connection might still get closed
|
||||
* when it is idle or not referred anymore. Have a look at \a
|
||||
* PJSIP_TRANSPORT_SERVER_IDLE_TIME
|
||||
* PJSIP_TRANSPORT_SERVER_IDLE_TIME.
|
||||
*
|
||||
* Notes:
|
||||
* - keep-alive packet is not considered as a valid message.
|
||||
* - This macro is specific to TCP usage and takes precedence over
|
||||
* a\ PJSIP_TRANSPORT_SERVER_IDLE_TIME_FIRST when both are set.
|
||||
*
|
||||
* Default: 0 (disabled)
|
||||
*/
|
||||
#ifndef PJSIP_TCP_INITIAL_TIMEOUT
|
||||
|
|
|
@ -870,6 +870,11 @@ struct pjsip_transport
|
|||
pj_size_t last_recv_len; /**< Last received data length. */
|
||||
|
||||
void *data; /**< Internal transport data. */
|
||||
unsigned initial_timeout;/**< Initial timeout interval
|
||||
to be applied to incoming
|
||||
TCP/TLS transports when no
|
||||
valid data received after
|
||||
a successful connection. */
|
||||
|
||||
/**
|
||||
* Function to be called by transport manager to send SIP message.
|
||||
|
|
|
@ -115,7 +115,8 @@ typedef struct pjsip_tcp_transport_cfg
|
|||
|
||||
/**
|
||||
* Intial timeout interval to be applied to incoming transports
|
||||
* (i.e. server side) when no data received after a successful connection.
|
||||
* (i.e. server side) when no valid data received after a successful
|
||||
* connection.
|
||||
*
|
||||
* Default: PJSIP_TCP_INITIAL_TIMEOUT
|
||||
*/
|
||||
|
|
|
@ -324,6 +324,15 @@ typedef struct pjsip_tls_setting
|
|||
*/
|
||||
pj_time_val timeout;
|
||||
|
||||
/**
|
||||
* Intial timeout interval to be applied to incoming transports
|
||||
* (i.e. server side) when no valid data received after a successful
|
||||
* connection.
|
||||
*
|
||||
* Default: PJSIP_TRANSPORT_SERVER_IDLE_TIME_FIRST
|
||||
*/
|
||||
unsigned initial_timeout;
|
||||
|
||||
/**
|
||||
* Should SO_REUSEADDR be used for the listener socket.
|
||||
* Default value is PJSIP_TLS_TRANSPORT_REUSEADDR.
|
||||
|
@ -437,6 +446,7 @@ PJ_INLINE(void) pjsip_tls_setting_default(pjsip_tls_setting *tls_opt)
|
|||
tls_opt->sockopt_ignore_error = PJ_TRUE;
|
||||
tls_opt->proto = PJSIP_SSL_DEFAULT_PROTO;
|
||||
tls_opt->enable_renegotiation = PJ_TRUE;
|
||||
tls_opt->initial_timeout = PJSIP_TRANSPORT_SERVER_IDLE_TIME_FIRST;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -102,8 +102,10 @@ PJ_DEF(void) pjsip_dump_config(void)
|
|||
PJSIP_MAX_TIMED_OUT_ENTRIES));
|
||||
PJ_LOG(3, (id, " PJSIP_TRANSPORT_IDLE_TIME : %d",
|
||||
PJSIP_TRANSPORT_IDLE_TIME));
|
||||
PJ_LOG(3, (id, " PJSIP_TRANSPORT_SERVER_IDLE_TIME : %d",
|
||||
PJ_LOG(3, (id, " PJSIP_TRANSPORT_SERVER_IDLE_TIME : %d",
|
||||
PJSIP_TRANSPORT_SERVER_IDLE_TIME));
|
||||
PJ_LOG(3, (id, " PJSIP_TRANSPORT_SERVER_IDLE_TIME_FIRST : %d",
|
||||
PJSIP_TRANSPORT_SERVER_IDLE_TIME_FIRST));
|
||||
PJ_LOG(3, (id, " PJSIP_MAX_TRANSPORT_USAGE : %d",
|
||||
PJSIP_MAX_TRANSPORT_USAGE));
|
||||
PJ_LOG(3, (id, " PJSIP_TCP_TRANSPORT_BACKLOG : %d",
|
||||
|
|
|
@ -90,6 +90,12 @@ static const char* print_tpsel_info(const pjsip_tpselector *sel)
|
|||
# define PJSIP_TRANSPORT_ENTRY_ALLOC_CNT 16
|
||||
#endif
|
||||
|
||||
/* Enum for id idle_timer. */
|
||||
enum timer_id {
|
||||
IDLE_TIMER_ID = 1,
|
||||
INITIAL_IDLE_TIMER_ID
|
||||
};
|
||||
|
||||
/* Prototype. */
|
||||
static pj_status_t mod_on_tx_msg(pjsip_tx_data *tdata);
|
||||
|
||||
|
@ -1066,6 +1072,8 @@ static void transport_idle_callback(pj_timer_heap_t *timer_heap,
|
|||
struct pj_timer_entry *entry)
|
||||
{
|
||||
pjsip_transport *tp = (pjsip_transport*) entry->user_data;
|
||||
int entry_id = entry->id;
|
||||
|
||||
pj_assert(tp != NULL);
|
||||
|
||||
PJ_UNUSED_ARG(timer_heap);
|
||||
|
@ -1079,8 +1087,23 @@ static void transport_idle_callback(pj_timer_heap_t *timer_heap,
|
|||
* race condition with pjsip_tpmgr_acquire_transport2().
|
||||
*/
|
||||
pj_lock_acquire(tp->tpmgr->lock);
|
||||
|
||||
if (pj_atomic_get(tp->ref_cnt) == 0) {
|
||||
tp->is_destroying = PJ_TRUE;
|
||||
PJ_LOG(4, (THIS_FILE, "Transport %s is being destroyed "
|
||||
"due to timeout in %s timer", tp->obj_name,
|
||||
(entry_id == IDLE_TIMER_ID)?"idle":"initial"));
|
||||
if (entry_id == INITIAL_IDLE_TIMER_ID) {
|
||||
if (tp->last_recv_len > 0 && tp->tpmgr->tp_drop_data_cb) {
|
||||
pjsip_tp_dropped_data dd;
|
||||
pj_bzero(&dd, sizeof(dd));
|
||||
dd.tp = tp;
|
||||
dd.data = NULL;
|
||||
dd.len = tp->last_recv_len;
|
||||
dd.status = PJ_ESOCKETSTOP;
|
||||
(*tp->tpmgr->tp_drop_data_cb)(&dd);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pj_lock_release(tp->tpmgr->lock);
|
||||
return;
|
||||
|
@ -1179,6 +1202,8 @@ PJ_DEF(pj_status_t) pjsip_transport_dec_ref( pjsip_transport *tp )
|
|||
{
|
||||
pj_time_val delay;
|
||||
|
||||
int timer_id = IDLE_TIMER_ID;
|
||||
|
||||
/* If transport is in graceful shutdown, then this is the
|
||||
* last user who uses the transport. Schedule to destroy the
|
||||
* transport immediately. Otherwise schedule idle timer.
|
||||
|
@ -1186,9 +1211,18 @@ PJ_DEF(pj_status_t) pjsip_transport_dec_ref( pjsip_transport *tp )
|
|||
if (tp->is_shutdown) {
|
||||
delay.sec = delay.msec = 0;
|
||||
} else {
|
||||
delay.sec = (tp->dir==PJSIP_TP_DIR_OUTGOING) ?
|
||||
PJSIP_TRANSPORT_IDLE_TIME :
|
||||
PJSIP_TRANSPORT_SERVER_IDLE_TIME;
|
||||
if (tp->dir == PJSIP_TP_DIR_OUTGOING) {
|
||||
delay.sec = PJSIP_TRANSPORT_IDLE_TIME;
|
||||
} else {
|
||||
delay.sec = PJSIP_TRANSPORT_SERVER_IDLE_TIME;
|
||||
if (tp->last_recv_ts.u64 == 0 && tp->initial_timeout) {
|
||||
PJ_LOG(4, (THIS_FILE,
|
||||
"Starting transport %s initial timer",
|
||||
tp->obj_name));
|
||||
timer_id = INITIAL_IDLE_TIMER_ID;
|
||||
delay.sec = tp->initial_timeout;
|
||||
}
|
||||
}
|
||||
delay.msec = 0;
|
||||
}
|
||||
|
||||
|
@ -1199,7 +1233,7 @@ PJ_DEF(pj_status_t) pjsip_transport_dec_ref( pjsip_transport *tp )
|
|||
pjsip_endpt_schedule_timer_w_grp_lock(tp->tpmgr->endpt,
|
||||
&tp->idle_timer,
|
||||
&delay,
|
||||
PJ_TRUE,
|
||||
timer_id,
|
||||
tp->grp_lock);
|
||||
}
|
||||
pj_lock_release(tpmgr->lock);
|
||||
|
@ -2048,6 +2082,20 @@ PJ_DEF(pj_ssize_t) pjsip_tpmgr_receive_packet( pjsip_tpmgr *mgr,
|
|||
dd.status = PJSIP_ERXOVERFLOW;
|
||||
(*mgr->tp_drop_data_cb)(&dd);
|
||||
}
|
||||
|
||||
if (rdata->tp_info.transport->idle_timer.id ==
|
||||
INITIAL_IDLE_TIMER_ID)
|
||||
{
|
||||
/* We are not getting the first valid SIP message
|
||||
* as expected, close the transport.
|
||||
*/
|
||||
PJ_LOG(4, (THIS_FILE, "Unexpected data was received "\
|
||||
"while waiting for a valid initial SIP messages. "\
|
||||
"Shutting down transport %s",
|
||||
rdata->tp_info.transport->obj_name));
|
||||
|
||||
pjsip_transport_shutdown(rdata->tp_info.transport);
|
||||
}
|
||||
|
||||
/* Exhaust all data. */
|
||||
return rdata->pkt_info.len;
|
||||
|
@ -2211,6 +2259,17 @@ PJ_DEF(pj_ssize_t) pjsip_tpmgr_receive_packet( pjsip_tpmgr *mgr,
|
|||
}
|
||||
*/
|
||||
|
||||
/* We have a valid message, cancel the initial timer. */
|
||||
if (rdata->tp_info.transport->idle_timer.id == INITIAL_IDLE_TIMER_ID) {
|
||||
PJ_LOG(4, (THIS_FILE, "Receive initial valid message from %s, "\
|
||||
"cancelling the initial timer",
|
||||
rdata->tp_info.transport->obj_name));
|
||||
|
||||
rdata->tp_info.transport->idle_timer.id = PJ_FALSE;
|
||||
pjsip_endpt_cancel_timer(mgr->endpt,
|
||||
&rdata->tp_info.transport->idle_timer);
|
||||
}
|
||||
|
||||
/* Call the transport manager's upstream message callback.
|
||||
*/
|
||||
mgr->on_rx_msg(mgr->endpt, PJ_SUCCESS, rdata);
|
||||
|
|
|
@ -124,8 +124,6 @@ struct tcp_transport
|
|||
/* Group lock to be used by TCP transport and ioqueue key */
|
||||
pj_grp_lock_t *grp_lock;
|
||||
|
||||
/* Initial timer. */
|
||||
pj_timer_entry initial_timer;
|
||||
};
|
||||
|
||||
|
||||
|
@ -235,7 +233,8 @@ PJ_DEF(void) pjsip_tcp_transport_cfg_default(pjsip_tcp_transport_cfg *cfg,
|
|||
pj_sockaddr_init(cfg->af, &cfg->bind_addr, NULL, 0);
|
||||
cfg->async_cnt = 1;
|
||||
cfg->reuse_addr = PJSIP_TCP_TRANSPORT_REUSEADDR;
|
||||
cfg->initial_timeout = PJSIP_TCP_INITIAL_TIMEOUT;
|
||||
cfg->initial_timeout = (PJSIP_TCP_INITIAL_TIMEOUT!=0)?
|
||||
PJSIP_TCP_INITIAL_TIMEOUT:PJSIP_TRANSPORT_SERVER_IDLE_TIME_FIRST;
|
||||
}
|
||||
|
||||
|
||||
|
@ -605,9 +604,6 @@ static pj_bool_t on_connect_complete(pj_activesock_t *asock,
|
|||
/* TCP keep-alive timer callback */
|
||||
static void tcp_keep_alive_timer(pj_timer_heap_t *th, pj_timer_entry *e);
|
||||
|
||||
/* TCP initial timer callback */
|
||||
static void tcp_initial_timer(pj_timer_heap_t *th, pj_timer_entry *e);
|
||||
|
||||
/* Clean up TCP resources */
|
||||
static void tcp_on_destroy(void *arg);
|
||||
|
||||
|
@ -688,6 +684,7 @@ static pj_status_t tcp_create( struct tcp_listener *listener,
|
|||
tcp->base.do_shutdown = &tcp_shutdown;
|
||||
tcp->base.destroy = &tcp_destroy_transport;
|
||||
tcp->base.factory = &listener->factory;
|
||||
tcp->base.initial_timeout = listener->initial_timeout;
|
||||
|
||||
/* Create group lock */
|
||||
status = pj_grp_lock_create_w_handler(pool, NULL, tcp, &tcp_on_destroy,
|
||||
|
@ -730,18 +727,10 @@ static pj_status_t tcp_create( struct tcp_listener *listener,
|
|||
pj_ioqueue_op_key_init(&tcp->ka_op_key.key, sizeof(pj_ioqueue_op_key_t));
|
||||
pj_strdup(tcp->base.pool, &tcp->ka_pkt, &ka_pkt);
|
||||
|
||||
/* Initialize initial timer. */
|
||||
if (is_server && listener->initial_timeout) {
|
||||
pj_time_val delay = { 0 };
|
||||
|
||||
tcp->initial_timer.user_data = (void*)tcp;
|
||||
tcp->initial_timer.cb = &tcp_initial_timer;
|
||||
|
||||
delay.sec = listener->initial_timeout;
|
||||
pjsip_endpt_schedule_timer(listener->endpt,
|
||||
&tcp->initial_timer,
|
||||
&delay);
|
||||
tcp->initial_timer.id = PJ_TRUE;
|
||||
/* Initialize initial timer. */
|
||||
pjsip_transport_add_ref(&tcp->base);
|
||||
pjsip_transport_dec_ref(&tcp->base);
|
||||
}
|
||||
|
||||
/* Done setting up basic transport. */
|
||||
|
@ -848,12 +837,6 @@ static pj_status_t tcp_destroy(pjsip_transport *transport,
|
|||
tcp->ka_timer.id = PJ_FALSE;
|
||||
}
|
||||
|
||||
/* Stop initial timer. */
|
||||
if (tcp->initial_timer.id) {
|
||||
pjsip_endpt_cancel_timer(tcp->base.endpt, &tcp->initial_timer);
|
||||
tcp->initial_timer.id = PJ_FALSE;
|
||||
}
|
||||
|
||||
/* Cancel all delayed transmits */
|
||||
while (!pj_list_empty(&tcp->delayed_list)) {
|
||||
struct delayed_tdata *pending_tx;
|
||||
|
@ -1394,12 +1377,6 @@ static pj_status_t tcp_shutdown(pjsip_transport *transport)
|
|||
tcp->ka_timer.id = PJ_FALSE;
|
||||
}
|
||||
|
||||
/* Stop initial timer. */
|
||||
if (tcp->initial_timer.id) {
|
||||
pjsip_endpt_cancel_timer(tcp->base.endpt, &tcp->initial_timer);
|
||||
tcp->initial_timer.id = PJ_FALSE;
|
||||
}
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1428,11 +1405,6 @@ static pj_bool_t on_data_read(pj_activesock_t *asock,
|
|||
return PJ_FALSE;
|
||||
}
|
||||
|
||||
if (tcp->initial_timer.id) {
|
||||
pjsip_endpt_cancel_timer(tcp->base.endpt, &tcp->initial_timer);
|
||||
tcp->initial_timer.id = PJ_FALSE;
|
||||
}
|
||||
|
||||
/* Houston, we have packet! Report the packet to transport manager
|
||||
* to be parsed.
|
||||
*/
|
||||
|
@ -1650,16 +1622,6 @@ static void tcp_keep_alive_timer(pj_timer_heap_t *th, pj_timer_entry *e)
|
|||
tcp->ka_timer.id = PJ_TRUE;
|
||||
}
|
||||
|
||||
/* Transport keep-alive timer callback */
|
||||
static void tcp_initial_timer(pj_timer_heap_t *th, pj_timer_entry *e)
|
||||
{
|
||||
pj_status_t status = PJ_ETIMEDOUT;
|
||||
struct tcp_transport *tcp = (struct tcp_transport*) e->user_data;
|
||||
|
||||
PJ_UNUSED_ARG(th);
|
||||
|
||||
tcp_init_shutdown(tcp, status);
|
||||
}
|
||||
|
||||
PJ_DEF(pj_sock_t) pjsip_tcp_transport_get_socket(pjsip_transport *transport)
|
||||
{
|
||||
|
|
|
@ -907,6 +907,7 @@ static pj_status_t tls_create( struct tls_listener *listener,
|
|||
tls->base.do_shutdown = &tls_shutdown;
|
||||
tls->base.destroy = &tls_destroy_transport;
|
||||
tls->base.factory = &listener->factory;
|
||||
tls->base.initial_timeout = listener->tls_setting.initial_timeout;
|
||||
|
||||
tls->ssock = ssock;
|
||||
tls->on_verify_cb = listener->tls_setting.on_verify_cb;
|
||||
|
|
Loading…
Reference in New Issue