Changeset 1114 for pjproject/trunk


Ignore:
Timestamp:
Mar 29, 2007 9:54:21 PM (18 years ago)
Author:
bennylp
Message:

Added ICE-CONTROLLING and ICE-CONTROLLED STUN attribute types

Location:
pjproject/trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/include/pjmedia/rtp.h

    r974 r1114  
    7878 
    7979/** 
    80  * RTP packet header. 
     80 * RTP packet header. Note that all RTP functions here will work with this 
     81 * header in network byte order. 
    8182 */ 
    8283#pragma pack(1) 
     
    230231 * @param ses           The session. 
    231232 * @param default_pt    Default payload type. 
    232  * @param sender_ssrc   SSRC used for outgoing packets. 
     233 * @param sender_ssrc   SSRC used for outgoing packets, in host byte order. 
    233234 * 
    234235 * @return              PJ_SUCCESS if successfull. 
     
    263264 * position regardless of any options present in the RTP packet. 
    264265 * 
     266 * Note that this function does not modify the returned RTP header to 
     267 * host byte order. 
     268 * 
    265269 * @param ses           The session. 
    266270 * @param pkt           The received RTP packet. 
    267271 * @param pkt_len       The length of the packet. 
    268  * @param hdr           Upon return will point to the location of the RTP header 
    269  *                      inside the packet. 
     272 * @param hdr           Upon return will point to the location of the RTP  
     273 *                      header inside the packet. Note that the RTP header 
     274 *                      will be given back as is, meaning that the fields 
     275 *                      will be in network byte order. 
    270276 * @param payload       Upon return will point to the location of the 
    271277 *                      payload inside the packet. 
     
    286292 * 
    287293 * @param ses       The session. 
    288  * @param hdr       The RTP header of the incoming packet. 
     294 * @param hdr       The RTP header of the incoming packet. The header must 
     295 *                  be given with fields in network byte order. 
    289296 * @param seq_st    Optional structure to receive the status of the RTP packet 
    290297 *                  processing. 
  • pjproject/trunk/pjmedia/src/pjmedia/transport_ice.c

    r1112 r1114  
    2525{ 
    2626    pjmedia_transport    base; 
    27     pj_ice_strans               *ice_st; 
     27    pj_ice_strans       *ice_st; 
    2828 
    2929    pj_time_val          start_ice; 
     
    409409    pj_ice_sess_cand cand[PJ_ICE_MAX_CAND]; 
    410410    const pjmedia_sdp_media *sdp_med; 
     411    pj_bool_t remote_is_lite = PJ_FALSE; 
     412    const pj_str_t STR_CANDIDATE = {"candidate", 9}; 
     413    const pj_str_t STR_ICE_LITE = {"ice-lite", 8}; 
    411414    pj_str_t uname, pass; 
    412415    pj_status_t status; 
     
    445448    pass = attr->value; 
    446449 
    447     /* Get all candidates */ 
     450    /* Get all candidates in the media */ 
    448451    cand_cnt = 0; 
    449452    for (i=0; i<sdp_med->attr_count; ++i) { 
     
    451454 
    452455        attr = sdp_med->attr[i]; 
    453         if (pj_strcmp2(&attr->name, "candidate")!=0) 
     456 
     457        if (pj_strcmp(&attr->name, &STR_ICE_LITE)==0) 
     458            remote_is_lite = PJ_TRUE; 
     459 
     460        if (pj_strcmp(&attr->name, &STR_CANDIDATE)!=0) 
    454461            continue; 
    455462 
     
    463470    /* Mark start time */ 
    464471    pj_gettimeofday(&tp_ice->start_ice); 
     472 
     473    /* If our role was controlled but it turns out that remote is  
     474     * a lite implementation, change our role to controlling. 
     475     */ 
     476    if (remote_is_lite &&  
     477        tp_ice->ice_st->ice->role == PJ_ICE_SESS_ROLE_CONTROLLED) 
     478    { 
     479        pj_ice_sess_change_role(tp_ice->ice_st->ice,  
     480                                PJ_ICE_SESS_ROLE_CONTROLLING); 
     481    } 
    465482 
    466483    /* Start ICE */ 
     
    553570    struct transport_ice *tp_ice = (struct transport_ice*)tp; 
    554571    return pj_ice_strans_sendto(tp_ice->ice_st, 1,  
    555                             pkt, size, &tp_ice->remote_rtp, 
    556                             sizeof(pj_sockaddr_in)); 
     572                                pkt, size, &tp_ice->remote_rtp, 
     573                                sizeof(pj_sockaddr_in)); 
    557574} 
    558575 
     
    565582    if (tp_ice->ice_st->comp_cnt > 1) { 
    566583        return pj_ice_strans_sendto(tp_ice->ice_st, 2,  
    567                                 pkt, size, &tp_ice->remote_rtp, 
    568                                 sizeof(pj_sockaddr_in)); 
     584                                    pkt, size, &tp_ice->remote_rtp, 
     585                                    sizeof(pj_sockaddr_in)); 
    569586    } else { 
    570587        return PJ_SUCCESS; 
  • pjproject/trunk/pjnath/include/pjnath/ice_session.h

    r1111 r1114  
    445445    pj_mutex_t          *mutex;                     /**< Mutex.             */ 
    446446    pj_ice_sess_role     role;                      /**< ICE role.          */ 
     447    pj_timestamp         tie_breaker;               /**< Tie breaker value  */ 
    447448    pj_bool_t            is_complete;               /**< Complete?          */ 
    448449    pj_status_t          ice_status;                /**< Error status.      */ 
     
    551552 
    552553/** 
     554 * Change session role. This happens for example when ICE session was 
     555 * created with controlled role when receiving an offer, but it turns out 
     556 * that the offer contains "a=ice-lite" attribute when the SDP gets 
     557 * inspected. 
     558 * 
     559 * @param ice           The ICE session. 
     560 * @param new_role      The new role to be set. 
     561 * 
     562 * @return              PJ_SUCCESS on success, or the appropriate error. 
     563 */ 
     564PJ_DECL(pj_status_t) pj_ice_sess_change_role(pj_ice_sess *ice, 
     565                                             pj_ice_sess_role new_role); 
     566 
     567 
     568/** 
    553569 * Add a candidate to this ICE session. Application must add candidates for 
    554570 * each components ID before it can start pairing the candidates and  
  • pjproject/trunk/pjnath/include/pjnath/ice_strans.h

    r1111 r1114  
    2828#include <pjlib-util/resolver.h> 
    2929#include <pj/ioqueue.h> 
     30#include <pj/timer.h> 
    3031 
    3132 
     
    315316    pj_sockaddr_in           stun_srv;  /**< STUN server address.       */ 
    316317    pj_sockaddr_in           turn_srv;  /**< TURN server address.       */ 
     318 
     319    pj_timer_entry           ka_timer;  /**< STUN keep-alive timer.     */ 
    317320}; 
    318321 
  • pjproject/trunk/pjnath/include/pjnath/stun_msg.h

    r1111 r1114  
    311311    PJ_STUN_ATTR_REFRESH_INTERVAL   = 0x8024,/**< REFRESH-INTERVAL.         */ 
    312312    PJ_STUN_ATTR_FINGERPRINT        = 0x8028,/**< FINGERPRINT attribute.    */ 
     313    PJ_STUN_ATTR_ICE_CONTROLLED     = 0x8029,/**< ICE-CCONTROLLED attribute.*/ 
     314    PJ_STUN_ATTR_ICE_CONTROLLING    = 0x802a,/**< ICE-CCONTROLLING attribute*/ 
    313315 
    314316    PJ_STUN_ATTR_END_EXTENDED_ATTR 
     
    345347    PJ_STUN_SC_ALLOCATION_QUOTA_REACHED = 486,  /**< Allocation Quota Reached 
    346348                                                     (TURN) */ 
     349    PJ_STUN_SC_ROLE_CONFLICT            = 487,  /**< Role Conflict          */ 
    347350    PJ_STUN_SC_SERVER_ERROR             = 500,  /**< Server Error           */ 
    348351    PJ_STUN_SC_INSUFFICIENT_CAPACITY    = 507,  /**< Insufficient Capacity  
     
    419422       |         Type                  |            Length             | 
    420423       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
    421        |                             Value                 ....        | 
    422        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
    423424 
    424425   \endverbatim 
     
    534535     
    535536    /** 
    536      * The 32bit value. 
     537     * The 32bit value, in host byte order. 
    537538     */ 
    538539    pj_uint32_t         value; 
    539540 
    540541} pj_stun_uint_attr; 
     542 
     543 
     544/** 
     545 * This structure represents a generic STUN attributes with 64bit (unsigned) 
     546 * integer value, such as ICE-CONTROLLED and ICE-CONTROLLING attributes. 
     547 */ 
     548typedef struct pj_stun_uint64_attr 
     549{ 
     550    /** 
     551     * Standard STUN attribute header. 
     552     */ 
     553    pj_stun_attr_hdr    hdr; 
     554     
     555    /** 
     556     * The 64bit value, in host byte order, represented with pj_timestamp. 
     557     */ 
     558    pj_timestamp        value; 
     559 
     560} pj_stun_uint64_attr; 
    541561 
    542562 
     
    622642 
    623643    /** 
    624      * The value must be zero. 
    625      */ 
    626     pj_uint16_t         zero; 
    627  
    628     /** 
    629      * Error class (1-6). 
    630      */ 
    631     pj_uint8_t          err_class; 
    632  
    633     /** 
    634      * Error number is the error number modulo 100. 
    635      */ 
    636     pj_uint8_t          number; 
     644     * STUN error code. 
     645     */ 
     646    int                 err_code; 
    637647 
    638648    /** 
     
    13501360 
    13511361/** 
     1362 * Create a STUN generic 64bit value attribute. 
     1363 * 
     1364 * @param pool          Pool to allocate memory from. 
     1365 * @param attr_type     Attribute type, from #pj_stun_attr_type. 
     1366 * @param value         Optional value to be assigned. 
     1367 * @param p_attr        Pointer to receive the attribute. 
     1368 * 
     1369 * @return              PJ_SUCCESS on success or the appropriate error code. 
     1370 */ 
     1371PJ_DEF(pj_status_t)  pj_stun_uint64_attr_create(pj_pool_t *pool, 
     1372                                                int attr_type, 
     1373                                                const pj_timestamp *value, 
     1374                                                pj_stun_uint64_attr **p_attr); 
     1375 
     1376 
     1377/** 
     1378 *  Create and add STUN generic 64bit value attribute to the message.  
     1379 * 
     1380 * @param pool          The pool to allocate memory from. 
     1381 * @param msg           The STUN message 
     1382 * @param attr_type     Attribute type, from #pj_stun_attr_type. 
     1383 * @param value         The 64bit value to be assigned to the attribute. 
     1384 * 
     1385 * @return              PJ_SUCCESS on success or the appropriate error code. 
     1386 */ 
     1387PJ_DECL(pj_status_t)  pj_stun_msg_add_uint64_attr(pj_pool_t *pool, 
     1388                                                  pj_stun_msg *msg, 
     1389                                                  int attr_type, 
     1390                                                  const pj_timestamp *value); 
     1391 
     1392/** 
    13521393 * Create a STUN MESSAGE-INTEGRITY attribute. 
    13531394 * 
  • pjproject/trunk/pjnath/include/pjnath/types.h

    r1111 r1114  
    5252 
    5353/** 
    54  * @mainpage PJNATH - Open Source STUN, TURN, and ICE Library 
     54 * @mainpage PJNATH - Open Source ICE, STUN, and TURN Library 
    5555 * 
    5656 * \n 
    5757 * This is the documentation of PJNATH, an Open Source library providing 
    58  * NAT traversal helper functionalities by using standard based protocols  
    59  * such as: 
    60  *  - <b>STUN</b> (Session Traversal Utilities), 
    61  *  - <b>TURN</b> (Obtaining Relay Addresses from STUN) 
    62  *  - <b>ICE</b> (Interactive Connectivity Establishment). 
    63  *  
    64  * The following sections will give a short overview about the protocols 
    65  * supported by this library, and how they are implemented in PJNATH. 
     58 * NAT traversal helper functionalities by using standard based protocols. 
    6659 * 
    6760 * \n 
     
    7164 * Session Traversal Utilities (STUN, or previously known as Simple  
    7265 * Traversal of User Datagram Protocol (UDP) Through Network Address  
    73  * Translators (NAT)s), was previously released as IETF standard 
    74  * <A HREF="http://www.ietf.org/rfc/rfc3489.txt">RFC 3489</A>, but since 
    75  * then it has been revised into the following: 
    76  *  - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-rfc3489bis-06.txt"> 
    77  *    <B>draft-ietf-behave-rfc3489bis-06</b></A> for the main STUN  
    78  *    specification, 
    79  *  - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-turn-03.txt"> 
    80  *    <B>draft-ietf-behave-turn-03</B></A> for TURN usage of STUN, 
    81  *  - and several other drafts explaining other STUN usages. 
     66 * Translators (NAT)s), is a lightweight protocol that serves as a tool for 
     67 * application protocols in dealing with NAT traversal. It allows a client 
     68 * to determine the IP address and port allocated to them by a NAT and to  
     69 * keep NAT bindings open. 
    8270 *  
    8371 * The PJNATH library provides facilities to support both the core  
     
    134122 * components with callback to send outgoing messages. 
    135123 *  
     124 * 
     125 * \subsection PJNATH_STUN_REF STUN Reference 
     126 * 
     127 * References for STUN: 
     128 * 
     129 *  - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-rfc3489bis-06.txt"> 
     130 *    <B>draft-ietf-behave-rfc3489bis-06</b></A>: Session Traversal  
     131 *     Utilities for (NAT) (STUN), 
     132 *  - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-turn-03.txt"> 
     133 *    <B>draft-ietf-behave-turn-03</B></A>: Obtaining Relay Addresses  
     134 *    from Simple Traversal Underneath NAT (STUN) 
     135 *  - Obsoleted: <A HREF="http://www.ietf.org/rfc/rfc3489.txt">RFC 3489</A>. 
     136 * 
    136137 * \n 
    137138 * 
     
    171172 *    ICE stream transport and provides SDP translations to be used 
    172173 *    for SIP offer/answer exchanges. 
     174 * 
     175 * \subsection PJNATH_ICE_REF Reference 
     176 * 
     177 * References for ICE: 
     178 *  - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-mmusic-ice-15.txt"> 
     179 *    <B>draft-ietf-mmusic-ice-15.txt</B></A>: Interactive Connectivity  
     180 *    Establishment (ICE): A Methodology for Network Address Translator  
     181 *    (NAT) Traversal for Offer/Answer Protocols 
    173182 */ 
    174183 
  • pjproject/trunk/pjnath/src/pjnath/ice_session.c

    r1113 r1114  
    5757}; 
    5858 
     59static const char *role_names[] =  
     60{ 
     61    "Controlled", 
     62    "Controlling" 
     63}; 
     64 
    5965#define CHECK_NAME_LEN          128 
    6066#define LOG4(expr)              PJ_LOG(4,expr) 
     
    197203    ice->pool = pool; 
    198204    ice->role = role; 
     205    ice->tie_breaker.u32.hi = pj_rand(); 
     206    ice->tie_breaker.u32.lo = pj_rand(); 
    199207 
    200208    pj_ansi_snprintf(ice->obj_name, sizeof(ice->obj_name), 
     
    238246    LOG4((ice->obj_name,  
    239247         "ICE session created, comp_cnt=%d, role is %s agent", 
    240          comp_cnt, 
    241          (ice->role==PJ_ICE_SESS_ROLE_CONTROLLING ?  
    242             "controlling":"controlled"))); 
     248         comp_cnt, role_names[ice->role])); 
    243249 
    244250    return PJ_SUCCESS; 
     
    290296    PJ_ASSERT_RETURN(ice, PJ_EINVAL); 
    291297    destroy_ice(ice, PJ_SUCCESS); 
     298    return PJ_SUCCESS; 
     299} 
     300 
     301 
     302/* 
     303 * Change session role.  
     304 */ 
     305PJ_DEF(pj_status_t) pj_ice_sess_change_role(pj_ice_sess *ice, 
     306                                            pj_ice_sess_role new_role) 
     307{ 
     308    PJ_ASSERT_RETURN(ice, PJ_EINVAL); 
     309 
     310    if (new_role != ice->role) { 
     311        ice->role = new_role; 
     312        LOG4((ice->obj_name, "Role changed to %s", role_names[new_role])); 
     313    } 
     314 
    292315    return PJ_SUCCESS; 
    293316} 
  • pjproject/trunk/pjnath/src/pjnath/ice_strans.c

    r1111 r1114  
    6161                                     const pj_stun_msg *response); 
    6262 
     63/* Keep-alive timer */ 
     64static void start_ka_timer(pj_ice_strans *ice_st); 
     65static void stop_ka_timer(pj_ice_strans *ice_st); 
     66 
    6367/* Utility: print error */ 
    6468#if PJ_LOG_MAX_LEVEL >= 3 
     
    126130    } 
    127131 
     132    /* Kill keep-alive timer, if any */ 
     133    stop_ka_timer(ice_st); 
     134 
    128135    /* Destroy ICE if we have ICE */ 
    129136    if (ice_st->ice) { 
     
    197204    return PJ_SUCCESS; 
    198205} 
    199  
    200206 
    201207/* Add new candidate */ 
     
    506512 
    507513 
     514/* STUN keep-alive timer callback */ 
     515static void ka_timer_cb(pj_timer_heap_t *th, pj_timer_entry *te) 
     516{ 
     517    pj_ice_strans *ice_st = (pj_ice_strans*)te->user_data; 
     518    unsigned i; 
     519    pj_status_t status; 
     520 
     521    PJ_UNUSED_ARG(th); 
     522 
     523    ice_st->ka_timer.id = PJ_FALSE; 
     524 
     525    for (i=0; i<ice_st->comp_cnt; ++i) { 
     526        pj_ice_strans_comp *comp = ice_st->comp[i]; 
     527        pj_stun_tx_data *tdata; 
     528        unsigned j; 
     529 
     530        /* Does this component have STUN server reflexive candidate? */ 
     531        for (j=0; j<comp->cand_cnt; ++j) { 
     532            if (comp->cand_list[j].type == PJ_ICE_CAND_TYPE_SRFLX) 
     533                break; 
     534        } 
     535        if (j == comp->cand_cnt) 
     536            continue; 
     537 
     538        /* Create STUN binding request */ 
     539        status = pj_stun_session_create_req(comp->stun_sess, 
     540                                            PJ_STUN_BINDING_REQUEST, &tdata); 
     541        if (status != PJ_SUCCESS) 
     542            continue; 
     543 
     544        /* tdata->user_data is NULL for keep-alive */ 
     545        tdata->user_data = NULL; 
     546 
     547        /* Send STUN binding request */ 
     548        PJ_LOG(5,(ice_st->obj_name, "Sending STUN keep-alive")); 
     549        status = pj_stun_session_send_msg(comp->stun_sess, PJ_FALSE,  
     550                                          &ice_st->stun_srv,  
     551                                          sizeof(pj_sockaddr_in), tdata); 
     552    } 
     553 
     554    /* Start next timer */ 
     555    start_ka_timer(ice_st); 
     556} 
     557 
     558/* Start STUN keep-alive timer */ 
     559static void start_ka_timer(pj_ice_strans *ice_st) 
     560{ 
     561    pj_time_val delay; 
     562 
     563    /* Skip if timer is already running */ 
     564    if (ice_st->ka_timer.id != PJ_FALSE) 
     565        return; 
     566 
     567    delay.sec = 20; 
     568    delay.msec = 0; 
     569 
     570    ice_st->ka_timer.cb = &ka_timer_cb; 
     571    ice_st->ka_timer.user_data = ice_st; 
     572     
     573    if (pj_timer_heap_schedule(ice_st->stun_cfg.timer_heap,  
     574                               &ice_st->ka_timer, &delay)==PJ_SUCCESS) 
     575    { 
     576        ice_st->ka_timer.id = PJ_TRUE; 
     577    } 
     578} 
     579 
     580 
     581/* Stop STUN keep-alive timer */ 
     582static void stop_ka_timer(pj_ice_strans *ice_st) 
     583{ 
     584    /* Skip if timer is already stop */ 
     585    if (ice_st->ka_timer.id == PJ_FALSE) 
     586        return; 
     587 
     588    pj_timer_heap_cancel(ice_st->stun_cfg.timer_heap, &ice_st->ka_timer); 
     589    ice_st->ka_timer.id = PJ_FALSE; 
     590} 
     591 
    508592 
    509593/* 
     
    831915    } 
    832916 
    833 #if 1 
    834     PJ_UNUSED_ARG(pkt_size); 
    835     PJ_UNUSED_ARG(status); 
    836  
    837     /* Otherwise return error */ 
    838     return PJNATH_EICEINPROGRESS; 
    839 #else 
    840     /* Otherwise send direcly with the socket */ 
     917    /* Otherwise send direcly with the socket. This is for compatibility 
     918     * with remote that doesn't support ICE. 
     919     */ 
    841920    pkt_size = data_len; 
    842921    status = pj_ioqueue_sendto(comp->key, &comp->write_op,  
     
    845924     
    846925    return (status==PJ_SUCCESS||status==PJ_EPENDING) ? PJ_SUCCESS : status; 
    847 #endif 
    848926} 
    849927 
     
    9431021    comp = (pj_ice_strans_comp*) pj_stun_session_get_user_data(sess); 
    9441022    cand = (pj_ice_strans_cand*) tdata->user_data; 
     1023 
     1024    if (cand == NULL) { 
     1025        /* This is keep-alive */ 
     1026        return; 
     1027    } 
    9451028 
    9461029    /* Decrement pending count for this component */ 
     
    9811064    comp->default_cand = (cand - comp->cand_list); 
    9821065    comp->last_status = PJ_SUCCESS; 
    983 } 
    984  
     1066 
     1067    /* We have STUN, so we must start the keep-alive timer */ 
     1068    start_ka_timer(comp->ice_st); 
     1069} 
     1070 
  • pjproject/trunk/pjnath/src/pjnath/stun_msg.c

    r1111 r1114  
    7272    { PJ_STUN_SC_CONNECTION_TIMEOUT,        "Connection Timeout"}, 
    7373    { PJ_STUN_SC_ALLOCATION_QUOTA_REACHED,  "Allocation Quota Reached"}, 
     74    { PJ_STUN_SC_ROLE_CONFLICT,             "Role Conflict"}, 
    7475    { PJ_STUN_SC_SERVER_ERROR,              "Server Error"}, 
    7576    { PJ_STUN_SC_INSUFFICIENT_CAPACITY,     "Insufficient Capacity"}, 
     
    8687    pj_status_t (*encode_attr)(const void *a, pj_uint8_t *buf,  
    8788                               unsigned len, unsigned *printed); 
    88  
    8989}; 
    9090 
     
    123123static pj_status_t encode_uint_attr(const void *a, pj_uint8_t *buf,  
    124124                                    unsigned len, unsigned *printed); 
     125static pj_status_t decode_uint64_attr(pj_pool_t *pool,  
     126                                      const pj_uint8_t *buf,  
     127                                      void **p_attr); 
     128static pj_status_t encode_uint64_attr(const void *a, pj_uint8_t *buf,  
     129                                      unsigned len, unsigned *printed); 
    125130static pj_status_t decode_binary_attr(pj_pool_t *pool,  
    126131                                      const pj_uint8_t *buf, 
     
    430435        &decode_uint_attr, 
    431436        &encode_uint_attr 
     437    }, 
     438    { 
     439        /* PJ_STUN_ATTR_ICE_CONTROLLED, */ 
     440        "ICE-CCONTROLLED", 
     441        &decode_uint64_attr, 
     442        &encode_uint64_attr 
     443    }, 
     444    { 
     445        /* PJ_STUN_ATTR_ICE_CONTROLLING, */ 
     446        "ICE-CCONTROLLING", 
     447        &decode_uint64_attr, 
     448        &encode_uint64_attr 
    432449    } 
    433450}; 
     
    552569 
    553570 
     571////////////////////////////////////////////////////////////////////////////// 
     572 
    554573 
    555574#define INIT_ATTR(a,t,l)    (a)->hdr.type=(pj_uint16_t)(t), \ 
     
    557576#define ATTR_HDR_LEN        4 
    558577 
    559 #define getval16(p, pos)    (pj_uint16_t)(((p)[(pos)] << 8) | \ 
    560                                           ((p)[(pos) + 1] << 0)) 
    561  
     578static pj_uint16_t GETVAL16H(const pj_uint8_t *buf, unsigned pos) 
     579{ 
     580    return (pj_uint16_t) ((buf[pos + 0] << 8) | \ 
     581                          (buf[pos + 1] << 0)); 
     582} 
     583 
     584static pj_uint16_t GETVAL16N(const pj_uint8_t *buf, unsigned pos) 
     585{ 
     586    return pj_htons(GETVAL16H(buf,pos)); 
     587} 
     588 
     589static void PUTVAL16H(pj_uint8_t *buf, unsigned pos, pj_uint16_t hval) 
     590{ 
     591    buf[pos+0] = (pj_uint8_t) ((hval & 0xFF00) >> 8); 
     592    buf[pos+1] = (pj_uint8_t) ((hval & 0x00FF) >> 0); 
     593} 
     594 
     595static pj_uint32_t GETVAL32H(const pj_uint8_t *buf, unsigned pos) 
     596{ 
     597    return (pj_uint32_t) ((buf[pos + 0] << 24UL) | \ 
     598                          (buf[pos + 1] << 16UL) | \ 
     599                          (buf[pos + 2] <<  8UL) | \ 
     600                          (buf[pos + 3] <<  0UL)); 
     601} 
     602 
     603static pj_uint32_t GETVAL32N(const pj_uint8_t *buf, unsigned pos) 
     604{ 
     605    return pj_htonl(GETVAL32H(buf,pos)); 
     606} 
     607 
     608static void PUTVAL32H(pj_uint8_t *buf, unsigned pos, pj_uint32_t hval) 
     609{ 
     610    buf[pos+0] = (pj_uint8_t) ((hval & 0xFF000000UL) >> 24); 
     611    buf[pos+1] = (pj_uint8_t) ((hval & 0x00FF0000UL) >> 16); 
     612    buf[pos+2] = (pj_uint8_t) ((hval & 0x0000FF00UL) >>  8); 
     613    buf[pos+3] = (pj_uint8_t) ((hval & 0x000000FFUL) >>  0); 
     614} 
     615 
     616static void GETVAL64H(const pj_uint8_t *buf, unsigned pos, pj_timestamp *ts) 
     617{ 
     618    ts->u32.hi = GETVAL32H(buf, pos); 
     619    ts->u32.lo = GETVAL32H(buf, pos+4); 
     620} 
     621 
     622static void PUTVAL64H(pj_uint8_t *buf, unsigned pos, const pj_timestamp *ts) 
     623{ 
     624    PUTVAL32H(buf, pos, ts->u32.hi); 
     625    PUTVAL32H(buf, pos+4, ts->u32.lo); 
     626} 
     627 
     628 
     629static void GETATTRHDR(const pj_uint8_t *buf, pj_stun_attr_hdr *hdr) 
     630{ 
     631    hdr->type = GETVAL16H(buf, 0); 
     632    hdr->length = GETVAL16H(buf, 2); 
     633} 
    562634 
    563635////////////////////////////////////////////////////////////////////////////// 
     
    627699    /* Create the attribute */ 
    628700    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_sockaddr_attr); 
    629     pj_memcpy(attr, buf, ATTR_HDR_LEN); 
    630  
    631     /* Convert to host byte order */ 
    632     attr->hdr.type = pj_ntohs(attr->hdr.type); 
    633     attr->hdr.length = pj_ntohs(attr->hdr.length); 
     701    GETATTRHDR(buf, &attr->hdr); 
    634702 
    635703    /* Check that the attribute length is valid */ 
     
    646714    /* Get port and address */ 
    647715    pj_sockaddr_in_init(&attr->sockaddr.ipv4, NULL, 0); 
    648     pj_memcpy(&attr->sockaddr.ipv4.sin_port, buf+ATTR_HDR_LEN+2, 2); 
    649     pj_memcpy(&attr->sockaddr.ipv4.sin_addr, buf+ATTR_HDR_LEN+4, 4); 
     716    attr->sockaddr.ipv4.sin_port = GETVAL16N(buf, ATTR_HDR_LEN+2); 
     717    attr->sockaddr.ipv4.sin_addr.s_addr = GETVAL32N(buf, ATTR_HDR_LEN+4); 
    650718 
    651719    /* Done */ 
     
    661729{ 
    662730    pj_stun_sockaddr_attr *attr; 
    663     pj_uint32_t val; 
    664  
    665     /* Create the attribute */ 
    666     attr = PJ_POOL_ZALLOC_T(pool, pj_stun_sockaddr_attr); 
    667     pj_memcpy(attr, buf, ATTR_HDR_LEN); 
    668  
    669     /* Convert to host byte order */ 
    670     attr->hdr.type = pj_ntohs(attr->hdr.type); 
    671     attr->hdr.length = pj_ntohs(attr->hdr.length); 
    672  
    673     /* Check that the attribute length is valid */ 
    674     if (attr->hdr.length != STUN_GENERIC_IP_ADDR_LEN) 
    675         return PJNATH_ESTUNINATTRLEN; 
    676  
    677     /* Check address family */ 
    678     val = *(pj_uint8_t*)(buf + ATTR_HDR_LEN + 1); 
    679  
    680     /* Check address family is valid (only supports ipv4 for now) */ 
    681     if (val != 1) 
    682         return PJNATH_ESTUNIPV6NOTSUPP; 
    683  
    684     /* Get port and address */ 
    685     pj_sockaddr_in_init(&attr->sockaddr.ipv4, NULL, 0); 
    686     pj_memcpy(&attr->sockaddr.ipv4.sin_port, buf+ATTR_HDR_LEN+2, 2); 
    687     pj_memcpy(&attr->sockaddr.ipv4.sin_addr, buf+ATTR_HDR_LEN+4, 4); 
    688  
     731    pj_status_t status; 
     732 
     733    status = decode_sockaddr_attr(pool, buf, &attr); 
     734    if (status != PJ_SUCCESS) 
     735        return status; 
     736 
     737    attr->xor_ed = PJ_TRUE; 
    689738    attr->sockaddr.ipv4.sin_port ^= pj_htons(0x2112); 
    690739    attr->sockaddr.ipv4.sin_addr.s_addr ^= pj_htonl(0x2112A442); 
     
    706755    const pj_stun_sockaddr_attr *ca =  
    707756        (const pj_stun_sockaddr_attr *)a; 
    708     pj_stun_sockaddr_attr *attr; 
    709757 
    710758    if (len < ATTR_LEN)  
     
    712760 
    713761    /* Copy and convert headers to network byte order */ 
    714     pj_memcpy(buf, a, ATTR_HDR_LEN); 
    715     attr = (pj_stun_sockaddr_attr*) buf; 
    716     attr->hdr.type = pj_htons(attr->hdr.type); 
    717     attr->hdr.length = pj_htons((pj_uint16_t)STUN_GENERIC_IP_ADDR_LEN); 
     762    PUTVAL16H(buf, 0, ca->hdr.type); 
     763    PUTVAL16H(buf, 2, STUN_GENERIC_IP_ADDR_LEN); 
    718764    buf += ATTR_HDR_LEN; 
    719765     
     
    820866    /* Create the attribute */ 
    821867    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_string_attr); 
    822  
    823     /* Copy the header */ 
    824     pj_memcpy(attr, buf, ATTR_HDR_LEN); 
    825  
    826     /* Convert to host byte order */ 
    827     attr->hdr.type = pj_ntohs(attr->hdr.type); 
    828     attr->hdr.length = pj_ntohs(attr->hdr.length); 
     868    GETATTRHDR(buf, &attr->hdr); 
    829869 
    830870    /* Get pointer to the string in the message */ 
     
    848888    const pj_stun_string_attr *ca =  
    849889        (const pj_stun_string_attr*)a; 
    850     pj_stun_attr_hdr *attr; 
    851890 
    852891    /* Calculated total attr_len (add padding if necessary) */ 
     
    857896    } 
    858897 
    859     /* Copy header */ 
    860     pj_memcpy(buf, a, ATTR_HDR_LEN); 
    861     attr = (pj_stun_attr_hdr*)buf; 
    862  
    863     /* Set the correct length */ 
    864     attr->length = (pj_uint16_t) ca->value.slen; 
    865  
    866     /* Convert to network byte order */ 
    867     attr->type = pj_htons(attr->type); 
    868     attr->length = pj_htons(attr->length); 
     898    PUTVAL16H(buf, 0, ca->hdr.type); 
     899    PUTVAL16H(buf, 2, (pj_uint16_t)ca->value.slen); 
     900     
    869901 
    870902    /* Copy the string */ 
     
    930962    /* Create the attribute */ 
    931963    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_empty_attr); 
    932     pj_memcpy(attr, buf, ATTR_HDR_LEN); 
    933  
    934     /* Convert to host byte order */ 
    935     attr->hdr.type = pj_ntohs(attr->hdr.type); 
    936     attr->hdr.length = pj_ntohs(attr->hdr.length); 
     964    GETATTRHDR(buf, &attr->hdr); 
    937965 
    938966    /* Check that the attribute length is valid */ 
     
    950978                                     unsigned len, unsigned *printed) 
    951979{ 
    952     pj_stun_empty_attr *attr; 
     980    const pj_stun_empty_attr *ca = (pj_stun_empty_attr*)a; 
    953981 
    954982    if (len < ATTR_HDR_LEN)  
    955983        return PJ_ETOOSMALL; 
    956984 
    957     /* Copy and convert attribute to network byte order */ 
    958     pj_memcpy(buf, a, ATTR_HDR_LEN); 
    959     attr = (pj_stun_empty_attr*) buf; 
    960     attr->hdr.type = pj_htons(attr->hdr.type); 
    961     attr->hdr.length = 0; 
     985    PUTVAL16H(buf, 0, ca->hdr.type); 
     986    PUTVAL16H(buf, 2, 0); 
    962987 
    963988    /* Done */ 
     
    972997 * STUN generic 32bit integer attribute. 
    973998 */ 
    974 #define STUN_UINT_LEN   4 
    975999 
    9761000/* 
     
    9881012 
    9891013    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_uint_attr); 
    990     INIT_ATTR(attr, attr_type, STUN_UINT_LEN); 
     1014    INIT_ATTR(attr, attr_type, 4); 
    9911015    attr->value = value; 
    9921016 
     
    10171041                                    void **p_attr) 
    10181042{ 
    1019     enum 
    1020     { 
    1021         ATTR_LEN = STUN_UINT_LEN + ATTR_HDR_LEN 
    1022     }; 
    10231043    pj_stun_uint_attr *attr; 
    1024  
    1025     /* Check that the struct address is valid */ 
    1026     pj_assert(sizeof(pj_stun_uint_attr) == ATTR_LEN); 
    10271044 
    10281045    /* Create the attribute */ 
    10291046    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_uint_attr); 
    1030     pj_memcpy(attr, buf, ATTR_LEN); 
    1031  
    1032     /* Convert to host byte order */ 
    1033     attr->hdr.type = pj_ntohs(attr->hdr.type); 
    1034     attr->hdr.length = pj_ntohs(attr->hdr.length); 
    1035     attr->value = pj_ntohl(attr->value); 
     1047    GETATTRHDR(buf, &attr->hdr); 
     1048 
     1049    attr->value = GETVAL32H(buf, 4); 
    10361050 
    10371051    /* Check that the attribute length is valid */ 
    1038     if (attr->hdr.length != STUN_UINT_LEN) 
     1052    if (attr->hdr.length != 4) 
    10391053        return PJNATH_ESTUNINATTRLEN; 
    10401054 
     
    10491063                                    unsigned len, unsigned *printed) 
    10501064{ 
    1051     enum 
    1052     { 
    1053         ATTR_LEN = STUN_UINT_LEN + ATTR_HDR_LEN 
    1054     }; 
    1055     pj_stun_uint_attr *attr; 
    1056  
    1057     if (len < ATTR_LEN)  
     1065    const pj_stun_uint_attr *ca = (const pj_stun_uint_attr*)a; 
     1066 
     1067    if (len < 8)  
    10581068        return PJ_ETOOSMALL; 
    10591069 
    1060     /* Copy and convert attribute to network byte order */ 
    1061     pj_memcpy(buf, a, ATTR_LEN); 
    1062     attr = (pj_stun_uint_attr*) buf; 
    1063     attr->hdr.type = pj_htons(attr->hdr.type); 
    1064     pj_assert(attr->hdr.length == STUN_UINT_LEN); 
    1065     attr->hdr.length = pj_htons(STUN_UINT_LEN); 
    1066     attr->value = pj_htonl(attr->value); 
    1067  
     1070    PUTVAL16H(buf, 0, ca->hdr.type); 
     1071    PUTVAL16H(buf, 2, (pj_uint16_t)4); 
     1072    PUTVAL32H(buf, 4, ca->value); 
     1073     
    10681074    /* Done */ 
    1069     *printed = ATTR_LEN; 
     1075    *printed = 8; 
    10701076 
    10711077    return PJ_SUCCESS; 
     
    10731079 
    10741080////////////////////////////////////////////////////////////////////////////// 
     1081 
     1082/* 
     1083 * Create a STUN generic 64bit value attribute. 
     1084 */ 
     1085PJ_DEF(pj_status_t)  
     1086pj_stun_uint64_attr_create(pj_pool_t *pool, 
     1087                           int attr_type, 
     1088                           const pj_timestamp *value, 
     1089                           pj_stun_uint64_attr **p_attr) 
     1090{ 
     1091    pj_stun_uint64_attr *attr; 
     1092 
     1093    PJ_ASSERT_RETURN(pool && p_attr, PJ_EINVAL); 
     1094 
     1095    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_uint64_attr); 
     1096    INIT_ATTR(attr, attr_type, 4); 
     1097 
     1098    if (value) { 
     1099        attr->value.u32.hi = value->u32.hi; 
     1100        attr->value.u32.lo = value->u32.lo; 
     1101    } 
     1102 
     1103    *p_attr = attr; 
     1104 
     1105    return PJ_SUCCESS; 
     1106} 
     1107 
     1108/* Create and add STUN generic 64bit value attribute to the message. */ 
     1109PJ_DEF(pj_status_t)  pj_stun_msg_add_uint64_attr(pj_pool_t *pool, 
     1110                                                 pj_stun_msg *msg, 
     1111                                                 int attr_type, 
     1112                                                 const pj_timestamp *value) 
     1113{ 
     1114    pj_stun_uint64_attr *attr = NULL; 
     1115    pj_status_t status; 
     1116 
     1117    status = pj_stun_uint64_attr_create(pool, attr_type, value, &attr); 
     1118    if (status != PJ_SUCCESS) 
     1119        return status; 
     1120 
     1121    return pj_stun_msg_add_attr(msg, &attr->hdr); 
     1122} 
     1123 
     1124static pj_status_t decode_uint64_attr(pj_pool_t *pool,  
     1125                                      const pj_uint8_t *buf,  
     1126                                      void **p_attr) 
     1127{ 
     1128    pj_stun_uint64_attr *attr; 
     1129 
     1130    /* Create the attribute */ 
     1131    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_uint64_attr); 
     1132    GETATTRHDR(buf, &attr->hdr); 
     1133 
     1134    if (attr->hdr.length != 8) 
     1135        return PJNATH_ESTUNINATTRLEN; 
     1136 
     1137    GETVAL64H(buf, 4, &attr->value);     
     1138 
     1139    /* Done */ 
     1140    *p_attr = attr; 
     1141 
     1142    return PJ_SUCCESS; 
     1143} 
     1144 
     1145 
     1146static pj_status_t encode_uint64_attr(const void *a, pj_uint8_t *buf,  
     1147                                      unsigned len, unsigned *printed) 
     1148{ 
     1149    const pj_stun_uint64_attr *ca = (const pj_stun_uint64_attr*)a; 
     1150 
     1151    if (len < 12)  
     1152        return PJ_ETOOSMALL; 
     1153 
     1154    PUTVAL16H(buf, 0, ca->hdr.type); 
     1155    PUTVAL16H(buf, 2, ca->hdr.length); 
     1156    PUTVAL64H(buf, 4, &ca->value); 
     1157 
     1158    /* Done */ 
     1159    *printed = 12; 
     1160 
     1161    return PJ_SUCCESS; 
     1162} 
     1163 
     1164 
     1165////////////////////////////////////////////////////////////////////////////// 
    10751166/* 
    10761167 * STUN MESSAGE-INTEGRITY attribute. 
    10771168 */ 
    1078  
    1079 #define STUN_MSG_INTEGRITY_LEN  20 
    10801169 
    10811170/* 
     
    10911180 
    10921181    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_msgint_attr); 
    1093     INIT_ATTR(attr, PJ_STUN_ATTR_MESSAGE_INTEGRITY, STUN_MSG_INTEGRITY_LEN); 
     1182    INIT_ATTR(attr, PJ_STUN_ATTR_MESSAGE_INTEGRITY, 20); 
    10941183 
    10951184    *p_attr = attr; 
     
    11161205                                      void **p_attr) 
    11171206{ 
    1118     enum 
    1119     { 
    1120         ATTR_LEN = STUN_MSG_INTEGRITY_LEN + ATTR_HDR_LEN 
    1121     }; 
    11221207    pj_stun_msgint_attr *attr; 
    1123  
    1124     /* Check that struct size is valid */ 
    1125     pj_assert(sizeof(pj_stun_msgint_attr)==ATTR_LEN); 
    11261208 
    11271209    /* Create attribute */ 
    11281210    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_msgint_attr); 
    1129     pj_memcpy(attr, buf, sizeof(pj_stun_msgint_attr)); 
    1130     attr->hdr.type = pj_ntohs(attr->hdr.type); 
    1131     attr->hdr.length = pj_ntohs(attr->hdr.length); 
     1211    GETATTRHDR(buf, &attr->hdr); 
    11321212 
    11331213    /* Check that the attribute length is valid */ 
    1134     if (attr->hdr.length != STUN_MSG_INTEGRITY_LEN) 
     1214    if (attr->hdr.length != 20) 
    11351215        return PJNATH_ESTUNINATTRLEN; 
     1216 
     1217    /* Copy hmac */ 
     1218    pj_memcpy(attr->hmac, buf+4, 20); 
    11361219 
    11371220    /* Done */ 
     
    11441227                                      unsigned len, unsigned *printed) 
    11451228{ 
    1146     enum 
    1147     { 
    1148         ATTR_LEN = STUN_MSG_INTEGRITY_LEN + ATTR_HDR_LEN 
    1149     }; 
    1150     pj_stun_msgint_attr *attr; 
    1151  
    1152     if (len < ATTR_LEN)  
     1229    const pj_stun_msgint_attr *ca = (const pj_stun_msgint_attr*)a; 
     1230 
     1231    if (len < 24)  
    11531232        return PJ_ETOOSMALL; 
    11541233 
    11551234    /* Copy and convert attribute to network byte order */ 
    1156     pj_memcpy(buf, a, ATTR_LEN); 
    1157     attr = (pj_stun_msgint_attr*) buf; 
    1158     attr->hdr.type = pj_htons(attr->hdr.type); 
    1159     pj_assert(attr->hdr.length == STUN_MSG_INTEGRITY_LEN); 
    1160     attr->hdr.length = pj_htons(STUN_MSG_INTEGRITY_LEN); 
     1235    PUTVAL16H(buf, 0, ca->hdr.type); 
     1236    PUTVAL16H(buf, 2, ca->hdr.length); 
     1237 
     1238    pj_memcpy(buf+4, ca->hmac, 20); 
    11611239 
    11621240    /* Done */ 
    1163     *printed = ATTR_LEN; 
     1241    *printed = 24; 
    11641242 
    11651243    return PJ_SUCCESS; 
     
    11981276    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_errcode_attr); 
    11991277    INIT_ATTR(attr, PJ_STUN_ATTR_ERROR_CODE, 4+err_reason->slen); 
    1200     attr->err_class = (pj_uint8_t)(err_code / 100); 
    1201     attr->number = (pj_uint8_t) (err_code % 100); 
     1278    attr->err_code = err_code; 
    12021279    pj_strdup(pool, &attr->reason, err_reason); 
    12031280 
     
    12331310    /* Create the attribute */ 
    12341311    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_errcode_attr); 
    1235  
    1236     /* Copy the header */ 
    1237     pj_memcpy(attr, buf, ATTR_HDR_LEN + 4); 
    1238  
    1239     /* Convert to host byte order */ 
    1240     attr->hdr.type = pj_ntohs(attr->hdr.type); 
    1241     attr->hdr.length = pj_ntohs(attr->hdr.length); 
     1312    GETATTRHDR(buf, &attr->hdr); 
     1313 
     1314    attr->err_code = buf[6] * 100 + buf[7]; 
    12421315 
    12431316    /* Get pointer to the string in the message */ 
     
    12601333    const pj_stun_errcode_attr *ca =  
    12611334        (const pj_stun_errcode_attr*)a; 
    1262     pj_stun_errcode_attr *attr; 
    12631335 
    12641336    if (len < ATTR_HDR_LEN + 4 + (unsigned)ca->reason.slen)  
     
    12661338 
    12671339    /* Copy and convert attribute to network byte order */ 
    1268     pj_memcpy(buf, ca, ATTR_HDR_LEN + 4); 
    1269  
    1270     /* Update length */ 
    1271     attr = (pj_stun_errcode_attr*) buf; 
    1272     attr->hdr.length = (pj_uint16_t)(4 + ca->reason.slen); 
    1273  
    1274     /* Convert fiends to network byte order */ 
    1275     attr->hdr.type = pj_htons(attr->hdr.type); 
    1276     attr->hdr.length = pj_htons(attr->hdr.length); 
     1340    PUTVAL16H(buf, 0, ca->hdr.type); 
     1341    PUTVAL16H(buf, 2, (pj_uint16_t)(4 + ca->reason.slen)); 
     1342    PUTVAL16H(buf, 4, 0); 
     1343    buf[6] = (pj_uint8_t)(ca->err_code / 100); 
     1344    buf[7] = (pj_uint8_t)(ca->err_code % 100); 
    12771345 
    12781346    /* Copy error string */ 
     
    13561424 
    13571425    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_unknown_attr); 
    1358     pj_memcpy(attr, buf, ATTR_HDR_LEN); 
    1359  
    1360     attr->hdr.type = pj_ntohs(attr->hdr.type); 
    1361     attr->hdr.length = pj_ntohs(attr->hdr.length); 
    1362  
     1426    GETATTRHDR(buf, &attr->hdr); 
     1427  
    13631428    attr->attr_count = (attr->hdr.length >> 1); 
    13641429    if (attr->attr_count > PJ_STUN_MAX_ATTR) 
     
    13811446{ 
    13821447    const pj_stun_unknown_attr *ca = (const pj_stun_unknown_attr*) a; 
    1383     pj_stun_unknown_attr *attr; 
    13841448    pj_uint16_t *dst_unk_attr; 
    13851449    unsigned i; 
     
    13891453        return PJ_ETOOSMALL; 
    13901454 
    1391     /* Copy to message */ 
    1392     pj_memcpy(buf, ca, ATTR_HDR_LEN); 
    1393  
    1394     /* Set the correct length */ 
    1395     attr = (pj_stun_unknown_attr *) buf; 
    1396     attr->hdr.length = (pj_uint16_t)(ca->attr_count << 1); 
    1397  
    1398     /* Convert to network byte order */ 
    1399     attr->hdr.type = pj_htons(attr->hdr.type); 
    1400     attr->hdr.length = pj_htons(attr->hdr.length); 
     1455    PUTVAL16H(buf, 0, ca->hdr.type); 
     1456    PUTVAL16H(buf, 2, (pj_uint16_t)(ca->attr_count << 1)); 
    14011457 
    14021458    /* Copy individual attribute */ 
    14031459    dst_unk_attr = (pj_uint16_t*)(buf + ATTR_HDR_LEN); 
    14041460    for (i=0; i < ca->attr_count; ++i, ++dst_unk_attr) { 
    1405         *dst_unk_attr = pj_htons(attr->attrs[i]); 
     1461        *dst_unk_attr = pj_htons(ca->attrs[i]); 
    14061462    } 
    14071463 
     
    14331489 
    14341490    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_binary_attr); 
    1435     INIT_ATTR(attr, attr_type, sizeof(pj_stun_binary_attr)); 
     1491    INIT_ATTR(attr, attr_type, length); 
    14361492 
    14371493    if (data && length) { 
     
    14751531    /* Create the attribute */ 
    14761532    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_binary_attr); 
    1477  
    1478     /* Copy the header */ 
    1479     pj_memcpy(attr, buf, ATTR_HDR_LEN); 
    1480  
    1481     /* Convert to host byte order */ 
    1482     attr->hdr.type = pj_ntohs(attr->hdr.type); 
    1483     attr->hdr.length = pj_ntohs(attr->hdr.length); 
     1533    GETATTRHDR(buf, &attr->hdr); 
    14841534 
    14851535    /* Copy the data to the attribute */ 
     
    15001550{ 
    15011551    const pj_stun_binary_attr *ca = (const pj_stun_binary_attr*)a; 
    1502     pj_stun_attr_hdr *attr; 
    15031552 
    15041553    /* Calculated total attr_len (add padding if necessary) */ 
     
    15071556        return PJ_ETOOSMALL; 
    15081557 
    1509     /* Copy header */ 
    1510     pj_memcpy(buf, a, ATTR_HDR_LEN); 
    1511  
    1512     /* Set the correct length */ 
    1513     attr = (pj_stun_attr_hdr*)buf; 
    1514     attr->length = (pj_uint16_t) ca->length; 
    1515  
    1516     /* Convert to network byte order */ 
    1517     attr->type = pj_htons(attr->type); 
    1518     attr->length = pj_htons(attr->length); 
     1558    PUTVAL16H(buf, 0, ca->hdr.type); 
     1559    PUTVAL16H(buf, 2, (pj_uint16_t) ca->length); 
    15191560 
    15201561    /* Copy the data */ 
     
    15831624 
    15841625 
    1585 PJ_INLINE(pj_uint16_t) GET_VAL16(const pj_uint8_t *pdu, unsigned pos) 
    1586 { 
    1587     return (pj_uint16_t) ((pdu[pos] << 8) + pdu[pos+1]); 
    1588 } 
    1589  
    1590 PJ_INLINE(pj_uint32_t) GET_VAL32(const pj_uint8_t *pdu, unsigned pos) 
    1591 { 
    1592     return (pdu[pos+0] << 24) + 
    1593            (pdu[pos+1] << 16) + 
    1594            (pdu[pos+2] <<  8) + 
    1595            (pdu[pos+3]); 
    1596 } 
    1597  
    1598  
    15991626/* 
    16001627 * Check that the PDU is potentially a valid STUN message. 
     
    16151642 
    16161643    /* Check the PDU length */ 
    1617     msg_len = GET_VAL16(pdu, 2); 
     1644    msg_len = GETVAL16H(pdu, 2); 
    16181645    if ((msg_len + 20 > pdu_len) ||  
    16191646        ((options & PJ_STUN_IS_DATAGRAM) && msg_len + 20 != pdu_len)) 
     
    16251652     * a STUN message. 
    16261653     */ 
    1627     if (GET_VAL32(pdu, 4) == PJ_STUN_MAGIC) { 
     1654    if (GETVAL32H(pdu, 4) == PJ_STUN_MAGIC) { 
    16281655 
    16291656        /* Check if FINGERPRINT attribute is present */ 
    1630         if (GET_VAL16(pdu, msg_len + 20) == PJ_STUN_ATTR_FINGERPRINT) { 
    1631             pj_uint16_t attr_len = GET_VAL16(pdu, msg_len + 22); 
    1632             pj_uint32_t fingerprint = GET_VAL32(pdu, msg_len + 24); 
     1657        if (GETVAL16H(pdu, msg_len + 20) == PJ_STUN_ATTR_FINGERPRINT) { 
     1658            pj_uint16_t attr_len = GETVAL16H(pdu, msg_len + 22); 
     1659            pj_uint32_t fingerprint = GETVAL32H(pdu, msg_len + 24); 
    16331660            pj_uint32_t crc; 
    16341661 
  • pjproject/trunk/pjnath/src/pjnath/stun_msg_dump.c

    r1080 r1114  
    141141            len = pj_ansi_snprintf(p, end-p, 
    142142                                   ", err_code=%d, reason=\"%.*s\"\n", 
    143                                    attr->err_class*100 + attr->number, 
     143                                   attr->err_code, 
    144144                                   (int)attr->reason.slen, 
    145145                                   attr->reason.ptr); 
  • pjproject/trunk/pjnath/src/pjnath/stun_transaction.c

    r1111 r1114  
    285285                pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_ERROR_CODE, 0); 
    286286 
    287     if (err_attr && err_attr->err_class <= 2) { 
     287    if (err_attr && err_attr->err_code <= 200) { 
    288288        /* draft-ietf-behave-rfc3489bis-05.txt Section 8.3.2: 
    289289         * Any response between 100 and 299 MUST result in the cessation 
     
    292292        PJ_LOG(4,(tsx->obj_name,  
    293293                  "STUN rx_msg() error: received provisional %d code (%.*s)", 
    294                   err_attr->err_class * 100 + err_attr->number, 
     294                  err_attr->err_code, 
    295295                  (int)err_attr->reason.slen, 
    296296                  err_attr->reason.ptr)); 
     
    301301        status = PJ_SUCCESS; 
    302302    } else { 
    303         status = PJ_STATUS_FROM_STUN_CODE(err_attr->err_class * 100 +  
    304                                           err_attr->number); 
     303        status = PJ_STATUS_FROM_STUN_CODE(err_attr->err_code); 
    305304    } 
    306305 
Note: See TracChangeset for help on using the changeset viewer.