Changeset 1473 for pjproject/trunk


Ignore:
Timestamp:
Oct 4, 2007 9:50:36 AM (17 years ago)
Author:
bennylp
Message:

Ticket #95: Keep-alive mechanism for TCP and TLS transports

Location:
pjproject/trunk/pjsip
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/build/pjsip_core.dsp

    r849 r1473  
    4141# PROP Intermediate_Dir ".\output\pjsip-core-i386-win32-vc6-release" 
    4242# PROP Target_Dir "" 
     43F90=df.exe 
    4344# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c 
    4445# ADD CPP /nologo /MD /W4 /Zi /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c 
     
    6566# PROP Intermediate_Dir ".\output\pjsip-core-i386-win32-vc6-debug" 
    6667# PROP Target_Dir "" 
     68F90=df.exe 
    6769# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c 
    6870# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /GZ /c 
  • pjproject/trunk/pjsip/include/pjsip/sip_config.h

    r1469 r1473  
    266266 * before the transport is destroyed. Value is in seconds. 
    267267 * 
    268  * Default: 60 
     268 * Default: 600 
    269269 */ 
    270270#ifndef PJSIP_TRANSPORT_IDLE_TIME 
    271 #   define PJSIP_TRANSPORT_IDLE_TIME    60 
     271#   define PJSIP_TRANSPORT_IDLE_TIME    600 
    272272#endif 
    273273 
     
    295295#ifndef PJSIP_TCP_TRANSPORT_BACKLOG 
    296296#   define PJSIP_TCP_TRANSPORT_BACKLOG  5 
     297#endif 
     298 
     299 
     300/** 
     301 * Set the interval to send keep-alive packet for TCP transports. 
     302 * If the value is zero, keep-alive will be disabled for TCP. 
     303 * 
     304 * Default: 90 (seconds) 
     305 * 
     306 * @see PJSIP_TCP_KEEP_ALIVE_DATA 
     307 */ 
     308#ifndef PJSIP_TCP_KEEP_ALIVE_INTERVAL 
     309#   define PJSIP_TCP_KEEP_ALIVE_INTERVAL    90 
     310#endif 
     311 
     312 
     313/** 
     314 * Set the payload of the TCP keep-alive packet. 
     315 * 
     316 * Default: CRLF 
     317 */ 
     318#ifndef PJSIP_TCP_KEEP_ALIVE_DATA 
     319#   define PJSIP_TCP_KEEP_ALIVE_DATA        { "\r\n", 2 } 
     320#endif 
     321 
     322 
     323/** 
     324 * Set the interval to send keep-alive packet for TLS transports. 
     325 * If the value is zero, keep-alive will be disabled for TLS. 
     326 * 
     327 * Default: 90 (seconds) 
     328 * 
     329 * @see PJSIP_TLS_KEEP_ALIVE_DATA 
     330 */ 
     331#ifndef PJSIP_TLS_KEEP_ALIVE_INTERVAL 
     332#   define PJSIP_TLS_KEEP_ALIVE_INTERVAL    90 
     333#endif 
     334 
     335 
     336/** 
     337 * Set the payload of the TLS keep-alive packet. 
     338 * 
     339 * Default: CRLF 
     340 */ 
     341#ifndef PJSIP_TLS_KEEP_ALIVE_DATA 
     342#   define PJSIP_TLS_KEEP_ALIVE_DATA        { "\r\n", 2 } 
    297343#endif 
    298344 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c

    r1405 r1473  
    4242#define POOL_TP_INC     4002 
    4343 
    44  
    4544struct tcp_listener; 
    4645struct tcp_transport; 
     
    113112    pj_bool_t                has_pending_connect; 
    114113 
     114    /* Keep-alive timer. */ 
     115    pj_timer_entry           ka_timer; 
     116    pj_time_val              last_activity; 
     117    pjsip_tx_data_op_key     ka_op_key; 
     118    pj_str_t                 ka_pkt; 
    115119 
    116120    /* TCP transport can only have  one rdata! 
     
    477481                                pj_status_t status); 
    478482 
     483/* TCP keep-alive timer callback */ 
     484static void tcp_keep_alive_timer(pj_timer_heap_t *th, pj_timer_entry *e); 
    479485 
    480486/* 
     
    492498    pj_ioqueue_t *ioqueue; 
    493499    pj_ioqueue_callback tcp_callback; 
     500    const pj_str_t ka_pkt = PJSIP_TCP_KEEP_ALIVE_DATA; 
    494501    pj_status_t status; 
    495502     
     
    569576 
    570577    tcp->is_registered = PJ_TRUE; 
     578 
     579    /* Initialize keep-alive timer */ 
     580    tcp->ka_timer.user_data = (void*)tcp; 
     581    tcp->ka_timer.cb = &tcp_keep_alive_timer; 
     582    pj_ioqueue_op_key_init(&tcp->ka_op_key.key, sizeof(pj_ioqueue_op_key_t)); 
     583    pj_strdup(tcp->base.pool, &tcp->ka_pkt, &ka_pkt); 
    571584 
    572585    /* Done setting up basic transport. */ 
     
    967980                    PJ_LOG(3,(tcp->base.obj_name, "New transport cancelled")); 
    968981                    tcp_destroy(&tcp->base, status); 
     982                } else { 
     983                    /* Start keep-alive timer */ 
     984                    if (PJSIP_TCP_KEEP_ALIVE_INTERVAL) { 
     985                        pj_time_val delay = {PJSIP_TCP_KEEP_ALIVE_INTERVAL, 0}; 
     986                        pjsip_endpt_schedule_timer(listener->endpt,  
     987                                                   &tcp->ka_timer,  
     988                                                   &delay); 
     989                        tcp->ka_timer.id = PJ_TRUE; 
     990                        pj_gettimeofday(&tcp->last_activity); 
     991                    } 
    969992                } 
    970993            } 
     
    10061029    pjsip_tx_data_op_key *tdata_op_key = (pjsip_tx_data_op_key*)op_key; 
    10071030 
     1031    /* Note that op_key may be the op_key from keep-alive, thus 
     1032     * it will not have tdata etc. 
     1033     */ 
     1034 
    10081035    tdata_op_key->tdata = NULL; 
    10091036 
     
    10261053         */ 
    10271054        tdata_op_key->callback(&tcp->base, tdata_op_key->token, bytes_sent); 
     1055 
     1056        /* Mark last activity time */ 
     1057        pj_gettimeofday(&tcp->last_activity); 
    10281058    } 
    10291059} 
     
    11281158/*  
    11291159 * This callback is called by transport manager to shutdown transport. 
    1130  * This normally is only used by UDP transport. 
    11311160 */ 
    11321161static pj_status_t tcp_shutdown(pjsip_transport *transport) 
    11331162{ 
    1134  
    1135     PJ_UNUSED_ARG(transport); 
    1136  
    1137     /* Nothing to do for TCP */ 
     1163    struct tcp_transport *tcp = (struct tcp_transport*)transport; 
     1164     
     1165    /* Stop keep-alive timer. */ 
     1166    if (tcp->ka_timer.id) { 
     1167        pjsip_endpt_cancel_timer(tcp->listener->endpt, &tcp->ka_timer); 
     1168        tcp->ka_timer.id = PJ_FALSE; 
     1169    } 
     1170 
    11381171    return PJ_SUCCESS; 
    11391172} 
     
    11751208        if (bytes_read > 0) { 
    11761209            pj_size_t size_eaten; 
     1210 
     1211            /* Mark this as an activity */ 
     1212            pj_gettimeofday(&tcp->last_activity); 
    11771213 
    11781214            /* Init pkt_info part. */ 
     
    13651401    /* Flush all pending send operations */ 
    13661402    tcp_flush_pending_tx(tcp); 
    1367 } 
     1403 
     1404    /* Start keep-alive timer */ 
     1405    if (PJSIP_TCP_KEEP_ALIVE_INTERVAL) { 
     1406        pj_time_val delay = { PJSIP_TCP_KEEP_ALIVE_INTERVAL, 0 }; 
     1407        pjsip_endpt_schedule_timer(tcp->listener->endpt, &tcp->ka_timer,  
     1408                                   &delay); 
     1409        tcp->ka_timer.id = PJ_TRUE; 
     1410        pj_gettimeofday(&tcp->last_activity); 
     1411    } 
     1412} 
     1413 
     1414/* Transport keep-alive timer callback */ 
     1415static void tcp_keep_alive_timer(pj_timer_heap_t *th, pj_timer_entry *e) 
     1416{ 
     1417    struct tcp_transport *tcp = (struct tcp_transport*) e->user_data; 
     1418    pj_time_val delay; 
     1419    pj_time_val now; 
     1420    pj_ssize_t size; 
     1421    pj_status_t status; 
     1422 
     1423    PJ_UNUSED_ARG(th); 
     1424 
     1425    tcp->ka_timer.id = PJ_TRUE; 
     1426 
     1427    pj_gettimeofday(&now); 
     1428    PJ_TIME_VAL_SUB(now, tcp->last_activity); 
     1429 
     1430    if (now.sec > 0 && now.sec < PJSIP_TCP_KEEP_ALIVE_INTERVAL) { 
     1431        /* There has been activity, so don't send keep-alive */ 
     1432        delay.sec = PJSIP_TCP_KEEP_ALIVE_INTERVAL - now.sec; 
     1433        delay.msec = 0; 
     1434 
     1435        pjsip_endpt_schedule_timer(tcp->listener->endpt, &tcp->ka_timer,  
     1436                                   &delay); 
     1437        tcp->ka_timer.id = PJ_TRUE; 
     1438        return; 
     1439    } 
     1440 
     1441    PJ_LOG(5,(tcp->base.obj_name, "Sending %d byte(s) keep-alive to %.*s:%d",  
     1442              (int)tcp->ka_pkt.slen, (int)tcp->base.remote_name.host.slen, 
     1443              tcp->base.remote_name.host.ptr, 
     1444              tcp->base.remote_name.port)); 
     1445 
     1446    /* Send the data */ 
     1447    size = tcp->ka_pkt.slen; 
     1448    status = pj_ioqueue_send(tcp->key, &tcp->ka_op_key.key, 
     1449                             tcp->ka_pkt.ptr, &size, 0); 
     1450 
     1451    if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
     1452        tcp_perror(tcp->base.obj_name,  
     1453                   "Error sending keep-alive packet", status); 
     1454        pjsip_transport_shutdown(&tcp->base); 
     1455        return; 
     1456    } 
     1457 
     1458    /* Register next keep-alive */ 
     1459    delay.sec = PJSIP_TCP_KEEP_ALIVE_INTERVAL; 
     1460    delay.msec = 0; 
     1461 
     1462    pjsip_endpt_schedule_timer(tcp->listener->endpt, &tcp->ka_timer,  
     1463                               &delay); 
     1464    tcp->ka_timer.id = PJ_TRUE; 
     1465} 
     1466 
    13681467 
    13691468#endif  /* PJ_HAS_TCP */ 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_tls_ossl.c

    r1405 r1473  
    167167    SSL                     *ssl; 
    168168    pj_bool_t                ssl_shutdown_called; 
     169 
     170    /* Keep alive */ 
     171    pj_timer_entry           ka_timer; 
     172    pj_time_val              last_activity; 
    169173 
    170174    /* TLS transport can only have  one rdata! 
     
    742746 
    743747/* Send outgoing data with SSL connection */ 
    744 static pj_status_t ssl_write(struct tls_transport *tls, 
    745                              pjsip_tx_data *tdata) 
    746 { 
    747     int size = tdata->buf.cur - tdata->buf.start; 
     748static pj_status_t ssl_write_bytes(struct tls_transport *tls, 
     749                                   const void *data, 
     750                                   int size, 
     751                                   const char *data_name) 
     752{ 
    748753    int sent = 0; 
    749754 
    750755    do { 
    751756        const int fragment_sent = SSL_write(tls->ssl, 
    752                                             tdata->buf.start + sent,  
     757                                            ((pj_uint8_t*)data) + sent,  
    753758                                            size - sent); 
    754759     
     
    799804            ssl_report_error(tls->base.obj_name, 4, PJ_SUCCESS, 
    800805                             "Error sending %s with SSL_write()", 
    801                              pjsip_tx_data_get_info(tdata)); 
     806                             data_name); 
    802807            return pj_get_netos_error() ? pj_get_netos_error()  
    803808                    : PJSIP_TLS_ESEND; 
     
    807812 
    808813    return PJ_SUCCESS; 
     814 
     815} 
     816 
     817/* Send outgoing tdata with SSL connection */ 
     818static pj_status_t ssl_write(struct tls_transport *tls, 
     819                             pjsip_tx_data *tdata) 
     820{ 
     821    return ssl_write_bytes(tls, tdata->buf.start,  
     822                           tdata->buf.cur - tdata->buf.start, 
     823                           pjsip_tx_data_get_info(tdata)); 
    809824} 
    810825 
     
    11621177                                pj_status_t status); 
    11631178 
     1179/* TLS keep-alive timer callback */ 
     1180static void tls_keep_alive_timer(pj_timer_heap_t *th, pj_timer_entry *e); 
    11641181 
    11651182/* 
     
    12041221 
    12051222    /* Initialize transport reference counter to 1 */ 
    1206     status = pj_atomic_create(pool, 1, &tls->base.ref_cnt); 
     1223    status = pj_atomic_create(pool, 0, &tls->base.ref_cnt); 
    12071224    if (status != PJ_SUCCESS) { 
    12081225        goto on_error; 
     
    12731290 
    12741291    tls->is_registered = PJ_TRUE; 
     1292 
     1293    /* Initialize keep-alive timer */ 
     1294    tls->ka_timer.user_data = (void*) tls; 
     1295    tls->ka_timer.cb = &tls_keep_alive_timer; 
     1296 
    12751297 
    12761298    /* Done setting up basic transport. */ 
     
    17241746                                 "Error creating incoming TLS transport"); 
    17251747                pjsip_transport_shutdown(&tls->base); 
     1748 
     1749            } else { 
     1750                /* Start keep-alive timer */ 
     1751                if (PJSIP_TLS_KEEP_ALIVE_INTERVAL) { 
     1752                    pj_time_val delay = {PJSIP_TLS_KEEP_ALIVE_INTERVAL, 0}; 
     1753                    pjsip_endpt_schedule_timer(listener->endpt,  
     1754                                               &tls->ka_timer,  
     1755                                               &delay); 
     1756                    tls->ka_timer.id = PJ_TRUE; 
     1757                    pj_gettimeofday(&tls->last_activity); 
     1758                } 
    17261759            } 
    17271760 
     
    17751808        if (tls->close_reason==PJ_SUCCESS) tls->close_reason = status; 
    17761809        pjsip_transport_shutdown(&tls->base); 
     1810    } else { 
     1811        /* Mark last activity */ 
     1812        pj_gettimeofday(&tls->last_activity); 
    17771813    } 
    17781814 
     
    19191955    /* Shutdown SSL */ 
    19201956    if (!tls->ssl_shutdown_called) { 
    1921         /* Release our reference counter and shutdown SSL */ 
    1922         pjsip_transport_dec_ref(transport); 
     1957        /* shutdown SSL */ 
    19231958        SSL_shutdown(tls->ssl); 
    19241959        tls->ssl_shutdown_called = PJ_TRUE; 
     
    19692004             */ 
    19702005            pj_size_t size_eaten; 
     2006 
     2007            /* Mark last activity */ 
     2008            pj_gettimeofday(&tls->last_activity); 
    19712009 
    19722010            /* Init pkt_info part. */ 
     
    22172255    /* Flush all pending send operations */ 
    22182256    tls_flush_pending_tx(tls); 
     2257 
     2258    /* Start keep-alive timer */ 
     2259    if (PJSIP_TLS_KEEP_ALIVE_INTERVAL) { 
     2260        pj_time_val delay = { PJSIP_TLS_KEEP_ALIVE_INTERVAL, 0 }; 
     2261        pjsip_endpt_schedule_timer(tls->listener->endpt, &tls->ka_timer,  
     2262                                   &delay); 
     2263        tls->ka_timer.id = PJ_TRUE; 
     2264        pj_gettimeofday(&tls->last_activity); 
     2265    } 
     2266 
     2267} 
     2268 
     2269 
     2270/* Transport keep-alive timer callback */ 
     2271static void tls_keep_alive_timer(pj_timer_heap_t *th, pj_timer_entry *e) 
     2272{ 
     2273    struct tls_transport *tls = (struct tls_transport*) e->user_data; 
     2274    const pj_str_t ka_data = PJSIP_TLS_KEEP_ALIVE_DATA; 
     2275    pj_time_val delay; 
     2276    pj_time_val now; 
     2277    pj_status_t status; 
     2278 
     2279    PJ_UNUSED_ARG(th); 
     2280 
     2281    tls->ka_timer.id = PJ_TRUE; 
     2282 
     2283    pj_gettimeofday(&now); 
     2284    PJ_TIME_VAL_SUB(now, tls->last_activity); 
     2285 
     2286    if (now.sec > 0 && now.sec < PJSIP_TLS_KEEP_ALIVE_INTERVAL) { 
     2287        /* There has been activity, so don't send keep-alive */ 
     2288        delay.sec = PJSIP_TLS_KEEP_ALIVE_INTERVAL - now.sec; 
     2289        delay.msec = 0; 
     2290 
     2291        pjsip_endpt_schedule_timer(tls->listener->endpt, &tls->ka_timer,  
     2292                                   &delay); 
     2293        tls->ka_timer.id = PJ_TRUE; 
     2294        return; 
     2295    } 
     2296 
     2297    PJ_LOG(5,(tls->base.obj_name, "Sending %d byte(s) keep-alive to %.*s:%d",  
     2298              (int)ka_data.slen, (int)tls->base.remote_name.host.slen, 
     2299              tls->base.remote_name.host.ptr, 
     2300              tls->base.remote_name.port)); 
     2301 
     2302    /* Send the data */ 
     2303    status = ssl_write_bytes(tls, ka_data.ptr, (int)ka_data.slen,  
     2304                             "keep-alive"); 
     2305    if (status != PJ_SUCCESS &&  
     2306        status != PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK)) 
     2307    { 
     2308        ssl_report_error(tls->base.obj_name, 1, status, 
     2309                         "Error sending keep-alive packet"); 
     2310        return; 
     2311    } 
     2312 
     2313    /* Register next keep-alive */ 
     2314    delay.sec = PJSIP_TLS_KEEP_ALIVE_INTERVAL; 
     2315    delay.msec = 0; 
     2316 
     2317    pjsip_endpt_schedule_timer(tls->listener->endpt, &tls->ka_timer,  
     2318                               &delay); 
     2319    tls->ka_timer.id = PJ_TRUE; 
    22192320} 
    22202321 
Note: See TracChangeset for help on using the changeset viewer.