Changeset 1034


Ignore:
Timestamp:
Mar 2, 2007 7:06:05 PM (12 years ago)
Author:
bennylp
Message:

Finishing up client-side STUN authentication, a simple STUN client, and simple STUN server

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

Legend:

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

    r996 r1034  
    4646typedef struct pj_stun_endpoint 
    4747{ 
     48    /** 
     49     * Pool factory to be used by the STUN endpoint and all objects created 
     50     * that use this STUN endpoint. 
     51     */ 
    4852    pj_pool_factory     *pf; 
     53 
     54    /** 
     55     * Ioqueue used by this endpoint. 
     56     */ 
    4957    pj_ioqueue_t        *ioqueue; 
     58 
     59    /** 
     60     * Timer heap instance used by this endpoint. 
     61     */ 
    5062    pj_timer_heap_t     *timer_heap; 
     63 
     64    /** 
     65     * Internal pool used by this endpoint. This shouldn't be used by 
     66     * application. 
     67     */ 
     68    pj_pool_t           *pool; 
     69 
     70    /** 
     71     * Options. 
     72     */ 
    5173    unsigned             options; 
    5274 
     75    /** 
     76     * The default initial STUN round-trip time estimation in msecs. 
     77     * The value normally is PJ_STUN_RTO_VALUE. 
     78     */ 
    5379    unsigned             rto_msec; 
    5480 
    55     pj_pool_t           *pool; 
     81    /** 
     82     * The interval to cache outgoing  STUN response in the STUN session, 
     83     * in miliseconds.  
     84     * 
     85     * Default 10000 (10 seconds). 
     86     */ 
     87    unsigned             res_cache_msec; 
    5688 
    5789} pj_stun_endpoint; 
  • pjproject/trunk/pjlib-util/include/pjlib-util/stun_session.h

    r1021 r1034  
    2424#include <pjlib-util/stun_transaction.h> 
    2525#include <pj/list.h> 
     26#include <pj/timer.h> 
    2627 
    2728PJ_BEGIN_DECL 
     
    140141 
    141142    pj_stun_client_tsx  *client_tsx;    /**< Client STUN transaction.       */ 
    142     pj_uint8_t           client_key[12];/**< Client transaction key.        */ 
     143    pj_uint32_t          msg_magic;     /**< Message magic.                 */ 
     144    pj_uint8_t           msg_key[12];   /**< Message/transaction key.       */ 
    143145 
    144146    void                *pkt;           /**< The STUN packet.               */ 
     
    146148    unsigned             pkt_size;      /**< The actual length of STUN pkt. */ 
    147149 
     150    unsigned             options;       /**< Options specified when sending */ 
    148151    unsigned             addr_len;      /**< Length of destination address. */ 
    149152    const pj_sockaddr_t *dst_addr;      /**< Destination address.           */ 
     153 
     154    pj_timer_entry       res_timer;     /**< Response cache timer.          */ 
    150155}; 
    151156 
     
    155160 * messages. These options may be specified as bitmask. 
    156161 */ 
    157 enum pj_stun_session_option 
     162enum pj_stun_session_send_option 
    158163{ 
    159164    /** 
     
    172177     * Add STUN fingerprint to the message. 
    173178     */ 
    174     PJ_STUN_USE_FINGERPRINT     = 4 
     179    PJ_STUN_USE_FINGERPRINT     = 4, 
     180 
     181    /** 
     182     * Instruct the session to cache outgoing response. This can only be  
     183     * used when sending outgoing response message, and when it's specified, 
     184     * the session will use \a res_cache_msec settings in pj_stun_endpoint 
     185     * as the duration of the cache. 
     186     */ 
     187    PJ_STUN_CACHE_RESPONSE      = 8 
    175188}; 
    176189 
     
    258271                                          const pj_str_t *user, 
    259272                                          const pj_str_t *passwd); 
     273 
    260274 
    261275/** 
     
    396410 * 
    397411 * @param sess      The STUN session instance. 
    398  * @param options   Optional flags, from pj_stun_session_option. 
     412 * @param options   Optional flags, from pj_stun_session_send_option. 
    399413 * @param dst_addr  The destination socket address. 
    400414 * @param addr_len  Length of destination address. 
  • pjproject/trunk/pjlib-util/src/pjlib-util/stun_endpoint.c

    r996 r1034  
    4848    endpt->timer_heap = timer_heap; 
    4949    endpt->rto_msec = PJ_STUN_RTO_VALUE; 
     50    endpt->res_cache_msec = 10000; 
    5051 
    5152    *p_endpt = endpt; 
  • pjproject/trunk/pjlib-util/src/pjlib-util/stun_session.c

    r1030 r1034  
    3838 
    3939    pj_stun_tx_data      pending_request_list; 
     40    pj_stun_tx_data      cached_response_list; 
    4041}; 
    4142 
     
    104105    tdata = sess->pending_request_list.next; 
    105106    while (tdata != &sess->pending_request_list) { 
    106         pj_assert(sizeof(tdata->client_key)==sizeof(msg->hdr.tsx_id)); 
    107         if (pj_memcmp(tdata->client_key, msg->hdr.tsx_id,  
     107        pj_assert(sizeof(tdata->msg_key)==sizeof(msg->hdr.tsx_id)); 
     108        if (tdata->msg_magic == msg->hdr.magic && 
     109            pj_memcmp(tdata->msg_key, msg->hdr.tsx_id,  
    108110                      sizeof(msg->hdr.tsx_id))==0) 
    109111        { 
     
    159161 
    160162    /* 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    pj_assert(sizeof(tdata->msg_key)==sizeof(tdata->msg->hdr.tsx_id)); 
     164    tdata->msg_magic = tdata->msg->hdr.magic; 
     165    pj_memcpy(tdata->msg_key, tdata->msg->hdr.tsx_id, 
    163166              sizeof(tdata->msg->hdr.tsx_id)); 
    164167 
     
    175178        tdata->client_tsx = NULL; 
    176179    } 
    177  
     180    if (tdata->res_timer.id != PJ_FALSE) { 
     181        pj_timer_heap_cancel(tdata->sess->endpt->timer_heap,  
     182                             &tdata->res_timer); 
     183        tdata->res_timer.id = PJ_FALSE; 
     184    } 
    178185    pj_pool_release(tdata->pool); 
    179186} 
     
    187194    PJ_UNUSED_ARG(sess); 
    188195    destroy_tdata(tdata); 
     196} 
     197 
     198 
     199/* Timer callback to be called when it's time to destroy response cache */ 
     200static void on_cache_timeout(pj_timer_heap_t *timer_heap, 
     201                             struct pj_timer_entry *entry) 
     202{ 
     203    pj_stun_tx_data *tdata; 
     204 
     205    PJ_UNUSED_ARG(timer_heap); 
     206 
     207    entry->id = PJ_FALSE; 
     208    tdata = (pj_stun_tx_data*) entry->user_data; 
     209 
     210    PJ_LOG(5,(SNAME(tdata->sess), "Response cache deleted")); 
     211 
     212    pj_list_erase(tdata); 
     213    pj_stun_msg_destroy_tdata(tdata->sess, tdata); 
    189214} 
    190215 
     
    329354 
    330355    pj_list_init(&sess->pending_request_list); 
     356    pj_list_init(&sess->cached_response_list); 
    331357 
    332358    status = pj_mutex_create_recursive(pool, name, &sess->mutex); 
     
    500526 
    501527    /* 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)); 
     528    pj_assert(sizeof(tdata->msg_key)==sizeof(req->hdr.tsx_id)); 
     529    tdata->msg_magic = req->hdr.magic; 
     530    pj_memcpy(tdata->msg_key, req->hdr.tsx_id, sizeof(req->hdr.tsx_id)); 
    504531 
    505532    *p_tdata = tdata; 
     
    553580    PJ_ASSERT_RETURN(sess && addr_len && server && tdata, PJ_EINVAL); 
    554581 
     582    tdata->options = options; 
     583 
    555584    /* Allocate packet */ 
    556585    tdata->max_len = PJ_STUN_MAX_PKT_LEN; 
     
    612641 
    613642    } else { 
     643        if ((options & PJ_STUN_CACHE_RESPONSE) &&  
     644            (PJ_STUN_IS_RESPONSE(tdata->msg->hdr.type) || 
     645             PJ_STUN_IS_ERROR_RESPONSE(tdata->msg->hdr.type)))  
     646        { 
     647            /* Requested to keep the response in the cache */ 
     648            pj_time_val timeout; 
     649             
     650            pj_memset(&tdata->res_timer, 0, sizeof(tdata->res_timer)); 
     651            pj_timer_entry_init(&tdata->res_timer, PJ_TRUE, tdata,  
     652                                &on_cache_timeout); 
     653 
     654            timeout.sec = sess->endpt->res_cache_msec / 1000; 
     655            timeout.msec = sess->endpt->res_cache_msec % 1000; 
     656 
     657            status = pj_timer_heap_schedule(sess->endpt->timer_heap,  
     658                                            &tdata->res_timer, 
     659                                            &timeout); 
     660            if (status != PJ_SUCCESS) { 
     661                pj_stun_msg_destroy_tdata(sess, tdata); 
     662                pj_mutex_unlock(sess->mutex); 
     663                LOG_ERR_(sess, "Error scheduling response timer", status); 
     664                return status; 
     665            } 
     666 
     667            pj_list_push_back(&sess->cached_response_list, tdata); 
     668        } 
     669     
    614670        /* Otherwise for non-request message, send directly to transport. */ 
    615671        status = sess->cb.on_send_msg(sess, tdata->pkt, tdata->pkt_size, 
     
    620676        } 
    621677 
    622         /* Destroy */ 
    623         pj_stun_msg_destroy_tdata(sess, tdata); 
     678        /* Destroy only when response is not cached*/ 
     679        if (tdata->res_timer.id == 0) { 
     680            pj_stun_msg_destroy_tdata(sess, tdata); 
     681        } 
    624682    } 
    625683 
     
    640698    tdata = tsx_lookup(sess, msg); 
    641699    if (tdata == NULL) { 
    642         LOG_ERR_(sess, "STUN error finding transaction", PJ_ENOTFOUND); 
    643         return PJ_ENOTFOUND; 
     700        PJ_LOG(4,(SNAME(sess),  
     701                  "Transaction not found, response silently discarded")); 
     702        return PJ_SUCCESS; 
    644703    } 
    645704 
     
    708767                                       unsigned src_addr_len) 
    709768{ 
     769    pj_stun_tx_data *t; 
    710770    pj_status_t status; 
     771 
     772    /* First lookup response in response cache */ 
     773    t = sess->cached_response_list.next; 
     774    while (t != &sess->cached_response_list) { 
     775        if (t->msg_magic == msg->hdr.magic && 
     776            pj_memcmp(t->msg_key, msg->hdr.tsx_id,  
     777                      sizeof(msg->hdr.tsx_id))==0) 
     778        { 
     779            break; 
     780        } 
     781        t = t->next; 
     782    } 
     783 
     784    if (t != &sess->cached_response_list) { 
     785        /* Found response in the cache */ 
     786        unsigned options; 
     787 
     788        PJ_LOG(5,(SNAME(sess),  
     789                 "Request retransmission, sending cached response")); 
     790 
     791        options = t->options; 
     792        options &= ~PJ_STUN_CACHE_RESPONSE; 
     793        pj_stun_session_send_msg(sess, options, src_addr, src_addr_len, t); 
     794        return PJ_SUCCESS; 
     795    } 
    711796 
    712797    /* Distribute to handler, or respond with Bad Request */ 
     
    726811    } 
    727812 
    728     return status;     
     813    return status; 
    729814} 
    730815 
  • pjproject/trunk/pjlib-util/src/pjstun-srv-test/server_main.c

    r1030 r1034  
    157157 
    158158    /* Send */ 
    159     status = pj_stun_session_send_msg(sess, 0, src_addr, src_addr_len, tdata); 
     159    status = pj_stun_session_send_msg(sess, PJ_STUN_CACHE_RESPONSE,  
     160                                      src_addr, src_addr_len, tdata); 
    160161    return status; 
    161162} 
Note: See TracChangeset for help on using the changeset viewer.