Ignore:
Timestamp:
Apr 9, 2008 9:38:12 AM (16 years ago)
Author:
bennylp
Message:

More ticket #485: huge changeset to support TURN TCP. Please see ticket #485 for the details

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjnath/src/pjturn-srv/server.c

    r1879 r1913  
    2929#define MAX_LISTENERS           16 
    3030#define MAX_THREADS             2 
    31 #define MAX_NET_EVENTS          10 
     31#define MAX_NET_EVENTS          1000 
    3232 
    3333/* Prototypes */ 
    3434static int server_thread_proc(void *arg); 
    3535static pj_status_t on_tx_stun_msg( pj_stun_session *sess, 
     36                                   void *token, 
    3637                                   const void *pkt, 
    3738                                   pj_size_t pkt_size, 
     
    4243                                      unsigned pkt_len, 
    4344                                      const pj_stun_rx_data *rdata, 
     45                                      void *user_data, 
    4446                                      const pj_sockaddr_t *src_addr, 
    4547                                      unsigned src_addr_len); 
     
    7880{ 
    7981    pj_pool_t *pool; 
     82    pj_stun_session_cb sess_cb; 
    8083    pj_turn_srv *srv; 
    8184    unsigned i; 
     
    125128                                        sizeof(srv->core.listener[0])); 
    126129 
    127     /* Array of STUN sessions, one for each listener */ 
    128     srv->core.stun_sess = (pj_stun_session**) 
    129                           pj_pool_calloc(pool, MAX_LISTENERS, 
    130                                          (sizeof(srv->core.stun_sess[0]))); 
    131  
    132130    /* Create hash tables */ 
    133131    srv->tables.alloc = pj_hash_create(pool, MAX_CLIENTS); 
     
    150148    srv->core.cred.data.dyn_cred.get_password = &pj_turn_get_password; 
    151149    srv->core.cred.data.dyn_cred.verify_nonce = &pj_turn_verify_nonce; 
     150 
     151    /* Create STUN session to handle new allocation */ 
     152    pj_bzero(&sess_cb, sizeof(sess_cb)); 
     153    sess_cb.on_rx_request = &on_rx_stun_request; 
     154    sess_cb.on_send_msg = &on_tx_stun_msg; 
     155 
     156    status = pj_stun_session_create(&srv->core.stun_cfg, srv->obj_name, 
     157                                    &sess_cb, PJ_FALSE, &srv->core.stun_sess); 
     158    if (status != PJ_SUCCESS) { 
     159        goto on_error; 
     160    } 
     161 
     162    pj_stun_session_set_user_data(srv->core.stun_sess, srv); 
     163    pj_stun_session_set_credential(srv->core.stun_sess, PJ_STUN_AUTH_LONG_TERM, 
     164                                   &srv->core.cred); 
     165 
    152166 
    153167    /* Array of worker threads */ 
     
    241255 
    242256    while (!srv->core.quit) { 
    243         pj_time_val timeout_max = {0, 500}; 
     257        pj_time_val timeout_max = {0, 100}; 
    244258        srv_handle_events(srv, &timeout_max); 
    245259    } 
     
    278292    } 
    279293     
    280     /* Destroy all listeners and STUN sessions associated with them. */ 
     294    /* Destroy all listeners. */ 
    281295    for (i=0; i<srv->core.lis_cnt; ++i) { 
    282296        if (srv->core.listener[i]) { 
     
    284298            srv->core.listener[i] = NULL; 
    285299        } 
    286         if (srv->core.stun_sess[i]) { 
    287             pj_stun_session_destroy(srv->core.stun_sess[i]); 
    288             srv->core.stun_sess[i] = NULL; 
    289         } 
     300    } 
     301 
     302    /* Destroy STUN session */ 
     303    if (srv->core.stun_sess) { 
     304        pj_stun_session_destroy(srv->core.stun_sess); 
     305        srv->core.stun_sess = NULL; 
    290306    } 
    291307 
     
    342358                                             pj_turn_listener *lis) 
    343359{ 
    344     pj_stun_session_cb sess_cb; 
    345360    unsigned index; 
    346     pj_stun_session *sess; 
    347     pj_status_t status; 
    348361 
    349362    PJ_ASSERT_RETURN(srv && lis, PJ_EINVAL); 
     
    354367    srv->core.listener[index] = lis; 
    355368    lis->server = srv; 
    356  
    357     /* Create STUN session to handle new allocation */ 
    358     pj_bzero(&sess_cb, sizeof(sess_cb)); 
    359     sess_cb.on_rx_request = &on_rx_stun_request; 
    360     sess_cb.on_send_msg = &on_tx_stun_msg; 
    361  
    362     status = pj_stun_session_create(&srv->core.stun_cfg, lis->obj_name,  
    363                                     &sess_cb, PJ_FALSE, &sess); 
    364     if (status != PJ_SUCCESS) { 
    365         srv->core.listener[index] = NULL; 
    366         return status; 
    367     } 
    368  
    369     pj_stun_session_set_user_data(sess, lis); 
    370     pj_stun_session_set_credential(sess, PJ_STUN_AUTH_LONG_TERM,  
    371                                    &srv->core.cred); 
    372  
    373     srv->core.stun_sess[index] = sess; 
    374369    lis->id = index; 
    375370    srv->core.lis_cnt++; 
     
    379374 
    380375    return PJ_SUCCESS; 
    381 } 
    382  
    383  
    384 /* 
    385  * Send packet with this listener. 
    386  */ 
    387 PJ_DEF(pj_status_t) pj_turn_listener_sendto(pj_turn_listener *listener, 
    388                                             const void *packet, 
    389                                             pj_size_t size, 
    390                                             unsigned flag, 
    391                                             const pj_sockaddr_t *addr, 
    392                                             int addr_len) 
    393 { 
    394     pj_assert(listener->id != PJ_TURN_INVALID_LIS_ID); 
    395     return listener->sendto(listener, packet, size, flag, addr, addr_len); 
    396376} 
    397377 
     
    412392            srv->core.lis_cnt--; 
    413393            listener->id = PJ_TURN_INVALID_LIS_ID; 
    414             if (srv->core.stun_sess[i]) { 
    415                 pj_stun_session_destroy(srv->core.stun_sess[i]); 
    416                 srv->core.stun_sess[i] = NULL; 
    417             } 
    418394            break; 
    419395        } 
     
    423399    /* Destroy */ 
    424400    return listener->destroy(listener); 
     401} 
     402 
     403 
     404/** 
     405 * Add a reference to a transport. 
     406 */ 
     407PJ_DEF(void) pj_turn_transport_add_ref( pj_turn_transport *transport, 
     408                                        pj_turn_allocation *alloc) 
     409{ 
     410    transport->add_ref(transport, alloc); 
     411} 
     412 
     413 
     414/** 
     415 * Decrement transport reference counter. 
     416 */ 
     417PJ_DEF(void) pj_turn_transport_dec_ref( pj_turn_transport *transport, 
     418                                        pj_turn_allocation *alloc) 
     419{ 
     420    transport->dec_ref(transport, alloc); 
    425421} 
    426422 
     
    467463 */ 
    468464static pj_status_t on_tx_stun_msg( pj_stun_session *sess, 
    469                                    const void *pkt, 
    470                                    pj_size_t pkt_size, 
     465                                   void *token, 
     466                                   const void *pdu, 
     467                                   pj_size_t pdu_size, 
    471468                                   const pj_sockaddr_t *dst_addr, 
    472469                                   unsigned addr_len) 
    473470{ 
    474     pj_turn_listener *listener; 
     471    pj_turn_transport *transport = (pj_turn_transport*) token; 
    475472     
    476     listener = (pj_turn_listener*) pj_stun_session_get_user_data(sess); 
    477  
    478     PJ_ASSERT_RETURN(listener!=NULL, PJ_EINVALIDOP); 
    479  
    480     return pj_turn_listener_sendto(listener, pkt, pkt_size, 0,  
    481                                    dst_addr, addr_len); 
     473    PJ_ASSERT_RETURN(transport!=NULL, PJ_EINVALIDOP); 
     474 
     475    PJ_UNUSED_ARG(sess); 
     476 
     477    return transport->sendto(transport, pdu, pdu_size, 0,  
     478                             dst_addr, addr_len); 
    482479} 
    483480 
     
    485482/* Respond to STUN request */ 
    486483static pj_status_t stun_respond(pj_stun_session *sess,  
     484                                pj_turn_transport *transport, 
    487485                                const pj_stun_rx_data *rdata, 
    488486                                unsigned code,  
     
    504502 
    505503    /* Send the response */ 
    506     return pj_stun_session_send_msg(sess, cache, dst_addr,  addr_len, tdata); 
     504    return pj_stun_session_send_msg(sess, transport, cache, PJ_FALSE,  
     505                                    dst_addr,  addr_len, tdata); 
    507506} 
    508507 
     
    510509/* Callback from our own STUN session when incoming request arrives. 
    511510 * This function is triggered by pj_stun_session_on_rx_pkt() call in 
    512   * pj_turn_srv_on_rx_pkt() function below. 
     511 * pj_turn_srv_on_rx_pkt() function below. 
    513512 */ 
    514513static pj_status_t on_rx_stun_request(pj_stun_session *sess, 
    515                                       const pj_uint8_t *pkt, 
    516                                       unsigned pkt_len, 
     514                                      const pj_uint8_t *pdu, 
     515                                      unsigned pdu_len, 
    517516                                      const pj_stun_rx_data *rdata, 
     517                                      void *token, 
    518518                                      const pj_sockaddr_t *src_addr, 
    519519                                      unsigned src_addr_len) 
    520520{ 
    521     pj_turn_listener *listener; 
     521    pj_turn_transport *transport; 
    522522    const pj_stun_msg *msg = rdata->msg; 
    523523    pj_turn_srv *srv; 
     
    525525    pj_status_t status; 
    526526 
    527     PJ_UNUSED_ARG(pkt); 
    528     PJ_UNUSED_ARG(pkt_len); 
    529  
    530     listener = (pj_turn_listener*) pj_stun_session_get_user_data(sess); 
    531     srv = listener->server; 
     527    PJ_UNUSED_ARG(pdu); 
     528    PJ_UNUSED_ARG(pdu_len); 
     529 
     530    transport = (pj_turn_transport*) token; 
     531    srv = transport->listener->server; 
    532532 
    533533    /* Respond any requests other than ALLOCATE with 437 response */ 
    534534    if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) { 
    535         stun_respond(sess, rdata, PJ_STUN_SC_ALLOCATION_MISMATCH, 
     535        stun_respond(sess, transport, rdata, PJ_STUN_SC_ALLOCATION_MISMATCH, 
    536536                     NULL, PJ_FALSE, src_addr, src_addr_len); 
    537537        return PJ_SUCCESS; 
     
    541541     * in this function. 
    542542     */ 
    543     status = pj_turn_allocation_create(listener, src_addr, src_addr_len, 
     543    status = pj_turn_allocation_create(transport, src_addr, src_addr_len, 
    544544                                       rdata, sess, &alloc); 
    545545    if (status != PJ_SUCCESS) { 
     
    577577    } else { 
    578578        /* Otherwise this is a new client */ 
    579         unsigned options, lis_id; 
     579        unsigned options; 
     580        unsigned parsed_len; 
    580581        pj_status_t status; 
    581582 
    582583        /* Check that this is a STUN message */ 
    583584        options = PJ_STUN_CHECK_PACKET; 
    584         if (pkt->listener->tp_type == PJ_TURN_TP_UDP) 
     585        if (pkt->transport->listener->tp_type == PJ_TURN_TP_UDP) 
    585586            options |= PJ_STUN_IS_DATAGRAM; 
    586587 
    587588        status = pj_stun_msg_check(pkt->pkt, pkt->len, options); 
    588589        if (status != PJ_SUCCESS) { 
    589             char errmsg[PJ_ERR_MSG_SIZE]; 
    590             char ip[PJ_INET6_ADDRSTRLEN+10]; 
    591  
    592             pj_strerror(status, errmsg, sizeof(errmsg)); 
    593             PJ_LOG(5,(srv->obj_name,  
    594                       "Non STUN packet from %s is dropped: %s", 
    595                       pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 
    596                       errmsg)); 
     590            /* If the first byte are not STUN, drop the packet. First byte 
     591             * of STUN message is always 0x00 or 0x01. Otherwise wait for 
     592             * more data as the data might have come from TCP. 
     593             * 
     594             * Also drop packet if it's unreasonably too big, as this might 
     595             * indicate invalid data that's building up in the buffer. 
     596             * 
     597             * Or if packet is a datagram. 
     598             */ 
     599            if ((*pkt->pkt != 0x00 && *pkt->pkt != 0x01) || 
     600                pkt->len > 1600 || 
     601                (options & PJ_STUN_IS_DATAGRAM))  
     602            { 
     603                char errmsg[PJ_ERR_MSG_SIZE]; 
     604                char ip[PJ_INET6_ADDRSTRLEN+10]; 
     605 
     606                pkt->len = 0; 
     607 
     608                pj_strerror(status, errmsg, sizeof(errmsg)); 
     609                PJ_LOG(5,(srv->obj_name,  
     610                          "Non-STUN packet from %s is dropped: %s", 
     611                          pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 
     612                          errmsg)); 
     613            } 
    597614            return; 
    598615        } 
    599  
    600         lis_id = pkt->listener->id; 
    601616 
    602617        /* Hand over processing to STUN session. This will trigger 
     
    605620         */ 
    606621        options &= ~PJ_STUN_CHECK_PACKET; 
    607         status = pj_stun_session_on_rx_pkt(srv->core.stun_sess[lis_id],  
    608                                            pkt->pkt, pkt->len, options, NULL, 
    609                                            &pkt->src.clt_addr,  
     622        parsed_len = 0; 
     623        status = pj_stun_session_on_rx_pkt(srv->core.stun_sess, pkt->pkt,  
     624                                           pkt->len, options, pkt->transport, 
     625                                           &parsed_len, &pkt->src.clt_addr,  
    610626                                           pkt->src_addr_len); 
    611627        if (status != PJ_SUCCESS) { 
     
    618634                      pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 
    619635                      errmsg)); 
    620             return; 
    621         } 
    622     } 
    623 } 
    624  
    625  
     636        } 
     637 
     638        if (pkt->transport->listener->tp_type == PJ_TURN_TP_UDP) { 
     639            pkt->len = 0; 
     640        } else if (parsed_len > 0) { 
     641            if (parsed_len == pkt->len) { 
     642                pkt->len = 0; 
     643            } else { 
     644                pj_memmove(pkt->pkt, pkt->pkt+parsed_len, 
     645                           pkt->len - parsed_len); 
     646                pkt->len -= parsed_len; 
     647            } 
     648        } 
     649    } 
     650} 
     651 
     652 
Note: See TracChangeset for help on using the changeset viewer.