- Timestamp:
- Jun 3, 2010 10:41:32 AM (14 years ago)
- Location:
- pjproject/trunk/pjsip
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjsip/include/pjsip/sip_dialog.h
r3068 r3196 91 91 92 92 /** 93 * Dialog capability status. 94 */ 95 typedef enum pjsip_dialog_cap_status 96 { 97 /** Capability is unsupported. */ 98 PJSIP_DIALOG_CAP_UNSUPPORTED = 0, 99 100 /** Capability is supported */ 101 PJSIP_DIALOG_CAP_SUPPORTED = 1, 102 103 /** 104 * Unknown capability status. This is usually because we lack the 105 * capability info which is retrieved from capability header specified 106 * in the dialog messages. 107 */ 108 PJSIP_DIALOG_CAP_UNKNOWN = 2 109 } pjsip_dialog_cap_status; 110 111 112 /** 93 113 * This structure describes the dialog structure. Application MUST NOT 94 114 * try to SET the values here directly, but instead it MUST use the … … 128 148 pjsip_dlg_party local; /**< Local party info. */ 129 149 pjsip_dlg_party remote; /**< Remote party info. */ 150 pjsip_hdr rem_cap_hdr;/**< List of remote capability header. */ 130 151 pjsip_role_e role; /**< Initial role. */ 131 152 pj_bool_t uac_has_2xx;/**< UAC has received 2xx response? */ … … 613 634 614 635 /** 636 * Check if remote peer have the specified capability as published 637 * in the dialog messages from remote peer. 638 * 639 * Notes: 640 * - The capability \a token lookup will apply exact match, but not 641 * case-sensitive, for example: <tt>"text/html"</tt> will not match 642 * <tt>"text / html"</tt> (notice the spaces). 643 * 644 * @param dlg The dialog. 645 * @param htype The header type to be checked, which value may be: 646 * - PJSIP_H_ACCEPT 647 * - PJSIP_H_ALLOW 648 * - PJSIP_H_SUPPORTED 649 * @param hname If htype specifies PJSIP_H_OTHER, then the header name 650 * must be supplied in this argument. Otherwise the value 651 * must be set to NULL. 652 * @param token The capability token to check. For example, if \a htype 653 * is PJSIP_H_ALLOW, then \a token specifies the method 654 * names; if \a htype is PJSIP_H_SUPPORTED, then \a token 655 * specifies the extension names such as "100rel". 656 * 657 * @return PJSIP_DIALOG_CAP_SUPPORTED if the specified capability 658 * is explicitly supported, see @pjsip_dialog_cap_status 659 * for more info. 660 */ 661 PJ_DECL(pjsip_dialog_cap_status) pjsip_dlg_remote_has_cap( 662 pjsip_dialog *dlg, 663 int htype, 664 const pj_str_t *hname, 665 const pj_str_t *token); 666 667 /** 668 * Get the specified capability header from the remote capability headers 669 * stored in the dialog. 670 * 671 * @param dlg The dialog. 672 * @param htype The header type to be retrieved, which value may be: 673 * - PJSIP_H_ACCEPT 674 * - PJSIP_H_ALLOW 675 * - PJSIP_H_SUPPORTED 676 * @param hname If htype specifies PJSIP_H_OTHER, then the header name 677 * must be supplied in this argument. Otherwise the value 678 * must be set to NULL. 679 * 680 * @return The appropriate header, or NULL if the header is not 681 * available. 682 */ 683 PJ_DECL(const pjsip_hdr*) pjsip_dlg_get_remote_cap_hdr(pjsip_dialog *dlg, 684 int htype, 685 const pj_str_t *hname); 686 687 /** 688 * Set remote capability from a SIP header containing array of capability 689 * tags/values. 690 * 691 * @param dlg The dialog. 692 * @param cap_hdr The SIP header. 693 * 694 * @return PJ_SUCCESS when successful, otherwise the appropriate 695 * error code will be returned. 696 */ 697 PJ_DECL(pj_status_t) pjsip_dlg_set_remote_cap_hdr( 698 pjsip_dialog *dlg, 699 const pjsip_generic_array_hdr *cap_hdr); 700 701 /** 702 * Remove a remote capability header. 703 * 704 * @param dlg The dialog. 705 * @param htype The header type to be removed, which value may be: 706 * - PJSIP_H_ACCEPT 707 * - PJSIP_H_ALLOW 708 * - PJSIP_H_SUPPORTED 709 * @param hname If htype specifies PJSIP_H_OTHER, then the header name 710 * must be supplied in this argument. Otherwise the value 711 * must be set to NULL. 712 * 713 * @return PJ_SUCCESS when successful, otherwise the appropriate 714 * error code will be returned. 715 */ 716 PJ_DECL(pj_status_t) pjsip_dlg_remove_remote_cap_hdr(pjsip_dialog *dlg, 717 int htype, 718 const pj_str_t *hname); 719 720 /** 721 * Update remote capabilities from a received message. The header types 722 * to be updated from the message will only be \a PJSIP_H_ACCEPT, 723 * \a PJSIP_H_ALLOW, and \a PJSIP_H_SUPPORTED. 724 * 725 * @param dlg The dialog. 726 * @param msg The received message. 727 * @param strict If this is set to PJ_TRUE, any header types missing 728 * from the message will cause removal of existing 729 * header types in the capability list. Otherwise, the 730 * capability list will not be modified when any header 731 * type is missing. 732 * 733 * @return PJ_SUCCESS when successful, otherwise the appropriate 734 * error code will be returned. 735 */ 736 PJ_DECL(pj_status_t) pjsip_dlg_update_remote_cap(pjsip_dialog *dlg, 737 const pjsip_msg *msg, 738 pj_bool_t strict); 739 740 741 742 /** 615 743 * @} 616 744 */ -
pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
r3172 r3196 2821 2821 pjsua_call_info *info); 2822 2822 2823 /** 2824 * Check if remote peer support the specified capability. 2825 * 2826 * @param call_id Call identification. 2827 * @param htype The header type to be checked, which value may be: 2828 * - PJSIP_H_ACCEPT 2829 * - PJSIP_H_ALLOW 2830 * - PJSIP_H_SUPPORTED 2831 * @param hname If htype specifies PJSIP_H_OTHER, then the header 2832 * name must be supplied in this argument. Otherwise the 2833 * value must be set to NULL. 2834 * @param token The capability token to check. For example, if \a 2835 * htype is PJSIP_H_ALLOW, then \a token specifies the 2836 * method names; if \a htype is PJSIP_H_SUPPORTED, then 2837 * \a token specifies the extension names such as 2838 * "100rel". 2839 * 2840 * @return PJSIP_DIALOG_CAP_SUPPORTED if the specified capability 2841 * is explicitly supported, see @pjsip_dialog_cap_status 2842 * for more info. 2843 */ 2844 PJ_DECL(pjsip_dialog_cap_status) pjsua_call_remote_has_cap( 2845 pjsua_call_id call_id, 2846 int htype, 2847 const pj_str_t *hname, 2848 const pj_str_t *token); 2823 2849 2824 2850 /** -
pjproject/trunk/pjsip/src/pjsip/sip_dialog.c
r3190 r3196 47 47 static const pj_str_t HCONTACT = { "Contact", 7 }; 48 48 49 49 50 PJ_DEF(pj_bool_t) pjsip_method_creates_dialog(const pjsip_method *m) 50 51 { … … 90 91 91 92 pj_list_init(&dlg->inv_hdr); 93 pj_list_init(&dlg->rem_cap_hdr); 92 94 93 95 status = pj_mutex_create_recursive(pool, dlg->obj_name, &dlg->mutex_); … … 523 525 dlg->remote.tag_hval = pj_hash_calc(0, dlg->remote.info->tag.ptr, 524 526 dlg->remote.info->tag.slen); 527 528 /* Update remote capabilities info */ 529 pjsip_dlg_update_remote_cap(dlg, rdata->msg_info.msg, PJ_TRUE); 525 530 526 531 /* Register this dialog to user agent. */ … … 1775 1780 pjsip_contact_hdr *contact; 1776 1781 1782 /* Update remote capability info, when To tags in the dialog remote 1783 * info and the incoming response are different, e.g: first response 1784 * with To-tag or forking, apply strict update. 1785 */ 1786 pjsip_dlg_update_remote_cap(dlg, rdata->msg_info.msg, 1787 pj_strcmp(&dlg->remote.info->tag, 1788 &rdata->msg_info.to->tag)); 1789 1777 1790 /* Update To tag. */ 1778 1791 pj_strdup(dlg->pool, &dlg->remote.info->tag, &rdata->msg_info.to->tag); 1779 1792 /* No need to update remote's tag_hval since its never used. */ 1780 1781 1793 1782 1794 /* RFC 3271 Section 12.1.2: … … 1860 1872 dlg_update_routeset(dlg, rdata); 1861 1873 } 1862 1863 1874 1864 1875 /* Pass to dialog usages. */ … … 1963 1974 } 1964 1975 1976 1977 /* 1978 * Check if the specified capability is supported by remote. 1979 */ 1980 PJ_DEF(pjsip_dialog_cap_status) pjsip_dlg_remote_has_cap( 1981 pjsip_dialog *dlg, 1982 int htype, 1983 const pj_str_t *hname, 1984 const pj_str_t *token) 1985 { 1986 const pjsip_generic_array_hdr *hdr; 1987 pjsip_dialog_cap_status cap_status = PJSIP_DIALOG_CAP_UNSUPPORTED; 1988 unsigned i; 1989 1990 PJ_ASSERT_RETURN(dlg && token, PJ_FALSE); 1991 1992 pjsip_dlg_inc_lock(dlg); 1993 1994 hdr = (const pjsip_generic_array_hdr*) 1995 pjsip_dlg_get_remote_cap_hdr(dlg, htype, hname); 1996 if (!hdr) { 1997 cap_status = PJSIP_DIALOG_CAP_UNKNOWN; 1998 } else { 1999 for (i=0; i<hdr->count; ++i) { 2000 if (!pj_stricmp(&hdr->values[i], token)) { 2001 cap_status = PJSIP_DIALOG_CAP_SUPPORTED; 2002 break; 2003 } 2004 } 2005 } 2006 2007 pjsip_dlg_dec_lock(dlg); 2008 2009 return cap_status; 2010 } 2011 2012 2013 /* 2014 * Update remote capability of ACCEPT, ALLOW, and SUPPORTED from 2015 * the received message. 2016 */ 2017 PJ_DEF(pj_status_t) pjsip_dlg_update_remote_cap(pjsip_dialog *dlg, 2018 const pjsip_msg *msg, 2019 pj_bool_t strict) 2020 { 2021 pjsip_hdr_e htypes[] = 2022 { PJSIP_H_ACCEPT, PJSIP_H_ALLOW, PJSIP_H_SUPPORTED }; 2023 unsigned i; 2024 2025 PJ_ASSERT_RETURN(dlg && msg, PJ_EINVAL); 2026 2027 pjsip_dlg_inc_lock(dlg); 2028 2029 /* Retrieve all specified capability header types */ 2030 for (i = 0; i < PJ_ARRAY_SIZE(htypes); ++i) { 2031 const pjsip_generic_array_hdr *hdr; 2032 pj_status_t status; 2033 2034 /* Find this capability type in the message */ 2035 hdr = (const pjsip_generic_array_hdr*) 2036 pjsip_msg_find_hdr(msg, htypes[i], NULL); 2037 if (!hdr) { 2038 /* Not found. 2039 * If strict update is specified, remote this capability type 2040 * from the capability list. 2041 */ 2042 if (strict) 2043 pjsip_dlg_remove_remote_cap_hdr(dlg, htypes[i], NULL); 2044 } else { 2045 /* Found, a capability type may be specified in multiple headers, 2046 * so combine all the capability tags/values into a temporary 2047 * header. 2048 */ 2049 pjsip_generic_array_hdr tmp_hdr; 2050 2051 /* Init temporary header */ 2052 pjsip_generic_array_hdr_init(dlg->pool, &tmp_hdr, NULL); 2053 pj_memcpy(&tmp_hdr, hdr, sizeof(pjsip_hdr)); 2054 2055 while (hdr) { 2056 unsigned j; 2057 2058 /* Append the header content to temporary header */ 2059 for(j=0; j<hdr->count && 2060 tmp_hdr.count<PJSIP_GENERIC_ARRAY_MAX_COUNT; ++j) 2061 { 2062 tmp_hdr.values[tmp_hdr.count++] = hdr->values[j]; 2063 } 2064 2065 /* Get the next header for this capability */ 2066 hdr = (const pjsip_generic_array_hdr*) 2067 pjsip_msg_find_hdr(msg, htypes[i], hdr->next); 2068 } 2069 2070 /* Save this capability */ 2071 status = pjsip_dlg_set_remote_cap_hdr(dlg, &tmp_hdr); 2072 if (status != PJ_SUCCESS) { 2073 pjsip_dlg_dec_lock(dlg); 2074 return status; 2075 } 2076 } 2077 } 2078 2079 pjsip_dlg_dec_lock(dlg); 2080 2081 return PJ_SUCCESS; 2082 } 2083 2084 2085 /* 2086 * Get the value of the specified capability header field of remote. 2087 */ 2088 PJ_DEF(const pjsip_hdr*) pjsip_dlg_get_remote_cap_hdr(pjsip_dialog *dlg, 2089 int htype, 2090 const pj_str_t *hname) 2091 { 2092 pjsip_hdr *hdr; 2093 2094 /* Check arguments. */ 2095 PJ_ASSERT_RETURN(dlg, NULL); 2096 PJ_ASSERT_RETURN((htype != PJSIP_H_OTHER) || (hname && hname->slen), 2097 NULL); 2098 2099 pjsip_dlg_inc_lock(dlg); 2100 2101 hdr = dlg->rem_cap_hdr.next; 2102 while (hdr != &dlg->rem_cap_hdr) { 2103 if ((htype != PJSIP_H_OTHER && htype == hdr->type) || 2104 (htype == PJSIP_H_OTHER && pj_stricmp(&hdr->name, hname) == 0)) 2105 { 2106 pjsip_dlg_dec_lock(dlg); 2107 return hdr; 2108 } 2109 hdr = hdr->next; 2110 } 2111 2112 pjsip_dlg_dec_lock(dlg); 2113 2114 return NULL; 2115 } 2116 2117 2118 /* 2119 * Set remote capability header from a SIP header containing array 2120 * of capability tags/values. 2121 */ 2122 PJ_DEF(pj_status_t) pjsip_dlg_set_remote_cap_hdr( 2123 pjsip_dialog *dlg, 2124 const pjsip_generic_array_hdr *cap_hdr) 2125 { 2126 pjsip_generic_array_hdr *hdr; 2127 2128 /* Check arguments. */ 2129 PJ_ASSERT_RETURN(dlg && cap_hdr, PJ_EINVAL); 2130 2131 pjsip_dlg_inc_lock(dlg); 2132 2133 /* Find the header. */ 2134 hdr = (pjsip_generic_array_hdr*) 2135 pjsip_dlg_get_remote_cap_hdr(dlg, cap_hdr->type, &cap_hdr->name); 2136 2137 /* Quick compare if the capability is up to date */ 2138 if (hdr && hdr->count == cap_hdr->count) { 2139 unsigned i; 2140 pj_bool_t uptodate = PJ_TRUE; 2141 2142 for (i=0; i<hdr->count; ++i) { 2143 if (pj_stricmp(&hdr->values[i], &cap_hdr->values[i])) 2144 uptodate = PJ_FALSE; 2145 } 2146 2147 /* Capability is up to date, just return PJ_SUCCESS */ 2148 if (uptodate) { 2149 pjsip_dlg_dec_lock(dlg); 2150 return PJ_SUCCESS; 2151 } 2152 } 2153 2154 /* Remove existing capability header if any */ 2155 if (hdr) 2156 pj_list_erase(hdr); 2157 2158 /* Add the new capability header */ 2159 hdr = (pjsip_generic_array_hdr*) pjsip_hdr_clone(dlg->pool, cap_hdr); 2160 hdr->type = cap_hdr->type; 2161 pj_strdup(dlg->pool, &hdr->name, &cap_hdr->name); 2162 pj_list_push_back(&dlg->rem_cap_hdr, hdr); 2163 2164 pjsip_dlg_dec_lock(dlg); 2165 2166 /* Done. */ 2167 return PJ_SUCCESS; 2168 } 2169 2170 /* 2171 * Remove a remote capability header. 2172 */ 2173 PJ_DEF(pj_status_t) pjsip_dlg_remove_remote_cap_hdr(pjsip_dialog *dlg, 2174 int htype, 2175 const pj_str_t *hname) 2176 { 2177 pjsip_generic_array_hdr *hdr; 2178 2179 /* Check arguments. */ 2180 PJ_ASSERT_RETURN(dlg, PJ_EINVAL); 2181 PJ_ASSERT_RETURN((htype != PJSIP_H_OTHER) || (hname && hname->slen), 2182 PJ_EINVAL); 2183 2184 pjsip_dlg_inc_lock(dlg); 2185 2186 hdr = (pjsip_generic_array_hdr*) 2187 pjsip_dlg_get_remote_cap_hdr(dlg, htype, hname); 2188 if (!hdr) { 2189 pjsip_dlg_dec_lock(dlg); 2190 return PJ_ENOTFOUND; 2191 } 2192 2193 pj_list_erase(hdr); 2194 2195 pjsip_dlg_dec_lock(dlg); 2196 2197 return PJ_SUCCESS; 2198 } -
pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
r3013 r3196 1321 1321 1322 1322 return PJ_SUCCESS; 1323 } 1324 1325 /* 1326 * Check if call remote peer support the specified capability. 1327 */ 1328 PJ_DEF(pjsip_dialog_cap_status) pjsua_call_remote_has_cap( 1329 pjsua_call_id call_id, 1330 int htype, 1331 const pj_str_t *hname, 1332 const pj_str_t *token) 1333 { 1334 pjsua_call *call; 1335 pjsip_dialog *dlg; 1336 pj_status_t status; 1337 pjsip_dialog_cap_status cap_status; 1338 1339 status = acquire_call("pjsua_call_peer_has_cap()", call_id, &call, &dlg); 1340 if (status != PJ_SUCCESS) 1341 return PJSIP_DIALOG_CAP_UNKNOWN; 1342 1343 cap_status = pjsip_dlg_remote_has_cap(dlg, htype, hname, token); 1344 1345 pjsip_dlg_dec_lock(dlg); 1346 1347 return cap_status; 1323 1348 } 1324 1349
Note: See TracChangeset
for help on using the changeset viewer.