Ignore:
Timestamp:
Mar 19, 2008 11:00:30 PM (16 years ago)
Author:
bennylp
Message:

Related to ticket #485: huge changeset to update STUN relating to managing authentication. See the ticket for the details

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjnath/src/pjnath/stun_msg.c

    r1852 r1877  
    2121#include <pjlib-util/crc32.h> 
    2222#include <pjlib-util/hmac_sha1.h> 
    23 #include <pjlib-util/md5.h> 
    2423#include <pj/assert.h> 
    2524#include <pj/log.h> 
     
    9190    pj_status_t (*encode_attr)(const void *a, pj_uint8_t *buf,  
    9291                               unsigned len, unsigned *printed); 
     92    void*       (*clone_attr)(pj_pool_t *pool, const void *src); 
    9393}; 
    9494 
     
    102102                                       unsigned len,  
    103103                                       unsigned *printed); 
     104static void*       clone_sockaddr_attr(pj_pool_t *pool, const void *src); 
    104105static pj_status_t decode_string_attr(pj_pool_t *pool,  
    105106                                      const pj_uint8_t *buf,  
     
    107108static pj_status_t encode_string_attr(const void *a, pj_uint8_t *buf,  
    108109                                      unsigned len, unsigned *printed); 
     110static void*       clone_string_attr(pj_pool_t *pool, const void *src); 
    109111static pj_status_t decode_msgint_attr(pj_pool_t *pool,  
    110112                                      const pj_uint8_t *buf, 
     
    112114static pj_status_t encode_msgint_attr(const void *a, pj_uint8_t *buf,  
    113115                                      unsigned len, unsigned *printed); 
     116static void*       clone_msgint_attr(pj_pool_t *pool, const void *src); 
    114117static pj_status_t decode_errcode_attr(pj_pool_t *pool,  
    115118                                       const pj_uint8_t *buf, 
     
    117120static pj_status_t encode_errcode_attr(const void *a, pj_uint8_t *buf,  
    118121                                       unsigned len, unsigned *printed); 
     122static void*       clone_errcode_attr(pj_pool_t *pool, const void *src); 
    119123static pj_status_t decode_unknown_attr(pj_pool_t *pool,  
    120124                                       const pj_uint8_t *buf,  
     
    122126static pj_status_t encode_unknown_attr(const void *a, pj_uint8_t *buf,  
    123127                                       unsigned len, unsigned *printed); 
     128static void*       clone_unknown_attr(pj_pool_t *pool, const void *src); 
    124129static pj_status_t decode_uint_attr(pj_pool_t *pool,  
    125130                                    const pj_uint8_t *buf,  
     
    127132static pj_status_t encode_uint_attr(const void *a, pj_uint8_t *buf,  
    128133                                    unsigned len, unsigned *printed); 
     134static void*       clone_uint_attr(pj_pool_t *pool, const void *src); 
    129135static pj_status_t decode_uint64_attr(pj_pool_t *pool,  
    130136                                      const pj_uint8_t *buf,  
     
    132138static pj_status_t encode_uint64_attr(const void *a, pj_uint8_t *buf,  
    133139                                      unsigned len, unsigned *printed); 
     140static void*       clone_uint64_attr(pj_pool_t *pool, const void *src); 
    134141static pj_status_t decode_binary_attr(pj_pool_t *pool,  
    135142                                      const pj_uint8_t *buf, 
     
    137144static pj_status_t encode_binary_attr(const void *a, pj_uint8_t *buf,  
    138145                                      unsigned len, unsigned *printed); 
     146static void*       clone_binary_attr(pj_pool_t *pool, const void *src); 
    139147static pj_status_t decode_empty_attr(pj_pool_t *pool,  
    140148                                     const pj_uint8_t *buf,  
     
    142150static pj_status_t encode_empty_attr(const void *a, pj_uint8_t *buf,  
    143151                                     unsigned len, unsigned *printed); 
    144  
     152static void*       clone_empty_attr(pj_pool_t *pool, const void *src); 
    145153 
    146154static struct attr_desc mandatory_attr_desc[] =  
     
    148156    { 
    149157        /* type zero */ 
     158        NULL, 
    150159        NULL, 
    151160        NULL, 
     
    156165        "MAPPED-ADDRESS", 
    157166        &decode_sockaddr_attr, 
    158         &encode_sockaddr_attr 
     167        &encode_sockaddr_attr, 
     168        &clone_sockaddr_attr 
    159169    }, 
    160170    { 
     
    162172        "RESPONSE-ADDRESS", 
    163173        &decode_sockaddr_attr, 
    164         &encode_sockaddr_attr 
     174        &encode_sockaddr_attr, 
     175        &clone_sockaddr_attr 
    165176    }, 
    166177    { 
     
    168179        "CHANGE-REQUEST", 
    169180        &decode_uint_attr, 
    170         &encode_uint_attr 
     181        &encode_uint_attr, 
     182        &clone_uint_attr 
    171183    }, 
    172184    { 
     
    174186        "SOURCE-ADDRESS", 
    175187        &decode_sockaddr_attr, 
    176         &encode_sockaddr_attr 
     188        &encode_sockaddr_attr, 
     189        &clone_sockaddr_attr 
    177190    }, 
    178191    { 
     
    180193        "CHANGED-ADDRESS", 
    181194        &decode_sockaddr_attr, 
    182         &encode_sockaddr_attr 
     195        &encode_sockaddr_attr, 
     196        &clone_sockaddr_attr 
    183197    }, 
    184198    { 
     
    186200        "USERNAME", 
    187201        &decode_string_attr, 
    188         &encode_string_attr 
     202        &encode_string_attr, 
     203        &clone_string_attr 
    189204    }, 
    190205    { 
     
    192207        "PASSWORD", 
    193208        &decode_string_attr, 
    194         &encode_string_attr 
     209        &encode_string_attr, 
     210        &clone_string_attr 
    195211    }, 
    196212    { 
     
    198214        "MESSAGE-INTEGRITY", 
    199215        &decode_msgint_attr, 
    200         &encode_msgint_attr 
     216        &encode_msgint_attr, 
     217        &clone_msgint_attr 
    201218    }, 
    202219    { 
     
    204221        "ERROR-CODE", 
    205222        &decode_errcode_attr, 
    206         &encode_errcode_attr 
     223        &encode_errcode_attr, 
     224        &clone_errcode_attr 
    207225    }, 
    208226    { 
     
    210228        "UNKNOWN-ATTRIBUTES", 
    211229        &decode_unknown_attr, 
    212         &encode_unknown_attr 
     230        &encode_unknown_attr, 
     231        &clone_unknown_attr 
    213232    }, 
    214233    { 
     
    216235        "REFLECTED-FROM", 
    217236        &decode_sockaddr_attr, 
    218         &encode_sockaddr_attr 
     237        &encode_sockaddr_attr, 
     238        &clone_sockaddr_attr 
    219239    }, 
    220240    { 
     
    222242        "CHANNEL-NUMBER", 
    223243        &decode_uint_attr, 
    224         &encode_uint_attr 
     244        &encode_uint_attr, 
     245        &clone_uint_attr 
    225246    }, 
    226247    { 
     
    228249        "LIFETIME", 
    229250        &decode_uint_attr, 
    230         &encode_uint_attr 
     251        &encode_uint_attr, 
     252        &clone_uint_attr 
    231253    }, 
    232254    { 
    233255        /* ID 0x000E is not assigned */ 
     256        NULL, 
    234257        NULL, 
    235258        NULL, 
     
    240263        "MAGIC-COOKIE", 
    241264        &decode_uint_attr, 
    242         &encode_uint_attr 
     265        &encode_uint_attr, 
     266        &clone_uint_attr 
    243267    }, 
    244268    { 
     
    246270        "BANDWIDTH", 
    247271        &decode_uint_attr, 
    248         &encode_uint_attr 
     272        &encode_uint_attr, 
     273        &clone_uint_attr 
    249274    }, 
    250275    { 
    251276        /* ID 0x0011 is not assigned */ 
     277        NULL, 
    252278        NULL, 
    253279        NULL, 
     
    258284        "PEER-ADDRESS", 
    259285        &decode_xored_sockaddr_attr, 
    260         &encode_sockaddr_attr 
     286        &encode_sockaddr_attr, 
     287        &clone_sockaddr_attr 
    261288    }, 
    262289    { 
     
    264291        "DATA", 
    265292        &decode_binary_attr, 
    266         &encode_binary_attr 
     293        &encode_binary_attr, 
     294        &clone_binary_attr 
    267295    }, 
    268296    { 
     
    270298        "REALM", 
    271299        &decode_string_attr, 
    272         &encode_string_attr 
     300        &encode_string_attr, 
     301        &clone_string_attr 
    273302    }, 
    274303    { 
     
    276305        "NONCE", 
    277306        &decode_string_attr, 
    278         &encode_string_attr 
     307        &encode_string_attr, 
     308        &clone_string_attr 
    279309    }, 
    280310    { 
     
    282312        "RELAY-ADDRESS", 
    283313        &decode_xored_sockaddr_attr, 
    284         &encode_sockaddr_attr 
     314        &encode_sockaddr_attr, 
     315        &clone_sockaddr_attr 
    285316    }, 
    286317    { 
     
    288319        "REQUESTED-ADDRESS-TYPE", 
    289320        &decode_uint_attr, 
    290         &encode_uint_attr 
     321        &encode_uint_attr, 
     322        &clone_uint_attr 
    291323    }, 
    292324    { 
     
    294326        "REQUESTED-PROPS", 
    295327        &decode_uint_attr, 
    296         &encode_uint_attr 
     328        &encode_uint_attr, 
     329        &clone_uint_attr 
    297330    }, 
    298331    { 
     
    300333        "REQUESTED-TRANSPORT", 
    301334        &decode_uint_attr, 
    302         &encode_uint_attr 
     335        &encode_uint_attr, 
     336        &clone_uint_attr 
    303337    }, 
    304338    { 
     
    306340        NULL, 
    307341        NULL, 
     342        NULL, 
    308343        NULL 
    309344    }, 
     
    312347        NULL, 
    313348        NULL, 
     349        NULL, 
    314350        NULL 
    315351    }, 
     
    318354        NULL, 
    319355        NULL, 
     356        NULL, 
    320357        NULL 
    321358    }, 
     
    324361        NULL, 
    325362        NULL, 
     363        NULL, 
    326364        NULL 
    327365    }, 
     
    330368        NULL, 
    331369        NULL, 
     370        NULL, 
    332371        NULL 
    333372    }, 
    334373    { 
    335374        /* ID 0x001F is not assigned */ 
     375        NULL, 
    336376        NULL, 
    337377        NULL, 
     
    342382        "XOR-MAPPED-ADDRESS", 
    343383        &decode_xored_sockaddr_attr, 
    344         &encode_sockaddr_attr 
     384        &encode_sockaddr_attr, 
     385        &clone_sockaddr_attr 
    345386    }, 
    346387    { 
     
    348389        "TIMER-VAL", 
    349390        &decode_uint_attr, 
    350         &encode_uint_attr 
     391        &encode_uint_attr, 
     392        &clone_uint_attr 
    351393    }, 
    352394    { 
     
    354396        "RESERVATION-TOKEN", 
    355397        &decode_uint64_attr, 
    356         &encode_uint64_attr 
     398        &encode_uint64_attr, 
     399        &clone_uint64_attr 
    357400    }, 
    358401    { 
     
    360403        "XOR-REFLECTED-FROM", 
    361404        &decode_xored_sockaddr_attr, 
    362         &encode_sockaddr_attr 
     405        &encode_sockaddr_attr, 
     406        &clone_sockaddr_attr 
    363407    }, 
    364408    { 
     
    366410        "PRIORITY", 
    367411        &decode_uint_attr, 
    368         &encode_uint_attr 
     412        &encode_uint_attr, 
     413        &clone_uint_attr 
    369414    }, 
    370415    { 
     
    372417        "USE-CANDIDATE", 
    373418        &decode_empty_attr, 
    374         &encode_empty_attr 
     419        &encode_empty_attr, 
     420        &clone_empty_attr 
    375421    }, 
    376422    { 
     
    378424        "XOR-INTERNAL-ADDRESS", 
    379425        &decode_xored_sockaddr_attr, 
    380         &encode_sockaddr_attr 
     426        &encode_sockaddr_attr, 
     427        &clone_sockaddr_attr 
    381428    }, 
    382429 
     
    386433        NULL, 
    387434        NULL, 
     435        NULL, 
    388436        NULL 
    389437    } 
     
    394442    { 
    395443        /* ID 0x8021 is not assigned */ 
     444        NULL, 
    396445        NULL, 
    397446        NULL, 
     
    402451        "SERVER", 
    403452        &decode_string_attr, 
    404         &encode_string_attr 
     453        &encode_string_attr, 
     454        &clone_string_attr 
    405455    }, 
    406456    { 
     
    408458        "ALTERNATE-SERVER", 
    409459        &decode_sockaddr_attr, 
    410         &encode_sockaddr_attr 
     460        &encode_sockaddr_attr, 
     461        &clone_sockaddr_attr 
    411462    }, 
    412463    { 
     
    414465        "REFRESH-INTERVAL", 
    415466        &decode_uint_attr, 
    416         &encode_uint_attr 
     467        &encode_uint_attr, 
     468        &clone_uint_attr 
    417469    }, 
    418470    { 
     
    420472        NULL, 
    421473        NULL, 
     474        NULL, 
    422475        NULL 
    423476    }, 
     
    426479        NULL, 
    427480        NULL, 
     481        NULL, 
    428482        NULL 
    429483    }, 
    430484    { 
    431485        /* CACHE-TIMEOUT, 0x8027 */ 
     486        NULL, 
    432487        NULL, 
    433488        NULL, 
     
    438493        "FINGERPRINT", 
    439494        &decode_uint_attr, 
    440         &encode_uint_attr 
     495        &encode_uint_attr, 
     496        &clone_uint_attr 
    441497    }, 
    442498    { 
     
    444500        "ICE-CONTROLLED", 
    445501        &decode_uint64_attr, 
    446         &encode_uint64_attr 
     502        &encode_uint64_attr, 
     503        &clone_uint64_attr 
    447504    }, 
    448505    { 
     
    450507        "ICE-CONTROLLING", 
    451508        &decode_uint64_attr, 
    452         &encode_uint64_attr 
     509        &encode_uint64_attr, 
     510        &clone_uint64_attr 
    453511    } 
    454512}; 
     
    827885 
    828886 
     887static void* clone_sockaddr_attr(pj_pool_t *pool, const void *src) 
     888{ 
     889    pj_stun_sockaddr_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_sockaddr_attr); 
     890    pj_memcpy(dst, src, sizeof(pj_stun_sockaddr_attr)); 
     891    return (void*)dst; 
     892} 
     893 
    829894////////////////////////////////////////////////////////////////////////////// 
    830895/* 
     
    9351000 
    9361001 
     1002static void* clone_string_attr(pj_pool_t *pool, const void *src) 
     1003{ 
     1004    const pj_stun_string_attr *asrc = (const pj_stun_string_attr*)src; 
     1005    pj_stun_string_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_string_attr); 
     1006 
     1007    pj_memcpy(dst, src, sizeof(pj_stun_attr_hdr)); 
     1008    pj_strdup(pool, &dst->value, &asrc->value); 
     1009 
     1010    return (void*)dst; 
     1011} 
     1012 
    9371013////////////////////////////////////////////////////////////////////////////// 
    9381014/* 
     
    10181094} 
    10191095 
     1096 
     1097static void* clone_empty_attr(pj_pool_t *pool, const void *src) 
     1098{ 
     1099    pj_stun_empty_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_empty_attr); 
     1100 
     1101    pj_memcpy(dst, src, sizeof(pj_stun_empty_attr)); 
     1102 
     1103    return (void*) dst; 
     1104} 
    10201105 
    10211106////////////////////////////////////////////////////////////////////////////// 
     
    11041189} 
    11051190 
     1191 
     1192static void* clone_uint_attr(pj_pool_t *pool, const void *src) 
     1193{ 
     1194    pj_stun_uint_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_uint_attr); 
     1195 
     1196    pj_memcpy(dst, src, sizeof(pj_stun_uint_attr)); 
     1197 
     1198    return (void*)dst; 
     1199} 
     1200 
    11061201////////////////////////////////////////////////////////////////////////////// 
    11071202 
     
    11901285 
    11911286 
     1287static void* clone_uint64_attr(pj_pool_t *pool, const void *src) 
     1288{ 
     1289    pj_stun_uint64_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_uint64_attr); 
     1290 
     1291    pj_memcpy(dst, src, sizeof(pj_stun_uint64_attr)); 
     1292 
     1293    return (void*)dst; 
     1294} 
     1295 
     1296 
    11921297////////////////////////////////////////////////////////////////////////////// 
    11931298/* 
     
    12701375 
    12711376    return PJ_SUCCESS; 
     1377} 
     1378 
     1379 
     1380static void* clone_msgint_attr(pj_pool_t *pool, const void *src) 
     1381{ 
     1382    pj_stun_msgint_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_msgint_attr); 
     1383 
     1384    pj_memcpy(dst, src, sizeof(pj_stun_msgint_attr)); 
     1385 
     1386    return (void*) dst; 
    12721387} 
    12731388 
     
    13821497} 
    13831498 
     1499 
     1500static void* clone_errcode_attr(pj_pool_t *pool, const void *src) 
     1501{ 
     1502    const pj_stun_errcode_attr *asrc = (const pj_stun_errcode_attr*)src; 
     1503    pj_stun_errcode_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_errcode_attr); 
     1504 
     1505    pj_memcpy(dst, src, sizeof(pj_stun_errcode_attr)); 
     1506    pj_strdup(pool, &dst->reason, &asrc->reason); 
     1507 
     1508    return (void*)dst; 
     1509} 
     1510 
    13841511////////////////////////////////////////////////////////////////////////////// 
    13851512/* 
     
    15001627 
    15011628 
     1629static void* clone_unknown_attr(pj_pool_t *pool, const void *src) 
     1630{ 
     1631    pj_stun_unknown_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_unknown_attr); 
     1632 
     1633    pj_memcpy(dst, src, sizeof(pj_stun_unknown_attr)); 
     1634     
     1635    return (void*)dst; 
     1636} 
     1637 
    15021638////////////////////////////////////////////////////////////////////////////// 
    15031639/* 
     
    15971733} 
    15981734 
     1735 
     1736static void* clone_binary_attr(pj_pool_t *pool, const void *src) 
     1737{ 
     1738    const pj_stun_binary_attr *asrc = (const pj_stun_binary_attr*)src; 
     1739    pj_stun_binary_attr *dst = PJ_POOL_ALLOC_T(pool, pj_stun_binary_attr); 
     1740 
     1741    pj_memcpy(dst, src, sizeof(pj_stun_binary_attr)); 
     1742 
     1743    if (asrc->length) { 
     1744        dst->data = (pj_uint8_t*) pj_pool_alloc(pool, asrc->length); 
     1745        pj_memcpy(dst->data, asrc->data, asrc->length); 
     1746    } 
     1747 
     1748    return (void*)dst; 
     1749} 
    15991750 
    16001751////////////////////////////////////////////////////////////////////////////// 
     
    16381789 
    16391790    return PJ_SUCCESS; 
     1791} 
     1792 
     1793 
     1794/* 
     1795 * Clone a STUN message with all of its attributes. 
     1796 */ 
     1797PJ_DEF(pj_stun_msg*) pj_stun_msg_clone( pj_pool_t *pool, 
     1798                                        const pj_stun_msg *src) 
     1799{ 
     1800    pj_stun_msg *dst; 
     1801    unsigned i; 
     1802 
     1803    PJ_ASSERT_RETURN(pool && src, NULL); 
     1804 
     1805    dst = PJ_POOL_ZALLOC_T(pool, pj_stun_msg); 
     1806    pj_memcpy(dst, src, sizeof(pj_stun_msg)); 
     1807 
     1808    /* Duplicate the attributes */ 
     1809    for (i=0, dst->attr_count=0; i<src->attr_count; ++i) { 
     1810        dst->attr[dst->attr_count] = pj_stun_attr_clone(pool, src->attr[i]); 
     1811        if (dst->attr[dst->attr_count]) 
     1812            ++dst->attr_count; 
     1813    } 
     1814 
     1815    return dst; 
    16401816} 
    16411817 
     
    19822158} 
    19832159 
    1984 /* Calculate HMAC-SHA1 key for long term credential, by getting 
    1985  * MD5 digest of username, realm, and password.  
    1986  */ 
    1987 static void calc_md5_key(pj_uint8_t digest[16], 
    1988                          const pj_str_t *realm, 
    1989                          const pj_str_t *username, 
    1990                          const pj_str_t *passwd) 
    1991 { 
    1992     /* The 16-byte key for MESSAGE-INTEGRITY HMAC is formed by taking 
    1993      * the MD5 hash of the result of concatenating the following five 
    1994      * fields: (1) The username, with any quotes and trailing nulls 
    1995      * removed, (2) A single colon, (3) The realm, with any quotes and 
    1996      * trailing nulls removed, (4) A single colon, and (5) The  
    1997      * password, with any trailing nulls removed. 
    1998      */ 
    1999     pj_md5_context ctx; 
    2000     pj_str_t s; 
    2001  
    2002     pj_md5_init(&ctx); 
    2003  
    2004 #define REMOVE_QUOTE(s) if (s.slen && *s.ptr=='"') \ 
    2005                             s.ptr++, s.slen--; \ 
    2006                         if (s.slen && s.ptr[s.slen-1]=='"') \ 
    2007                             s.slen--; 
    2008  
    2009     /* Add username */ 
    2010     s = *username; 
    2011     REMOVE_QUOTE(s); 
    2012     pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen); 
    2013  
    2014     /* Add single colon */ 
    2015     pj_md5_update(&ctx, (pj_uint8_t*)":", 1); 
    2016  
    2017     /* Add realm */ 
    2018     s = *realm; 
    2019     REMOVE_QUOTE(s); 
    2020     pj_md5_update(&ctx, (pj_uint8_t*)s.ptr, s.slen); 
    2021  
    2022 #undef REMOVE_QUOTE 
    2023  
    2024     /* Another colon */ 
    2025     pj_md5_update(&ctx, (pj_uint8_t*)":", 1); 
    2026  
    2027     /* Add password */ 
    2028     pj_md5_update(&ctx, (pj_uint8_t*)passwd->ptr, passwd->slen); 
    2029  
    2030     /* Done */ 
    2031     pj_md5_final(&ctx, digest); 
    2032 } 
    2033  
    2034  
    2035 /* 
    2036  * Create authentication key to be used for encoding the message with 
    2037  * MESSAGE-INTEGRITY.  
    2038  */ 
    2039 PJ_DEF(void) pj_stun_create_key(pj_pool_t *pool, 
    2040                                 pj_str_t *key, 
    2041                                 const pj_str_t *realm, 
    2042                                 const pj_str_t *username, 
    2043                                 const pj_str_t *passwd) 
    2044 { 
    2045     PJ_ASSERT_ON_FAIL(pool && key && username && passwd, return); 
    2046  
    2047     if (realm && realm->slen) { 
    2048         key->ptr = (char*) pj_pool_alloc(pool, 16); 
    2049         calc_md5_key((pj_uint8_t*)key->ptr, realm, username, passwd); 
    2050         key->slen = 16; 
    2051     } else { 
    2052         pj_strdup(pool, key, passwd); 
    2053     } 
    2054 } 
    2055  
    2056  
    20572160/* 
    20582161static char *print_binary(const pj_uint8_t *data, unsigned data_len) 
     
    22082311         * the last attribute before FINGERPRINT. 
    22092312         */ 
    2210         if (i < msg->attr_count-2) { 
     2313        if (msg->attr_count>1 && i < msg->attr_count-2) { 
    22112314            /* Should not happen for message generated by us */ 
    22122315            pj_assert(PJ_FALSE); 
     
    22992402} 
    23002403 
     2404 
     2405/* 
     2406 * Clone a STUN attribute. 
     2407 */ 
     2408PJ_DEF(pj_stun_attr_hdr*) pj_stun_attr_clone( pj_pool_t *pool, 
     2409                                              const pj_stun_attr_hdr *attr) 
     2410{ 
     2411    const struct attr_desc *adesc; 
     2412 
     2413    /* Get the attribute descriptor */ 
     2414    adesc = find_attr_desc(attr->type); 
     2415    PJ_ASSERT_RETURN(adesc != NULL, NULL); 
     2416 
     2417    return (pj_stun_attr_hdr*) (*adesc->clone_attr)(pool, attr); 
     2418} 
     2419 
     2420 
Note: See TracChangeset for help on using the changeset viewer.