Changeset 3138
- Timestamp:
- Apr 14, 2010 6:57:35 AM (13 years ago)
- Location:
- pjproject/trunk/pjsip
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/include/pjsip/sip_transaction.h
r3071 r3138 125 125 pending transport flag 126 126 to be set on tsx. */ 127 pjsip_tp_state_listener_key *tp_st_key; /**< Transport state listener 128 key. */ 127 129 128 130 /* -
pjproject/trunk/pjsip/include/pjsip/sip_transport.h
r3119 r3138 750 750 pjsip_tpmgr *tpmgr; /**< Transport manager. */ 751 751 pj_timer_entry idle_timer; /**< Timer when ref cnt is zero.*/ 752 753 void *data; /**< Internal transport data. */ 752 754 753 755 /** … … 1271 1273 1272 1274 /** 1275 * Definition of transport state listener key. 1276 */ 1277 typedef void pjsip_tp_state_listener_key; 1278 1279 /** 1273 1280 * Structure of transport state info passed by #pjsip_tp_state_callback. 1274 1281 */ … … 1283 1290 */ 1284 1291 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 1285 1299 } pjsip_transport_state_info; 1286 1300 … … 1302 1316 1303 1317 /** 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. 1307 1327 * 1308 1328 * @param mgr Transport manager. 1309 1329 * @param cb Callback to be called to notify caller about transport 1310 * stat uschanging.1330 * state changing. 1311 1331 * 1312 1332 * @return PJ_SUCCESS on success, or the appropriate error code. 1313 1333 */ 1314 PJ_DECL(pj_status_t) pjsip_tpmgr_set_stat us_cb(pjsip_tpmgr *mgr,1315 1316 1317 1318 /** 1319 * Get ting the callback oftransport state notification.1334 PJ_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. 1320 1340 * 1321 1341 * @param mgr Transport manager. … … 1323 1343 * @return The transport state callback or NULL if it is not set. 1324 1344 */ 1325 PJ_DECL(pjsip_tp_state_callback) pjsip_tpmgr_get_status_cb( 1326 const pjsip_tpmgr *mgr); 1345 PJ_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 */ 1360 PJ_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 */ 1377 PJ_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); 1327 1381 1328 1382 -
pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
r3114 r3138 181 181 static void tsx_timer_callback( pj_timer_heap_t *theap, 182 182 pj_timer_entry *entry); 183 static void tsx_tp_state_callback( 184 pjsip_transport *tp, 185 pjsip_transport_state state, 186 const pjsip_transport_state_info *info); 183 187 static pj_status_t tsx_create( pjsip_module *tsx_user, 184 188 pjsip_transaction **p_tsx); … … 188 192 static int tsx_send_msg( pjsip_transaction *tsx, 189 193 pjsip_tx_data *tdata); 194 static void tsx_update_transport( pjsip_transaction *tsx, 195 pjsip_transport *tp); 190 196 191 197 … … 986 992 struct tsx_lock_data *lck; 987 993 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 993 997 /* Decrement reference counter in transport selector */ 994 998 pjsip_tpselector_dec_ref(&tsx->tp_sel); … … 1405 1409 */ 1406 1410 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); 1409 1412 pj_memcpy(&tsx->addr, &tsx->res_addr.addr, tsx->res_addr.addr_len); 1410 1413 tsx->addr_len = tsx->res_addr.addr_len; … … 1676 1679 if (tsx->transport != send_state->cur_transport) { 1677 1680 /* 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); 1684 1682 1685 1683 /* Update remote address. */ … … 1730 1728 * release the transport. 1731 1729 */ 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); 1738 1732 1739 1733 /* Also stop processing if transaction has been flagged with … … 1837 1831 lock_tsx(tsx, &lck); 1838 1832 1839 /* Dereference transport. */ 1840 pjsip_transport_dec_ref(tsx->transport); 1841 tsx->transport = NULL; 1833 /* Release transport. */ 1834 tsx_update_transport(tsx, NULL); 1842 1835 1843 1836 /* Terminate transaction. */ … … 1849 1842 } 1850 1843 } 1844 1845 1846 /* 1847 * Callback when transport state changes. 1848 */ 1849 static 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 1851 1878 1852 1879 /* … … 1887 1914 * resolution procedure. 1888 1915 */ 1889 if (tsx->transport) { 1890 pjsip_transport_dec_ref(tsx->transport); 1891 tsx->transport = NULL; 1892 } 1916 tsx_update_transport(tsx, NULL); 1917 1893 1918 tsx->addr_len = 0; 1894 1919 tsx->res_addr.transport = NULL; … … 2096 2121 2097 2122 return PJ_SUCCESS; 2123 } 2124 2125 static 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 } 2098 2143 } 2099 2144 -
pjproject/trunk/pjsip/src/pjsip/sip_transport.c
r3119 r3138 34 34 #include <pj/assert.h> 35 35 #include <pj/lock.h> 36 #include <pj/list.h> 36 37 37 38 … … 91 92 pj_status_t (*on_tx_msg)(pjsip_endpoint*, pjsip_tx_data*); 92 93 pjsip_tp_state_callback tp_state_cb; 93 void *tp_state_user_data;94 94 }; 95 96 97 /* Transport state listener list type */ 98 typedef 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 */ 110 typedef struct transport_data 111 { 112 /* Transport listeners */ 113 tp_state_listener st_listeners; 114 tp_state_listener st_listeners_empty; 115 } transport_data; 95 116 96 117 … … 179 200 }; 180 201 202 static void tp_state_callback(pjsip_transport *tp, 203 pjsip_transport_state state, 204 const pjsip_transport_state_info *info); 205 206 181 207 struct transport_names_t *get_tpname(pjsip_transport_type_e type) 182 208 { … … 1092 1118 #endif 1093 1119 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 1094 1125 PJ_LOG(5, (THIS_FILE, "Transport manager created.")); 1095 1126 … … 1738 1769 } 1739 1770 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 */ 1774 PJ_DEF(pj_status_t) pjsip_tpmgr_set_state_cb(pjsip_tpmgr *mgr, 1775 pjsip_tp_state_callback cb) 1742 1776 { 1743 1777 PJ_ASSERT_RETURN(mgr, PJ_EINVAL); … … 1748 1782 } 1749 1783 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 */ 1787 PJ_DEF(pjsip_tp_state_callback) pjsip_tpmgr_get_state_cb( 1788 const pjsip_tpmgr *mgr) 1752 1789 { 1753 1790 PJ_ASSERT_RETURN(mgr, NULL); … … 1755 1792 return mgr->tp_state_cb; 1756 1793 } 1794 1795 1796 /** 1797 * Allocate and init transport data. 1798 */ 1799 static 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 1812 static 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 1841 on_return: 1842 pj_lock_release(tp->lock); 1843 } 1844 1845 1846 /** 1847 * Add a listener to the specified transport for transport state notification. 1848 */ 1849 PJ_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 */ 1894 PJ_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 185 185 186 186 /* Notify application of transport disconnected state */ 187 state_cb = pjsip_tpmgr_get_stat us_cb(tcp->base.tpmgr);187 state_cb = pjsip_tpmgr_get_state_cb(tcp->base.tpmgr); 188 188 if (state_cb) { 189 189 pjsip_transport_state_info state_info; … … 1010 1010 1011 1011 /* Notify application of transport state accepted */ 1012 state_cb = pjsip_tpmgr_get_stat us_cb(tcp->base.tpmgr);1012 state_cb = pjsip_tpmgr_get_state_cb(tcp->base.tpmgr); 1013 1013 if (state_cb) { 1014 1014 pjsip_transport_state_info state_info; … … 1337 1337 1338 1338 /* Notify application of transport state connected */ 1339 state_cb = pjsip_tpmgr_get_stat us_cb(tcp->base.tpmgr);1339 state_cb = pjsip_tpmgr_get_state_cb(tcp->base.tpmgr); 1340 1340 if (state_cb) { 1341 1341 pjsip_transport_state_info state_info; -
pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c
r3128 r3138 192 192 193 193 /* Notify application of transport disconnected state */ 194 state_cb = pjsip_tpmgr_get_stat us_cb(tls->base.tpmgr);194 state_cb = pjsip_tpmgr_get_state_cb(tls->base.tpmgr); 195 195 if (state_cb) { 196 196 pjsip_transport_state_info state_info; … … 1049 1049 1050 1050 /* Notify transport state to application */ 1051 state_cb = pjsip_tpmgr_get_stat us_cb(tls->base.tpmgr);1051 state_cb = pjsip_tpmgr_get_state_cb(tls->base.tpmgr); 1052 1052 if (state_cb) { 1053 1053 pjsip_transport_state_info state_info; … … 1467 1467 1468 1468 /* Notify transport state to application */ 1469 state_cb = pjsip_tpmgr_get_stat us_cb(tls->base.tpmgr);1469 state_cb = pjsip_tpmgr_get_state_cb(tls->base.tpmgr); 1470 1470 if (state_cb) { 1471 1471 pjsip_transport_state_info state_info; -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
r3128 r3138 1890 1890 1891 1891 tpmgr = pjsip_endpt_get_tpmgr(pjsua_var.endpt); 1892 tpcb = pjsip_tpmgr_get_stat us_cb(tpmgr);1892 tpcb = pjsip_tpmgr_get_state_cb(tpmgr); 1893 1893 1894 1894 if (tpcb != &on_tp_state_callback) { 1895 1895 pjsua_var.old_tp_cb = tpcb; 1896 pjsip_tpmgr_set_stat us_cb(tpmgr, &on_tp_state_callback);1896 pjsip_tpmgr_set_state_cb(tpmgr, &on_tp_state_callback); 1897 1897 } 1898 1898 }
Note: See TracChangeset
for help on using the changeset viewer.