Ignore:
Timestamp:
Mar 1, 2007 12:08:27 AM (18 years ago)
Author:
bennylp
Message:

More work on STUN session framework

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib-util/src/pjlib-util/stun_session.c

    r1008 r1021  
    2424    pj_stun_endpoint    *endpt; 
    2525    pj_pool_t           *pool; 
     26    pj_mutex_t          *mutex; 
    2627    pj_stun_session_cb   cb; 
    2728    void                *user_data; 
     
    4849 
    4950#if PJ_LOG_MAX_LEVEL >= 4 
    50 #   define LOG_ERR_(sess, title, rc) 
     51#   define LOG_ERR_(sess, title, rc) stun_perror(sess, title, rc) 
    5152static void stun_perror(pj_stun_session *sess, const char *title,  
    5253                        pj_status_t status) 
     
    6061 
    6162#else 
    62 #   define ERR_(sess, title, rc) 
     63#   define LOG_ERR_(sess, title, rc) 
    6364#endif 
    6465 
     
    116117 
    117118static pj_status_t create_tdata(pj_stun_session *sess, 
    118                                 unsigned msg_type, 
    119119                                void *user_data, 
    120120                                pj_stun_tx_data **p_tdata) 
    121121{ 
    122122    pj_pool_t *pool; 
    123     pj_status_t status; 
    124123    pj_stun_tx_data *tdata; 
    125124 
     
    134133    tdata->user_data = user_data; 
    135134 
     135    *p_tdata = tdata; 
     136 
     137    return PJ_SUCCESS; 
     138} 
     139 
     140static pj_status_t create_request_tdata(pj_stun_session *sess, 
     141                                        unsigned msg_type, 
     142                                        void *user_data, 
     143                                        pj_stun_tx_data **p_tdata) 
     144{ 
     145    pj_status_t status; 
     146    pj_stun_tx_data *tdata; 
     147 
     148    status = create_tdata(sess, user_data, &tdata); 
     149    if (status != PJ_SUCCESS) 
     150        return status; 
     151 
    136152    /* Create STUN message */ 
    137     status = pj_stun_msg_create(pool, msg_type,  PJ_STUN_MAGIC,  
     153    status = pj_stun_msg_create(tdata->pool, msg_type,  PJ_STUN_MAGIC,  
    138154                                NULL, &tdata->msg); 
    139155    if (status != PJ_SUCCESS) { 
    140         pj_pool_release(pool); 
    141         return status; 
    142     } 
    143  
    144     /* If this is a request, then copy the request's transaction ID 
    145      * as the transaction key. 
    146      */ 
    147     if (PJ_STUN_IS_REQUEST(msg_type)) { 
    148         pj_assert(sizeof(tdata->client_key)==sizeof(tdata->msg->hdr.tsx_id)); 
    149         pj_memcpy(tdata->client_key, tdata->msg->hdr.tsx_id, 
    150                   sizeof(tdata->msg->hdr.tsx_id)); 
    151     } 
     156        pj_pool_release(tdata->pool); 
     157        return status; 
     158    } 
     159 
     160    /* copy the request's transaction ID as the transaction key. */ 
     161    pj_assert(sizeof(tdata->client_key)==sizeof(tdata->msg->hdr.tsx_id)); 
     162    pj_memcpy(tdata->client_key, tdata->msg->hdr.tsx_id, 
     163              sizeof(tdata->msg->hdr.tsx_id)); 
    152164 
    153165    *p_tdata = tdata; 
     
    167179} 
    168180 
    169 static pj_status_t session_apply_req(pj_stun_session *sess, 
     181/* 
     182 * Destroy the transmit data. 
     183 */ 
     184PJ_DEF(void) pj_stun_msg_destroy_tdata( pj_stun_session *sess, 
     185                                        pj_stun_tx_data *tdata) 
     186{ 
     187    PJ_UNUSED_ARG(sess); 
     188    destroy_tdata(tdata); 
     189} 
     190 
     191static pj_status_t apply_msg_options(pj_stun_session *sess, 
    170192                                     pj_pool_t *pool, 
    171193                                     unsigned options, 
    172                                      pj_stun_msg *msg) 
     194                                     pj_stun_msg *msg, 
     195                                     pj_str_t **p_passwd) 
    173196{ 
    174197    pj_status_t status; 
     
    182205        pj_stun_generic_string_attr *arealm; 
    183206 
     207        *p_passwd = &sess->l_password; 
     208 
    184209        /* Create and add USERNAME attribute */ 
    185         status = pj_stun_generic_string_attr_create(sess->pool,  
     210        status = pj_stun_generic_string_attr_create(pool,  
    186211                                                    PJ_STUN_ATTR_USERNAME, 
    187212                                                    &sess->l_username, 
     
    193218 
    194219        /* Add REALM only when long term credential is used */ 
    195         status = pj_stun_generic_string_attr_create(sess->pool,  
     220        status = pj_stun_generic_string_attr_create(pool,  
    196221                                                    PJ_STUN_ATTR_REALM, 
    197222                                                    &sess->l_realm, 
     
    203228 
    204229        /* Add MESSAGE-INTEGRITY attribute */ 
    205         status = pj_stun_msg_integrity_attr_create(sess->pool, &amsgi); 
     230        status = pj_stun_msg_integrity_attr_create(pool, &amsgi); 
    206231        PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 
    207232 
    208233        status = pj_stun_msg_add_attr(msg, &amsgi->hdr); 
    209234        PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 
    210  
    211         PJ_TODO(COMPUTE_MESSAGE_INTEGRITY1); 
    212235 
    213236    } else if (options & PJ_STUN_USE_SHORT_TERM_CRED) { 
     
    215238        pj_stun_msg_integrity_attr *amsgi; 
    216239 
     240        *p_passwd = &sess->s_password; 
     241 
    217242        /* Create and add USERNAME attribute */ 
    218         status = pj_stun_generic_string_attr_create(sess->pool,  
     243        status = pj_stun_generic_string_attr_create(pool,  
    219244                                                    PJ_STUN_ATTR_USERNAME, 
    220245                                                    &sess->s_username, 
     
    226251 
    227252        /* Add MESSAGE-INTEGRITY attribute */ 
    228         status = pj_stun_msg_integrity_attr_create(sess->pool, &amsgi); 
     253        status = pj_stun_msg_integrity_attr_create(pool, &amsgi); 
    229254        PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 
    230255 
     
    232257        PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 
    233258 
    234         PJ_TODO(COMPUTE_MESSAGE_INTEGRITY2); 
     259    } else { 
     260        *p_passwd = NULL; 
    235261    } 
    236262 
     
    239265        pj_stun_fingerprint_attr *af; 
    240266 
    241         status = pj_stun_generic_uint_attr_create(sess->pool,  
     267        status = pj_stun_generic_uint_attr_create(pool,  
    242268                                                  PJ_STUN_ATTR_FINGERPRINT, 
    243269                                                  0, &af); 
     
    260286    tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); 
    261287 
    262     switch (PJ_STUN_GET_METHOD(tdata->msg->hdr.type)) { 
    263     case PJ_STUN_BINDING_METHOD: 
    264         tdata->sess->cb.on_bind_response(tdata->sess, status, tdata, response); 
    265         break; 
    266     case PJ_STUN_ALLOCATE_METHOD: 
    267         tdata->sess->cb.on_allocate_response(tdata->sess, status, 
    268                                              tdata, response); 
    269         break; 
    270     case PJ_STUN_SET_ACTIVE_DESTINATION_METHOD: 
    271         tdata->sess->cb.on_set_active_destination_response(tdata->sess, status, 
    272                                                            tdata, response); 
    273         break; 
    274     case PJ_STUN_CONNECT_METHOD: 
    275         tdata->sess->cb.on_connect_response(tdata->sess, status, tdata, 
    276                                             response); 
    277         break; 
    278     default: 
    279         pj_assert(!"Unknown method"); 
    280         break; 
     288    if (tdata->sess->cb.on_request_complete) { 
     289        (*tdata->sess->cb.on_request_complete)(tdata->sess, status, tdata,  
     290                                               response); 
    281291    } 
    282292} 
     
    290300    tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); 
    291301 
    292     return tdata->sess->cb.on_send_msg(tdata, stun_pkt, pkt_size, 
    293                                        tdata->addr_len, tdata->dst_addr); 
     302    return tdata->sess->cb.on_send_msg(tdata->sess, stun_pkt, pkt_size, 
     303                                       tdata->dst_addr, tdata->addr_len); 
    294304} 
    295305 
     
    303313    pj_pool_t   *pool; 
    304314    pj_stun_session *sess; 
     315    pj_status_t status; 
    305316 
    306317    PJ_ASSERT_RETURN(endpt && cb && p_sess, PJ_EINVAL); 
     318 
     319    if (name==NULL) 
     320        name = "sess%p"; 
    307321 
    308322    pool = pj_pool_create(endpt->pf, name, 4000, 4000, NULL); 
     
    316330    pj_list_init(&sess->pending_request_list); 
    317331 
     332    status = pj_mutex_create_recursive(pool, name, &sess->mutex); 
     333    if (status != PJ_SUCCESS) { 
     334        pj_pool_release(pool); 
     335        return status; 
     336    } 
     337 
    318338    *p_sess = sess; 
    319339 
    320     PJ_TODO(MUTEX_PROTECTION); 
    321  
    322340    return PJ_SUCCESS; 
    323341} 
     
    327345    PJ_ASSERT_RETURN(sess, PJ_EINVAL); 
    328346 
     347    pj_mutex_destroy(sess->mutex); 
    329348    pj_pool_release(sess->pool); 
    330349 
     
    337356{ 
    338357    PJ_ASSERT_RETURN(sess, PJ_EINVAL); 
     358    pj_mutex_lock(sess->mutex); 
    339359    sess->user_data = user_data; 
     360    pj_mutex_unlock(sess->mutex); 
    340361    return PJ_SUCCESS; 
    341362} 
     
    356377 
    357378    PJ_ASSERT_RETURN(sess, PJ_EINVAL); 
     379 
     380    pj_mutex_lock(sess->mutex); 
    358381    pj_strdup_with_null(sess->pool, &sess->l_realm, realm ? realm : &nil); 
    359382    pj_strdup_with_null(sess->pool, &sess->l_username, user ? user : &nil); 
    360383    pj_strdup_with_null(sess->pool, &sess->l_password, passwd ? passwd : &nil); 
     384    pj_mutex_unlock(sess->mutex); 
    361385 
    362386    return PJ_SUCCESS; 
     
    372396 
    373397    PJ_ASSERT_RETURN(sess, PJ_EINVAL); 
     398 
     399    pj_mutex_lock(sess->mutex); 
    374400    pj_strdup_with_null(sess->pool, &sess->s_username, user ? user : &nil); 
    375401    pj_strdup_with_null(sess->pool, &sess->s_password, passwd ? passwd : &nil); 
     402    pj_mutex_unlock(sess->mutex); 
    376403 
    377404    return PJ_SUCCESS; 
     
    387414    PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL); 
    388415 
    389     status = create_tdata(sess, PJ_STUN_BINDING_REQUEST, NULL, &tdata); 
     416    status = create_request_tdata(sess, PJ_STUN_BINDING_REQUEST, NULL,  
     417                                  &tdata); 
    390418    if (status != PJ_SUCCESS) 
    391419        return status; 
     
    398426                                                        pj_stun_tx_data **p_tdata) 
    399427{ 
     428    PJ_UNUSED_ARG(sess); 
     429    PJ_UNUSED_ARG(p_tdata); 
    400430    PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 
    401431} 
     
    406436                                                  pj_stun_tx_data **p_tdata) 
    407437{ 
     438    PJ_UNUSED_ARG(sess); 
     439    PJ_UNUSED_ARG(p_tdata); 
    408440    PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 
    409441} 
     
    412444                                                        pj_stun_tx_data **p_tdata) 
    413445{ 
     446    PJ_UNUSED_ARG(sess); 
     447    PJ_UNUSED_ARG(p_tdata); 
    414448    PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 
    415449} 
     
    419453                                             pj_stun_tx_data **p_tdata) 
    420454{ 
     455    PJ_UNUSED_ARG(sess); 
     456    PJ_UNUSED_ARG(p_tdata); 
    421457    PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 
    422458} 
     
    425461                                                     pj_stun_tx_data **p_tdata) 
    426462{ 
     463    PJ_UNUSED_ARG(sess); 
     464    PJ_UNUSED_ARG(p_tdata); 
    427465    PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 
    428466} 
     
    431469                                                     pj_stun_tx_data **p_tdata) 
    432470{ 
     471    PJ_UNUSED_ARG(sess); 
     472    PJ_UNUSED_ARG(p_tdata); 
    433473    PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 
    434474} 
     475 
     476 
     477/* 
     478 * Create a STUN response message. 
     479 */ 
     480PJ_DEF(pj_status_t) pj_stun_session_create_response( pj_stun_session *sess, 
     481                                                     const pj_stun_msg *req, 
     482                                                     unsigned err_code, 
     483                                                     const pj_str_t *err_msg, 
     484                                                     pj_stun_tx_data **p_tdata) 
     485{ 
     486    pj_status_t status; 
     487    pj_stun_tx_data *tdata; 
     488 
     489    status = create_tdata(sess, NULL, &tdata); 
     490    if (status != PJ_SUCCESS) 
     491        return status; 
     492 
     493    /* Create STUN response message */ 
     494    status = pj_stun_msg_create_response(tdata->pool, req, err_code, err_msg, 
     495                                         &tdata->msg); 
     496    if (status != PJ_SUCCESS) { 
     497        pj_pool_release(tdata->pool); 
     498        return status; 
     499    } 
     500 
     501    /* copy the request's transaction ID as the transaction key. */ 
     502    pj_assert(sizeof(tdata->client_key)==sizeof(req->hdr.tsx_id)); 
     503    pj_memcpy(tdata->client_key, req->hdr.tsx_id, sizeof(req->hdr.tsx_id)); 
     504 
     505    *p_tdata = tdata; 
     506 
     507    return PJ_SUCCESS; 
     508} 
     509 
     510 
     511/* Print outgoing message to log */ 
     512static void dump_tx_msg(pj_stun_session *sess, const pj_stun_msg *msg, 
     513                        unsigned pkt_size, const pj_sockaddr_t *addr) 
     514{ 
     515    const char *dst_name; 
     516    int dst_port; 
     517    const pj_sockaddr *dst = (const pj_sockaddr*)addr; 
     518    char buf[512]; 
     519     
     520    if (dst->sa_family == PJ_AF_INET) { 
     521        const pj_sockaddr_in *dst4 = (const pj_sockaddr_in*)dst; 
     522        dst_name = pj_inet_ntoa(dst4->sin_addr); 
     523        dst_port = pj_ntohs(dst4->sin_port); 
     524    } else if (dst->sa_family == PJ_AF_INET6) { 
     525        const pj_sockaddr_in6 *dst6 = (const pj_sockaddr_in6*)dst; 
     526        dst_name = "IPv6"; 
     527        dst_port = pj_ntohs(dst6->sin6_port); 
     528    } else { 
     529        LOG_ERR_(sess, "Invalid address family", PJ_EINVAL); 
     530        return; 
     531    } 
     532 
     533    PJ_LOG(5,(SNAME(sess),  
     534              "TX %d bytes STUN message to %s:%d:\n" 
     535              "--- begin STUN message ---\n" 
     536              "%s" 
     537              "--- end of STUN message ---\n", 
     538              pkt_size, dst_name, dst_port, 
     539              pj_stun_msg_dump(msg, buf, sizeof(buf), NULL))); 
     540 
     541} 
     542 
    435543 
    436544PJ_DEF(pj_status_t) pj_stun_session_send_msg( pj_stun_session *sess, 
    437545                                              unsigned options, 
     546                                              const pj_sockaddr_t *server, 
    438547                                              unsigned addr_len, 
    439                                               const pj_sockaddr_t *server, 
    440548                                              pj_stun_tx_data *tdata) 
    441549{ 
     550    pj_str_t *password; 
    442551    pj_status_t status; 
    443552 
     
    448557    tdata->pkt = pj_pool_alloc(tdata->pool, tdata->max_len); 
    449558 
    450     if (PJ_LOG_MAX_LEVEL >= 5) { 
    451         char *buf = (char*) tdata->pkt; 
    452         const char *dst_name; 
    453         int dst_port; 
    454         const pj_sockaddr *dst = (const pj_sockaddr*)server; 
    455          
    456         if (dst->sa_family == PJ_AF_INET) { 
    457             const pj_sockaddr_in *dst4 = (const pj_sockaddr_in*)dst; 
    458             dst_name = pj_inet_ntoa(dst4->sin_addr); 
    459             dst_port = pj_ntohs(dst4->sin_port); 
    460         } else if (dst->sa_family == PJ_AF_INET6) { 
    461             const pj_sockaddr_in6 *dst6 = (const pj_sockaddr_in6*)dst; 
    462             dst_name = "IPv6"; 
    463             dst_port = pj_ntohs(dst6->sin6_port); 
    464         } else { 
    465             LOG_ERR_(sess, "Invalid address family", PJ_EINVAL); 
    466             return PJ_EINVAL; 
    467         } 
    468  
    469         PJ_LOG(5,(SNAME(sess),  
    470                   "Sending STUN message to %s:%d:\n" 
    471                   "--- begin STUN message ---\n" 
    472                   "%s" 
    473                   "--- end of STUN message ---\n", 
    474                   dst_name, dst_port, 
    475                   pj_stun_msg_dump(tdata->msg, buf, tdata->max_len, NULL))); 
    476     } 
     559    /* Start locking the session now */ 
     560    pj_mutex_lock(sess->mutex); 
    477561 
    478562    /* Apply options */ 
    479     status = session_apply_req(sess, tdata->pool, options, tdata->msg); 
     563    status = apply_msg_options(sess, tdata->pool, options,  
     564                               tdata->msg, &password); 
    480565    if (status != PJ_SUCCESS) { 
     566        pj_stun_msg_destroy_tdata(sess, tdata); 
     567        pj_mutex_unlock(sess->mutex); 
    481568        LOG_ERR_(sess, "Error applying options", status); 
    482         destroy_tdata(tdata); 
    483569        return status; 
    484570    } 
     
    488574                                0, NULL, &tdata->pkt_size); 
    489575    if (status != PJ_SUCCESS) { 
     576        pj_stun_msg_destroy_tdata(sess, tdata); 
     577        pj_mutex_unlock(sess->mutex); 
    490578        LOG_ERR_(sess, "STUN encode() error", status); 
    491         destroy_tdata(tdata); 
    492         return status; 
    493     } 
     579        return status; 
     580    } 
     581 
     582    /* Dump packet */ 
     583    dump_tx_msg(sess, tdata->msg, tdata->pkt_size, server); 
    494584 
    495585    /* If this is a STUN request message, then send the request with 
     
    512602                                             tdata->pkt, tdata->pkt_size); 
    513603        if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
     604            pj_stun_msg_destroy_tdata(sess, tdata); 
     605            pj_mutex_unlock(sess->mutex); 
    514606            LOG_ERR_(sess, "Error sending STUN request", status); 
    515             destroy_tdata(tdata); 
    516607            return status; 
    517608        } 
     
    522613    } else { 
    523614        /* Otherwise for non-request message, send directly to transport. */ 
    524         status = sess->cb.on_send_msg(tdata, tdata->pkt, tdata->pkt_size, 
    525                                       addr_len, server); 
     615        status = sess->cb.on_send_msg(sess, tdata->pkt, tdata->pkt_size, 
     616                                      server, addr_len); 
    526617 
    527618        if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
    528619            LOG_ERR_(sess, "Error sending STUN request", status); 
    529             destroy_tdata(tdata); 
    530             return status; 
    531620        } 
    532     } 
    533  
    534  
     621 
     622        /* Destroy */ 
     623        pj_stun_msg_destroy_tdata(sess, tdata); 
     624    } 
     625 
     626 
     627    pj_mutex_unlock(sess->mutex); 
    535628    return status; 
     629} 
     630 
     631 
     632/* Handle incoming response */ 
     633static pj_status_t on_incoming_response(pj_stun_session *sess, 
     634                                        pj_stun_msg *msg) 
     635{ 
     636    pj_stun_tx_data *tdata; 
     637    pj_status_t status; 
     638 
     639    /* Lookup pending client transaction */ 
     640    tdata = tsx_lookup(sess, msg); 
     641    if (tdata == NULL) { 
     642        LOG_ERR_(sess, "STUN error finding transaction", PJ_ENOTFOUND); 
     643        return PJ_ENOTFOUND; 
     644    } 
     645 
     646    /* Pass the response to the transaction.  
     647     * If the message is accepted, transaction callback will be called, 
     648     * and this will call the session callback too. 
     649     */ 
     650    status = pj_stun_client_tsx_on_rx_msg(tdata->client_tsx, msg); 
     651    if (status != PJ_SUCCESS) { 
     652        return status; 
     653    } 
     654 
     655    /* If transaction has completed, destroy the transmit data. 
     656     * This will remove the transaction from the pending list too. 
     657     */ 
     658    if (pj_stun_client_tsx_is_complete(tdata->client_tsx)) { 
     659        pj_stun_msg_destroy_tdata(sess, tdata); 
     660        tdata = NULL; 
     661    } 
     662 
     663    return PJ_SUCCESS; 
     664} 
     665 
     666 
     667/* Send response */ 
     668static pj_status_t send_response(pj_stun_session *sess, unsigned options, 
     669                                 pj_pool_t *pool, pj_stun_msg *response, 
     670                                 const pj_sockaddr_t *addr, unsigned addr_len) 
     671{ 
     672    pj_uint8_t *out_pkt; 
     673    unsigned out_max_len, out_len; 
     674    pj_str_t *passwd; 
     675    pj_status_t status; 
     676 
     677    /* Alloc packet buffer */ 
     678    out_max_len = PJ_STUN_MAX_PKT_LEN; 
     679    out_pkt = pj_pool_alloc(pool, out_max_len); 
     680 
     681    /* Apply options */ 
     682    apply_msg_options(sess, pool, options, response, &passwd); 
     683 
     684    /* Encode */ 
     685    status = pj_stun_msg_encode(response, out_pkt, out_max_len, 0,  
     686                                passwd, &out_len); 
     687    if (status != PJ_SUCCESS) { 
     688        LOG_ERR_(sess, "Error encoding message", status); 
     689        return status; 
     690    } 
     691 
     692    /* Print log */ 
     693    dump_tx_msg(sess, response, out_len, addr); 
     694 
     695    /* Send packet */ 
     696    status = sess->cb.on_send_msg(sess, out_pkt, out_len, addr, addr_len); 
     697 
     698    return status; 
     699} 
     700 
     701/* Handle incoming request */ 
     702static pj_status_t on_incoming_request(pj_stun_session *sess, 
     703                                       pj_pool_t *tmp_pool, 
     704                                       const pj_uint8_t *in_pkt, 
     705                                       unsigned in_pkt_len, 
     706                                       const pj_stun_msg *msg, 
     707                                       const pj_sockaddr_t *src_addr, 
     708                                       unsigned src_addr_len) 
     709{ 
     710    pj_status_t status; 
     711 
     712    /* Distribute to handler, or respond with Bad Request */ 
     713    if (sess->cb.on_rx_request) { 
     714        status = (*sess->cb.on_rx_request)(sess, in_pkt, in_pkt_len, msg, 
     715                                           src_addr, src_addr_len); 
     716    } else { 
     717        pj_stun_msg *response = NULL; 
     718 
     719        status = pj_stun_msg_create_response(tmp_pool, msg,  
     720                                             PJ_STUN_STATUS_BAD_REQUEST, NULL, 
     721                                             &response); 
     722        if (status == PJ_SUCCESS && response) { 
     723            status = send_response(sess, 0, tmp_pool, response,  
     724                                   src_addr, src_addr_len); 
     725        } 
     726    } 
     727 
     728    return status;     
     729} 
     730 
     731 
     732/* Handle incoming indication */ 
     733static pj_status_t on_incoming_indication(pj_stun_session *sess, 
     734                                          pj_pool_t *tmp_pool, 
     735                                          const pj_uint8_t *in_pkt, 
     736                                          unsigned in_pkt_len, 
     737                                          const pj_stun_msg *msg, 
     738                                          const pj_sockaddr_t *src_addr, 
     739                                          unsigned src_addr_len) 
     740{ 
     741    PJ_UNUSED_ARG(tmp_pool); 
     742 
     743    /* Distribute to handler */ 
     744    if (sess->cb.on_rx_indication) { 
     745        return (*sess->cb.on_rx_indication)(sess, in_pkt, in_pkt_len, msg, 
     746                                            src_addr, src_addr_len); 
     747    } else { 
     748        return PJ_SUCCESS; 
     749    } 
    536750} 
    537751 
     
    540754                                              const void *packet, 
    541755                                              pj_size_t pkt_size, 
    542                                               unsigned *parsed_len) 
     756                                              unsigned options, 
     757                                              unsigned *parsed_len, 
     758                                              const pj_sockaddr_t *src_addr, 
     759                                              unsigned src_addr_len) 
    543760{ 
    544761    pj_stun_msg *msg, *response; 
     
    555772    /* Try to parse the message */ 
    556773    status = pj_stun_msg_decode(tmp_pool, (const pj_uint8_t*)packet, 
    557                                 pkt_size, 0, &msg, parsed_len, 
    558                                 &response); 
     774                                pkt_size, options,  
     775                                &msg, parsed_len, &response); 
    559776    if (status != PJ_SUCCESS) { 
    560777        LOG_ERR_(sess, "STUN msg_decode() error", status); 
    561778        if (response) { 
    562             PJ_TODO(SEND_RESPONSE); 
     779            send_response(sess, 0, tmp_pool, response,  
     780                          src_addr, src_addr_len); 
    563781        } 
    564782        pj_pool_release(tmp_pool); 
     
    568786    dump = pj_pool_alloc(tmp_pool, PJ_STUN_MAX_PKT_LEN); 
    569787 
    570     PJ_LOG(4,(SNAME(sess),  
     788    PJ_LOG(4,(SNAME(sess), 
    571789              "RX STUN message:\n" 
    572               "--- begin STUN message ---" 
     790              "--- begin STUN message ---\n" 
    573791              "%s" 
    574792              "--- end of STUN message ---\n", 
    575793              pj_stun_msg_dump(msg, dump, PJ_STUN_MAX_PKT_LEN, NULL))); 
    576794 
     795    pj_mutex_lock(sess->mutex); 
    577796 
    578797    if (PJ_STUN_IS_RESPONSE(msg->hdr.type) || 
    579798        PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) 
    580799    { 
    581         pj_stun_tx_data *tdata; 
    582  
    583         /* Lookup pending client transaction */ 
    584         tdata = tsx_lookup(sess, msg); 
    585         if (tdata == NULL) { 
    586             LOG_ERR_(sess, "STUN error finding transaction", PJ_ENOTFOUND); 
    587             pj_pool_release(tmp_pool); 
    588             return PJ_ENOTFOUND; 
    589         } 
    590  
    591         /* Pass the response to the transaction.  
    592          * If the message is accepted, transaction callback will be called, 
    593          * and this will call the session callback too. 
    594          */ 
    595         status = pj_stun_client_tsx_on_rx_msg(tdata->client_tsx, msg); 
    596         if (status != PJ_SUCCESS) { 
    597             pj_pool_release(tmp_pool); 
    598             return status; 
    599         } 
    600  
    601         /* If transaction has completed, destroy the transmit data. 
    602          * This will remove the transaction from the pending list too. 
    603          */ 
    604         if (pj_stun_client_tsx_is_complete(tdata->client_tsx)) { 
    605             destroy_tdata(tdata); 
    606             tdata = NULL; 
    607         } 
    608  
    609         pj_pool_release(tmp_pool); 
    610         return PJ_SUCCESS; 
     800        status = on_incoming_response(sess, msg); 
    611801 
    612802    } else if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { 
    613803 
    614         PJ_TODO(HANDLE_INCOMING_STUN_REQUEST); 
     804        status = on_incoming_request(sess, tmp_pool, packet, pkt_size, msg, 
     805                                     src_addr, src_addr_len); 
    615806 
    616807    } else if (PJ_STUN_IS_INDICATION(msg->hdr.type)) { 
    617808 
    618         PJ_TODO(HANDLE_INCOMING_STUN_INDICATION); 
     809        status = on_incoming_indication(sess, tmp_pool, packet, pkt_size, 
     810                                        msg, src_addr, src_addr_len); 
    619811 
    620812    } else { 
    621813        pj_assert(!"Unexpected!"); 
    622     } 
     814        status = PJ_EBUG; 
     815    } 
     816 
     817    pj_mutex_unlock(sess->mutex); 
    623818 
    624819    pj_pool_release(tmp_pool); 
    625     return PJ_ENOTSUP; 
    626 } 
    627  
     820    return status; 
     821} 
     822 
     823 
Note: See TracChangeset for help on using the changeset viewer.