Ignore:
Timestamp:
Jun 3, 2010 10:41:32 AM (14 years ago)
Author:
nanang
Message:

Re #1089:

  • Added a feature in dialog to store and retrieve remote capabilities dug from the remote messages.
  • Added few APIs in dialog to query and update remote capabilities, also added an API in pjsua_call to query whether a capability is supported by remote.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip/sip_dialog.c

    r3190 r3196  
    4747static const pj_str_t HCONTACT = { "Contact", 7 }; 
    4848 
     49 
    4950PJ_DEF(pj_bool_t) pjsip_method_creates_dialog(const pjsip_method *m) 
    5051{ 
     
    9091 
    9192    pj_list_init(&dlg->inv_hdr); 
     93    pj_list_init(&dlg->rem_cap_hdr); 
    9294 
    9395    status = pj_mutex_create_recursive(pool, dlg->obj_name, &dlg->mutex_); 
     
    523525    dlg->remote.tag_hval = pj_hash_calc(0, dlg->remote.info->tag.ptr,  
    524526                                        dlg->remote.info->tag.slen); 
     527 
     528    /* Update remote capabilities info */ 
     529    pjsip_dlg_update_remote_cap(dlg, rdata->msg_info.msg, PJ_TRUE); 
    525530 
    526531    /* Register this dialog to user agent. */ 
     
    17751780        pjsip_contact_hdr *contact; 
    17761781 
     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 
    17771790        /* Update To tag. */ 
    17781791        pj_strdup(dlg->pool, &dlg->remote.info->tag, &rdata->msg_info.to->tag); 
    17791792        /* No need to update remote's tag_hval since its never used. */ 
    1780  
    17811793 
    17821794        /* RFC 3271 Section 12.1.2: 
     
    18601872        dlg_update_routeset(dlg, rdata); 
    18611873    } 
    1862  
    18631874 
    18641875    /* Pass to dialog usages. */ 
     
    19631974} 
    19641975 
     1976 
     1977/* 
     1978 * Check if the specified capability is supported by remote. 
     1979 */ 
     1980PJ_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 */ 
     2017PJ_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 */ 
     2088PJ_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 */ 
     2122PJ_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 */ 
     2173PJ_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} 
Note: See TracChangeset for help on using the changeset viewer.