Changeset 3138 for pjproject/trunk/pjsip/src/pjsip/sip_transport.c
- Timestamp:
- Apr 14, 2010 6:57:35 AM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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 }
Note: See TracChangeset
for help on using the changeset viewer.