Changeset 3138


Ignore:
Timestamp:
Apr 14, 2010 6:57:35 AM (14 years ago)
Author:
nanang
Message:

Ticket #1056:

  • Added functions to set/unset transport state notification callback on specific transport.
  • Updated transaction to immediately terminate the transactions when their transport gets disconnected.
  • Minor update: renamed function pjsip_tpmgr_set/get_status_cb() to pjsip_tpmgr_set/get_state_cb().
Location:
pjproject/trunk/pjsip
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/include/pjsip/sip_transaction.h

    r3071 r3138  
    125125                                                     pending transport flag 
    126126                                                     to be set on tsx.      */ 
     127    pjsip_tp_state_listener_key *tp_st_key;     /**< Transport state listener 
     128                                                     key.                   */ 
    127129 
    128130    /* 
  • pjproject/trunk/pjsip/include/pjsip/sip_transport.h

    r3119 r3138  
    750750    pjsip_tpmgr            *tpmgr;          /**< Transport manager.         */ 
    751751    pj_timer_entry          idle_timer;     /**< Timer when ref cnt is zero.*/ 
     752 
     753    void                   *data;           /**< Internal transport data.   */ 
    752754 
    753755    /** 
     
    12711273 
    12721274/** 
     1275 * Definition of transport state listener key. 
     1276 */ 
     1277typedef void pjsip_tp_state_listener_key; 
     1278 
     1279/** 
    12731280 * Structure of transport state info passed by #pjsip_tp_state_callback. 
    12741281 */ 
     
    12831290     */ 
    12841291    void                *ext_info; 
     1292 
     1293    /** 
     1294     * Optional user data. In global transport state notification, this will 
     1295     * always be NULL. 
     1296     */ 
     1297    void                *user_data; 
     1298 
    12851299} pjsip_transport_state_info; 
    12861300 
     
    13021316 
    13031317/** 
    1304  * Setting callback of transport state notification. The caller will be 
    1305  * notified whenever the state of transport is changed. The type of 
    1306  * events are defined in #pjsip_transport_state. 
     1318 * Set callback of global transport state notification. The caller will be 
     1319 * notified whenever the state of any transport is changed. The type of events 
     1320 * are defined in #pjsip_transport_state. 
     1321 * 
     1322 * Note that this function will override the existing callback, if any, so 
     1323 * application is recommended to keep the old callback and manually forward 
     1324 * the notification to the old callback, otherwise other component that  
     1325 * concerns about the transport state will no longer receive transport state  
     1326 * events. 
    13071327 *  
    13081328 * @param mgr       Transport manager. 
    13091329 * @param cb        Callback to be called to notify caller about transport  
    1310  *                  status changing. 
     1330 *                  state changing. 
    13111331 * 
    13121332 * @return          PJ_SUCCESS on success, or the appropriate error code. 
    13131333 */ 
    1314 PJ_DECL(pj_status_t) pjsip_tpmgr_set_status_cb(pjsip_tpmgr *mgr, 
    1315                                                pjsip_tp_state_callback cb); 
    1316  
    1317  
    1318 /** 
    1319  * Getting the callback of transport state notification. 
     1334PJ_DECL(pj_status_t) pjsip_tpmgr_set_state_cb(pjsip_tpmgr *mgr, 
     1335                                              pjsip_tp_state_callback cb); 
     1336 
     1337 
     1338/** 
     1339 * Get the callback of global transport state notification. 
    13201340 *  
    13211341 * @param mgr       Transport manager. 
     
    13231343 * @return          The transport state callback or NULL if it is not set. 
    13241344 */ 
    1325 PJ_DECL(pjsip_tp_state_callback) pjsip_tpmgr_get_status_cb( 
    1326                                                const pjsip_tpmgr *mgr); 
     1345PJ_DECL(pjsip_tp_state_callback) pjsip_tpmgr_get_state_cb( 
     1346                                              const pjsip_tpmgr *mgr); 
     1347 
     1348 
     1349/** 
     1350 * Add a listener to the specified transport for transport state notification. 
     1351 *  
     1352 * @param tp        The transport. 
     1353 * @param cb        Callback to be called to notify listener about transport  
     1354 *                  state changing. 
     1355 * @param user_data The user data. 
     1356 * @param key       Output key, used to remove this listener. 
     1357 * 
     1358 * @return          PJ_SUCCESS on success, or the appropriate error code. 
     1359 */ 
     1360PJ_DECL(pj_status_t) pjsip_transport_add_state_listener ( 
     1361                                            pjsip_transport *tp, 
     1362                                            pjsip_tp_state_callback cb, 
     1363                                            void *user_data, 
     1364                                            pjsip_tp_state_listener_key **key); 
     1365 
     1366 
     1367/** 
     1368 * Remove a listener from the specified transport for transport state  
     1369 * notification. 
     1370 *  
     1371 * @param tp        The transport. 
     1372 * @param key       The listener key. 
     1373 * @param user_data The user data, for validation purpose. 
     1374 * 
     1375 * @return          PJ_SUCCESS on success, or the appropriate error code. 
     1376 */ 
     1377PJ_DECL(pj_status_t) pjsip_transport_remove_state_listener ( 
     1378                                    pjsip_transport *tp, 
     1379                                    pjsip_tp_state_listener_key *key, 
     1380                                    const void *user_data); 
    13271381 
    13281382 
  • pjproject/trunk/pjsip/src/pjsip/sip_transaction.c

    r3114 r3138  
    181181static void        tsx_timer_callback( pj_timer_heap_t *theap,  
    182182                                       pj_timer_entry *entry); 
     183static void        tsx_tp_state_callback( 
     184                                       pjsip_transport *tp, 
     185                                       pjsip_transport_state state, 
     186                                       const pjsip_transport_state_info *info); 
    183187static pj_status_t tsx_create( pjsip_module *tsx_user, 
    184188                               pjsip_transaction **p_tsx); 
     
    188192static int         tsx_send_msg( pjsip_transaction *tsx,  
    189193                                 pjsip_tx_data *tdata); 
     194static void        tsx_update_transport( pjsip_transaction *tsx,  
     195                                         pjsip_transport *tp); 
    190196 
    191197 
     
    986992    struct tsx_lock_data *lck; 
    987993 
    988     /* Decrement transport reference counter. */ 
    989     if (tsx->transport) { 
    990         pjsip_transport_dec_ref( tsx->transport ); 
    991         tsx->transport = NULL; 
    992     } 
     994    /* Release the transport */ 
     995    tsx_update_transport(tsx, NULL); 
     996 
    993997    /* Decrement reference counter in transport selector */ 
    994998    pjsip_tpselector_dec_ref(&tsx->tp_sel); 
     
    14051409     */ 
    14061410    if (tsx->res_addr.transport) { 
    1407         tsx->transport = tsx->res_addr.transport; 
    1408         pjsip_transport_add_ref(tsx->transport); 
     1411        tsx_update_transport(tsx, tsx->res_addr.transport); 
    14091412        pj_memcpy(&tsx->addr, &tsx->res_addr.addr, tsx->res_addr.addr_len); 
    14101413        tsx->addr_len = tsx->res_addr.addr_len; 
     
    16761679        if (tsx->transport != send_state->cur_transport) { 
    16771680            /* Update transport. */ 
    1678             if (tsx->transport) { 
    1679                 pjsip_transport_dec_ref(tsx->transport); 
    1680                 tsx->transport = NULL; 
    1681             } 
    1682             tsx->transport = send_state->cur_transport; 
    1683             pjsip_transport_add_ref(tsx->transport); 
     1681            tsx_update_transport(tsx, send_state->cur_transport); 
    16841682 
    16851683            /* Update remote address. */ 
     
    17301728         * release the transport. 
    17311729         */ 
    1732         if (send_state->cur_transport==tsx->transport && 
    1733             tsx->transport != NULL) 
    1734         { 
    1735             pjsip_transport_dec_ref(tsx->transport); 
    1736             tsx->transport = NULL; 
    1737         } 
     1730        if (send_state->cur_transport==tsx->transport) 
     1731            tsx_update_transport(tsx, NULL); 
    17381732 
    17391733        /* Also stop processing if transaction has been flagged with 
     
    18371831        lock_tsx(tsx, &lck); 
    18381832 
    1839         /* Dereference transport. */ 
    1840         pjsip_transport_dec_ref(tsx->transport); 
    1841         tsx->transport = NULL; 
     1833        /* Release transport. */ 
     1834        tsx_update_transport(tsx, NULL); 
    18421835 
    18431836        /* Terminate transaction. */ 
     
    18491842   } 
    18501843} 
     1844 
     1845 
     1846/* 
     1847 * Callback when transport state changes. 
     1848 */ 
     1849static void tsx_tp_state_callback( pjsip_transport *tp, 
     1850                                   pjsip_transport_state state, 
     1851                                   const pjsip_transport_state_info *info) 
     1852{ 
     1853    if (state == PJSIP_TP_STATE_DISCONNECTED) { 
     1854        pjsip_transaction *tsx; 
     1855        struct tsx_lock_data lck; 
     1856 
     1857        pj_assert(tp && info && info->user_data); 
     1858 
     1859        tsx = (pjsip_transaction*)info->user_data; 
     1860 
     1861        lock_tsx(tsx, &lck); 
     1862 
     1863        /* Terminate transaction when transport disconnected */ 
     1864        if (tsx->state < PJSIP_TSX_STATE_TERMINATED) { 
     1865            pj_str_t err; 
     1866            char errmsg[PJ_ERR_MSG_SIZE]; 
     1867 
     1868            err = pj_strerror(info->status, errmsg, sizeof(errmsg)); 
     1869            tsx_set_status_code(tsx, PJSIP_SC_TSX_TRANSPORT_ERROR, &err); 
     1870            tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,  
     1871                           PJSIP_EVENT_TRANSPORT_ERROR, NULL); 
     1872        } 
     1873 
     1874        unlock_tsx(tsx, &lck); 
     1875    } 
     1876} 
     1877 
    18511878 
    18521879/* 
     
    18871914             * resolution procedure. 
    18881915             */ 
    1889             if (tsx->transport) { 
    1890                 pjsip_transport_dec_ref(tsx->transport); 
    1891                 tsx->transport = NULL; 
    1892             } 
     1916            tsx_update_transport(tsx, NULL); 
     1917 
    18931918            tsx->addr_len = 0; 
    18941919            tsx->res_addr.transport = NULL; 
     
    20962121 
    20972122    return PJ_SUCCESS; 
     2123} 
     2124 
     2125static void tsx_update_transport( pjsip_transaction *tsx,  
     2126                                  pjsip_transport *tp) 
     2127{ 
     2128    pj_assert(tsx); 
     2129 
     2130    if (tsx->transport) { 
     2131        pjsip_transport_remove_state_listener(tsx->transport,  
     2132                                               tsx->tp_st_key, tsx); 
     2133        pjsip_transport_dec_ref( tsx->transport ); 
     2134        tsx->transport = NULL; 
     2135    } 
     2136 
     2137    if (tp) { 
     2138        tsx->transport = tp; 
     2139        pjsip_transport_add_ref(tp); 
     2140        pjsip_transport_add_state_listener(tp, &tsx_tp_state_callback, tsx, 
     2141                                            &tsx->tp_st_key); 
     2142    } 
    20982143} 
    20992144 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport.c

    r3119 r3138  
    3434#include <pj/assert.h> 
    3535#include <pj/lock.h> 
     36#include <pj/list.h> 
    3637 
    3738 
     
    9192    pj_status_t    (*on_tx_msg)(pjsip_endpoint*, pjsip_tx_data*); 
    9293    pjsip_tp_state_callback tp_state_cb; 
    93     void *tp_state_user_data; 
    9494}; 
     95 
     96 
     97/* Transport state listener list type */ 
     98typedef struct tp_state_listener 
     99{ 
     100    PJ_DECL_LIST_MEMBER(struct tp_state_listener); 
     101 
     102    pjsip_tp_state_callback  cb; 
     103    void *user_data; 
     104} tp_state_listener; 
     105 
     106 
     107/* 
     108 * Transport data. 
     109 */ 
     110typedef struct transport_data 
     111{ 
     112    /* Transport listeners */ 
     113    tp_state_listener       st_listeners; 
     114    tp_state_listener       st_listeners_empty; 
     115} transport_data; 
    95116 
    96117 
     
    179200}; 
    180201 
     202static void tp_state_callback(pjsip_transport *tp, 
     203                              pjsip_transport_state state, 
     204                              const pjsip_transport_state_info *info); 
     205 
     206 
    181207struct transport_names_t *get_tpname(pjsip_transport_type_e type) 
    182208{ 
     
    10921118#endif 
    10931119 
     1120    /* Set transport state callback */ 
     1121    status = pjsip_tpmgr_set_state_cb(mgr, &tp_state_callback); 
     1122    if (status != PJ_SUCCESS) 
     1123        return status; 
     1124 
    10941125    PJ_LOG(5, (THIS_FILE, "Transport manager created.")); 
    10951126 
     
    17381769} 
    17391770 
    1740 PJ_DEF(pj_status_t) pjsip_tpmgr_set_status_cb(pjsip_tpmgr *mgr, 
    1741                                               pjsip_tp_state_callback cb) 
     1771/** 
     1772 * Set callback of global transport state notification. 
     1773 */ 
     1774PJ_DEF(pj_status_t) pjsip_tpmgr_set_state_cb(pjsip_tpmgr *mgr, 
     1775                                             pjsip_tp_state_callback cb) 
    17421776{ 
    17431777    PJ_ASSERT_RETURN(mgr, PJ_EINVAL); 
     
    17481782} 
    17491783 
    1750 PJ_DEF(pjsip_tp_state_callback) pjsip_tpmgr_get_status_cb( 
    1751                                               const pjsip_tpmgr *mgr) 
     1784/** 
     1785 * Get callback of global transport state notification. 
     1786 */ 
     1787PJ_DEF(pjsip_tp_state_callback) pjsip_tpmgr_get_state_cb( 
     1788                                             const pjsip_tpmgr *mgr) 
    17521789{ 
    17531790    PJ_ASSERT_RETURN(mgr, NULL); 
     
    17551792    return mgr->tp_state_cb; 
    17561793} 
     1794 
     1795 
     1796/** 
     1797 * Allocate and init transport data. 
     1798 */ 
     1799static void init_tp_data(pjsip_transport *tp) 
     1800{ 
     1801    transport_data *tp_data; 
     1802 
     1803    pj_assert(tp && !tp->data); 
     1804 
     1805    tp_data = PJ_POOL_ZALLOC_T(tp->pool, transport_data); 
     1806    pj_list_init(&tp_data->st_listeners); 
     1807    pj_list_init(&tp_data->st_listeners_empty); 
     1808    tp->data = tp_data; 
     1809} 
     1810 
     1811 
     1812static void tp_state_callback(pjsip_transport *tp, 
     1813                              pjsip_transport_state state, 
     1814                              const pjsip_transport_state_info *info) 
     1815{ 
     1816    transport_data *tp_data; 
     1817 
     1818    pj_lock_acquire(tp->lock); 
     1819 
     1820    tp_data = (transport_data*)tp->data; 
     1821 
     1822    /* Notify the transport state listeners, if any. */ 
     1823    if (!tp_data || pj_list_empty(&tp_data->st_listeners)) { 
     1824        goto on_return; 
     1825    } else { 
     1826        pjsip_transport_state_info st_info; 
     1827        tp_state_listener *st_listener = tp_data->st_listeners.next; 
     1828 
     1829        /* As we need to put the user data into the transport state info, 
     1830         * let's use a copy of transport state info. 
     1831         */ 
     1832        pj_memcpy(&st_info, info, sizeof(st_info)); 
     1833        while (st_listener != &tp_data->st_listeners) { 
     1834            st_info.user_data = st_listener->user_data; 
     1835            (*st_listener->cb)(tp, state, &st_info); 
     1836 
     1837            st_listener = st_listener->next; 
     1838        } 
     1839    } 
     1840 
     1841on_return: 
     1842    pj_lock_release(tp->lock); 
     1843} 
     1844 
     1845 
     1846/** 
     1847 * Add a listener to the specified transport for transport state notification. 
     1848 */ 
     1849PJ_DEF(pj_status_t) pjsip_transport_add_state_listener ( 
     1850                                            pjsip_transport *tp, 
     1851                                            pjsip_tp_state_callback cb, 
     1852                                            void *user_data, 
     1853                                            pjsip_tp_state_listener_key **key) 
     1854{ 
     1855    transport_data *tp_data; 
     1856    tp_state_listener *entry; 
     1857 
     1858    PJ_ASSERT_RETURN(tp && cb && key, PJ_EINVAL); 
     1859 
     1860    pj_lock_acquire(tp->lock); 
     1861 
     1862    /* Init transport data, if it hasn't */ 
     1863    if (!tp->data) 
     1864        init_tp_data(tp); 
     1865 
     1866    tp_data = (transport_data*)tp->data; 
     1867 
     1868    /* Init the new listener entry. Use available empty slot, if any, 
     1869     * otherwise allocate it using the transport pool. 
     1870     */ 
     1871    if (!pj_list_empty(&tp_data->st_listeners_empty)) { 
     1872        entry = tp_data->st_listeners_empty.next; 
     1873        pj_list_erase(entry); 
     1874    } else { 
     1875        entry = PJ_POOL_ZALLOC_T(tp->pool, tp_state_listener); 
     1876    } 
     1877    entry->cb = cb; 
     1878    entry->user_data = user_data; 
     1879 
     1880    /* Add the new listener entry to the listeners list */ 
     1881    pj_list_push_back(&tp_data->st_listeners, entry); 
     1882 
     1883    *key = entry; 
     1884 
     1885    pj_lock_release(tp->lock); 
     1886 
     1887    return PJ_SUCCESS; 
     1888} 
     1889 
     1890/** 
     1891 * Remove a listener from the specified transport for transport state  
     1892 * notification. 
     1893 */ 
     1894PJ_DEF(pj_status_t) pjsip_transport_remove_state_listener ( 
     1895                                    pjsip_transport *tp, 
     1896                                    pjsip_tp_state_listener_key *key, 
     1897                                    const void *user_data) 
     1898{ 
     1899    transport_data *tp_data; 
     1900    tp_state_listener *entry; 
     1901 
     1902    PJ_ASSERT_RETURN(tp && key, PJ_EINVAL); 
     1903 
     1904    pj_lock_acquire(tp->lock); 
     1905 
     1906    tp_data = (transport_data*)tp->data; 
     1907 
     1908    /* Transport data is NULL or no registered listener? */ 
     1909    if (!tp_data || pj_list_empty(&tp_data->st_listeners)) { 
     1910        pj_lock_release(tp->lock); 
     1911        return PJ_ENOTFOUND; 
     1912    } 
     1913 
     1914    entry = (tp_state_listener*)key; 
     1915 
     1916    /* Validate the user data */ 
     1917    if (entry->user_data != user_data) { 
     1918        pj_assert(!"Invalid transport state listener key"); 
     1919        pj_lock_release(tp->lock); 
     1920        return PJ_EBUG; 
     1921    } 
     1922 
     1923    /* Reset the entry and move it to the empty list */ 
     1924    entry->cb = NULL; 
     1925    entry->user_data = NULL; 
     1926    pj_list_erase(entry); 
     1927    pj_list_push_back(&tp_data->st_listeners_empty, entry); 
     1928 
     1929    pj_lock_release(tp->lock); 
     1930 
     1931    return PJ_SUCCESS; 
     1932} 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c

    r3128 r3138  
    185185 
    186186    /* Notify application of transport disconnected state */ 
    187     state_cb = pjsip_tpmgr_get_status_cb(tcp->base.tpmgr); 
     187    state_cb = pjsip_tpmgr_get_state_cb(tcp->base.tpmgr); 
    188188    if (state_cb) { 
    189189        pjsip_transport_state_info state_info; 
     
    10101010 
    10111011            /* Notify application of transport state accepted */ 
    1012             state_cb = pjsip_tpmgr_get_status_cb(tcp->base.tpmgr); 
     1012            state_cb = pjsip_tpmgr_get_state_cb(tcp->base.tpmgr); 
    10131013            if (state_cb) { 
    10141014                pjsip_transport_state_info state_info; 
     
    13371337 
    13381338    /* Notify application of transport state connected */ 
    1339     state_cb = pjsip_tpmgr_get_status_cb(tcp->base.tpmgr); 
     1339    state_cb = pjsip_tpmgr_get_state_cb(tcp->base.tpmgr); 
    13401340    if (state_cb) { 
    13411341        pjsip_transport_state_info state_info; 
  • pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c

    r3128 r3138  
    192192 
    193193    /* Notify application of transport disconnected state */ 
    194     state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr); 
     194    state_cb = pjsip_tpmgr_get_state_cb(tls->base.tpmgr); 
    195195    if (state_cb) { 
    196196        pjsip_transport_state_info state_info; 
     
    10491049 
    10501050    /* Notify transport state to application */ 
    1051     state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr); 
     1051    state_cb = pjsip_tpmgr_get_state_cb(tls->base.tpmgr); 
    10521052    if (state_cb) { 
    10531053        pjsip_transport_state_info state_info; 
     
    14671467 
    14681468    /* Notify transport state to application */ 
    1469     state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr); 
     1469    state_cb = pjsip_tpmgr_get_state_cb(tls->base.tpmgr); 
    14701470    if (state_cb) { 
    14711471        pjsip_transport_state_info state_info; 
  • pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c

    r3128 r3138  
    18901890 
    18911891        tpmgr = pjsip_endpt_get_tpmgr(pjsua_var.endpt); 
    1892         tpcb = pjsip_tpmgr_get_status_cb(tpmgr); 
     1892        tpcb = pjsip_tpmgr_get_state_cb(tpmgr); 
    18931893 
    18941894        if (tpcb != &on_tp_state_callback) { 
    18951895            pjsua_var.old_tp_cb = tpcb; 
    1896             pjsip_tpmgr_set_status_cb(tpmgr, &on_tp_state_callback); 
     1896            pjsip_tpmgr_set_state_cb(tpmgr, &on_tp_state_callback); 
    18971897        } 
    18981898    } 
Note: See TracChangeset for help on using the changeset viewer.