Changeset 1052


Ignore:
Timestamp:
Mar 9, 2007 11:25:11 PM (12 years ago)
Author:
bennylp
Message:

Today's work on TURN server. All looks to be implemented

Location:
pjproject/trunk/pjlib-util
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib-util/include/pjlib-util/stun_msg.h

    r1049 r1052  
    335335    PJ_STUN_ATTR_LIFETIME           = 0x000D,/**< LIFETIME attribute.       */ 
    336336    PJ_STUN_ATTR_BANDWIDTH          = 0x0010,/**< BANDWIDTH attribute       */ 
    337     PJ_STUN_ATTR_REMOTE_ADDRESS     = 0x0012,/**< REMOTE-ADDRESS attribute  */ 
     337    PJ_STUN_ATTR_REMOTE_ADDR        = 0x0012,/**< REMOTE-ADDRESS attribute  */ 
    338338    PJ_STUN_ATTR_DATA               = 0x0013,/**< DATA attribute.           */ 
    339339    PJ_STUN_ATTR_REALM              = 0x0014,/**< REALM attribute.          */ 
     
    355355    PJ_STUN_ATTR_START_EXTENDED_ATTR= 0x8021, 
    356356 
    357     PJ_STUN_ATTR_FINGERPRINT        = 0x8021,/**< FINGERPRINT attribute.    */ 
    358357    PJ_STUN_ATTR_SERVER             = 0x8022,/**< SERVER attribute.         */ 
    359358    PJ_STUN_ATTR_ALTERNATE_SERVER   = 0x8023,/**< ALTERNATE-SERVER.         */ 
    360359    PJ_STUN_ATTR_REFRESH_INTERVAL   = 0x8024,/**< REFRESH-INTERVAL.         */ 
     360    PJ_STUN_ATTR_FINGERPRINT        = 0x8028,/**< FINGERPRINT attribute.    */ 
    361361 
    362362    PJ_STUN_ATTR_END_EXTENDED_ATTR 
     
    370370typedef enum pj_stun_status 
    371371{ 
    372     PJ_STUN_STATUS_TRY_ALTERNATE            = 300,  /**< Try Alternate      */ 
    373     PJ_STUN_STATUS_BAD_REQUEST              = 400,  /**< Bad Request        */ 
    374     PJ_STUN_STATUS_UNAUTHORIZED             = 401,  /**< Unauthorized       */ 
    375     PJ_STUN_STATUS_UNKNOWN_ATTRIBUTE        = 420,  /**< Unknown Attribute  */ 
    376     PJ_STUN_STATUS_STALE_CREDENTIALS        = 430,  /**< Stale Credentials  */ 
    377     PJ_STUN_STATUS_INTEGRITY_CHECK_FAILURE  = 431,  /**< Integrity Chk Fail */ 
    378     PJ_STUN_STATUS_MISSING_USERNAME         = 432,  /**< Missing Username   */ 
    379     PJ_STUN_STATUS_USE_TLS                  = 433,  /**< Use TLS            */ 
    380     PJ_STUN_STATUS_MISSING_REALM            = 434,  /**< Missing Realm      */ 
    381     PJ_STUN_STATUS_MISSING_NONCE            = 435,  /**< Missing Nonce      */ 
    382     PJ_STUN_STATUS_UNKNOWN_USERNAME         = 436,  /**< Unknown Username   */ 
    383     PJ_STUN_STATUS_NO_BINDING               = 437,  /**< No Binding.        */ 
    384     PJ_STUN_STATUS_STALE_NONCE              = 438,  /**< Stale Nonce        */ 
    385     PJ_STUN_STATUS_TRANSITIONING            = 439,  /**< Transitioning.     */ 
    386     PJ_STUN_STATUS_WRONG_USERNAME           = 441,  /**< Wrong Username.    */ 
    387     PJ_STUN_STATUS_UNSUPP_TRANSPORT_PROTO   = 442,  /**< Unsupported Transport Protocol */ 
    388     PJ_STUN_STATUS_INVALID_IP_ADDR          = 443,  /**< Invalid IP Address */ 
    389     PJ_STUN_STATUS_INVALID_PORT             = 444,  /**< Invalid Port       */ 
    390     PJ_STUN_STATUS_OPER_TCP_ONLY            = 445,  /**< Operation for TCP Only */ 
    391     PJ_STUN_STATUS_CONNECTION_FAILURE       = 446,  /**< Connection Failure */ 
    392     PJ_STUN_STATUS_CONNECTION_TIMEOUT       = 447,  /**< Connection Timeout */ 
    393     PJ_STUN_STATUS_ALLOCATION_QUOTA_REACHED = 486,  /**< Allocation Quota Reached (TURN) */ 
    394     PJ_STUN_STATUS_SERVER_ERROR             = 500,  /**< Server Error       */ 
    395     PJ_STUN_STATUS_INSUFFICIENT_CAPACITY    = 507,  /**< Insufficient Capacity (TURN) */ 
    396     PJ_STUN_STATUS_GLOBAL_FAILURE           = 600   /**< Global Failure     */ 
     372    PJ_STUN_SC_TRY_ALTERNATE            = 300,  /**< Try Alternate          */ 
     373    PJ_STUN_SC_BAD_REQUEST              = 400,  /**< Bad Request            */ 
     374    PJ_STUN_SC_UNAUTHORIZED             = 401,  /**< Unauthorized           */ 
     375    PJ_STUN_SC_UNKNOWN_ATTRIBUTE        = 420,  /**< Unknown Attribute      */ 
     376    PJ_STUN_SC_STALE_CREDENTIALS        = 430,  /**< Stale Credentials      */ 
     377    PJ_STUN_SC_INTEGRITY_CHECK_FAILURE  = 431,  /**< Integrity Chk Fail     */ 
     378    PJ_STUN_SC_MISSING_USERNAME         = 432,  /**< Missing Username       */ 
     379    PJ_STUN_SC_USE_TLS                  = 433,  /**< Use TLS                */ 
     380    PJ_STUN_SC_MISSING_REALM            = 434,  /**< Missing Realm          */ 
     381    PJ_STUN_SC_MISSING_NONCE            = 435,  /**< Missing Nonce          */ 
     382    PJ_STUN_SC_UNKNOWN_USERNAME         = 436,  /**< Unknown Username       */ 
     383    PJ_STUN_SC_NO_BINDING               = 437,  /**< No Binding.            */ 
     384    PJ_STUN_SC_STALE_NONCE              = 438,  /**< Stale Nonce            */ 
     385    PJ_STUN_SC_TRANSITIONING            = 439,  /**< Transitioning.         */ 
     386    PJ_STUN_SC_WRONG_USERNAME           = 441,  /**< Wrong Username.        */ 
     387    PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO   = 442,  /**< Unsupported Transport or 
     388                                                     Protocol */ 
     389    PJ_STUN_SC_INVALID_IP_ADDR          = 443,  /**< Invalid IP Address     */ 
     390    PJ_STUN_SC_INVALID_PORT             = 444,  /**< Invalid Port           */ 
     391    PJ_STUN_SC_OPER_TCP_ONLY            = 445,  /**< Operation for TCP Only */ 
     392    PJ_STUN_SC_CONNECTION_FAILURE       = 446,  /**< Connection Failure     */ 
     393    PJ_STUN_SC_CONNECTION_TIMEOUT       = 447,  /**< Connection Timeout     */ 
     394    PJ_STUN_SC_ALLOCATION_QUOTA_REACHED = 486,  /**< Allocation Quota Reached 
     395                                                     (TURN) */ 
     396    PJ_STUN_SC_SERVER_ERROR             = 500,  /**< Server Error           */ 
     397    PJ_STUN_SC_INSUFFICIENT_CAPACITY    = 507,  /**< Insufficient Capacity  
     398                                                     (TURN) */ 
     399    PJ_STUN_SC_GLOBAL_FAILURE           = 600   /**< Global Failure         */ 
    397400} pj_stun_status; 
    398401 
  • pjproject/trunk/pjlib-util/include/pjlib-util/stun_session.h

    r1037 r1052  
    139139    pj_stun_session     *sess;          /**< The STUN session.              */ 
    140140    pj_stun_msg         *msg;           /**< The STUN message.              */ 
    141     void                *user_data;     /**< Arbitrary user data.           */ 
    142141 
    143142    pj_stun_client_tsx  *client_tsx;    /**< Client STUN transaction.       */ 
     
    233232 
    234233/** 
    235  * Create a STUN Bind request message. After the message has been  
    236  * successfully created, application can send the message by calling  
     234 * Create a STUN request message. After the message has been successfully 
     235 * created, application can send the message by calling  
    237236 * pj_stun_session_send_msg(). 
    238237 * 
    239238 * @param sess      The STUN session instance. 
     239 * @param msg_type  The STUN request message type, from pj_stun_method_e or 
     240 *                  from pj_stun_msg_type. 
    240241 * @param p_tdata   Pointer to receive STUN transmit data instance containing 
    241242 *                  the request. 
     
    243244 * @return          PJ_SUCCESS on success, or the appropriate error code. 
    244245 */ 
    245 PJ_DECL(pj_status_t) pj_stun_session_create_bind_req(pj_stun_session *sess, 
    246                                                      pj_stun_tx_data **p_tdata); 
    247  
    248 /** 
    249  * Create a STUN Allocate request message. After the message has been 
    250  * successfully created, application can send the message by calling   
     246PJ_DECL(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, 
     247                                                int msg_type, 
     248                                                pj_stun_tx_data **p_tdata); 
     249 
     250/** 
     251 * Create a STUN Indication message. After the message  has been successfully 
     252 * created, application can send the message by calling  
    251253 * pj_stun_session_send_msg(). 
    252254 * 
    253255 * @param sess      The STUN session instance. 
    254  * @param p_tdata   Pointer to receive STUN transmit data instance containing 
    255  *                  the request. 
    256  * 
    257  * @return          PJ_SUCCESS on success, or the appropriate error code. 
    258  */ 
    259 PJ_DECL(pj_status_t) pj_stun_session_create_allocate_req(pj_stun_session *sess, 
    260                                                          pj_stun_tx_data **p_tdata); 
    261  
    262 /** 
    263  * Create a STUN Set Active Destination request message. After the message  
    264  * has been successfully created, application can send the message by calling 
    265  * pj_stun_session_send_msg(). 
    266  * 
    267  * @param sess      The STUN session instance. 
    268  * @param p_tdata   Pointer to receive STUN transmit data instance containing 
    269  *                  the request. 
    270  * 
    271  * @return          PJ_SUCCESS on success, or the appropriate error code. 
    272  */ 
    273 PJ_DECL(pj_status_t)  
    274 pj_stun_session_create_set_active_destination_req(pj_stun_session *sess, 
    275                                                   pj_stun_tx_data **p_tdata); 
    276  
    277 /** 
    278  * Create a STUN Connect request message. After the message has been  
    279  * successfully created, application can send the message by calling  
    280  * pj_stun_session_send_msg(). 
    281  * 
    282  * @param sess      The STUN session instance. 
    283  * @param p_tdata   Pointer to receive STUN transmit data instance containing 
    284  *                  the request. 
    285  * 
    286  * @return          PJ_SUCCESS on success, or the appropriate error code. 
    287  */ 
    288 PJ_DECL(pj_status_t) pj_stun_session_create_connect_req(pj_stun_session *sess, 
    289                                                         pj_stun_tx_data **p_tdata); 
    290  
    291 /** 
    292  * Create a STUN Connection Status Indication message. After the message  
    293  * has been successfully created, application can send the message by calling 
    294  * pj_stun_session_send_msg(). 
    295  * 
    296  * @param sess      The STUN session instance. 
     256 * @param msg_type  The STUN request message type, from pj_stun_method_e or 
     257 *                  from pj_stun_msg_type. This function will add the 
     258 *                  indication bit as necessary. 
    297259 * @param p_tdata   Pointer to receive STUN transmit data instance containing 
    298260 *                  the message. 
     
    300262 * @return          PJ_SUCCESS on success, or the appropriate error code. 
    301263 */ 
    302 PJ_DECL(pj_status_t) 
    303 pj_stun_session_create_connection_status_ind(pj_stun_session *sess, 
    304                                              pj_stun_tx_data **p_tdata); 
    305  
    306 /** 
    307  * Create a STUN Send Indication message. After the message has been  
    308  * successfully created, application can send the message by calling  
    309  * pj_stun_session_send_msg(). 
    310  * 
    311  * @param sess      The STUN session instance. 
    312  * @param p_tdata   Pointer to receive STUN transmit data instance containing 
    313  *                  the message. 
    314  * 
    315  * @return          PJ_SUCCESS on success, or the appropriate error code. 
    316  */ 
    317 PJ_DECL(pj_status_t) pj_stun_session_create_send_ind(pj_stun_session *sess, 
    318                                                      pj_stun_tx_data **p_tdata); 
    319  
    320 /** 
    321  * Create a STUN Data Indication message. After the message has been  
    322  * successfully created, application can send the message by calling  
    323  * pj_stun_session_send_msg(). 
    324  * 
    325  * @param sess      The STUN session instance. 
    326  * @param p_tdata   Pointer to receive STUN transmit data instance containing 
    327  *                  the message. 
    328  * 
    329  * @return          PJ_SUCCESS on success, or the appropriate error code. 
    330  */ 
    331 PJ_DECL(pj_status_t) pj_stun_session_create_data_ind(pj_stun_session *sess, 
    332                                                      pj_stun_tx_data **p_tdata); 
     264PJ_DECL(pj_status_t) pj_stun_session_create_ind(pj_stun_session *sess, 
     265                                                int msg_type, 
     266                                                pj_stun_tx_data **p_tdata); 
    333267 
    334268/** 
     
    400334 * @param packet     The packet containing STUN message. 
    401335 * @param pkt_size   Size of the packet. 
    402  * @param options    Options, from pj_stun_options. 
     336 * @param options    Options, from #pj_stun_decode_options. 
    403337 * @param parsed_len Optional pointer to receive the size of the parsed 
    404338 *                   STUN message (useful if packet is received via a 
  • pjproject/trunk/pjlib-util/src/pjlib-util/stun_auth.c

    r1037 r1052  
    157157    if (amsgi == NULL) { 
    158158        if (p_response) { 
    159             create_challenge(pool, msg, PJ_STUN_STATUS_UNAUTHORIZED, NULL, 
     159            create_challenge(pool, msg, PJ_STUN_SC_UNAUTHORIZED, NULL, 
    160160                             &realm, &nonce, p_response); 
    161161        } 
     
    168168    if (auser == NULL) { 
    169169        if (p_response) { 
    170             create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_USERNAME, NULL, 
     170            create_challenge(pool, msg, PJ_STUN_SC_MISSING_USERNAME, NULL, 
    171171                             &realm, &nonce, p_response); 
    172172        } 
     
    199199        /* Username mismatch */ 
    200200        if (p_response) { 
    201             create_challenge(pool, msg, PJ_STUN_STATUS_UNKNOWN_USERNAME, NULL, 
     201            create_challenge(pool, msg, PJ_STUN_SC_UNKNOWN_USERNAME, NULL, 
    202202                             &realm, &nonce, p_response); 
    203203        } 
     
    214214        /* Long term credential is required and REALM is not present */ 
    215215        if (p_response) { 
    216             create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_REALM, NULL, 
     216            create_challenge(pool, msg, PJ_STUN_SC_MISSING_REALM, NULL, 
    217217                             &realm, &nonce, p_response); 
    218218        } 
     
    225225        if (anonce == NULL) { 
    226226            if (p_response) { 
    227                 create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_NONCE,  
     227                create_challenge(pool, msg, PJ_STUN_SC_MISSING_NONCE,  
    228228                                 NULL, &realm, &nonce, p_response); 
    229229            } 
     
    235235            /* REALM doesn't match */ 
    236236            if (p_response) { 
    237                 create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_REALM,  
     237                create_challenge(pool, msg, PJ_STUN_SC_MISSING_REALM,  
    238238                                 NULL, &realm, &nonce, p_response); 
    239239            } 
     
    258258        if (nonce.slen != 0) { 
    259259            if (p_response) { 
    260                 create_challenge(pool, msg, PJ_STUN_STATUS_MISSING_NONCE,  
     260                create_challenge(pool, msg, PJ_STUN_SC_MISSING_NONCE,  
    261261                                 NULL, &realm, &nonce, p_response); 
    262262            } 
     
    284284        if (!ok) { 
    285285            if (p_response) { 
    286                 create_challenge(pool, msg, PJ_STUN_STATUS_STALE_NONCE,  
     286                create_challenge(pool, msg, PJ_STUN_SC_STALE_NONCE,  
    287287                                 NULL, &realm, &nonce, p_response); 
    288288            } 
     
    329329        /* HMAC value mismatch */ 
    330330        if (p_response) { 
    331             create_challenge(pool, msg, PJ_STUN_STATUS_INTEGRITY_CHECK_FAILURE, 
     331            create_challenge(pool, msg, PJ_STUN_SC_INTEGRITY_CHECK_FAILURE, 
    332332                             NULL, &realm, &nonce, p_response); 
    333333        } 
  • pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg.c

    r1049 r1052  
    5151} stun_err_msg_map[] =  
    5252{ 
    53     { PJ_STUN_STATUS_TRY_ALTERNATE,         "Try Alternate"},  
    54     { PJ_STUN_STATUS_BAD_REQUEST,           "Bad Request"}, 
    55     { PJ_STUN_STATUS_UNAUTHORIZED,          "Unauthorized"}, 
    56     { PJ_STUN_STATUS_UNKNOWN_ATTRIBUTE,     "Unknown Attribute"}, 
    57     { PJ_STUN_STATUS_STALE_CREDENTIALS,     "Stale Credentials"}, 
    58     { PJ_STUN_STATUS_INTEGRITY_CHECK_FAILURE,"Integrity Check Failure"}, 
    59     { PJ_STUN_STATUS_MISSING_USERNAME,      "Missing Username"}, 
    60     { PJ_STUN_STATUS_USE_TLS,               "Use TLS"}, 
    61     { PJ_STUN_STATUS_MISSING_REALM,         "Missing Realm"}, 
    62     { PJ_STUN_STATUS_MISSING_NONCE,         "Missing Nonce"}, 
    63     { PJ_STUN_STATUS_UNKNOWN_USERNAME,      "Unknown Username"}, 
    64     { PJ_STUN_STATUS_NO_BINDING,            "No Binding"}, 
    65     { PJ_STUN_STATUS_STALE_NONCE,           "Stale Nonce"}, 
    66     { PJ_STUN_STATUS_TRANSITIONING,         "Transitioning"}, 
    67     { PJ_STUN_STATUS_WRONG_USERNAME,        "Wrong Username"}, 
    68     { PJ_STUN_STATUS_UNSUPP_TRANSPORT_PROTO,"Unsupported Transport Protocol"}, 
    69     { PJ_STUN_STATUS_INVALID_IP_ADDR,       "Invalid IP Address"}, 
    70     { PJ_STUN_STATUS_INVALID_PORT,          "Invalid Port"}, 
    71     { PJ_STUN_STATUS_OPER_TCP_ONLY,         "Operation for TCP Only"}, 
    72     { PJ_STUN_STATUS_CONNECTION_FAILURE,    "Connection Failure"}, 
    73     { PJ_STUN_STATUS_CONNECTION_TIMEOUT,    "Connection Timeout"}, 
    74     { PJ_STUN_STATUS_ALLOCATION_QUOTA_REACHED, "Allocation Quota Reached"}, 
    75     { PJ_STUN_STATUS_SERVER_ERROR,          "Server Error"}, 
    76     { PJ_STUN_STATUS_INSUFFICIENT_CAPACITY, "Insufficient Capacity"}, 
    77     { PJ_STUN_STATUS_GLOBAL_FAILURE,        "Global Failure"} 
     53    { PJ_STUN_SC_TRY_ALTERNATE,             "Try Alternate"},  
     54    { PJ_STUN_SC_BAD_REQUEST,               "Bad Request"}, 
     55    { PJ_STUN_SC_UNAUTHORIZED,              "Unauthorized"}, 
     56    { PJ_STUN_SC_UNKNOWN_ATTRIBUTE,         "Unknown Attribute"}, 
     57    { PJ_STUN_SC_STALE_CREDENTIALS,         "Stale Credentials"}, 
     58    { PJ_STUN_SC_INTEGRITY_CHECK_FAILURE,   "Integrity Check Failure"}, 
     59    { PJ_STUN_SC_MISSING_USERNAME,          "Missing Username"}, 
     60    { PJ_STUN_SC_USE_TLS,                   "Use TLS"}, 
     61    { PJ_STUN_SC_MISSING_REALM,             "Missing Realm"}, 
     62    { PJ_STUN_SC_MISSING_NONCE,             "Missing Nonce"}, 
     63    { PJ_STUN_SC_UNKNOWN_USERNAME,          "Unknown Username"}, 
     64    { PJ_STUN_SC_NO_BINDING,                "No Binding"}, 
     65    { PJ_STUN_SC_STALE_NONCE,               "Stale Nonce"}, 
     66    { PJ_STUN_SC_TRANSITIONING,             "Active Destination Already Set"}, 
     67    { PJ_STUN_SC_WRONG_USERNAME,            "Wrong Username"}, 
     68    { PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO,    "Unsupported Transport Protocol"}, 
     69    { PJ_STUN_SC_INVALID_IP_ADDR,           "Invalid IP Address"}, 
     70    { PJ_STUN_SC_INVALID_PORT,              "Invalid Port"}, 
     71    { PJ_STUN_SC_OPER_TCP_ONLY,             "Operation for TCP Only"}, 
     72    { PJ_STUN_SC_CONNECTION_FAILURE,        "Connection Failure"}, 
     73    { PJ_STUN_SC_CONNECTION_TIMEOUT,        "Connection Timeout"}, 
     74    { PJ_STUN_SC_ALLOCATION_QUOTA_REACHED, "Allocation Quota Reached"}, 
     75    { PJ_STUN_SC_SERVER_ERROR,              "Server Error"}, 
     76    { PJ_STUN_SC_INSUFFICIENT_CAPACITY,    "Insufficient Capacity"}, 
     77    { PJ_STUN_SC_GLOBAL_FAILURE,            "Global Failure"} 
    7878}; 
    7979 
     
    382382{ 
    383383    { 
     384        /* ID 0x8021 is not assigned */ 
     385        NULL, 
     386        NULL, 
     387        NULL 
     388    }, 
     389    { 
     390        /* PJ_STUN_ATTR_SERVER, */ 
     391        "SERVER", 
     392        &decode_string_attr, 
     393        &encode_string_attr 
     394    }, 
     395    { 
     396        /* PJ_STUN_ATTR_ALTERNATE_SERVER, */ 
     397        "ALTERNATE-SERVER", 
     398        &decode_ip_addr_attr, 
     399        &encode_ip_addr_attr 
     400    }, 
     401    { 
     402        /* PJ_STUN_ATTR_REFRESH_INTERVAL, */ 
     403        "REFRESH-INTERVAL", 
     404        &decode_uint_attr, 
     405        &encode_uint_attr 
     406    }, 
     407    { 
     408        /* Unassigned, 0x8025 */ 
     409        NULL, 
     410        NULL, 
     411        NULL 
     412    }, 
     413    { 
     414        /* Padding, 0x8026 */ 
     415        NULL, 
     416        NULL, 
     417        NULL 
     418    }, 
     419    { 
     420        /* Padding, 0x8027 */ 
     421        NULL, 
     422        NULL, 
     423        NULL 
     424    }, 
     425    { 
    384426        /* PJ_STUN_ATTR_FINGERPRINT, */ 
    385427        "FINGERPRINT", 
    386428        &decode_uint_attr, 
    387429        &encode_uint_attr 
    388     }, 
    389     { 
    390         /* PJ_STUN_ATTR_SERVER, */ 
    391         "SERVER", 
    392         &decode_string_attr, 
    393         &encode_string_attr 
    394     }, 
    395     { 
    396         /* PJ_STUN_ATTR_ALTERNATE_SERVER, */ 
    397         "ALTERNATE-SERVER", 
    398         &decode_ip_addr_attr, 
    399         &encode_ip_addr_attr 
    400     }, 
    401     { 
    402         /* PJ_STUN_ATTR_REFRESH_INTERVAL, */ 
    403         "REFRESH-INTERVAL", 
    404         &decode_uint_attr, 
    405         &encode_uint_attr 
    406     }, 
     430    } 
    407431}; 
    408432 
     
    16501674            if (p_response) { 
    16511675                pj_stun_msg_create_response(pool, msg,  
    1652                                             PJ_STUN_STATUS_BAD_REQUEST,  
     1676                                            PJ_STUN_SC_BAD_REQUEST,  
    16531677                                            &err_msg, p_response); 
    16541678            } 
     
    16711695                 */ 
    16721696                if (p_response) { 
    1673                     unsigned err_code = PJ_STUN_STATUS_UNKNOWN_ATTRIBUTE; 
     1697                    unsigned err_code = PJ_STUN_SC_UNKNOWN_ATTRIBUTE; 
    16741698 
    16751699                    status = pj_stun_msg_create_response(pool, msg, 
     
    17061730 
    17071731                    pj_stun_msg_create_response(pool, msg, 
    1708                                                 PJ_STUN_STATUS_BAD_REQUEST, 
     1732                                                PJ_STUN_SC_BAD_REQUEST, 
    17091733                                                &e, p_response); 
    17101734                } 
     
    17271751                        e = pj_str("MESSAGE-INTEGRITY already present"); 
    17281752                        pj_stun_msg_create_response(pool, msg, 
    1729                                                     PJ_STUN_STATUS_BAD_REQUEST, 
     1753                                                    PJ_STUN_SC_BAD_REQUEST, 
    17301754                                                    NULL, p_response); 
    17311755                    } 
     
    17411765                        e = pj_str("FINGERPRINT already present"); 
    17421766                        pj_stun_msg_create_response(pool, msg, 
    1743                                                     PJ_STUN_STATUS_BAD_REQUEST, 
     1767                                                    PJ_STUN_SC_BAD_REQUEST, 
    17441768                                                    NULL, p_response); 
    17451769                    } 
     
    17551779                        e = pj_str("Invalid attribute order"); 
    17561780                        pj_stun_msg_create_response(pool, msg, 
    1757                                                     PJ_STUN_STATUS_BAD_REQUEST, 
     1781                                                    PJ_STUN_SC_BAD_REQUEST, 
    17581782                                                    NULL, p_response); 
    17591783                    } 
     
    17701794                    e = pj_str("Too many attributes"); 
    17711795                    pj_stun_msg_create_response(pool, msg, 
    1772                                                 PJ_STUN_STATUS_BAD_REQUEST, 
     1796                                                PJ_STUN_SC_BAD_REQUEST, 
    17731797                                                &e, p_response); 
    17741798                } 
  • pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg_dump.c

    r1049 r1052  
    6969    case PJ_STUN_ATTR_CHANGED_ADDR: 
    7070    case PJ_STUN_ATTR_REFLECTED_FROM: 
    71     case PJ_STUN_ATTR_REMOTE_ADDRESS: 
     71    case PJ_STUN_ATTR_REMOTE_ADDR: 
    7272    case PJ_STUN_ATTR_RELAY_ADDR: 
    7373    case PJ_STUN_ATTR_XOR_MAPPED_ADDR: 
  • pjproject/trunk/pjlib-util/src/pjlib-util/stun_session.c

    r1049 r1052  
    114114 
    115115static pj_status_t create_tdata(pj_stun_session *sess, 
    116                                 void *user_data, 
    117116                                pj_stun_tx_data **p_tdata) 
    118117{ 
     
    128127    tdata->pool = pool; 
    129128    tdata->sess = sess; 
    130     tdata->user_data = user_data; 
    131129 
    132130    *p_tdata = tdata; 
     
    137135static pj_status_t create_request_tdata(pj_stun_session *sess, 
    138136                                        unsigned msg_type, 
    139                                         void *user_data, 
    140137                                        pj_stun_tx_data **p_tdata) 
    141138{ 
     
    143140    pj_stun_tx_data *tdata; 
    144141 
    145     status = create_tdata(sess, user_data, &tdata); 
     142    status = create_tdata(sess, &tdata); 
    146143    if (status != PJ_SUCCESS) 
    147144        return status; 
     
    406403 
    407404 
    408 PJ_DEF(pj_status_t) pj_stun_session_create_bind_req(pj_stun_session *sess, 
    409                                                     pj_stun_tx_data **p_tdata) 
     405PJ_DEF(pj_status_t) pj_stun_session_create_req(pj_stun_session *sess, 
     406                                               int method, 
     407                                               pj_stun_tx_data **p_tdata) 
    410408{ 
    411409    pj_stun_tx_data *tdata = NULL; 
     
    414412    PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL); 
    415413 
    416     status = create_request_tdata(sess, PJ_STUN_BINDING_REQUEST, NULL,  
    417                                   &tdata); 
     414    status = create_request_tdata(sess, method, &tdata); 
    418415    if (status != PJ_SUCCESS) 
    419416        return status; 
     
    423420} 
    424421 
    425 PJ_DEF(pj_status_t) pj_stun_session_create_allocate_req(pj_stun_session *sess, 
    426                                                         pj_stun_tx_data **p_tdata) 
    427 { 
    428     PJ_UNUSED_ARG(sess); 
    429     PJ_UNUSED_ARG(p_tdata); 
    430     PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 
    431 } 
    432  
    433  
    434 PJ_DEF(pj_status_t)  
    435 pj_stun_session_create_set_active_destination_req(pj_stun_session *sess, 
    436                                                   pj_stun_tx_data **p_tdata) 
    437 { 
    438     PJ_UNUSED_ARG(sess); 
    439     PJ_UNUSED_ARG(p_tdata); 
    440     PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 
    441 } 
    442  
    443 PJ_DEF(pj_status_t) pj_stun_session_create_connect_req( pj_stun_session *sess, 
    444                                                         pj_stun_tx_data **p_tdata) 
    445 { 
    446     PJ_UNUSED_ARG(sess); 
    447     PJ_UNUSED_ARG(p_tdata); 
    448     PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 
    449 } 
    450  
    451 PJ_DEF(pj_status_t)  
    452 pj_stun_session_create_connection_status_ind(pj_stun_session *sess, 
    453                                              pj_stun_tx_data **p_tdata) 
    454 { 
    455     PJ_UNUSED_ARG(sess); 
    456     PJ_UNUSED_ARG(p_tdata); 
    457     PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 
    458 } 
    459  
    460 PJ_DEF(pj_status_t) pj_stun_session_create_send_ind( pj_stun_session *sess, 
    461                                                      pj_stun_tx_data **p_tdata) 
    462 { 
    463     PJ_UNUSED_ARG(sess); 
    464     PJ_UNUSED_ARG(p_tdata); 
    465     PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 
    466 } 
    467  
    468 PJ_DEF(pj_status_t) pj_stun_session_create_data_ind( pj_stun_session *sess, 
    469                                                      pj_stun_tx_data **p_tdata) 
    470 { 
    471     PJ_UNUSED_ARG(sess); 
    472     PJ_UNUSED_ARG(p_tdata); 
    473     PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 
    474 } 
    475  
     422PJ_DEF(pj_status_t) pj_stun_session_create_ind(pj_stun_session *sess, 
     423                                               int msg_type, 
     424                                               pj_stun_tx_data **p_tdata) 
     425{ 
     426    pj_stun_tx_data *tdata = NULL; 
     427    pj_status_t status; 
     428 
     429    PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL); 
     430 
     431    status = create_tdata(sess, &tdata); 
     432    if (status != PJ_SUCCESS) 
     433        return status; 
     434 
     435    /* Create STUN message */ 
     436    msg_type |= PJ_STUN_INDICATION_BIT; 
     437    status = pj_stun_msg_create(tdata->pool, msg_type,  PJ_STUN_MAGIC,  
     438                                NULL, &tdata->msg); 
     439    if (status != PJ_SUCCESS) { 
     440        pj_pool_release(tdata->pool); 
     441        return status; 
     442    } 
     443 
     444    *p_tdata = tdata; 
     445    return PJ_SUCCESS; 
     446} 
    476447 
    477448/* 
     
    487458    pj_stun_tx_data *tdata = NULL; 
    488459 
    489     status = create_tdata(sess, NULL, &tdata); 
     460    status = create_tdata(sess, &tdata); 
    490461    if (status != PJ_SUCCESS) 
    491462        return status; 
     
    811782 
    812783        status = pj_stun_msg_create_response(tmp_pool, msg,  
    813                                              PJ_STUN_STATUS_BAD_REQUEST, NULL, 
     784                                             PJ_STUN_SC_BAD_REQUEST, NULL, 
    814785                                             &response); 
    815786        if (status == PJ_SUCCESS && response) { 
  • pjproject/trunk/pjlib-util/src/pjstun-client/client_main.c

    r1037 r1052  
    237237} 
    238238 
     239static void send_bind_request(void) 
     240{ 
     241    pj_stun_tx_data *tdata; 
     242    pj_status_t rc; 
     243 
     244    rc = pj_stun_session_create_req(g.sess, PJ_STUN_BINDING_REQUEST, &tdata); 
     245    pj_assert(rc == PJ_SUCCESS); 
     246 
     247    rc = pj_stun_session_send_msg(g.sess, PJ_FALSE,  
     248                                  &g.dst_addr, sizeof(g.dst_addr), 
     249                                  tdata); 
     250    if (rc != PJ_SUCCESS) 
     251        my_perror("Error sending STUN request", rc); 
     252} 
     253 
     254static void send_allocate_request(void) 
     255{ 
     256} 
     257 
     258static void send_sad_request(void) 
     259{ 
     260} 
     261 
     262static void send_send_ind(void) 
     263{ 
     264} 
     265 
     266static void send_raw_data(void) 
     267{ 
     268} 
     269 
    239270static void menu(void) 
    240271{ 
    241272    puts("Menu:"); 
    242     puts("  b      Send Bind request"); 
    243     puts("  q      Quit"); 
     273    puts("  br      Send Bind request"); 
     274    puts("  ar      Send Allocate request"); 
     275    puts("  sr      Send Set Active Indication request"); 
     276    puts("  si      Send Send Indication"); 
     277    puts("  rw      Send raw data"); 
     278    puts("  q       Quit"); 
    244279    puts(""); 
    245280    printf("Choice: "); 
     
    255290        fgets(input, sizeof(input), stdin); 
    256291         
    257         switch (input[0]) { 
    258         case 'b': 
    259             { 
    260                 pj_stun_tx_data *tdata; 
    261                 pj_status_t rc; 
    262  
    263                 rc = pj_stun_session_create_bind_req(g.sess, &tdata); 
    264                 pj_assert(rc == PJ_SUCCESS); 
    265  
    266                 rc = pj_stun_session_send_msg(g.sess, PJ_FALSE,  
    267                                               &g.dst_addr, sizeof(g.dst_addr), 
    268                                               tdata); 
    269                 if (rc != PJ_SUCCESS) 
    270                     my_perror("Error sending STUN request", rc); 
    271             } 
    272             break; 
    273         case 'q': 
     292        if (input[0]=='b' && input[1]=='r') { 
     293            send_bind_request(); 
     294             
     295        } else if (input[0]=='a' && input[1]=='r') { 
     296            send_allocate_request(); 
     297             
     298        } else if (input[0]=='s' && input[1]=='r') { 
     299            send_sad_request(); 
     300             
     301        } else if (input[0]=='s' && input[1]=='i') { 
     302            send_send_ind(); 
     303             
     304        } else if (input[0]=='r' && input[1]=='w') { 
     305            send_raw_data(); 
     306             
     307        } else if (input[0]=='q') { 
    274308            g.quit = 1; 
    275             break; 
    276         default: 
    277             break; 
    278309        } 
    279310    } 
  • pjproject/trunk/pjlib-util/src/pjstun-srv-test/turn_usage.c

    r1049 r1052  
    2222 
    2323#define MAX_CLIENTS             8000 
    24 #define MAX_PEER_PER_CLIENTS    16 
     24#define MAX_PEER_PER_CLIENT     16 
    2525#define START_PORT              2000 
    2626#define END_PORT                65530 
    2727 
    28 static void tu_on_rx_data(pj_stun_usage *usage, 
    29                           void *pkt, 
    30                           pj_size_t pkt_size, 
    31                           const pj_sockaddr_t *src_addr, 
    32                           unsigned src_addr_len); 
    33 static void tu_on_destroy(pj_stun_usage *usage); 
    34  
    35 static pj_status_t sess_on_send_msg(pj_stun_session *sess, 
    36                                     const void *pkt, 
    37                                     pj_size_t pkt_size, 
    38                                     const pj_sockaddr_t *dst_addr, 
    39                                     unsigned addr_len); 
    40 static pj_status_t sess_on_rx_request(pj_stun_session *sess, 
    41                                       const pj_uint8_t *pkt, 
    42                                       unsigned pkt_len, 
    43                                       const pj_stun_msg *msg, 
    44                                       const pj_sockaddr_t *src_addr, 
    45                                       unsigned src_addr_len); 
     28/* 
     29 * Forward declarations. 
     30 */ 
     31struct turn_usage; 
     32struct turn_client; 
     33 
     34static void        tu_on_rx_data(pj_stun_usage *usage, 
     35                                 void *pkt, 
     36                                 pj_size_t pkt_size, 
     37                                 const pj_sockaddr_t *src_addr, 
     38                                 unsigned src_addr_len); 
     39static void        tu_on_destroy(pj_stun_usage *usage); 
     40static pj_status_t tu_sess_on_send_msg(pj_stun_session *sess, 
     41                                       const void *pkt, 
     42                                       pj_size_t pkt_size, 
     43                                       const pj_sockaddr_t *dst_addr, 
     44                                       unsigned addr_len); 
     45static pj_status_t tu_sess_on_rx_request(pj_stun_session *sess, 
     46                                         const pj_uint8_t *pkt, 
     47                                         unsigned pkt_len, 
     48                                         const pj_stun_msg *msg, 
     49                                         const pj_sockaddr_t *src_addr, 
     50                                         unsigned src_addr_len); 
     51 
     52static pj_status_t client_create(struct turn_usage *tu, 
     53                                 const pj_sockaddr_t *src_addr, 
     54                                 unsigned src_addr_len, 
     55                                 struct turn_client **p_client); 
     56static pj_status_t client_destroy(struct turn_client *client, 
     57                                  pj_status_t reason); 
     58static pj_status_t client_handle_stun_msg(struct turn_client *client, 
     59                                          const pj_stun_msg *msg, 
     60                                          const pj_sockaddr_t *src_addr, 
     61                                          unsigned src_addr_len); 
    4662 
    4763 
     
    5167    pj_stun_endpoint    *endpt; 
    5268    pj_ioqueue_t        *ioqueue; 
     69    pj_timer_heap_t     *timer_heap; 
    5370    pj_pool_t           *pool; 
     71    pj_mutex_t          *mutex; 
    5472    pj_stun_usage       *usage; 
    5573    int                  type; 
    5674    pj_stun_session     *default_session; 
    5775    pj_hash_table_t     *client_htable; 
    58     pj_hash_table_t     *peer_htable; 
    5976 
    6077    unsigned             max_bw_kbps; 
     
    6885struct turn_client 
    6986{ 
     87    char                 obj_name[PJ_MAX_OBJ_NAME]; 
    7088    struct turn_usage   *tu; 
    7189    pj_pool_t           *pool; 
    72     pj_sockaddr_in       addr; 
    7390    pj_stun_session     *session; 
    74  
     91    pj_mutex_t          *mutex; 
     92    int                  sock_type; 
     93 
     94    /* Socket and socket address of the allocated port */ 
     95    pj_sock_t            sock; 
     96    pj_ioqueue_key_t    *key; 
     97    pj_sockaddr_in       client_addr; 
     98 
     99    /* Allocation properties */ 
    75100    unsigned             bw_kbps; 
    76101    unsigned             lifetime; 
    77  
    78     pj_sock_t            sock; 
    79     pj_ioqueue_key_t    *key; 
    80     char                 packet[4000]; 
    81     pj_sockaddr_in       src_addr; 
    82     int                  src_addr_len; 
    83     pj_ioqueue_op_key_t  read_key; 
    84     pj_ioqueue_op_key_t  write_key; 
    85  
    86     pj_bool_t            has_ad; 
    87     pj_bool_t            ad_is_pending; 
    88     pj_sockaddr_in       ad; 
     102    pj_timer_entry       expiry_timer; 
     103 
     104 
     105    /* Hash table to keep all peers, key-ed by their address */ 
     106    pj_hash_table_t     *peer_htable; 
     107 
     108    /* Active destination, or sin_addr.s_addr will be zero if 
     109     * no active destination is set. 
     110     */ 
     111    struct peer         *active_peer; 
     112 
     113    /* Current packet received/sent from/to the allocated port */ 
     114    pj_uint8_t           pkt[4000]; 
     115    pj_sockaddr_in       pkt_src_addr; 
     116    int                  pkt_src_addr_len; 
     117    pj_ioqueue_op_key_t  pkt_read_key; 
     118    pj_ioqueue_op_key_t  pkt_write_key; 
    89119}; 
    90120 
     
    102132 
    103133 
     134/* 
     135 * This is the only public API, to create and start the TURN usage. 
     136 */ 
    104137PJ_DEF(pj_status_t) pj_stun_turn_usage_create(pj_stun_server *srv, 
    105138                                              int type, 
     
    127160    tu->pf = si->pf; 
    128161    tu->endpt = si->endpt; 
     162    tu->timer_heap = si->timer_heap; 
    129163    tu->next_port = START_PORT; 
    130164 
     
    149183    /* Init hash tables */ 
    150184    tu->client_htable = pj_hash_create(tu->pool, MAX_CLIENTS); 
    151     tu->peer_htable = pj_hash_create(tu->pool, MAX_CLIENTS); 
    152185 
    153186    /* Create default session */ 
    154187    pj_bzero(&sess_cb, sizeof(sess_cb)); 
    155     sess_cb.on_send_msg = &sess_on_send_msg; 
    156     sess_cb.on_rx_request = &sess_on_rx_request; 
     188    sess_cb.on_send_msg = &tu_sess_on_send_msg; 
     189    sess_cb.on_rx_request = &tu_sess_on_rx_request; 
    157190    status = pj_stun_session_create(si->endpt, "turns%p", &sess_cb, PJ_FALSE, 
    158191                                    &tu->default_session); 
     
    166199    pj_stun_session_set_user_data(tu->default_session, sd); 
    167200 
     201    /* Create mutex */ 
     202    status = pj_mutex_create_recursive(pool, "turn%p", &tu->mutex); 
     203    if (status != PJ_SUCCESS) { 
     204        pj_stun_usage_destroy(tu->usage); 
     205        return status; 
     206    } 
     207 
    168208    *p_bu = tu->usage; 
    169209 
     
    172212 
    173213 
     214/*  
     215 * This is a callback called by usage.c when the particular STUN usage 
     216 * is to be destroyed. 
     217 */ 
    174218static void tu_on_destroy(pj_stun_usage *usage) 
    175219{ 
    176220    struct turn_usage *tu; 
     221    pj_hash_iterator_t hit, *it; 
    177222 
    178223    tu = (struct turn_usage*) pj_stun_usage_get_user_data(usage); 
    179     PJ_TODO(DESTROY_ALL_CLIENTS); 
     224 
     225    /* Destroy all clients */ 
     226    it = pj_hash_first(tu->client_htable, &hit); 
     227    while (it) { 
     228        struct turn_client *client; 
     229 
     230        client = (struct turn_client *)pj_hash_this(tu->client_htable, it); 
     231        client_destroy(client, PJ_SUCCESS); 
     232 
     233        it = pj_hash_next(tu->client_htable, it); 
     234    } 
     235 
     236    pj_stun_session_destroy(tu->default_session); 
     237    pj_mutex_destroy(tu->mutex); 
    180238    pj_pool_release(tu->pool); 
    181239} 
    182240 
    183241 
     242/* 
     243 * This is a callback called by the usage.c to notify the TURN usage,  
     244 * that incoming packet (may or may not be a STUN packet) is received 
     245 * on the port where the TURN usage is listening. 
     246 */ 
    184247static void tu_on_rx_data(pj_stun_usage *usage, 
    185248                          void *pkt, 
     
    189252{ 
    190253    struct turn_usage *tu; 
    191     pj_stun_session *session; 
    192254    struct turn_client *client; 
    193255    unsigned flags; 
     
    201263                                               src_addr_len, NULL); 
    202264 
    203     if (client == NULL) { 
    204         session = tu->default_session; 
    205     } else { 
    206         session = client->session; 
    207     } 
    208      
    209     /* Handle packet to session */ 
    210     flags = PJ_STUN_CHECK_PACKET; 
     265    /* STUN message decoding flag */ 
     266    flags = 0; 
    211267    if (tu->type == PJ_SOCK_DGRAM) 
    212268        flags |= PJ_STUN_IS_DATAGRAM; 
    213  
    214     status = pj_stun_session_on_rx_pkt(session, (pj_uint8_t*)pkt, pkt_size, 
    215                                        flags, NULL, src_addr, src_addr_len); 
    216     if (status != PJ_SUCCESS) { 
    217         pj_stun_perror(THIS_FILE, "Error handling incoming packet", status); 
    218         return; 
    219     } 
    220 } 
    221  
    222  
     269     
     270 
     271    if (client) { 
     272        status = pj_stun_msg_check(pkt, pkt_size, flags); 
     273 
     274        if (status == PJ_SUCCESS) { 
     275            /* Received STUN message */ 
     276            status = pj_stun_session_on_rx_pkt(client->session,  
     277                                               (pj_uint8_t*)pkt, pkt_size,  
     278                                               flags, NULL,  
     279                                               src_addr, src_addr_len); 
     280        } else if (client->active_peer) { 
     281            /* Received non-STUN message and client has active destination */ 
     282            pj_ssize_t sz = pkt_size; 
     283            pj_ioqueue_sendto(client->key, &client->pkt_write_key, 
     284                              pkt, &sz, 0, 
     285                              &client->active_peer->addr, 
     286                              sizeof(client->active_peer->addr)); 
     287        } else { 
     288            /* Received non-STUN message and client doesn't have active  
     289             * destination. 
     290             */ 
     291            /* Ignore */ 
     292        } 
     293 
     294    } else { 
     295        /* Received packet (could be STUN or no) from new source */ 
     296        flags |= PJ_STUN_CHECK_PACKET; 
     297        pj_stun_session_on_rx_pkt(tu->default_session, (pj_uint8_t*)pkt,  
     298                                  pkt_size, flags, NULL,  
     299                                  src_addr, src_addr_len); 
     300    } 
     301} 
     302 
     303 
     304/* 
     305 * This is a utility function provided by TU (Turn Usage) to reserve 
     306 * or allocate internal port/socket. The allocation needs to be  
     307 * coordinated to minimize bind() collissions. 
     308 */ 
    223309static pj_status_t tu_alloc_port(struct turn_usage *tu,  
    224310                                 int type,  
     
    236322    if (req_addr && req_addr->sin_port != 0) { 
    237323 
    238         *err_code = PJ_STUN_STATUS_INVALID_PORT; 
     324        *err_code = PJ_STUN_SC_INVALID_PORT; 
    239325 
    240326        /* Allocate specific port */ 
     
    255341 
    256342    } else { 
    257         *err_code = PJ_STUN_STATUS_INSUFFICIENT_CAPACITY; 
     343        status = -1; 
     344        *err_code = PJ_STUN_SC_INSUFFICIENT_CAPACITY; 
    258345 
    259346        if (req_addr && req_addr->sin_addr.s_addr) { 
    260             *err_code = PJ_STUN_STATUS_INVALID_IP_ADDR; 
     347            *err_code = PJ_STUN_SC_INVALID_IP_ADDR; 
    261348            pj_memcpy(&addr, req_addr, sizeof(pj_sockaddr_in)); 
    262349        } else { 
     
    309396} 
    310397 
     398 
     399/*  
     400 * This callback is called by the TU's STUN session when it receives 
     401 * a valid STUN message. This is called from tu_on_rx_data above. 
     402 */ 
     403static pj_status_t tu_sess_on_rx_request(pj_stun_session *sess, 
     404                                         const pj_uint8_t *pkt, 
     405                                         unsigned pkt_len, 
     406                                         const pj_stun_msg *msg, 
     407                                         const pj_sockaddr_t *src_addr, 
     408                                         unsigned src_addr_len) 
     409{ 
     410    struct session_data *sd; 
     411    struct turn_client *client; 
     412    pj_stun_tx_data *tdata; 
     413    pj_status_t status; 
     414 
     415    PJ_UNUSED_ARG(pkt); 
     416    PJ_UNUSED_ARG(pkt_len); 
     417 
     418    sd = (struct session_data*) pj_stun_session_get_user_data(sess); 
     419 
     420    pj_assert(sd->client == NULL); 
     421 
     422    if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) { 
     423        if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { 
     424            status = pj_stun_session_create_response(sess, msg,  
     425                                                     PJ_STUN_SC_NO_BINDING, 
     426                                                     NULL, &tdata); 
     427            if (status==PJ_SUCCESS) { 
     428                status = pj_stun_session_send_msg(sess, PJ_FALSE,  
     429                                                  src_addr, src_addr_len, 
     430                                                  tdata); 
     431            } 
     432        } else { 
     433            PJ_LOG(4,(THIS_FILE,  
     434                      "Received %s %s without matching Allocation, " 
     435                      "ignored", pj_stun_get_method_name(msg->hdr.type), 
     436                      pj_stun_get_class_name(msg->hdr.type))); 
     437        } 
     438        return PJ_SUCCESS; 
     439    } 
     440 
     441    status = client_create(sd->tu, src_addr, src_addr_len, &client); 
     442    if (status != PJ_SUCCESS) { 
     443        pj_stun_perror(THIS_FILE, "Error creating new TURN client",  
     444                       status); 
     445        return status; 
     446    } 
     447 
     448 
     449    /* Hand over message to client */ 
     450    pj_mutex_lock(client->mutex); 
     451    status = client_handle_stun_msg(client, msg, src_addr, src_addr_len); 
     452    pj_mutex_unlock(client->mutex); 
     453 
     454    return status; 
     455} 
     456 
     457 
     458/* 
     459 * This callback is called by STUN session when it needs to send packet 
     460 * to the network. 
     461 */ 
     462static pj_status_t tu_sess_on_send_msg(pj_stun_session *sess, 
     463                                       const void *pkt, 
     464                                       pj_size_t pkt_size, 
     465                                       const pj_sockaddr_t *dst_addr, 
     466                                       unsigned addr_len) 
     467{ 
     468    struct session_data *sd; 
     469 
     470    sd = (struct session_data*) pj_stun_session_get_user_data(sess); 
     471 
     472    if (sd->tu->type == PJ_SOCK_DGRAM) { 
     473        return pj_stun_usage_sendto(sd->tu->usage, pkt, pkt_size, 0, 
     474                                    dst_addr, addr_len); 
     475    } else { 
     476        return PJ_ENOTSUP; 
     477    } 
     478} 
     479 
     480 
    311481/****************************************************************************/ 
    312  
     482/* 
     483 * TURN client operations. 
     484 */ 
     485 
     486/* Function prototypes */ 
     487static pj_status_t client_create_relay(struct turn_client *client); 
     488static pj_status_t client_destroy_relay(struct turn_client *client); 
     489static void        client_on_expired(pj_timer_heap_t *th, pj_timer_entry *e); 
     490static void        client_on_read_complete(pj_ioqueue_key_t *key,  
     491                                           pj_ioqueue_op_key_t *op_key,  
     492                                           pj_ssize_t bytes_read); 
     493static pj_status_t client_respond(struct turn_client *client,  
     494                                  const pj_stun_msg *msg, 
     495                                  int err_code, 
     496                                  const char *err_msg, 
     497                                  const pj_sockaddr_t *dst_addr, 
     498                                  int dst_addr_len); 
     499static struct peer* client_get_peer(struct turn_client *client, 
     500                                    const pj_sockaddr_in *peer_addr, 
     501                                    pj_uint32_t *hval); 
     502static struct peer* client_add_peer(struct turn_client *client, 
     503                                    const pj_sockaddr_in *peer_addr, 
     504                                    pj_uint32_t hval); 
     505 
     506 
     507/* 
     508 * This callback is called when incoming STUN message is received 
     509 * in the TURN usage. This is called from by tu_on_rx_data() when 
     510 * the packet is handed over to the client. 
     511 */ 
     512static pj_status_t client_sess_on_rx_request(pj_stun_session *sess, 
     513                                             const pj_uint8_t *pkt, 
     514                                             unsigned pkt_len, 
     515                                             const pj_stun_msg *msg, 
     516                                             const pj_sockaddr_t *src_addr, 
     517                                             unsigned src_addr_len) 
     518{ 
     519    struct session_data *sd; 
     520 
     521    PJ_UNUSED_ARG(pkt); 
     522    PJ_UNUSED_ARG(pkt_len); 
     523 
     524    sd = (struct session_data*) pj_stun_session_get_user_data(sess); 
     525    pj_assert(sd->client != PJ_SUCCESS); 
     526 
     527    return client_handle_stun_msg(sd->client, msg, src_addr, src_addr_len); 
     528} 
     529 
     530 
     531/* 
     532 * This callback is called by client's STUN session to send outgoing 
     533 * STUN packet. It's called when client calls pj_stun_session_send_msg() 
     534 * function. 
     535 */ 
     536static pj_status_t client_sess_on_send_msg(pj_stun_session *sess, 
     537                                           const void *pkt, 
     538                                           pj_size_t pkt_size, 
     539                                           const pj_sockaddr_t *dst_addr, 
     540                                           unsigned addr_len) 
     541{ 
     542    struct session_data *sd; 
     543 
     544    sd = (struct session_data*) pj_stun_session_get_user_data(sess); 
     545 
     546    if (sd->tu->type == PJ_SOCK_DGRAM) { 
     547        return pj_stun_usage_sendto(sd->tu->usage, pkt, pkt_size, 0, 
     548                                    dst_addr, addr_len); 
     549    } else { 
     550        return PJ_ENOTSUP; 
     551    } 
     552} 
     553 
     554 
     555/* 
     556 * Create a new TURN client for the specified source address. 
     557 */ 
    313558static pj_status_t client_create(struct turn_usage *tu, 
    314                                  const pj_stun_msg *msg, 
    315559                                 const pj_sockaddr_t *src_addr, 
    316560                                 unsigned src_addr_len, 
     
    323567    pj_status_t status; 
    324568 
    325     PJ_UNUSED_ARG(msg); 
    326  
    327569    pool = pj_pool_create(tu->pf, "turnc%p", 4000, 4000, NULL); 
    328570    client = PJ_POOL_ZALLOC_T(pool, struct turn_client); 
     
    331573    client->sock = PJ_INVALID_SOCKET; 
    332574 
     575    if (src_addr) { 
     576        const pj_sockaddr_in *a4 = (const pj_sockaddr_in *)src_addr; 
     577        pj_ansi_snprintf(client->obj_name, sizeof(client->obj_name), 
     578                         "%s:%d", 
     579                         pj_inet_ntoa(a4->sin_addr), 
     580                         (int)pj_ntohs(a4->sin_port)); 
     581        client->obj_name[sizeof(client->obj_name)-1] = '\0'; 
     582    } 
     583 
    333584    /* Create session */ 
    334585    pj_bzero(&sess_cb, sizeof(sess_cb)); 
    335     sess_cb.on_send_msg = &sess_on_send_msg; 
    336     sess_cb.on_rx_request = &sess_on_rx_request; 
     586    sess_cb.on_send_msg = &client_sess_on_send_msg; 
     587    sess_cb.on_rx_request = &client_sess_on_rx_request; 
    337588    status = pj_stun_session_create(tu->endpt, "turnc%p", &sess_cb, PJ_FALSE, 
    338589                                    &client->session); 
     
    347598    pj_stun_session_set_user_data(client->session, sd); 
    348599 
     600    /* Mutex */ 
     601    status = pj_mutex_create_recursive(client->pool, pool->obj_name,  
     602                                       &client->mutex); 
     603    if (status != PJ_SUCCESS) { 
     604        client_destroy(client, status); 
     605        return status; 
     606    } 
     607 
     608    /* Create hash table */ 
     609    client->peer_htable = pj_hash_create(client->pool, MAX_PEER_PER_CLIENT); 
     610    if (client->peer_htable == NULL) { 
     611        client_destroy(client, status); 
     612        return PJ_ENOMEM; 
     613    } 
     614 
     615    /* Init timer entry */ 
     616    client->expiry_timer.user_data = client; 
     617    client->expiry_timer.cb = &client_on_expired; 
     618    client->expiry_timer.id = 0; 
     619 
    349620    /* Register to hash table */ 
     621    pj_mutex_lock(tu->mutex); 
    350622    pj_hash_set(pool, tu->client_htable, src_addr, src_addr_len, 0, client); 
    351  
     623    pj_mutex_unlock(tu->mutex); 
     624 
     625    /* Done */ 
    352626    *p_client = client; 
     627 
     628    PJ_LOG(4,(THIS_FILE, "TURN client %s created", client->obj_name)); 
     629 
    353630    return PJ_SUCCESS; 
    354631} 
    355632 
    356 static pj_status_t client_destroy(struct turn_client *client) 
    357 { 
    358 } 
    359  
    360 static void client_on_read_complete(pj_ioqueue_key_t *key,  
    361                                     pj_ioqueue_op_key_t *op_key,  
    362                                     pj_ssize_t bytes_read) 
    363 { 
    364 } 
    365  
    366 static void client_on_write_complete(pj_ioqueue_key_t *key,  
    367                                      pj_ioqueue_op_key_t *op_key,  
    368                                      pj_ssize_t bytes_sent) 
    369 { 
    370 } 
    371  
     633 
     634/* 
     635 * Destroy TURN client. 
     636 */ 
     637static pj_status_t client_destroy(struct turn_client *client, 
     638                                  pj_status_t reason) 
     639{ 
     640    struct turn_usage *tu = client->tu; 
     641    char name[PJ_MAX_OBJ_NAME]; 
     642 
     643    pj_assert(sizeof(name)==sizeof(client->obj_name)); 
     644    pj_memcpy(name, client->obj_name, sizeof(name)); 
     645 
     646    /* Kill timer if it's active */ 
     647    if (client->expiry_timer.id != 0) { 
     648        pj_timer_heap_cancel(tu->timer_heap, &client->expiry_timer); 
     649        client->expiry_timer.id = PJ_FALSE; 
     650    } 
     651 
     652    /* Destroy relay */ 
     653    client_destroy_relay(client); 
     654 
     655    /* Unregister client from hash table */ 
     656    pj_mutex_lock(tu->mutex); 
     657    pj_hash_set(NULL, tu->client_htable,  
     658                &client->client_addr, sizeof(client->client_addr), 0, NULL); 
     659    pj_mutex_unlock(tu->mutex); 
     660 
     661    /* Destroy STUN session */ 
     662    if (client->session) { 
     663        pj_stun_session_destroy(client->session); 
     664        client->session = NULL; 
     665    } 
     666 
     667    /* Mutex */ 
     668    if (client->mutex) { 
     669        pj_mutex_destroy(client->mutex); 
     670        client->mutex = NULL; 
     671    } 
     672 
     673    /* Finally destroy pool */ 
     674    if (client->pool) { 
     675        pj_pool_t *pool = client->pool; 
     676        client->pool = NULL; 
     677        pj_pool_release(pool); 
     678    } 
     679 
     680    if (reason == PJ_SUCCESS) { 
     681        PJ_LOG(4,(THIS_FILE, "TURN client %s destroyed", name)); 
     682    } 
     683 
     684    return PJ_SUCCESS; 
     685} 
     686 
     687 
     688/* 
     689 * This utility function is used to setup relay (with ioqueue) after 
     690 * socket has been allocated for the TURN client. 
     691 */ 
    372692static pj_status_t client_create_relay(struct turn_client *client) 
    373693{ 
     
    378698    pj_bzero(&client_ioq_cb, sizeof(client_ioq_cb)); 
    379699    client_ioq_cb.on_read_complete = &client_on_read_complete; 
    380     client_ioq_cb.on_write_complete = &client_on_write_complete; 
    381700    status = pj_ioqueue_register_sock(client->pool, client->tu->ioqueue,  
    382701                                      client->sock, client, 
     
    388707    } 
    389708 
    390     pj_ioqueue_op_key_init(&client->read_key, sizeof(client->read_key)); 
    391     pj_ioqueue_op_key_init(&client->write_key, sizeof(client->write_key)); 
     709    pj_ioqueue_op_key_init(&client->pkt_read_key,  
     710                           sizeof(client->pkt_read_key)); 
     711    pj_ioqueue_op_key_init(&client->pkt_write_key,  
     712                           sizeof(client->pkt_write_key)); 
    392713 
    393714    /* Trigger the first read */ 
    394     client_on_read_complete(client->key, &client->read_key, 0); 
     715    client_on_read_complete(client->key, &client->pkt_read_key, 0); 
    395716 
    396717    return PJ_SUCCESS; 
    397718} 
    398719 
     720 
     721/* 
     722 * This utility function is used to destroy the port allocated for 
     723 * the TURN client. 
     724 */ 
     725static pj_status_t client_destroy_relay(struct turn_client *client) 
     726{ 
     727    /* Close socket */ 
     728    if (client->key) { 
     729        pj_ioqueue_unregister(client->key); 
     730        client->key = NULL; 
     731        client->sock = PJ_INVALID_SOCKET; 
     732    } else if (client->sock && client->sock != PJ_INVALID_SOCKET) { 
     733        pj_sock_close(client->sock); 
     734        client->sock = PJ_INVALID_SOCKET; 
     735    } 
     736 
     737    PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocation %s:%d destroyed", 
     738              client->obj_name, 
     739              pj_inet_ntoa(client->client_addr.sin_addr), 
     740              (int)pj_ntohs(client->client_addr.sin_port))); 
     741    return PJ_SUCCESS; 
     742} 
     743 
     744 
     745/* 
     746 * From the source packet address, get the peer instance from hash table. 
     747 */ 
     748static struct peer* client_get_peer(struct turn_client *client, 
     749                                    const pj_sockaddr_in *peer_addr, 
     750                                    pj_uint32_t *hval) 
     751{ 
     752    return (struct peer*) 
     753        pj_hash_get(client->peer_htable, peer_addr, sizeof(*peer_addr), hval); 
     754} 
     755 
     756 
     757/* 
     758 * Add a peer instance to the peer hash table. 
     759 */ 
     760static struct peer* client_add_peer(struct turn_client *client, 
     761                                    const pj_sockaddr_in *peer_addr, 
     762                                    unsigned hval) 
     763{ 
     764    struct peer *peer; 
     765 
     766    peer = PJ_POOL_ZALLOC_T(client->pool, struct peer); 
     767    peer->client = client; 
     768    pj_memcpy(&peer->addr, peer_addr, sizeof(*peer_addr)); 
     769 
     770    pj_hash_set(client->pool, client->peer_htable, 
     771                peer_addr, sizeof(*peer_addr), hval, peer); 
     772 
     773    PJ_LOG(4,(THIS_FILE, "TURN client %s: peer %s:%s:%d added", 
     774              client->obj_name, "udp", pj_inet_ntoa(peer_addr->sin_addr), 
     775              (int)pj_ntohs(peer_addr->sin_port))); 
     776 
     777    return peer; 
     778} 
     779 
     780 
     781/* 
     782 * Utility to send STUN response message (normally to send error response). 
     783 */ 
     784static pj_status_t client_respond(struct turn_client *client,  
     785                                  const pj_stun_msg *msg, 
     786                                  int err_code, 
     787                                  const char *custom_msg, 
     788                                  const pj_sockaddr_t *dst_addr, 
     789                                  int dst_addr_len) 
     790{ 
     791    pj_str_t err_msg; 
     792    pj_str_t *p_err_msg = NULL; 
     793    pj_stun_tx_data *response; 
     794    pj_status_t status; 
     795 
     796    if (custom_msg) 
     797        pj_cstr(&err_msg, custom_msg), p_err_msg = &err_msg; 
     798     
     799    status = pj_stun_session_create_response(client->session, msg,  
     800                                             err_code, p_err_msg,  
     801                                             &response); 
     802    if (status == PJ_SUCCESS) 
     803        status = pj_stun_session_send_msg(client->session, PJ_TRUE, 
     804                                          dst_addr, dst_addr_len, response); 
     805 
     806    return status; 
     807} 
     808 
     809 
     810/* 
     811 * Handle incoming initial or subsequent Allocate Request. 
     812 * This function is called by client_handle_stun_msg() below. 
     813 */ 
    399814static pj_status_t client_handle_allocate_req(struct turn_client *client, 
    400                                               const pj_uint8_t *pkt, 
    401                                               unsigned pkt_len, 
    402815                                              const pj_stun_msg *msg, 
    403816                                              const pj_sockaddr_t *src_addr, 
     
    412825    pj_sockaddr_in req_addr; 
    413826    int addr_len; 
    414     unsigned type; 
    415827    unsigned rpp_bits; 
     828    pj_time_val timeout; 
    416829    pj_status_t status; 
    417830 
     
    432845    /* Process BANDWIDTH attribute */ 
    433846    if (a_bw && a_bw->value > client->tu->max_bw_kbps) { 
    434         status = pj_stun_session_create_response(client->session, msg,  
    435                                                  PJ_STUN_STATUS_INSUFFICIENT_CAPACITY,  
    436                                                  NULL, &response); 
    437         if (status == PJ_SUCCESS && response) { 
    438             pj_stun_session_send_msg(client->session, PJ_TRUE,  
    439                                      src_addr, src_addr_len, response); 
    440         } 
    441         return -1; 
     847        client_respond(client, msg, PJ_STUN_SC_INSUFFICIENT_CAPACITY, NULL, 
     848                       src_addr, src_addr_len); 
     849        return PJ_SUCCESS; 
    442850    } else if (a_bw) { 
    443851        client->bw_kbps = a_bw->value; 
     
    448856    /* Process REQUESTED-TRANSPORT attribute */ 
    449857    if (a_rt && a_rt->value != 0) { 
    450         status = pj_stun_session_create_response(client->session, msg,  
    451                                                  PJ_STUN_STATUS_UNSUPP_TRANSPORT_PROTO,  
    452                                                  NULL, &response); 
    453         if (status == PJ_SUCCESS && response) { 
    454             pj_stun_session_send_msg(client->session, PJ_TRUE,  
    455                                      src_addr, src_addr_len, response); 
    456         } 
    457         return -1; 
     858        client_respond(client, msg, PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, NULL, 
     859                       src_addr, src_addr_len); 
     860        return PJ_SUCCESS; 
    458861    } else if (a_rt) { 
    459         type = a_rt->value ? PJ_SOCK_STREAM : PJ_SOCK_DGRAM; 
     862        client->sock_type = a_rt->value ? PJ_SOCK_STREAM : PJ_SOCK_DGRAM; 
    460863    } else { 
    461         type = client->tu->type;; 
     864        client->sock_type = client->tu->type;; 
    462865    } 
    463866 
    464867    /* Process REQUESTED-IP attribute */ 
    465868    if (a_rip && a_rip->addr.addr.sa_family != PJ_AF_INET) { 
    466         status = pj_stun_session_create_response(client->session, msg,  
    467                                                  PJ_STUN_STATUS_INVALID_IP_ADDR,  
    468                                                  NULL, &response); 
    469         if (status == PJ_SUCCESS && response) { 
    470             pj_stun_session_send_msg(client->session, PJ_TRUE,  
    471                                      src_addr, src_addr_len, response); 
    472         } 
    473         return -1; 
     869        client_respond(client, msg, PJ_STUN_SC_INVALID_IP_ADDR, NULL, 
     870                       src_addr, src_addr_len); 
     871        return PJ_SUCCESS; 
    474872         
    475873    } else if (a_rip) { 
     
    498896 
    499897    /* Allocate socket if we don't have one */ 
    500     if (client->sock == PJ_INVALID_SOCKET) { 
     898    if (client->key == NULL) { 
    501899        int err_code; 
    502900 
    503         status = tu_alloc_port(client->tu, type, rpp_bits, &req_addr,  
    504                                &client->sock, &err_code); 
     901        PJ_LOG(4,(THIS_FILE, "TURN client %s: received initial Allocate " 
     902                             "request, requested type:addr:port=%d:%s:%d, rpp " 
     903                             "bits=%d", 
     904                  client->obj_name, client->sock_type, 
     905                  pj_inet_ntoa(req_addr.sin_addr), pj_ntohs(req_addr.sin_port), 
     906                  rpp_bits)); 
     907 
     908        status = tu_alloc_port(client->tu, client->sock_type, rpp_bits,  
     909                               &req_addr, &client->sock, &err_code); 
    505910        if (status != PJ_SUCCESS) { 
    506  
    507             status = pj_stun_session_create_response(client->session, msg,  
    508                                                      err_code, NULL,  
    509                                                      &response); 
    510             if (status == PJ_SUCCESS && response) { 
    511                 pj_stun_session_send_msg(client->session, PJ_TRUE,  
    512                                          src_addr, src_addr_len, response); 
    513             } 
    514             return -1; 
     911            char errmsg[PJ_ERR_MSG_SIZE]; 
     912 
     913            pj_strerror(status, errmsg, sizeof(errmsg)); 
     914            PJ_LOG(4,(THIS_FILE, "TURN client %s: error allocating relay port" 
     915                                 ": %s", 
     916                      client->obj_name, errmsg)); 
     917 
     918            client_respond(client, msg, err_code, NULL, 
     919                           src_addr, src_addr_len); 
     920 
     921            return status; 
    515922        } 
    516923 
    517924        status = client_create_relay(client); 
    518925        if (status != PJ_SUCCESS) { 
    519             status = pj_stun_session_create_response(client->session, msg,  
    520                                                      PJ_STUN_STATUS_SERVER_ERROR,  
    521                                                      NULL, &response); 
    522             if (status == PJ_SUCCESS && response) { 
    523                 pj_stun_session_send_msg(client->session, PJ_TRUE,  
    524                                          src_addr, src_addr_len, response); 
    525             } 
    526             return -1; 
     926            client_respond(client, msg, PJ_STUN_SC_SERVER_ERROR, NULL, 
     927                           src_addr, src_addr_len); 
     928            return status; 
    527929        } 
    528930    } else { 
    529931        /* Otherwise check if the port parameter stays the same */ 
    530932        /* TODO */ 
    531     } 
     933        PJ_LOG(4,(THIS_FILE, "TURN client %s: received Allocate refresh", 
     934                  client->obj_name)); 
     935    } 
     936 
     937    /* Refresh timer */ 
     938    if (client->expiry_timer.id != PJ_FALSE) { 
     939        pj_timer_heap_cancel(client->tu->timer_heap, &client->expiry_timer); 
     940        client->expiry_timer.id = PJ_FALSE; 
     941    } 
     942    timeout.sec = client->lifetime; 
     943    timeout.msec = 0; 
     944    pj_timer_heap_schedule(client->tu->timer_heap, &client->expiry_timer, &timeout); 
     945 
    532946 
    533947    /* Done successfully, create and send success response */ 
     
    535949                                             0, NULL, &response); 
    536950    if (status != PJ_SUCCESS) { 
    537         return -1; 
     951        return status; 
    538952    } 
    539953 
     
    555969                                 &req_addr, addr_len); 
    556970 
     971    PJ_LOG(4,(THIS_FILE, "TURN client %s: relay allocated or refreshed, " 
     972                         "internal address is %s:%d", 
     973                         client->obj_name, 
     974                         pj_inet_ntoa(req_addr.sin_addr), 
     975                         (int)pj_ntohs(req_addr.sin_port))); 
     976 
    557977    return pj_stun_session_send_msg(client->session, PJ_TRUE,  
    558978                                    src_addr, src_addr_len, response); 
    559979} 
    560980 
     981 
     982/*  
     983 * client handling incoming STUN Set Active Destination request  
     984 * This function is called by client_handle_stun_msg() below. 
     985 */ 
     986static pj_status_t client_handle_sad(struct turn_client *client, 
     987                                     const pj_stun_msg *msg, 
     988                                     const pj_sockaddr_t *src_addr, 
     989                                     unsigned src_addr_len) 
     990{ 
     991    pj_stun_remote_addr_attr *a_raddr; 
     992 
     993    a_raddr = (pj_stun_remote_addr_attr*) 
     994              pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REMOTE_ADDR, 0); 
     995    if (!a_raddr) { 
     996        /* Remote active destination needs to be cleared */ 
     997        client->active_peer = NULL; 
     998 
     999    } else if (a_raddr->addr.addr.sa_family != PJ_AF_INET) { 
     1000        /* Bad request (not IPv4) */ 
     1001        client_respond(client, msg, PJ_STUN_SC_BAD_REQUEST, NULL, 
     1002                       src_addr, src_addr_len); 
     1003        return PJ_SUCCESS; 
     1004 
     1005    } else if (client->active_peer) { 
     1006        /* Client tries to set new active destination without clearing 
     1007         * it first. Reject with 439. 
     1008         */ 
     1009        client_respond(client, msg, PJ_STUN_SC_TRANSITIONING, NULL, 
     1010                       src_addr, src_addr_len); 
     1011        return PJ_SUCCESS; 
     1012 
     1013    } else { 
     1014        struct peer *peer; 
     1015        pj_uint32_t hval = 0; 
     1016 
     1017        /* Add a new peer/permission if we don't have one for this address */ 
     1018        peer = client_get_peer(client, &a_raddr->addr.ipv4, &hval); 
     1019        if (peer==NULL) { 
     1020            peer = client_add_peer(client, &a_raddr->addr.ipv4, hval); 
     1021        } 
     1022 
     1023        /* Set active destination */ 
     1024        client->active_peer = peer; 
     1025    } 
     1026 
     1027    PJ_LOG(4,(THIS_FILE, "TURN client %s: active destination set to %s:%d", 
     1028                         client->obj_name, 
     1029                         pj_inet_ntoa(client->active_peer->addr.sin_addr), 
     1030                         (int)pj_ntohs(client->active_peer->addr.sin_port))); 
     1031 
     1032    /* Respond with successful response */ 
     1033    client_respond(client, msg, 0, NULL, src_addr, src_addr_len); 
     1034 
     1035    return PJ_SUCCESS; 
     1036} 
     1037 
     1038 
     1039/*  
     1040 * client handling incoming STUN Send Indication  
     1041 * This function is called by client_handle_stun_msg() below. 
     1042 */ 
    5611043static pj_status_t client_handle_send_ind(struct turn_client *client, 
    562                                           const pj_uint8_t *pkt, 
    563                                           unsigned pkt_len, 
     1044                                          const pj_stun_msg *msg) 
     1045{ 
     1046    pj_stun_remote_addr_attr *a_raddr; 
     1047    pj_stun_data_attr *a_data; 
     1048    pj_uint32_t hval = 0; 
     1049    const pj_uint8_t *data; 
     1050    pj_ssize_t datalen; 
     1051 
     1052    /* Get REMOTE-ADDRESS attribute */ 
     1053    a_raddr = (pj_stun_remote_addr_attr*) 
     1054              pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_REMOTE_ADDR, 0); 
     1055    if (!a_raddr) { 
     1056        /* REMOTE-ADDRESS not present, discard packet */ 
     1057        return PJ_SUCCESS; 
     1058 
     1059    } else if (a_raddr->addr.addr.sa_family != PJ_AF_INET) { 
     1060        /* REMOTE-ADDRESS present but not IPv4, discard packet */ 
     1061        return PJ_SUCCESS; 
     1062 
     1063    } 
     1064 
     1065    /* Get the DATA attribute */ 
     1066    a_data = (pj_stun_data_attr*) 
     1067             pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_DATA, 0); 
     1068    if (a_data) { 
     1069        data = (const pj_uint8_t *)a_data->data; 
     1070        datalen = a_data->length; 
     1071 
     1072    } else if (client->sock_type == PJ_SOCK_STREAM) { 
     1073        /* Discard if no Data and Allocation type is TCP */ 
     1074        return PJ_SUCCESS; 
     1075 
     1076    } else { 
     1077        data = (const pj_uint8_t *)""; 
     1078        datalen = 0; 
     1079    } 
     1080 
     1081    /* Add to peer table if necessary */ 
     1082    if (client_get_peer(client, &a_raddr->addr.ipv4, &hval)==NULL) 
     1083        client_add_peer(client, &a_raddr->addr.ipv4, hval); 
     1084 
     1085    /* Send the packet */ 
     1086    pj_ioqueue_sendto(client->key, &client->pkt_write_key,  
     1087                      data, &datalen, 0, 
     1088                      &a_raddr->addr.ipv4, sizeof(a_raddr->addr.ipv4)); 
     1089 
     1090    return PJ_SUCCESS; 
     1091} 
     1092 
     1093 
     1094/*  
     1095 * client handling unknown incoming STUN message. 
     1096 * This function is called by client_handle_stun_msg() below. 
     1097 */ 
     1098static pj_status_t client_handle_unknown_msg(struct turn_client *client, 
     1099                                             const pj_stun_msg *msg, 
     1100                                             const pj_sockaddr_t *src_addr, 
     1101                                             unsigned src_addr_len) 
     1102{ 
     1103    PJ_LOG(4,(THIS_FILE, "TURN client %s: unhandled %s %s", 
     1104              client->obj_name, pj_stun_get_method_name(msg->hdr.type), 
     1105              pj_stun_get_class_name(msg->hdr.type))); 
     1106 
     1107    if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { 
     1108        return client_respond(client, msg, PJ_STUN_SC_BAD_REQUEST, NULL, 
     1109                              src_addr, src_addr_len); 
     1110    } else { 
     1111        /* Ignore */ 
     1112        return PJ_SUCCESS; 
     1113    } 
     1114} 
     1115 
     1116 
     1117/*  
     1118 * Main entry for handling STUN messages arriving on the main TURN port,  
     1119 * for this client  
     1120 */ 
     1121static pj_status_t client_handle_stun_msg(struct turn_client *client, 
    5641122                                          const pj_stun_msg *msg, 
    5651123                                          const pj_sockaddr_t *src_addr, 
    5661124                                          unsigned src_addr_len) 
    5671125{ 
    568 } 
    569  
    570 static pj_status_t client_handle_unknown_msg(struct turn_client *client, 
    571                                              const pj_uint8_t *pkt, 
    572                                              unsigned pkt_len, 
    573                                              const pj_stun_msg *msg, 
    574                                              const pj_sockaddr_t *src_addr, 
    575                                              unsigned src_addr_len) 
    576 { 
    577 } 
    578  
    579 static pj_status_t client_handle_stun_msg(struct turn_client *client, 
    580                                           const pj_uint8_t *pkt, 
    581                                           unsigned pkt_len, 
    582                                           const pj_stun_msg *msg, 
    583                                           const pj_sockaddr_t *src_addr, 
    584                                           unsigned src_addr_len) 
    585 { 
    5861126    pj_status_t status; 
    5871127 
    5881128    switch (msg->hdr.type) { 
     1129    case PJ_STUN_SEND_INDICATION: 
     1130        status = client_handle_send_ind(client, msg); 
     1131 
     1132    case PJ_STUN_SET_ACTIVE_DESTINATION_REQUEST: 
     1133        status = client_handle_sad(client, msg, 
     1134                                   src_addr, src_addr_len); 
    5891135    case PJ_STUN_ALLOCATE_REQUEST: 
    590         return client_handle_allocate_req(client, pkt, pkt_len, msg, 
    591                                           src_addr, src_addr_len); 
    592  
    593     case PJ_STUN_SEND_INDICATION: 
    594         return client_handle_send_ind(client, pkt, pkt_len, msg, 
    595                                       src_addr, src_addr_len); 
     1136        status = client_handle_allocate_req(client, msg, 
     1137                                            src_addr, src_addr_len); 
    5961138 
    5971139    default: 
    598         return client_handle_unknown_msg(client, pkt, pkt_len, msg, 
    599                                          src_addr, src_addr_len); 
    600     } 
    601 } 
    602  
    603  
    604 static pj_status_t sess_on_rx_request(pj_stun_session *sess, 
    605                                       const pj_uint8_t *pkt, 
    606                                       unsigned pkt_len, 
    607                                       const pj_stun_msg *msg, 
    608                                       const pj_sockaddr_t *src_addr, 
    609                                       unsigned src_addr_len) 
    610 { 
    611     struct session_data *sd; 
     1140        status = client_handle_unknown_msg(client, msg, 
     1141                                           src_addr, src_addr_len); 
     1142    } 
     1143 
     1144    return status; 
     1145} 
     1146 
     1147 
     1148PJ_INLINE(pj_uint32_t) GET_VAL32(const pj_uint8_t *pdu, unsigned pos) 
     1149{ 
     1150    return (pdu[pos+0] << 24) + 
     1151           (pdu[pos+1] << 16) + 
     1152           (pdu[pos+2] <<  8) + 
     1153           (pdu[pos+3]); 
     1154} 
     1155 
     1156 
     1157/*  
     1158 * Handle incoming data from peer  
     1159 * This function is called by client_on_read_complete() below. 
     1160 */ 
     1161static void client_handle_peer_data(struct turn_client *client, 
     1162                                    unsigned bytes_read) 
     1163{ 
     1164    struct peer *peer; 
     1165    pj_bool_t has_magic_cookie; 
     1166    pj_status_t status; 
     1167 
     1168    /* Has the sender been registered as peer? */ 
     1169    peer = client_get_peer(client, &client->pkt_src_addr, NULL); 
     1170    if (peer == NULL) { 
     1171        /* Nope. Discard packet */ 
     1172        return; 
     1173    } 
     1174 
     1175    /* Check if packet has STUN magic cookie */ 
     1176    has_magic_cookie = (GET_VAL32(client->pkt, 4) == PJ_STUN_MAGIC); 
     1177 
     1178    /* If this is the Active Destination and the packet doesn't have 
     1179     * STUN magic cookie, send the packet to client as is. 
     1180     */ 
     1181    if (peer == client->active_peer && !has_magic_cookie) { 
     1182        pj_stun_usage_sendto(client->tu->usage, client->pkt, bytes_read, 0, 
     1183                             &client->pkt_src_addr, client->pkt_src_addr_len); 
     1184    } else { 
     1185        /* Otherwise wrap in Data Indication */ 
     1186        pj_stun_tx_data *data_ind; 
     1187 
     1188        status = pj_stun_session_create_ind(client->session,  
     1189                                            PJ_STUN_DATA_INDICATION, 
     1190                                            &data_ind); 
     1191        if (status != PJ_SUCCESS) 
     1192            return; 
     1193 
     1194        pj_stun_msg_add_ip_addr_attr(data_ind->pool, data_ind->msg,  
     1195                                     PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE, 
     1196                                     &client->pkt_src_addr, 
     1197                                     client->pkt_src_addr_len); 
     1198        pj_stun_msg_add_binary_attr(data_ind->pool, data_ind->msg, 
     1199                                    PJ_STUN_ATTR_DATA,  
     1200                                    client->pkt, bytes_read); 
     1201 
     1202 
     1203        pj_stun_session_send_msg(client->session, PJ_FALSE, 
     1204                                 &client->pkt_src_addr,  
     1205                                 client->pkt_src_addr_len, 
     1206                                 data_ind); 
     1207    } 
     1208} 
     1209 
     1210 
     1211/*  
     1212 * This callback is called by the ioqueue when read operation has 
     1213 * completed on the allocated relay port. 
     1214 */ 
     1215static void client_on_read_complete(pj_ioqueue_key_t *key,  
     1216                                    pj_ioqueue_op_key_t *op_key,  
     1217                                    pj_ssize_t bytes_read) 
     1218{ 
     1219    enum { MAX_LOOP = 10 }; 
    6121220    struct turn_client *client; 
    613     pj_stun_tx_data *tdata; 
     1221    unsigned count; 
    6141222    pj_status_t status; 
    6151223 
    616     sd = (struct session_data*) pj_stun_session_get_user_data(sess); 
    617  
    618     if (sd->client == NULL) { 
    619         /* No client is associated with this source address. Create a new 
    620          * one if this is an Allocate request. 
    621          */ 
    622         if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) { 
    623             PJ_LOG(4,(THIS_FILE, "Received first packet not Allocate request")); 
    624             return PJ_SUCCESS; 
     1224    PJ_UNUSED_ARG(op_key); 
     1225 
     1226    client = pj_ioqueue_get_user_data(key); 
     1227     
     1228    /* Lock client */ 
     1229    pj_mutex_lock(client->mutex); 
     1230 
     1231    for (count=0; ; ++count) { 
     1232        unsigned flags; 
     1233 
     1234        if (bytes_read > 0) { 
     1235            /* Received data from peer! */ 
     1236            client_handle_peer_data(client, bytes_read); 
     1237 
     1238        } else if (bytes_read < 0) { 
     1239            char errmsg[PJ_ERR_MSG_SIZE]; 
     1240            pj_strerror(-bytes_read, errmsg, sizeof(errmsg)); 
     1241            PJ_LOG(4,(THIS_FILE, "TURN client %s: error reading data " 
     1242                                 "from allocated relay port: %s", 
     1243                                 client->obj_name, errmsg)); 
    6251244        } 
    6261245 
    627         PJ_TODO(SUPPORT_MOVE); 
    628  
    629         status = client_create(sd->tu, msg, src_addr, src_addr_len, &client); 
    630         if (status != PJ_SUCCESS) { 
    631             pj_stun_perror(THIS_FILE, "Error creating new TURN client", status); 
    632             return status; 
    633         } 
    634  
    635     } else { 
    636         client = sd->client; 
    637     } 
    638  
    639     return client_handle_stun_msg(client, pkt, pkt_len, msg,  
    640                                   src_addr, src_addr_len); 
    641 } 
    642  
    643 static pj_status_t sess_on_send_msg(pj_stun_session *sess, 
    644                                     const void *pkt, 
    645                                     pj_size_t pkt_size, 
    646                                     const pj_sockaddr_t *dst_addr, 
    647                                     unsigned addr_len) 
    648 { 
    649     struct session_data *sd; 
    650  
    651     sd = (struct session_data*) pj_stun_session_get_user_data(sess); 
    652  
    653     if (sd->tu->type == PJ_SOCK_DGRAM) { 
    654         return pj_stun_usage_sendto(sd->tu->usage, pkt, pkt_size, 0, 
    655                                     dst_addr, addr_len); 
    656     } else { 
    657         return PJ_ENOTSUP; 
    658     } 
    659 } 
    660  
    661  
    662  
     1246        bytes_read = sizeof(client->pkt); 
     1247        flags = (count >= MAX_LOOP) ? PJ_IOQUEUE_ALWAYS_ASYNC : 0; 
     1248        client->pkt_src_addr_len = sizeof(client->pkt_src_addr); 
     1249        status = pj_ioqueue_recvfrom(client->key,  
     1250                                     &client->pkt_read_key, 
     1251                                     client->pkt, &bytes_read, flags, 
     1252                                     &client->pkt_src_addr,  
     1253                                     &client->pkt_src_addr_len); 
     1254        if (status == PJ_EPENDING) 
     1255            break; 
     1256    } 
     1257 
     1258    /* Unlock client */ 
     1259    pj_mutex_unlock(client->mutex); 
     1260} 
     1261 
     1262 
     1263/* On Allocation timer timeout (i.e. we don't receive new Allocate request 
     1264 * to refresh the allocation in time) 
     1265 */ 
     1266static void client_on_expired(pj_timer_heap_t *th, pj_timer_entry *e) 
     1267{ 
     1268    struct turn_client *client; 
     1269 
     1270    PJ_UNUSED_ARG(th); 
     1271 
     1272    client = (struct turn_client*) e->user_data; 
     1273 
     1274    PJ_LOG(4,(THIS_FILE, "TURN client %s: allocation timer timeout, " 
     1275                         "destroying client", 
     1276                         client->obj_name)); 
     1277    client_destroy(client, PJ_SUCCESS); 
     1278} 
     1279 
Note: See TracChangeset for help on using the changeset viewer.