Changeset 1852 for pjproject


Ignore:
Timestamp:
Mar 9, 2008 12:55:00 PM (17 years ago)
Author:
bennylp
Message:

More work for ticket #485: updated pjnath with TURN-07 and added authentication in the server

Location:
pjproject/trunk/pjnath
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjnath/build/pjturn_srv.dsp

    r1850 r1852  
    4343# PROP Target_Dir "" 
    4444# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 
    45 # ADD CPP /nologo /MD /W3 /GX /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 
     45# ADD CPP /nologo /MD /W4 /GX /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 
    4646# ADD BASE RSC /l 0x409 /d "NDEBUG" 
    4747# ADD RSC /l 0x409 /d "NDEBUG" 
     
    6767# PROP Target_Dir "" 
    6868# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 
    69 # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c 
     69# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c 
    7070# ADD BASE RSC /l 0x409 /d "_DEBUG" 
    7171# ADD RSC /l 0x409 /d "_DEBUG" 
     
    9292# Begin Source File 
    9393 
     94SOURCE="..\src\pjturn-srv\auth.c" 
     95# End Source File 
     96# Begin Source File 
     97 
    9498SOURCE="..\src\pjturn-srv\listener_udp.c" 
    9599# End Source File 
     
    108112# Begin Source File 
    109113 
     114SOURCE="..\src\pjturn-srv\auth.h" 
     115# End Source File 
     116# Begin Source File 
     117 
    110118SOURCE="..\src\pjturn-srv\turn.h" 
    111119# End Source File 
  • pjproject/trunk/pjnath/include/pjnath/stun_msg.h

    r1850 r1852  
    298298    PJ_STUN_ATTR_RELAY_ADDR         = 0x0016,/**< RELAY-ADDRESS attribute.  */ 
    299299    PJ_STUN_ATTR_REQ_ADDR_TYPE      = 0x0017,/**< REQUESTED-ADDRESS-TYPE    */ 
    300     PJ_STUN_ATTR_REQ_PORT_PROPS     = 0x0018,/**< REQUESTED-PORT-PROPS      */ 
     300    PJ_STUN_ATTR_REQ_PROPS          = 0x0018,/**< REQUESTED-PROPS           */ 
    301301    PJ_STUN_ATTR_REQ_TRANSPORT      = 0x0019,/**< REQUESTED-TRANSPORT       */ 
    302302    PJ_STUN_ATTR_XOR_MAPPED_ADDR    = 0x0020,/**< XOR-MAPPED-ADDRESS        */ 
    303303    PJ_STUN_ATTR_TIMER_VAL          = 0x0021,/**< TIMER-VAL attribute.      */ 
    304     PJ_STUN_ATTR_REQ_IP             = 0x0022,/**< REQUESTED-IP attribute    */ 
     304    PJ_STUN_ATTR_RESERVATION_TOKEN  = 0x0022,/**< TURN RESERVATION-TOKEN    */ 
    305305    PJ_STUN_ATTR_XOR_REFLECTED_FROM = 0x0023,/**< XOR-REFLECTED-FROM        */ 
    306306    PJ_STUN_ATTR_PRIORITY           = 0x0024,/**< PRIORITY                  */ 
     
    359359    PJ_STUN_SC_INSUFFICIENT_CAPACITY    = 507,  /**< Insufficient Capacity  
    360360                                                     (TURN) */ 
     361    PJ_STUN_SC_INSUFFICIENT_PORT_CAPACITY=508,  /**< Insufficient Port Capacity  
     362                                                     (TURN) */ 
    361363    PJ_STUN_SC_GLOBAL_FAILURE           = 600   /**< Global Failure         */ 
    362364} pj_stun_status; 
     
    946948 
    947949/** 
    948  * This describes the TURN REQUESTED-PORT-PROPS attribute, encoded as 
     950 * This describes the TURN REQUESTED-PROPS attribute, encoded as 
    949951 * STUN 32bit integer attribute. Few macros are provided to manipulate 
    950952 * the values in this attribute: #PJ_STUN_GET_RPP_BITS(),  
    951953 * #PJ_STUN_SET_RPP_BITS(), #PJ_STUN_GET_RPP_PORT(), and 
    952954 * #PJ_STUN_SET_RPP_PORT(). 
    953  * 
     955 *  
    954956 * This attribute allows the client to request certain properties for 
    955  * the port that is allocated by the server.  The attribute can be used 
    956  * with any transport protocol that has the notion of a 16 bit port 
    957  * space (including TCP and UDP).  The attribute is 32 bits long.  Its 
    958  * format is: 
     957 * the relayed transport address that is allocated by the server.  The 
     958 * attribute is 32 bits long.  Its format is: 
    959959 
    960960 \verbatim 
     
    963963      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
    964964     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
    965      |       Reserved = 0        | A |    Specific Port Number       | 
     965     |   Prop-type   |                  Reserved = 0                 | 
    966966     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
    967967 
    968968 \endverbatim 
    969969 
    970  * The two bits labeled A in the diagram above are for requested port 
    971  * alignment and have the following meaning: 
    972  * 
    973  *  - 00  no specific port alignment 
    974  *  - 01  odd port number 
    975  *  - 10  even port number 
    976  *  - 11  even port number; reserve next higher port 
    977  */ 
    978 typedef struct pj_stun_uint_attr pj_stun_req_port_props_attr; 
    979  
    980 /** 
    981  * Get the 2 bits requested port alignment value from a 32bit integral 
    982  * value of TURN REQUESTED-PORT-PROPS attribute. 
    983  */ 
    984 #define PJ_STUN_GET_RPP_BITS(u32)   ((u32 >> 16) & 0x03) 
    985  
    986 /** 
    987  * Convert 2 bits requested port alignment value to a 32bit integral 
    988  * value of TURN REQUESTED-PORT-PROPS attribute. 
    989  */ 
    990 #define PJ_STUN_SET_RPP_BITS(A)     (A << 16) 
    991  
    992 /** 
    993  * Get the port number in TURN REQUESTED-PORT-PROPS attribute. The port 
    994  * number is returned in host byte order. 
    995  */ 
    996 #define PJ_STUN_GET_RPP_PORT(u32)   pj_ntohs((pj_uint16_t)(u32 & 0x0000FFFFL)) 
    997  
    998 /** 
    999  * Convert port number in host byte order to 32bit value to be encoded in  
    1000  * TURN REQUESTED-PORT-PROPS attribute. 
    1001  */ 
    1002 #define PJ_STUN_SET_RPP_PORT(port) ((pj_uint32_t)pj_htons((pj_uint16_t)(port))) 
     970 * The field labeled "Prop-type" is an 8-bit field specifying the 
     971 * desired property.  The rest of the attribute is RFFU (Reserved For 
     972 * Future Use) and MUST be set to 0 on transmission and ignored on 
     973 * reception.  The values of the "Prop-type" field are: 
     974 *  
     975 *    0x00  (Reserved) 
     976 *    0x01  Even port number 
     977 *    0x02  Pair of ports  
     978 */ 
     979typedef struct pj_stun_uint_attr pj_stun_req_props_attr; 
     980 
     981/** 
     982 * Get the 8bit Prop-type value from a 32bit integral value of TURN  
     983 * TURN REQUESTED-PROPS attribute. 
     984 */ 
     985#define PJ_STUN_GET_PROP_TYPE(u32)      (u32 >> 24) 
     986 
     987/** 
     988 * Convert 8bit Prop-type value to a 32bit integral value of TURN  
     989 * REQUESTED-PROPS attribute. 
     990 */ 
     991#define PJ_STUN_SET_PROP_TYPE(PropType) (PropType << 24) 
    1003992 
    1004993 
     
    10471036 
    10481037/** 
    1049  * This describes the TURN REQUESTED-IP attribute. 
    1050  * The REQUESTED-IP attribute is used by the client to request that a 
    1051  * specific IP address be allocated by the TURN server.  This attribute 
    1052  * is needed since it is anticipated that TURN servers will be multi- 
    1053  * homed so as to be able to allocate more than 64k transport addresses. 
    1054  * As a consequence, a client needing a second transport address on the 
    1055  * same interface as a previous one can use this attribute to request a 
    1056  * remote address from the same TURN server interface as the TURN 
    1057  * client's previous remote address. 
     1038 * This describes the TURN RESERVATION-TOKEN attribute. 
     1039 * The RESERVATION-TOKEN attribute contains a token that uniquely 
     1040 * identifies a relayed transport address being held in reserve by the 
     1041 * server.  The server includes this attribute in a success response to 
     1042 * tell the client about the token, and the client includes this 
     1043 * attribute in a subsequent Allocate request to request the server use 
     1044 * that relayed transport address for the allocation. 
    10581045 *  
    1059  * The format of this attribute is identical to XOR-MAPPED-ADDRESS. 
    1060  * However, the port component of the attribute MUST be ignored by the 
    1061  * server.  If a client wishes to request a specific IP address and 
    1062  * port, it uses both the REQUESTED-IP and REQUESTED-PORT-PROPS 
    1063  * attributes.  
    1064  */ 
    1065 typedef struct pj_stun_sockaddr_attr pj_stun_req_ip_attr; 
     1046 * The attribute value is a 64-bit-long field containing the token 
     1047 * value.  
     1048 */ 
     1049typedef struct pj_stun_uint64_attr pj_stun_res_token_attr; 
    10661050 
    10671051/** 
  • pjproject/trunk/pjnath/include/pjnath/stun_session.h

    r1498 r1852  
    294294 * Create a STUN response message. After the message has been  
    295295 * successfully created, application can send the message by calling  
    296  * pj_stun_session_send_msg(). 
     296 * pj_stun_session_send_msg(). Alternatively application may use 
     297 * pj_stun_session_respond() to create and send response in one function 
     298 * call. 
    297299 * 
    298300 * @param sess      The STUN session instance. 
     
    316318                                                pj_stun_tx_data **p_tdata); 
    317319 
    318  
    319320/** 
    320321 * Send STUN message to the specified destination. This function will encode 
     
    341342                                              unsigned addr_len, 
    342343                                              pj_stun_tx_data *tdata); 
     344 
     345/** 
     346 * Create and send STUN response message. 
     347 * 
     348 * @param sess      The STUN session instance. 
     349 * @param req       The STUN request message to be responded. 
     350 * @param err_code  Error code to be set in the response, if error response 
     351 *                  is to be created, according to pj_stun_status enumeration. 
     352 *                  This argument MUST be zero if successful response is 
     353 *                  to be created. 
     354 * @param err_msg   Optional pointer for the error message string, when 
     355 *                  creating error response. If the value is NULL and the 
     356 *                  \a err_code is non-zero, then default error message will 
     357 *                  be used. 
     358 * @param cache     Specify whether session should cache this response for 
     359 *                  future request retransmission. If TRUE, subsequent request 
     360 *                  retransmission will be handled by the session and it  
     361 *                  will not call request callback. 
     362 * @param dst_addr  Destination address of the response (or equal to the 
     363 *                  source address of the original request). 
     364 * @param addr_len  Address length. 
     365 * 
     366 * @return          PJ_SUCCESS on success, or the appropriate error code. 
     367 */ 
     368PJ_DECL(pj_status_t) pj_stun_session_respond(pj_stun_session *sess,  
     369                                             const pj_stun_msg *req, 
     370                                             unsigned code,  
     371                                             const char *err_msg, 
     372                                             pj_bool_t cache,  
     373                                             const pj_sockaddr_t *dst_addr,  
     374                                             unsigned addr_len); 
    343375 
    344376/** 
  • pjproject/trunk/pjnath/src/pjnath/stun_msg.c

    r1850 r1852  
    7878    { PJ_STUN_SC_SERVER_ERROR,              "Server Error"}, 
    7979    { PJ_STUN_SC_INSUFFICIENT_CAPACITY,     "Insufficient Capacity"}, 
     80    { PJ_STUN_SC_INSUFFICIENT_PORT_CAPACITY,"Insufficient Port Capacity"}, 
    8081    { PJ_STUN_SC_GLOBAL_FAILURE,            "Global Failure"} 
    8182}; 
     
    290291    }, 
    291292    { 
    292         /* PJ_STUN_ATTR_REQUESTED_PORT_PROPS, */ 
    293         "REQUESTED-PORT-PROPS", 
     293        /* PJ_STUN_ATTR_REQUESTED_PROPS, */ 
     294        "REQUESTED-PROPS", 
    294295        &decode_uint_attr, 
    295296        &encode_uint_attr 
     
    350351    }, 
    351352    { 
    352         /* PJ_STUN_ATTR_REQUESTED_IP, */ 
    353         "REQUESTED-IP", 
    354         &decode_xored_sockaddr_attr, 
    355         &encode_sockaddr_attr 
     353        /* PJ_STUN_ATTR_RESERVATION_TOKEN, */ 
     354        "RESERVATION-TOKEN", 
     355        &decode_uint64_attr, 
     356        &encode_uint64_attr 
    356357    }, 
    357358    { 
  • pjproject/trunk/pjnath/src/pjnath/stun_msg_dump.c

    r1811 r1852  
    7575    case PJ_STUN_ATTR_RELAY_ADDR: 
    7676    case PJ_STUN_ATTR_XOR_MAPPED_ADDR: 
    77     case PJ_STUN_ATTR_REQ_IP: 
    7877    case PJ_STUN_ATTR_XOR_REFLECTED_FROM: 
    7978    case PJ_STUN_ATTR_XOR_INTERNAL_ADDR: 
     
    118117    case PJ_STUN_ATTR_BANDWIDTH: 
    119118    case PJ_STUN_ATTR_REQ_ADDR_TYPE: 
    120     case PJ_STUN_ATTR_REQ_PORT_PROPS: 
     119    case PJ_STUN_ATTR_REQ_PROPS: 
    121120    case PJ_STUN_ATTR_REQ_TRANSPORT: 
    122121    case PJ_STUN_ATTR_TIMER_VAL: 
     
    208207    case PJ_STUN_ATTR_ICE_CONTROLLED: 
    209208    case PJ_STUN_ATTR_ICE_CONTROLLING: 
     209    case PJ_STUN_ATTR_RESERVATION_TOKEN: 
    210210        { 
    211211            const pj_stun_uint64_attr *attr; 
  • pjproject/trunk/pjnath/src/pjnath/stun_session.c

    r1654 r1852  
    712712} 
    713713 
     714 
     715/* 
     716 * Create and send STUN response message. 
     717 */ 
     718PJ_DEF(pj_status_t) pj_stun_session_respond( pj_stun_session *sess,  
     719                                             const pj_stun_msg *req, 
     720                                             unsigned code,  
     721                                             const char *errmsg, 
     722                                             pj_bool_t cache,  
     723                                             const pj_sockaddr_t *dst_addr,  
     724                                             unsigned addr_len) 
     725{ 
     726    pj_status_t status; 
     727    pj_str_t reason; 
     728    pj_stun_tx_data *tdata; 
     729 
     730    status = pj_stun_session_create_res(sess, req, code,  
     731                                        (errmsg?pj_cstr(&reason,errmsg):NULL),  
     732                                        &tdata); 
     733    if (status != PJ_SUCCESS) 
     734        return status; 
     735 
     736    return pj_stun_session_send_msg(sess, cache, dst_addr,  addr_len, tdata); 
     737} 
     738 
     739 
    714740/* 
    715741 * Cancel outgoing STUN transaction.  
  • pjproject/trunk/pjnath/src/pjturn-srv/allocation.c

    r1850 r1852  
    1818 */ 
    1919#include "turn.h" 
     20#include "auth.h" 
     21 
    2022 
    2123#define THIS_FILE   "allocation.c" 
     
    3133#define PEER_TABLE_SIZE     32 
    3234 
     35#define MAX_CLIENT_BANDWIDTH    128  /* In Kbps */ 
     36#define DEFA_CLIENT_BANDWIDTH   64 
     37 
     38#define MIN_LIFETIME            30 
     39#define MAX_LIFETIME            600 
     40#define DEF_LIFETIME            300 
     41 
     42 
     43 
    3344/* ChannelData header */ 
    3445typedef struct channel_data_hdr 
     
    3950 
    4051 
     52/* Parsed Allocation request. */ 
     53typedef struct alloc_request 
     54{ 
     55    unsigned            tp_type;                    /* Requested transport  */ 
     56    char                addr[PJ_INET6_ADDRSTRLEN];  /* Requested IP         */ 
     57    unsigned            bandwidth;                  /* Requested bandwidth  */ 
     58    unsigned            lifetime;                   /* Lifetime.            */ 
     59    unsigned            rpp_bits;                   /* A bits               */ 
     60    unsigned            rpp_port;                   /* Requested port       */ 
     61} alloc_request; 
     62 
     63 
     64 
    4165/* Prototypes */ 
    42 static pj_status_t create_relay(pjturn_allocation *alloc, 
    43                                 const pjturn_allocation_req *req); 
     66static void destroy_allocation(pj_turn_allocation *alloc); 
     67static pj_status_t create_relay(pj_turn_srv *srv, 
     68                                pj_turn_allocation *alloc, 
     69                                const pj_stun_msg *msg, 
     70                                const alloc_request *req, 
     71                                pj_turn_relay_res *relay); 
     72static void destroy_relay(pj_turn_relay_res *relay); 
    4473static void on_rx_from_peer(pj_ioqueue_key_t *key,  
    4574                            pj_ioqueue_op_key_t *op_key,  
    4675                            pj_ssize_t bytes_read); 
    47 static void destroy_relay(pjturn_relay_res *relay); 
    4876static pj_status_t stun_on_send_msg(pj_stun_session *sess, 
    4977                                    const void *pkt, 
     
    6593 
    6694/* Log allocation error */ 
    67 static void alloc_err(pjturn_allocation *alloc, const char *title, 
     95static void alloc_err(pj_turn_allocation *alloc, const char *title, 
    6896                      pj_status_t status) 
    6997{ 
     
    75103} 
    76104 
     105 
     106/* Parse ALLOCATE request */ 
     107static pj_status_t parse_allocate_req(alloc_request *cfg, 
     108                                      pj_stun_session *sess, 
     109                                      const pj_stun_msg *req, 
     110                                      const pj_sockaddr_t *src_addr, 
     111                                      unsigned src_addr_len) 
     112{ 
     113    pj_stun_bandwidth_attr *attr_bw; 
     114    pj_stun_req_transport_attr *attr_req_tp; 
     115    pj_stun_res_token_attr *attr_res_token; 
     116    pj_stun_req_props_attr *attr_rpp; 
     117    pj_stun_lifetime_attr *attr_lifetime; 
     118 
     119    pj_bzero(cfg, sizeof(*cfg)); 
     120 
     121    /* Get BANDWIDTH attribute, if any. */ 
     122    attr_bw = (pj_stun_uint_attr*) 
     123              pj_stun_msg_find_attr(req, PJ_STUN_ATTR_BANDWIDTH, 0); 
     124    if (attr_bw) { 
     125        cfg->bandwidth = attr_bw->value; 
     126    } else { 
     127        cfg->bandwidth = DEFA_CLIENT_BANDWIDTH; 
     128    } 
     129 
     130    /* Check if we can satisfy the bandwidth */ 
     131    if (cfg->bandwidth > MAX_CLIENT_BANDWIDTH) { 
     132        pj_stun_session_respond(sess, req, PJ_STUN_SC_ALLOCATION_QUOTA_REACHED, 
     133                                "Invalid bandwidth", PJ_TRUE, 
     134                                src_addr, src_addr_len); 
     135        return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_ALLOCATION_QUOTA_REACHED); 
     136    } 
     137 
     138    /* MUST have REQUESTED-TRANSPORT attribute */ 
     139    attr_req_tp = (pj_stun_uint_attr*) 
     140                  pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_TRANSPORT, 0); 
     141    if (attr_req_tp == NULL) { 
     142        pj_stun_session_respond(sess, req, PJ_STUN_SC_BAD_REQUEST, 
     143                                "Missing REQUESTED-TRANSPORT attribute",  
     144                                PJ_TRUE, src_addr, src_addr_len); 
     145        return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); 
     146    } 
     147 
     148    cfg->tp_type = PJ_STUN_GET_RT_PROTO(attr_req_tp->value); 
     149 
     150    /* Can only support UDP for now */ 
     151    if (cfg->tp_type != PJ_TURN_TP_UDP) { 
     152        pj_stun_session_respond(sess, req, PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, 
     153                                NULL, PJ_TRUE, src_addr, src_addr_len); 
     154        return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO); 
     155    } 
     156 
     157    /* Get RESERVATION-TOKEN attribute, if any */ 
     158    attr_res_token = (pj_stun_res_token_attr*) 
     159                     pj_stun_msg_find_attr(req, PJ_STUN_ATTR_RESERVATION_TOKEN, 
     160                                           0); 
     161    if (attr_res_token) { 
     162        /* We don't support RESERVATION-TOKEN for now */ 
     163        pj_stun_session_respond(sess, req,  
     164                                PJ_STUN_SC_BAD_REQUEST, 
     165                                "RESERVATION-TOKEN is not supported", PJ_TRUE,  
     166                                src_addr, src_addr_len); 
     167        return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); 
     168    } 
     169 
     170    /* Get REQUESTED-PROPS attribute, if any */ 
     171    attr_rpp = (pj_stun_req_props_attr*) 
     172               pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_PROPS, 0); 
     173    if (attr_rpp) { 
     174        /* We don't support REQUESTED-PROPS for now */ 
     175        pj_stun_session_respond(sess, req,  
     176                                PJ_STUN_SC_BAD_REQUEST, 
     177                                "REQUESTED-PROPS is not supported", PJ_TRUE,  
     178                                src_addr, src_addr_len); 
     179        return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); 
     180    } 
     181 
     182    /* Get LIFETIME attribute */ 
     183    attr_lifetime = (pj_stun_uint_attr*) 
     184                    pj_stun_msg_find_attr(req, PJ_STUN_ATTR_LIFETIME, 0); 
     185    if (attr_lifetime) { 
     186        cfg->lifetime = attr_lifetime->value; 
     187        if (cfg->lifetime < MIN_LIFETIME) { 
     188            pj_stun_session_respond(sess, req, PJ_STUN_SC_BAD_REQUEST, 
     189                                    "LIFETIME too short", PJ_TRUE,  
     190                                    src_addr, src_addr_len); 
     191            return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); 
     192        } 
     193        if (cfg->lifetime > MAX_LIFETIME) 
     194            cfg->lifetime = MAX_LIFETIME; 
     195    } else { 
     196        cfg->lifetime = DEF_LIFETIME; 
     197    } 
     198 
     199    return PJ_SUCCESS; 
     200} 
     201 
     202 
     203/* Respond to ALLOCATE request */ 
     204static pj_status_t send_allocate_response(pj_turn_allocation *alloc, 
     205                                          pj_stun_session *srv_sess, 
     206                                          const pj_stun_msg *msg) 
     207{ 
     208    pj_stun_tx_data *tdata; 
     209    pj_status_t status; 
     210 
     211    /* Respond the original ALLOCATE request */ 
     212    status = pj_stun_session_create_res(srv_sess, msg, 0, NULL, &tdata); 
     213    if (status != PJ_SUCCESS) 
     214        return status; 
     215 
     216    /* Add RELAYED-ADDRESS attribute */ 
     217    pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
     218                                  PJ_STUN_ATTR_RELAY_ADDR, PJ_TRUE, 
     219                                  &alloc->relay.hkey.addr, 
     220                                  pj_sockaddr_get_len(&alloc->relay.hkey.addr)); 
     221 
     222    /* Add LIFETIME. */ 
     223    pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 
     224                              PJ_STUN_ATTR_LIFETIME,  
     225                              (unsigned)alloc->relay.lifetime); 
     226 
     227    /* Add BANDWIDTH */ 
     228    pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 
     229                              PJ_STUN_ATTR_BANDWIDTH, 
     230                              alloc->bandwidth); 
     231 
     232    /* Add RESERVATION-TOKEN */ 
     233    PJ_TODO(ADD_RESERVATION_TOKEN); 
     234 
     235    /* Add XOR-MAPPED-ADDRESS */ 
     236    pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
     237                                  PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE, 
     238                                  &alloc->hkey.clt_addr, 
     239                                  pj_sockaddr_get_len(&alloc->hkey.clt_addr)); 
     240     
     241    /* Send the response */ 
     242    return pj_stun_session_send_msg(srv_sess, PJ_TRUE, 
     243                                    &alloc->hkey.clt_addr,  
     244                                    pj_sockaddr_get_len(&alloc->hkey.clt_addr), 
     245                                    tdata); 
     246} 
     247 
     248 
     249/* 
     250 * Init credential for the allocation. We use static credential, meaning that 
     251 * the user's password must not change during allocation. 
     252 */ 
     253static pj_status_t init_cred(pj_turn_allocation *alloc, const pj_stun_msg *req) 
     254{ 
     255    const pj_stun_username_attr *user; 
     256    const pj_stun_realm_attr *realm; 
     257    const pj_stun_nonce_attr *nonce; 
     258    pj_status_t status; 
     259 
     260    realm = (const pj_stun_realm_attr*) 
     261            pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REALM, 0); 
     262    PJ_ASSERT_RETURN(realm != NULL, PJ_EBUG); 
     263 
     264    user = (const pj_stun_username_attr*) 
     265           pj_stun_msg_find_attr(req, PJ_STUN_ATTR_USERNAME, 0); 
     266    PJ_ASSERT_RETURN(user != NULL, PJ_EBUG); 
     267 
     268    nonce = (const pj_stun_nonce_attr*) 
     269            pj_stun_msg_find_attr(req, PJ_STUN_ATTR_NONCE, 0); 
     270    PJ_ASSERT_RETURN(nonce != NULL, PJ_EBUG); 
     271 
     272    /* Lookup the password */ 
     273    status = pj_turn_get_password(NULL, NULL, &realm->value,  
     274                                  &user->value, alloc->pool,  
     275                                  &alloc->cred.data.static_cred.data_type,  
     276                                  &alloc->cred.data.static_cred.data); 
     277    if (status != PJ_SUCCESS) 
     278        return status; 
     279 
     280    /* Save credential */ 
     281    alloc->cred.type = PJ_STUN_AUTH_CRED_STATIC; 
     282    pj_strdup(alloc->pool, &alloc->cred.data.static_cred.realm, &realm->value); 
     283    pj_strdup(alloc->pool, &alloc->cred.data.static_cred.username, &user->value); 
     284    pj_strdup(alloc->pool, &alloc->cred.data.static_cred.nonce, &nonce->value); 
     285 
     286    return PJ_SUCCESS; 
     287} 
     288 
     289 
    77290/* 
    78291 * Create new allocation. 
    79292 */ 
    80 PJ_DEF(pj_status_t) pjturn_allocation_create(pjturn_listener *listener, 
    81                                              const pj_sockaddr_t *src_addr, 
    82                                              unsigned src_addr_len, 
    83                                              const pj_stun_msg *msg, 
    84                                              const pjturn_allocation_req *req, 
    85                                              pjturn_allocation **p_alloc) 
    86 { 
    87     pjturn_srv *srv = listener->server; 
     293PJ_DEF(pj_status_t) pj_turn_allocation_create(pj_turn_listener *listener, 
     294                                              const pj_sockaddr_t *src_addr, 
     295                                              unsigned src_addr_len, 
     296                                              const pj_stun_msg *msg, 
     297                                              pj_stun_session *srv_sess, 
     298                                              pj_turn_allocation **p_alloc) 
     299{ 
     300    pj_turn_srv *srv = listener->server; 
    88301    pj_pool_t *pool; 
    89     pjturn_allocation *alloc; 
     302    alloc_request req; 
     303    pj_turn_allocation *alloc; 
    90304    pj_stun_session_cb sess_cb; 
    91     char relay_info[80]; 
     305    char str_tmp[80]; 
    92306    pj_status_t status; 
    93307 
     308    /* Parse ALLOCATE request */ 
     309    status = parse_allocate_req(&req, srv_sess, msg, src_addr, src_addr_len); 
     310    if (status != PJ_SUCCESS) 
     311        return status; 
     312 
    94313    pool = pj_pool_create(srv->core.pf, "alloc%p", 1000, 1000, NULL); 
    95314 
    96315    /* Init allocation structure */ 
    97     alloc = PJ_POOL_ZALLOC_T(pool, pjturn_allocation); 
     316    alloc = PJ_POOL_ZALLOC_T(pool, pj_turn_allocation); 
    98317    alloc->pool = pool; 
    99318    alloc->obj_name = pool->obj_name; 
     
    102321    alloc->relay.tp.sock = PJ_INVALID_SOCKET; 
    103322 
    104     alloc->bandwidth = req->bandwidth; 
     323    alloc->bandwidth = req.bandwidth; 
    105324 
    106325    alloc->hkey.tp_type = listener->tp_type; 
     
    110329                                            &alloc->lock); 
    111330    if (status != PJ_SUCCESS) { 
    112         pjturn_allocation_destroy(alloc); 
    113         return status; 
     331        goto on_error; 
    114332    } 
    115333 
     
    121339 
    122340    /* Print info */ 
    123     pj_ansi_strcpy(alloc->info, pjturn_tp_type_name(listener->tp_type)); 
     341    pj_ansi_strcpy(alloc->info, pj_turn_tp_type_name(listener->tp_type)); 
    124342    alloc->info[3] = ':'; 
    125343    pj_sockaddr_print(src_addr, alloc->info+4, sizeof(alloc->info)-4, 3); 
     
    133351                                    &sess_cb, PJ_FALSE, &alloc->sess); 
    134352    if (status != PJ_SUCCESS) { 
    135         pjturn_allocation_destroy(alloc); 
    136         return status; 
     353        goto on_error; 
    137354    } 
    138355 
     
    140357    pj_stun_session_set_user_data(alloc->sess, alloc); 
    141358 
     359    /* Init authentication credential */ 
     360    status = init_cred(alloc, msg); 
     361    if (status != PJ_SUCCESS) { 
     362        goto on_error; 
     363    } 
     364 
     365    /* Attach authentication credential to STUN session */ 
     366    pj_stun_session_set_credential(alloc->sess, &alloc->cred); 
     367 
    142368    /* Create the relay resource */ 
    143     status = pjturn_allocation_create_relay(srv, alloc, msg, req,  
    144                                             &alloc->relay); 
     369    status = create_relay(srv, alloc, msg, &req, &alloc->relay); 
    145370    if (status != PJ_SUCCESS) { 
    146         pjturn_allocation_destroy(alloc); 
    147         return status; 
     371        goto on_error; 
    148372    } 
    149373 
    150374    /* Register this allocation */ 
    151     pjturn_srv_register_allocation(srv, alloc); 
    152  
    153     pj_sockaddr_print(&alloc->relay.hkey.addr, relay_info,  
    154                       sizeof(relay_info), 3); 
     375    pj_turn_srv_register_allocation(srv, alloc); 
     376 
     377    /* Respond to ALLOCATE request */ 
     378    status = send_allocate_response(alloc, srv_sess, msg); 
     379    if (status != PJ_SUCCESS) 
     380        goto on_error; 
     381 
     382    /* Done */ 
     383    pj_sockaddr_print(&alloc->relay.hkey.addr, str_tmp,  
     384                      sizeof(str_tmp), 3); 
    155385    PJ_LOG(4,(alloc->obj_name, "Client %s created, relay addr=%s:%s",  
    156               alloc->info, pjturn_tp_type_name(req->tp_type), relay_info)); 
     386              alloc->info, pj_turn_tp_type_name(req.tp_type), str_tmp)); 
    157387 
    158388    /* Success */ 
    159389    *p_alloc = alloc; 
    160390    return PJ_SUCCESS; 
    161 } 
    162  
    163  
    164 /* 
    165  * Destroy allocation. 
    166  */ 
    167 PJ_DECL(void) pjturn_allocation_destroy(pjturn_allocation *alloc) 
    168 { 
    169     pj_pool_t *pool; 
    170  
    171     /* Unregister this allocation */ 
    172     pjturn_srv_unregister_allocation(alloc->listener->server, alloc); 
    173  
    174     /* Destroy relay */ 
    175     destroy_relay(&alloc->relay); 
    176  
    177     /* Must lock only after destroying relay otherwise deadlock */ 
    178     if (alloc->lock) { 
    179         pj_lock_acquire(alloc->lock); 
    180     } 
    181  
    182     /* Destroy STUN session */ 
    183     if (alloc->sess) { 
    184         pj_stun_session_destroy(alloc->sess); 
    185         alloc->sess = NULL; 
    186     } 
    187  
    188     /* Destroy lock */ 
    189     if (alloc->lock) { 
    190         pj_lock_release(alloc->lock); 
    191         pj_lock_destroy(alloc->lock); 
    192         alloc->lock = NULL; 
    193     } 
    194  
    195     /* Destroy pool */ 
    196     pool = alloc->pool; 
    197     if (pool) { 
    198         alloc->pool = NULL; 
    199         pj_pool_release(pool); 
    200     } 
     391 
     392on_error: 
     393    /* Send reply to the ALLOCATE request */ 
     394    pj_strerror(status, str_tmp, sizeof(str_tmp)); 
     395    pj_stun_session_respond(srv_sess, msg, PJ_STUN_SC_BAD_REQUEST, str_tmp,  
     396                            PJ_TRUE, src_addr, src_addr_len); 
     397 
     398    /* Cleanup */ 
     399    destroy_allocation(alloc); 
     400    return status; 
    201401} 
    202402 
    203403 
    204404/* Destroy relay resource */ 
    205 static void destroy_relay(pjturn_relay_res *relay) 
     405static void destroy_relay(pj_turn_relay_res *relay) 
    206406{ 
    207407    if (relay->timer.id) { 
     
    224424} 
    225425 
    226 /* Initiate shutdown sequence for this allocation */ 
    227 static void alloc_shutdown(pjturn_allocation *alloc) 
     426 
     427/* 
     428 * Really destroy allocation. 
     429 */ 
     430static void destroy_allocation(pj_turn_allocation *alloc) 
     431{ 
     432    pj_pool_t *pool; 
     433 
     434    /* Unregister this allocation */ 
     435    pj_turn_srv_unregister_allocation(alloc->listener->server, alloc); 
     436 
     437    /* Destroy relay */ 
     438    destroy_relay(&alloc->relay); 
     439 
     440    /* Must lock only after destroying relay otherwise deadlock */ 
     441    if (alloc->lock) { 
     442        pj_lock_acquire(alloc->lock); 
     443    } 
     444 
     445    /* Destroy STUN session */ 
     446    if (alloc->sess) { 
     447        pj_stun_session_destroy(alloc->sess); 
     448        alloc->sess = NULL; 
     449    } 
     450 
     451    /* Destroy lock */ 
     452    if (alloc->lock) { 
     453        pj_lock_release(alloc->lock); 
     454        pj_lock_destroy(alloc->lock); 
     455        alloc->lock = NULL; 
     456    } 
     457 
     458    /* Destroy pool */ 
     459    pool = alloc->pool; 
     460    if (pool) { 
     461        alloc->pool = NULL; 
     462        pj_pool_release(pool); 
     463    } 
     464} 
     465 
     466 
     467PJ_DECL(void) pj_turn_allocation_destroy(pj_turn_allocation *alloc) 
     468{ 
     469    destroy_allocation(alloc); 
     470} 
     471 
     472 
     473/* Initiate shutdown sequence for this allocation and start destroy timer. 
     474 * Once allocation is marked as shutting down, any packets will be  
     475 * rejected/discarded  
     476 */ 
     477static void alloc_shutdown(pj_turn_allocation *alloc) 
    228478{ 
    229479    pj_time_val destroy_delay = DESTROY_DELAY; 
     
    231481    /* Work with existing schedule */ 
    232482    if (alloc->relay.timer.id == TIMER_ID_TIMEOUT) { 
    233         /* Cancel existing timer */ 
     483        /* Cancel existing shutdown timer */ 
    234484        pj_timer_heap_cancel(alloc->listener->server->core.timer_heap, 
    235485                             &alloc->relay.timer); 
     
    258508} 
    259509 
     510 
    260511/* Reschedule timeout using current lifetime setting */ 
    261 static pj_status_t resched_timeout(pjturn_allocation *alloc) 
     512static pj_status_t resched_timeout(pj_turn_allocation *alloc) 
    262513{ 
    263514    pj_time_val delay; 
     
    292543static void relay_timeout_cb(pj_timer_heap_t *heap, pj_timer_entry *e) 
    293544{ 
    294     pjturn_relay_res *rel; 
    295     pjturn_allocation *alloc; 
    296  
    297     rel = (pjturn_relay_res*) e->user_data; 
     545    pj_turn_relay_res *rel; 
     546    pj_turn_allocation *alloc; 
     547 
     548    PJ_UNUSED_ARG(heap); 
     549 
     550    rel = (pj_turn_relay_res*) e->user_data; 
    298551    alloc = rel->allocation; 
    299552 
     
    314567                  alloc->info)); 
    315568 
    316         pjturn_allocation_destroy(alloc); 
     569        destroy_allocation(alloc); 
    317570    } 
    318571} 
     
    322575 * Create relay. 
    323576 */ 
    324 PJ_DEF(pj_status_t) pjturn_allocation_create_relay(pjturn_srv *srv, 
    325                                                    pjturn_allocation *alloc, 
    326                                                    const pj_stun_msg *msg, 
    327                                                    const pjturn_allocation_req *req, 
    328                                                    pjturn_relay_res *relay) 
     577static pj_status_t create_relay(pj_turn_srv *srv, 
     578                                pj_turn_allocation *alloc, 
     579                                const pj_stun_msg *msg, 
     580                                const alloc_request *req, 
     581                                pj_turn_relay_res *relay) 
    329582{ 
    330583    enum { RETRY = 40 }; 
     
    366619 
    367620    /* Create the socket */ 
    368     if (req->tp_type == PJTURN_TP_UDP) { 
     621    if (req->tp_type == PJ_TURN_TP_UDP) { 
    369622        sock_type = pj_SOCK_DGRAM(); 
    370     } else if (req->tp_type == PJTURN_TP_TCP) { 
     623    } else if (req->tp_type == PJ_TURN_TP_TCP) { 
    371624        sock_type = pj_SOCK_STREAM(); 
    372625    } else { 
     
    396649        if (req->rpp_port) { 
    397650            port = (pj_uint16_t) req->rpp_port; 
    398         } else if (req->tp_type == PJTURN_TP_UDP) { 
     651        } else if (req->tp_type == PJ_TURN_TP_UDP) { 
    399652            port = (pj_uint16_t) srv->ports.next_udp++; 
    400653            if (srv->ports.next_udp > srv->ports.max_udp) 
    401654                srv->ports.next_udp = srv->ports.min_udp; 
    402         } else if (req->tp_type == PJTURN_TP_TCP) { 
     655        } else if (req->tp_type == PJ_TURN_TP_TCP) { 
    403656            port = (pj_uint16_t) srv->ports.next_tcp++; 
    404657            if (srv->ports.next_tcp > srv->ports.max_tcp) 
     
    406659        } else { 
    407660            pj_assert(!"Invalid transport"); 
     661            port = 0; 
    408662        } 
    409663 
     
    464718 
    465719/* Create and send error response */ 
    466 static void send_reply_err(pjturn_allocation *alloc, 
     720static void send_reply_err(pj_turn_allocation *alloc, 
    467721                           const pj_stun_msg *req, 
    468722                           pj_bool_t cache,  
     
    470724{ 
    471725    pj_status_t status; 
    472     pj_str_t reason; 
    473     pj_stun_tx_data *tdata; 
    474  
    475     status = pj_stun_session_create_res(alloc->sess, req,  
    476                                         code, (errmsg?pj_cstr(&reason,errmsg):NULL),  
    477                                         &tdata); 
    478     if (status != PJ_SUCCESS) { 
    479         alloc_err(alloc, "Error creating STUN error response", status); 
    480         return; 
    481     } 
    482  
    483     status = pj_stun_session_send_msg(alloc->sess, cache,  
    484                                       &alloc->hkey.clt_addr,   
    485                                       pj_sockaddr_get_len(&alloc->hkey.clt_addr),  
    486                                       tdata); 
     726 
     727    status = pj_stun_session_respond(alloc->sess, req, code, errmsg, cache, 
     728                                     &alloc->hkey.clt_addr, 
     729                                     pj_sockaddr_get_len(&alloc->hkey.clt_addr.addr)); 
    487730    if (status != PJ_SUCCESS) { 
    488731        alloc_err(alloc, "Error sending STUN error response", status); 
     
    492735 
    493736/* Create and send successful response */ 
    494 static void send_reply_ok(pjturn_allocation *alloc, 
     737static void send_reply_ok(pj_turn_allocation *alloc, 
    495738                          const pj_stun_msg *req) 
    496739{ 
     
    535778 
    536779/* Create new permission */ 
    537 static pjturn_permission *create_permission(pjturn_allocation *alloc, 
     780static pj_turn_permission *create_permission(pj_turn_allocation *alloc, 
    538781                                            const pj_sockaddr_t *peer_addr, 
    539782                                            unsigned addr_len) 
    540783{ 
    541     pjturn_permission *perm; 
    542  
    543     perm = PJ_POOL_ZALLOC_T(alloc->pool, pjturn_permission); 
     784    pj_turn_permission *perm; 
     785 
     786    perm = PJ_POOL_ZALLOC_T(alloc->pool, pj_turn_permission); 
    544787    pj_memcpy(&perm->hkey.peer_addr, peer_addr, addr_len); 
    545788     
    546     if (alloc->listener->tp_type == PJTURN_TP_UDP) { 
     789    if (alloc->listener->tp_type == PJ_TURN_TP_UDP) { 
    547790        perm->sock = alloc->listener->sock; 
    548791    } else { 
     
    552795 
    553796    perm->allocation = alloc; 
    554     perm->channel = PJTURN_INVALID_CHANNEL; 
     797    perm->channel = PJ_TURN_INVALID_CHANNEL; 
    555798 
    556799    pj_gettimeofday(&perm->expiry); 
    557     perm->expiry.sec += PJTURN_PERM_TIMEOUT; 
     800    perm->expiry.sec += PJ_TURN_PERM_TIMEOUT; 
    558801 
    559802    return perm; 
     
    561804 
    562805/* Check if a permission isn't expired. Return NULL if expired. */ 
    563 static pjturn_permission *check_permission_expiry(pjturn_permission *perm) 
    564 { 
    565     pjturn_allocation *alloc = perm->allocation; 
     806static pj_turn_permission *check_permission_expiry(pj_turn_permission *perm) 
     807{ 
     808    pj_turn_allocation *alloc = perm->allocation; 
    566809    pj_time_val now; 
    567810 
     
    577820 
    578821    /* Remove from channel hash table, if assigned a channel number */ 
    579     if (perm->channel != PJTURN_INVALID_CHANNEL) { 
     822    if (perm->channel != PJ_TURN_INVALID_CHANNEL) { 
    580823        pj_hash_set(NULL, alloc->ch_table, &perm->channel,  
    581824                    sizeof(perm->channel), 0, NULL); 
     
    586829 
    587830/* Lookup permission in hash table by the peer address */ 
    588 static pjturn_permission* 
    589 lookup_permission_by_addr(pjturn_allocation *alloc, 
     831static pj_turn_permission* 
     832lookup_permission_by_addr(pj_turn_allocation *alloc, 
    590833                          const pj_sockaddr_t *peer_addr, 
    591834                          unsigned addr_len) 
    592835{ 
    593     pjturn_permission_key key; 
    594     pjturn_permission *perm; 
     836    pj_turn_permission_key key; 
     837    pj_turn_permission *perm; 
    595838 
    596839    pj_bzero(&key, sizeof(key)); 
     
    598841 
    599842    /* Lookup in peer hash table */ 
    600     perm = (pjturn_permission*) pj_hash_get(alloc->peer_table, &key, 
     843    perm = (pj_turn_permission*) pj_hash_get(alloc->peer_table, &key, 
    601844                                            sizeof(key), NULL); 
    602845    return check_permission_expiry(perm); 
     
    604847 
    605848/* Lookup permission in hash table by the channel number */ 
    606 static pjturn_permission* 
    607 lookup_permission_by_chnum(pjturn_allocation *alloc, 
     849static pj_turn_permission* 
     850lookup_permission_by_chnum(pj_turn_allocation *alloc, 
    608851                           unsigned chnum) 
    609852{ 
    610853    pj_uint16_t chnum16 = (pj_uint16_t)chnum; 
    611     pjturn_permission *perm; 
     854    pj_turn_permission *perm; 
    612855 
    613856    /* Lookup in peer hash table */ 
    614     perm = (pjturn_permission*) pj_hash_get(alloc->peer_table, &chnum16, 
     857    perm = (pj_turn_permission*) pj_hash_get(alloc->peer_table, &chnum16, 
    615858                                            sizeof(chnum16), NULL); 
    616859    return check_permission_expiry(perm); 
     
    620863 * Return PJ_TRUE is permission is found. 
    621864 */ 
    622 static pj_bool_t refresh_permission(pjturn_permission *perm) 
     865static pj_bool_t refresh_permission(pj_turn_permission *perm) 
    623866{ 
    624867    pj_gettimeofday(&perm->expiry); 
    625     if (perm->channel == PJTURN_INVALID_CHANNEL) 
    626         perm->expiry.sec += PJTURN_PERM_TIMEOUT; 
     868    if (perm->channel == PJ_TURN_INVALID_CHANNEL) 
     869        perm->expiry.sec += PJ_TURN_PERM_TIMEOUT; 
    627870    else 
    628         perm->expiry.sec += PJTURN_CHANNEL_TIMEOUT; 
     871        perm->expiry.sec += PJ_TURN_CHANNEL_TIMEOUT; 
    629872    return PJ_TRUE; 
    630873} 
    631874 
    632875/* 
    633  * Handle incoming packet from client. 
     876 * Handle incoming packet from client. This would have been called by 
     877 * server upon receiving packet from a listener. 
    634878 */ 
    635 PJ_DEF(void) pjturn_allocation_on_rx_client_pkt( pjturn_allocation *alloc, 
    636                                                  pjturn_pkt *pkt) 
     879PJ_DEF(void) pj_turn_allocation_on_rx_client_pkt(pj_turn_allocation *alloc, 
     880                                                 pj_turn_pkt *pkt) 
    637881{ 
    638882    pj_bool_t is_stun; 
    639883    pj_status_t status; 
     884 
     885    /* Lock this allocation */ 
     886    pj_lock_acquire(alloc->lock); 
    640887 
    641888    /* Quickly check if this is STUN message */ 
     
    650897         */ 
    651898        unsigned options = PJ_STUN_CHECK_PACKET; 
    652         if (pkt->listener->tp_type == PJTURN_TP_UDP) 
     899        if (pkt->listener->tp_type == PJ_TURN_TP_UDP) 
    653900            options |= PJ_STUN_IS_DATAGRAM; 
    654901 
     
    659906        if (status != PJ_SUCCESS) { 
    660907            alloc_err(alloc, "Error handling STUN packet", status); 
    661             return; 
     908            goto on_return; 
    662909        } 
    663910 
     
    667914         */ 
    668915        channel_data_hdr *cd = (channel_data_hdr*)pkt->pkt; 
    669         pjturn_permission *perm; 
     916        pj_turn_permission *perm; 
    670917        pj_ssize_t len; 
    671918 
    672919        /* For UDP check the packet length */ 
    673         if (alloc->listener->tp_type == PJTURN_TP_UDP) { 
     920        if (alloc->listener->tp_type == PJ_TURN_TP_UDP) { 
    674921            if (pkt->len < pj_ntohs(cd->length)+sizeof(*cd)) { 
    675922                PJ_LOG(4,(alloc->obj_name,  
    676923                          "ChannelData from %s discarded: UDP size error", 
    677924                          alloc->info)); 
    678                 return; 
     925                goto on_return; 
    679926            } 
    680927        } else { 
    681928            pj_assert(!"Unsupported transport"); 
    682             return; 
     929            goto on_return; 
    683930        } 
    684931 
     
    689936                      "ChannelData from %s discarded: not found", 
    690937                      alloc->info)); 
    691             return; 
     938            goto on_return; 
    692939        } 
    693940 
     
    701948        refresh_permission(perm); 
    702949    } 
    703 } 
     950 
     951on_return: 
     952    /* Release lock */ 
     953    pj_lock_release(alloc->lock); 
     954} 
     955 
    704956 
    705957/* 
     
    707959 * on_rx_from_peer(). 
    708960 */ 
    709 static void on_rx_peer_pkt(pjturn_allocation *alloc, 
    710                            pjturn_relay_res *rel, 
    711                            char *pkt, pj_size_t len, 
    712                            const pj_sockaddr *src_addr) 
    713 { 
    714     pjturn_permission *perm; 
     961static void handle_peer_pkt(pj_turn_allocation *alloc, 
     962                            pj_turn_relay_res *rel, 
     963                            char *pkt, pj_size_t len, 
     964                            const pj_sockaddr *src_addr) 
     965{ 
     966    pj_turn_permission *perm; 
    715967 
    716968    /* Lookup permission */ 
     
    725977     * this permission is attached to a channel number. 
    726978     */ 
    727     if (perm->channel != PJTURN_INVALID_CHANNEL) { 
     979    if (perm->channel != PJ_TURN_INVALID_CHANNEL) { 
    728980        /* Send ChannelData */ 
    729981        channel_data_hdr *cd = (channel_data_hdr*)rel->tp.tx_pkt; 
    730982 
    731         if (len > PJTURN_MAX_PKT_LEN) { 
     983        if (len > PJ_TURN_MAX_PKT_LEN) { 
    732984            char peer_addr[80]; 
    733985            pj_sockaddr_print(src_addr, peer_addr, sizeof(peer_addr), 3); 
    734             PJ_LOG(1,(alloc->obj_name, "Client %s: discarded data from %s " 
     986            PJ_LOG(4,(alloc->obj_name, "Client %s: discarded data from %s " 
    735987                      "because it's too long (%d bytes)", 
    736988                      alloc->info, peer_addr, len)); 
     
    746998 
    747999        /* Send to client */ 
    748         pjturn_listener_sendto(alloc->listener, rel->tp.tx_pkt, 
     1000        pj_turn_listener_sendto(alloc->listener, rel->tp.tx_pkt, 
    7491001                               len+sizeof(channel_data_hdr), 0, 
    7501002                               &alloc->hkey.clt_addr, 
     
    7711023                            pj_ssize_t bytes_read) 
    7721024{ 
    773     pjturn_relay_res *rel; 
     1025    pj_turn_relay_res *rel; 
    7741026    pj_status_t status; 
    7751027 
    776     rel = (pjturn_relay_res*) pj_ioqueue_get_user_data(key); 
     1028    rel = (pj_turn_relay_res*) pj_ioqueue_get_user_data(key); 
     1029 
     1030    /* Lock the allocation */ 
     1031    pj_lock_acquire(rel->allocation->lock); 
    7771032 
    7781033    do { 
    7791034        if (bytes_read > 0) { 
    780             on_rx_peer_pkt(rel->allocation, rel, rel->tp.rx_pkt, 
    781                            bytes_read, &rel->tp.src_addr); 
     1035            handle_peer_pkt(rel->allocation, rel, rel->tp.rx_pkt, 
     1036                            bytes_read, &rel->tp.src_addr); 
    7821037        } 
    7831038 
     
    7951050    } while (status != PJ_EPENDING && status != PJ_ECANCELLED); 
    7961051 
     1052    /* Release allocation lock */ 
     1053    pj_lock_release(rel->allocation->lock); 
    7971054} 
    7981055 
     
    8071064                                    unsigned addr_len) 
    8081065{ 
    809     pjturn_allocation *alloc; 
    810  
    811     alloc = (pjturn_allocation*) pj_stun_session_get_user_data(sess); 
    812  
    813     return pjturn_listener_sendto(alloc->listener, pkt, pkt_size, 0, 
     1066    pj_turn_allocation *alloc; 
     1067 
     1068    alloc = (pj_turn_allocation*) pj_stun_session_get_user_data(sess); 
     1069 
     1070    return pj_turn_listener_sendto(alloc->listener, pkt, pkt_size, 0, 
    8141071                                  dst_addr, addr_len); 
    8151072} 
     
    8181075 * Callback notification from STUN session when it receives STUN 
    8191076 * requests. This callback was trigger by STUN incoming message 
    820  * processing in pjturn_allocation_on_rx_client_pkt(). 
     1077 * processing in pj_turn_allocation_on_rx_client_pkt(). 
    8211078 */ 
    8221079static pj_status_t stun_on_rx_request(pj_stun_session *sess, 
     
    8271084                                      unsigned src_addr_len) 
    8281085{ 
    829     pjturn_allocation *alloc; 
    830  
    831     alloc = (pjturn_allocation*) pj_stun_session_get_user_data(sess); 
     1086    pj_turn_allocation *alloc; 
     1087 
     1088    PJ_UNUSED_ARG(pkt); 
     1089    PJ_UNUSED_ARG(pkt_len); 
     1090    PJ_UNUSED_ARG(src_addr); 
     1091    PJ_UNUSED_ARG(src_addr_len); 
     1092 
     1093    alloc = (pj_turn_allocation*) pj_stun_session_get_user_data(sess); 
    8321094 
    8331095    /* Refuse to serve any request if we've been shutdown */ 
    8341096    if (alloc->relay.lifetime == 0) { 
     1097        /* Reject with 437 if we're shutting down */ 
    8351098        send_reply_err(alloc, msg, PJ_TRUE,  
    8361099                       PJ_STUN_SC_ALLOCATION_MISMATCH, NULL); 
     
    8951158        pj_stun_channel_number_attr *ch_attr; 
    8961159        pj_stun_peer_addr_attr *peer_attr; 
    897         pjturn_permission *p1, *p2; 
     1160        pj_turn_permission *p1, *p2; 
    8981161 
    8991162        ch_attr = (pj_stun_channel_number_attr*) 
     
    9341197        p2 = lookup_permission_by_addr(alloc, &peer_attr->sockaddr, 
    9351198                                       pj_sockaddr_get_len(&peer_attr->sockaddr)); 
    936         if (p2 && p2->channel != PJTURN_INVALID_CHANNEL) { 
     1199        if (p2 && p2->channel != PJ_TURN_INVALID_CHANNEL) { 
    9371200            send_reply_err(alloc, msg, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST,  
    9381201                           "Peer address already assigned a channel number"); 
     
    9771240 * Callback notification from STUN session when it receives STUN 
    9781241 * indications. This callback was trigger by STUN incoming message 
    979  * processing in pjturn_allocation_on_rx_client_pkt(). 
     1242 * processing in pj_turn_allocation_on_rx_client_pkt(). 
    9801243 */ 
    9811244static pj_status_t stun_on_rx_indication(pj_stun_session *sess, 
     
    9881251    pj_stun_peer_addr_attr *peer_attr; 
    9891252    pj_stun_data_attr *data_attr; 
    990     pjturn_allocation *alloc; 
    991     pjturn_permission *perm; 
    992  
    993     alloc = (pjturn_allocation*) pj_stun_session_get_user_data(sess); 
     1253    pj_turn_allocation *alloc; 
     1254    pj_turn_permission *perm; 
     1255 
     1256    PJ_UNUSED_ARG(pkt); 
     1257    PJ_UNUSED_ARG(pkt_len); 
     1258    PJ_UNUSED_ARG(src_addr); 
     1259    PJ_UNUSED_ARG(src_addr_len); 
     1260 
     1261    alloc = (pj_turn_allocation*) pj_stun_session_get_user_data(sess); 
    9941262 
    9951263    /* Only expect Send Indication */ 
     
    10251293 
    10261294    /* Relay the data to client */ 
    1027     if (alloc->hkey.tp_type == PJTURN_TP_UDP) { 
     1295    if (alloc->hkey.tp_type == PJ_TURN_TP_UDP) { 
    10281296        pj_ssize_t len = data_attr->length; 
    10291297        pj_sock_sendto(alloc->listener->sock, data_attr->data,  
  • pjproject/trunk/pjnath/src/pjturn-srv/listener_udp.c

    r1812 r1852  
    2222{ 
    2323    pj_ioqueue_op_key_t op_key; 
    24     pjturn_pkt          pkt; 
     24    pj_turn_pkt         pkt; 
    2525}; 
    2626 
    2727struct udp_listener 
    2828{ 
    29     pjturn_listener          base; 
     29    pj_turn_listener         base; 
    3030    pj_ioqueue_key_t        *key; 
    3131    unsigned                 read_cnt; 
     
    3434 
    3535 
    36 static pj_status_t udp_sendto(pjturn_listener *listener, 
     36static pj_status_t udp_sendto(pj_turn_listener *listener, 
    3737                              const void *packet, 
    3838                              pj_size_t size, 
     
    4040                              const pj_sockaddr_t *addr, 
    4141                              int addr_len); 
    42 static pj_status_t udp_destroy(pjturn_listener *udp); 
     42static pj_status_t udp_destroy(pj_turn_listener *udp); 
    4343static void on_read_complete(pj_ioqueue_key_t *key,  
    4444                             pj_ioqueue_op_key_t *op_key,  
     
    4949 * Create a new listener on the specified port. 
    5050 */ 
    51 PJ_DEF(pj_status_t) pjturn_listener_create_udp( pjturn_srv *srv, 
     51PJ_DEF(pj_status_t) pj_turn_listener_create_udp( pj_turn_srv *srv, 
    5252                                                int af, 
    5353                                                const pj_str_t *bound_addr, 
     
    5555                                                unsigned concurrency_cnt, 
    5656                                                unsigned flags, 
    57                                                 pjturn_listener **p_listener) 
     57                                                pj_turn_listener **p_listener) 
    5858{ 
    5959    pj_pool_t *pool; 
     
    6464 
    6565    /* Create structure */ 
    66     pool = pj_pool_create(srv->core.pf, "udplis%p", 1000, 1000, NULL); 
     66    pool = pj_pool_create(srv->core.pf, "udp%p", 1000, 1000, NULL); 
    6767    udp = PJ_POOL_ZALLOC_T(pool, struct udp_listener); 
    6868    udp->base.pool = pool; 
     69    udp->base.obj_name = pool->obj_name; 
    6970    udp->base.server = srv; 
    70     udp->base.tp_type = PJTURN_TP_UDP; 
     71    udp->base.tp_type = PJ_TURN_TP_UDP; 
    7172    udp->base.sock = PJ_INVALID_SOCKET; 
    7273    udp->base.sendto = &udp_sendto; 
     
    8687        goto on_error; 
    8788     
     89    /* Create info */ 
     90    pj_ansi_strcpy(udp->base.info, "UDP:"); 
     91    pj_sockaddr_print(&udp->base.addr, udp->base.info+4,  
     92                      sizeof(udp->base.info)-4, 3); 
     93 
    8894    /* Bind socket */ 
    8995    status = pj_sock_bind(udp->base.sock, &udp->base.addr,  
     
    105111    for (i=0; i<concurrency_cnt; ++i) { 
    106112        pj_pool_t *rpool = pj_pool_create(srv->core.pf, "rop%p",  
    107                                           1000, 1000, NULL); 
     113                                          sizeof(struct read_op)+1000,  
     114                                          1000, NULL); 
    108115 
    109116        udp->read_op[i] = PJ_POOL_ZALLOC_T(rpool, struct read_op); 
     
    114121 
    115122    /* Done */ 
     123    PJ_LOG(4,(udp->base.obj_name, "Listener %s created", udp->base.info)); 
     124 
    116125    *p_listener = &udp->base; 
    117126    return PJ_SUCCESS; 
     
    127136 * Destroy listener. 
    128137 */ 
    129 static pj_status_t udp_destroy(pjturn_listener *listener) 
     138static pj_status_t udp_destroy(pj_turn_listener *listener) 
    130139{ 
    131140    struct udp_listener *udp = (struct udp_listener *)listener; 
     
    150159 
    151160    if (udp->base.pool) { 
    152         pj_pool_release(udp->base.pool); 
     161        pj_pool_t *pool = udp->base.pool; 
     162 
     163        PJ_LOG(4,(udp->base.obj_name, "Listener %s destroyed",  
     164                  udp->base.info)); 
     165 
    153166        udp->base.pool = NULL; 
     167        pj_pool_release(pool); 
    154168    } 
    155169    return PJ_SUCCESS; 
     
    159173 * Callback to send packet. 
    160174 */ 
    161 static pj_status_t udp_sendto(pjturn_listener *listener, 
     175static pj_status_t udp_sendto(pj_turn_listener *listener, 
    162176                              const void *packet, 
    163177                              pj_size_t size, 
     
    167181{ 
    168182    pj_ssize_t len = size; 
    169     return pj_sock_sendto(listener->sock, packet, &len, flag, addr, 
    170                           pj_sockaddr_get_len(addr)); 
     183    return pj_sock_sendto(listener->sock, packet, &len, flag, addr, addr_len); 
    171184} 
    172185 
     
    192205            pj_gettimeofday(&read_op->pkt.rx_time); 
    193206 
    194             pjturn_srv_on_rx_pkt(udp->base.server, &read_op->pkt); 
     207            pj_turn_srv_on_rx_pkt(udp->base.server, &read_op->pkt); 
    195208        } 
    196209 
  • pjproject/trunk/pjnath/src/pjturn-srv/main.c

    r1812 r1852  
    11#include "turn.h" 
     2 
     3int err(const char *title, pj_status_t status) 
     4{ 
     5    char errmsg[PJ_ERR_MSG_SIZE]; 
     6    pj_strerror(status, errmsg, sizeof(errmsg)); 
     7 
     8    printf("%s: %s\n", title, errmsg); 
     9    return 1; 
     10} 
     11 
     12int main() 
     13{ 
     14    pj_caching_pool cp; 
     15    pj_turn_srv *srv; 
     16    pj_turn_listener *listener; 
     17    pj_status_t status; 
     18 
     19    status = pj_init(); 
     20    if (status != PJ_SUCCESS) 
     21        return err("pj_init() error", status); 
     22 
     23    pj_caching_pool_init(&cp, NULL, 0); 
     24 
     25    status = pj_turn_srv_create(&cp.factory, &srv); 
     26    if (status != PJ_SUCCESS) 
     27        return err("Error creating server", status); 
     28 
     29    status = pj_turn_listener_create_udp(srv, pj_AF_INET(), NULL, 3478, 1, 0, &listener); 
     30    if (status != PJ_SUCCESS) 
     31        return err("Error creating listener", status); 
     32 
     33    status = pj_turn_srv_add_listener(srv, listener); 
     34    if (status != PJ_SUCCESS) 
     35        return err("Error adding listener", status); 
     36 
     37    puts("Server is running"); 
     38    puts("Press <ENTER> to quit"); 
     39 
     40    { 
     41        char line[10]; 
     42        fgets(line, sizeof(line), stdin); 
     43    } 
     44 
     45    pj_turn_srv_destroy(srv); 
     46    pj_caching_pool_destroy(&cp); 
     47    pj_shutdown(); 
     48 
     49    return 0; 
     50} 
     51 
  • pjproject/trunk/pjnath/src/pjturn-srv/server.c

    r1850 r1852  
    1818 */ 
    1919#include "turn.h" 
     20#include "auth.h" 
    2021 
    2122#define MAX_CLIENTS             32 
    2223#define MAX_PEERS_PER_CLIENT    8 
    23 #define MAX_HANDLES             (MAX_CLIENTS*MAX_PEERS_PER_CLIENT+MAX_LISTENERS) 
     24//#define MAX_HANDLES           (MAX_CLIENTS*MAX_PEERS_PER_CLIENT+MAX_LISTENERS) 
     25#define MAX_HANDLES             PJ_IOQUEUE_MAX_HANDLES 
    2426#define MAX_TIMER               (MAX_HANDLES * 2) 
    2527#define MIN_PORT                49152 
     
    2729#define MAX_LISTENERS           16 
    2830#define MAX_THREADS             2 
    29  
    30 #define MAX_CLIENT_BANDWIDTH    128  /* In Kbps */ 
    31 #define DEFA_CLIENT_BANDWIDTH   64 
    32  
    33 #define MIN_LIFETIME            32 
    34 #define MAX_LIFETIME            600 
    35 #define DEF_LIFETIME            300 
    36  
     31#define MAX_NET_EVENTS          10 
    3732 
    3833/* Prototypes */ 
     34static int server_thread_proc(void *arg); 
    3935static pj_status_t on_tx_stun_msg( pj_stun_session *sess, 
    4036                                   const void *pkt, 
     
    4945                                      unsigned src_addr_len); 
    5046 
    51 /* 
    52  * Get transport type name. 
    53  */ 
    54 PJ_DEF(const char*) pjturn_tp_type_name(int tp_type) 
     47struct saved_cred 
     48{ 
     49    pj_str_t realm; 
     50    pj_str_t username; 
     51    pj_str_t nonce; 
     52    int      data_type; 
     53    pj_str_t data; 
     54}; 
     55 
     56 
     57/* 
     58 * Get transport type name, normally for logging purpose only. 
     59 */ 
     60PJ_DEF(const char*) pj_turn_tp_type_name(int tp_type) 
    5561{ 
    5662    /* Must be 3 characters long! */ 
    57     if (tp_type == PJTURN_TP_UDP) 
     63    if (tp_type == PJ_TURN_TP_UDP) { 
    5864        return "UDP"; 
    59     else if (tp_type == PJTURN_TP_TCP) 
     65    } else if (tp_type == PJ_TURN_TP_TCP) { 
    6066        return "TCP"; 
    61     else 
     67    } else { 
     68        pj_assert(!"Unsupported transport"); 
    6269        return "???"; 
     70    } 
    6371} 
    6472 
     
    6674 * Create server. 
    6775 */ 
    68 PJ_DEF(pj_status_t) pjturn_srv_create( pj_pool_factory *pf, 
    69                                        pjturn_srv **p_srv) 
     76PJ_DEF(pj_status_t) pj_turn_srv_create(pj_pool_factory *pf,  
     77                                       pj_turn_srv **p_srv) 
    7078{ 
    7179    pj_pool_t *pool; 
    72     pjturn_srv *srv; 
     80    pj_turn_srv *srv; 
     81    unsigned i; 
    7382    pj_status_t status; 
    7483 
     
    7786    /* Create server and init core settings */ 
    7887    pool = pj_pool_create(pf, "srv%p", 1000, 1000, NULL); 
    79     srv = PJ_POOL_ZALLOC_T(pool, pjturn_srv); 
    80     srv->core.obj_name = pool->obj_name; 
     88    srv = PJ_POOL_ZALLOC_T(pool, pj_turn_srv); 
     89    srv->obj_name = pool->obj_name; 
    8190    srv->core.pf = pf; 
    8291    srv->core.pool = pool; 
     92    srv->core.tls_key = srv->core.tls_data = -1; 
    8393     
     94    /* Create ioqueue */ 
    8495    status = pj_ioqueue_create(pool, MAX_HANDLES, &srv->core.ioqueue); 
    8596    if (status != PJ_SUCCESS) 
    8697        goto on_error; 
    8798 
     99    /* Server mutex */ 
     100    status = pj_lock_create_recursive_mutex(pool, srv->obj_name,  
     101                                            &srv->core.lock); 
     102    if (status != PJ_SUCCESS) 
     103        goto on_error; 
     104 
     105    /* Allocate TLS */ 
     106    status = pj_thread_local_alloc(&srv->core.tls_key); 
     107    if (status != PJ_SUCCESS) 
     108        goto on_error; 
     109 
     110    status = pj_thread_local_alloc(&srv->core.tls_data); 
     111    if (status != PJ_SUCCESS) 
     112        goto on_error; 
     113     
     114    /* Create timer heap */ 
    88115    status = pj_timer_heap_create(pool, MAX_TIMER, &srv->core.timer_heap); 
    89116    if (status != PJ_SUCCESS) 
    90117        goto on_error; 
    91118 
    92     srv->core.listener = pj_pool_calloc(pool, MAX_LISTENERS,  
     119    /* Configure lock for the timer heap */ 
     120    pj_timer_heap_set_lock(srv->core.timer_heap, srv->core.lock, PJ_FALSE); 
     121 
     122    /* Array of listeners */ 
     123    srv->core.listener = (pj_turn_listener**) 
     124                         pj_pool_calloc(pool, MAX_LISTENERS,  
    93125                                        sizeof(srv->core.listener[0])); 
    94     srv->core.stun_sess = pj_pool_calloc(pool, MAX_LISTENERS, 
     126 
     127    /* Array of STUN sessions, one for each listener */ 
     128    srv->core.stun_sess = (pj_stun_session**) 
     129                          pj_pool_calloc(pool, MAX_LISTENERS, 
    95130                                         (sizeof(srv->core.stun_sess[0]))); 
    96  
    97     srv->core.thread_cnt = MAX_THREADS; 
    98     srv->core.thread = pj_pool_calloc(pool, srv->core.thread_cnt,  
    99                                       sizeof(pj_thread_t*)); 
    100  
    101     status = pj_lock_create_recursive_mutex(pool, "srv%p", &srv->core.lock); 
    102     if (status != PJ_SUCCESS) 
    103         goto on_error; 
    104131 
    105132    /* Create hash tables */ 
     
    117144                        srv->core.timer_heap); 
    118145 
     146    /* Init STUN credential */ 
     147    srv->core.cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; 
     148    srv->core.cred.data.dyn_cred.user_data = srv; 
     149    srv->core.cred.data.dyn_cred.get_auth = &pj_turn_get_auth; 
     150    srv->core.cred.data.dyn_cred.get_cred = &pj_turn_srv_get_cred; 
     151    srv->core.cred.data.dyn_cred.get_password = &pj_turn_get_password; 
     152    srv->core.cred.data.dyn_cred.verify_nonce = &pj_turn_verify_nonce; 
     153 
     154    /* Array of worker threads */ 
     155    srv->core.thread_cnt = MAX_THREADS; 
     156    srv->core.thread = (pj_thread_t**) 
     157                       pj_pool_calloc(pool, srv->core.thread_cnt,  
     158                                      sizeof(pj_thread_t*)); 
     159 
     160    /* Start the worker threads */ 
     161    for (i=0; i<srv->core.thread_cnt; ++i) { 
     162        status = pj_thread_create(pool, srv->obj_name, &server_thread_proc,  
     163                                  srv, 0, 0, &srv->core.thread[i]); 
     164        if (status != PJ_SUCCESS) 
     165            goto on_error; 
     166    } 
     167 
     168    /* We're done. Application should add listeners now */ 
     169    PJ_LOG(4,(srv->obj_name, "TURN server v%s is running",  
     170              pj_get_version())); 
     171 
    119172    *p_srv = srv; 
    120173    return PJ_SUCCESS; 
    121174 
    122175on_error: 
    123     pjturn_srv_destroy(srv); 
     176    pj_turn_srv_destroy(srv); 
    124177    return status; 
    125178} 
    126179 
    127 /**  
    128  * Create server. 
    129  */ 
    130 PJ_DEF(pj_status_t) pjturn_srv_destroy(pjturn_srv *srv) 
    131 { 
     180 
     181/*  
     182 * Handle timer and network events  
     183 */ 
     184static void srv_handle_events(pj_turn_srv *srv, const pj_time_val *max_timeout) 
     185{ 
     186    /* timeout is 'out' var. This just to make compiler happy. */ 
     187    pj_time_val timeout = { 0, 0}; 
     188    unsigned net_event_count = 0; 
     189    int c; 
     190 
     191    /* Poll the timer. The timer heap has its own mutex for better  
     192     * granularity, so we don't need to lock the server.  
     193     */ 
     194    timeout.sec = timeout.msec = 0; 
     195    c = pj_timer_heap_poll( srv->core.timer_heap, &timeout ); 
     196 
     197    /* timer_heap_poll should never ever returns negative value, or otherwise 
     198     * ioqueue_poll() will block forever! 
     199     */ 
     200    pj_assert(timeout.sec >= 0 && timeout.msec >= 0); 
     201    if (timeout.msec >= 1000) timeout.msec = 999; 
     202 
     203    /* If caller specifies maximum time to wait, then compare the value with 
     204     * the timeout to wait from timer, and use the minimum value. 
     205     */ 
     206    if (max_timeout && PJ_TIME_VAL_GT(timeout, *max_timeout)) { 
     207        timeout = *max_timeout; 
     208    } 
     209 
     210    /* Poll ioqueue.  
     211     * Repeat polling the ioqueue while we have immediate events, because 
     212     * timer heap may process more than one events, so if we only process 
     213     * one network events at a time (such as when IOCP backend is used), 
     214     * the ioqueue may have trouble keeping up with the request rate. 
     215     * 
     216     * For example, for each send() request, one network event will be 
     217     *   reported by ioqueue for the send() completion. If we don't poll 
     218     *   the ioqueue often enough, the send() completion will not be 
     219     *   reported in timely manner. 
     220     */ 
     221    do { 
     222        c = pj_ioqueue_poll( srv->core.ioqueue, &timeout); 
     223        if (c < 0) { 
     224            pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout)); 
     225            return; 
     226        } else if (c == 0) { 
     227            break; 
     228        } else { 
     229            net_event_count += c; 
     230            timeout.sec = timeout.msec = 0; 
     231        } 
     232    } while (c > 0 && net_event_count < MAX_NET_EVENTS); 
     233 
     234} 
     235 
     236/* 
     237 * Server worker thread proc. 
     238 */ 
     239static int server_thread_proc(void *arg) 
     240{ 
     241    pj_turn_srv *srv = (pj_turn_srv*)arg; 
     242 
     243    while (!srv->core.quit) { 
     244        pj_time_val timeout_max = {0, 500}; 
     245        srv_handle_events(srv, &timeout_max); 
     246    } 
     247 
     248    return 0; 
     249} 
     250 
     251/* 
     252 * Destroy the server. 
     253 */ 
     254PJ_DEF(pj_status_t) pj_turn_srv_destroy(pj_turn_srv *srv) 
     255{ 
     256    pj_hash_iterator_t itbuf, *it; 
     257    unsigned i; 
     258 
     259    /* Stop all worker threads */ 
     260    srv->core.quit = PJ_TRUE; 
     261    for (i=0; i<srv->core.thread_cnt; ++i) { 
     262        if (srv->core.thread[i]) { 
     263            pj_thread_join(srv->core.thread[i]); 
     264            pj_thread_destroy(srv->core.thread[i]); 
     265            srv->core.thread[i] = NULL; 
     266        } 
     267    } 
     268 
     269    /* Destroy all listeners and STUN sessions associated with them. */ 
     270    for (i=0; i<srv->core.lis_cnt; ++i) { 
     271        if (srv->core.listener[i]) { 
     272            pj_turn_listener_destroy(srv->core.listener[i]); 
     273            srv->core.listener[i] = NULL; 
     274        } 
     275        if (srv->core.stun_sess[i]) { 
     276            pj_stun_session_destroy(srv->core.stun_sess[i]); 
     277            srv->core.stun_sess[i] = NULL; 
     278        } 
     279    } 
     280 
     281    /* Destroy all allocations */ 
     282    if (srv->tables.alloc) { 
     283        it = pj_hash_first(srv->tables.alloc, &itbuf); 
     284        while (it != NULL) { 
     285            pj_turn_allocation *alloc = (pj_turn_allocation*) 
     286                                        pj_hash_this(srv->tables.alloc, it); 
     287            pj_turn_allocation_destroy(alloc); 
     288            it = pj_hash_next(srv->tables.alloc, it); 
     289        } 
     290    } 
     291     
     292 
     293    /* Destroy hash tables (well, sort of) */ 
     294    if (srv->tables.alloc) { 
     295        srv->tables.alloc = NULL; 
     296        srv->tables.res = NULL; 
     297    } 
     298     
     299    /* Destroy timer heap */ 
     300    if (srv->core.timer_heap) { 
     301        pj_timer_heap_destroy(srv->core.timer_heap); 
     302        srv->core.timer_heap = NULL; 
     303    } 
     304 
     305    /* Destroy ioqueue */ 
     306    if (srv->core.ioqueue) { 
     307        pj_ioqueue_destroy(srv->core.ioqueue); 
     308        srv->core.ioqueue = NULL; 
     309    } 
     310 
     311    /* Destroy thread local IDs */ 
     312    if (srv->core.tls_key != -1) { 
     313        pj_thread_local_free(srv->core.tls_key); 
     314        srv->core.tls_key = -1; 
     315    } 
     316    if (srv->core.tls_data != -1) { 
     317        pj_thread_local_free(srv->core.tls_data); 
     318        srv->core.tls_data = -1; 
     319    } 
     320 
     321    /* Destroy server lock */ 
     322    if (srv->core.lock) { 
     323        pj_lock_destroy(srv->core.lock); 
     324        srv->core.lock = NULL; 
     325    } 
     326 
     327    /* Release pool */ 
     328    if (srv->core.pool) { 
     329        pj_pool_t *pool = srv->core.pool; 
     330        srv->core.pool = NULL; 
     331        pj_pool_release(pool); 
     332    } 
     333 
     334    /* Done */ 
    132335    return PJ_SUCCESS; 
    133336} 
    134337 
    135 /**  
     338 
     339/* 
    136340 * Add listener. 
    137341 */ 
    138 PJ_DEF(pj_status_t) pjturn_srv_add_listener(pjturn_srv *srv, 
    139                                             pjturn_listener *lis) 
     342PJ_DEF(pj_status_t) pj_turn_srv_add_listener(pj_turn_srv *srv, 
     343                                             pj_turn_listener *lis) 
    140344{ 
    141345    pj_stun_session_cb sess_cb; 
     
    157361    sess_cb.on_send_msg = &on_tx_stun_msg; 
    158362 
    159     status = pj_stun_session_create(&srv->core.stun_cfg, "lis%p", &sess_cb, 
    160                                     PJ_FALSE, &sess); 
     363    status = pj_stun_session_create(&srv->core.stun_cfg, lis->obj_name,  
     364                                    &sess_cb, PJ_FALSE, &sess); 
    161365    if (status != PJ_SUCCESS) { 
    162366        srv->core.listener[index] = NULL; 
     
    165369 
    166370    pj_stun_session_set_user_data(sess, lis); 
     371    pj_stun_session_set_credential(sess, &srv->core.cred); 
    167372 
    168373    srv->core.stun_sess[index] = sess; 
     
    170375    srv->core.lis_cnt++; 
    171376 
     377    PJ_LOG(4,(srv->obj_name, "Listener %s/%s added at index %d", 
     378              lis->obj_name, lis->info, lis->id)); 
     379 
    172380    return PJ_SUCCESS; 
    173381} 
    174382 
    175 /** 
    176  * Register an allocation. 
    177  */ 
    178 PJ_DEF(pj_status_t) pjturn_srv_register_allocation(pjturn_srv *srv, 
    179                                                    pjturn_allocation *alloc) 
     383 
     384/* 
     385 * Send packet with this listener. 
     386 */ 
     387PJ_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); 
     396} 
     397 
     398 
     399/* 
     400 * Destroy listener. 
     401 */ 
     402PJ_DEF(pj_status_t) pj_turn_listener_destroy(pj_turn_listener *listener) 
     403{ 
     404    pj_turn_srv *srv = listener->server; 
     405    unsigned i; 
     406 
     407    /* Remove from our listener list */ 
     408    pj_lock_acquire(srv->core.lock); 
     409    for (i=0; i<srv->core.lis_cnt; ++i) { 
     410        if (srv->core.listener[i] == listener) { 
     411            srv->core.listener[i] = NULL; 
     412            srv->core.lis_cnt--; 
     413            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            } 
     418            break; 
     419        } 
     420    } 
     421    pj_lock_release(srv->core.lock); 
     422 
     423    /* Destroy */ 
     424    return listener->destroy(listener); 
     425} 
     426 
     427 
     428/* 
     429 * Register an allocation to the hash tables. 
     430 */ 
     431PJ_DEF(pj_status_t) pj_turn_srv_register_allocation(pj_turn_srv *srv, 
     432                                                    pj_turn_allocation *alloc) 
    180433{ 
    181434    /* Add to hash tables */ 
     
    191444} 
    192445 
    193 /** 
    194  * Unregister an allocation. 
    195  */ 
    196 PJ_DEF(pj_status_t) pjturn_srv_unregister_allocation(pjturn_srv *srv, 
    197                                                      pjturn_allocation *alloc) 
     446 
     447/* 
     448 * Unregister an allocation from the hash tables. 
     449 */ 
     450PJ_DEF(pj_status_t) pj_turn_srv_unregister_allocation(pj_turn_srv *srv, 
     451                                                     pj_turn_allocation *alloc) 
    198452{ 
    199453    /* Unregister from hash tables */ 
     
    209463 
    210464 
    211 /* Callback from our own STUN session to send packet */ 
     465/* Callback from our own STUN session whenever it needs to send  
     466 * outgoing STUN packet. 
     467 */ 
    212468static pj_status_t on_tx_stun_msg( pj_stun_session *sess, 
    213469                                   const void *pkt, 
     
    216472                                   unsigned addr_len) 
    217473{ 
    218     pjturn_listener *listener; 
     474    pj_turn_listener *listener; 
    219475     
    220     listener = (pjturn_listener*) pj_stun_session_get_user_data(sess); 
     476    listener = (pj_turn_listener*) pj_stun_session_get_user_data(sess); 
    221477 
    222478    PJ_ASSERT_RETURN(listener!=NULL, PJ_EINVALIDOP); 
    223479 
    224     return pjturn_listener_sendto(listener, pkt, pkt_size, 0,  
    225                                   dst_addr, addr_len); 
    226 } 
    227  
    228 /* Create and send error response */ 
    229 static pj_status_t respond_error(pj_stun_session *sess, const pj_stun_msg *req, 
    230                                  pj_bool_t cache, int code, const char *errmsg, 
    231                                  const pj_sockaddr_t *dst_addr,  
    232                                  unsigned addr_len) 
     480    return pj_turn_listener_sendto(listener, pkt, pkt_size, 0,  
     481                                   dst_addr, addr_len); 
     482} 
     483 
     484 
     485/* Respond to STUN request */ 
     486static pj_status_t stun_respond(pj_turn_srv *srv, 
     487                                pj_stun_session *sess,  
     488                                const pj_stun_msg *req, 
     489                                unsigned code,  
     490                                const char *errmsg, 
     491                                pj_bool_t cache,  
     492                                const pj_sockaddr_t *dst_addr,  
     493                                unsigned addr_len) 
    233494{ 
    234495    pj_status_t status; 
     
    236497    pj_stun_tx_data *tdata; 
    237498 
    238     status = pj_stun_session_create_res(sess, req,  
    239                                         code, (errmsg?pj_cstr(&reason,errmsg):NULL),  
     499    /* Create response */ 
     500    status = pj_stun_session_create_res(sess, req, code,  
     501                                        (errmsg?pj_cstr(&reason,errmsg):NULL), 
    240502                                        &tdata); 
    241503    if (status != PJ_SUCCESS) 
    242504        return status; 
    243505 
    244     status = pj_stun_session_send_msg(sess, cache, dst_addr,  addr_len, tdata); 
    245     return status; 
    246  
    247 } 
    248  
    249 /* Parse ALLOCATE request */ 
    250 static pj_status_t parse_allocate_req(pjturn_allocation_req *cfg, 
    251                                       pjturn_listener *listener, 
    252                                       pj_stun_session *sess, 
    253                                       const pj_stun_msg *req, 
    254                                       const pj_sockaddr_t *src_addr, 
    255                                       unsigned src_addr_len) 
    256 { 
    257     pj_stun_bandwidth_attr *attr_bw; 
    258     pj_stun_req_transport_attr *attr_req_tp; 
    259     pj_stun_req_ip_attr *attr_req_ip; 
    260     pj_stun_req_port_props_attr *attr_rpp; 
    261     pj_stun_lifetime_attr *attr_lifetime; 
    262  
    263     pj_bzero(cfg, sizeof(*cfg)); 
    264  
    265     /* Get BANDWIDTH attribute, if any. */ 
    266     attr_bw = (pj_stun_uint_attr*) 
    267               pj_stun_msg_find_attr(req, PJ_STUN_ATTR_BANDWIDTH, 0); 
    268     if (attr_bw) { 
    269         cfg->bandwidth = attr_bw->value; 
    270     } else { 
    271         cfg->bandwidth = DEFA_CLIENT_BANDWIDTH; 
    272     } 
    273  
    274     /* Check if we can satisfy the bandwidth */ 
    275     if (cfg->bandwidth > MAX_CLIENT_BANDWIDTH) { 
    276         respond_error(sess, req, PJ_FALSE,  
    277                       PJ_STUN_SC_ALLOCATION_QUOTA_REACHED,  
    278                       "Invalid bandwidth", src_addr, src_addr_len); 
    279         return -1; 
    280     } 
    281  
    282     /* Get REQUESTED-TRANSPORT attribute, is any */ 
    283     attr_req_tp = (pj_stun_uint_attr*) 
    284                   pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_TRANSPORT, 0); 
    285     if (attr_req_tp) { 
    286         cfg->tp_type = PJ_STUN_GET_RT_PROTO(attr_req_tp->value); 
    287     } else { 
    288         cfg->tp_type = listener->tp_type; 
    289     } 
    290  
    291     /* Can only support UDP for now */ 
    292     if (cfg->tp_type != PJTURN_TP_UDP) { 
    293         respond_error(sess, req, PJ_FALSE,  
    294                       PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO,  
    295                       NULL, src_addr, src_addr_len); 
    296         return -1; 
    297     } 
    298  
    299     /* Get REQUESTED-IP attribute, if any */ 
    300     attr_req_ip = (pj_stun_sockaddr_attr*) 
    301                   pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_IP, 0); 
    302     if (attr_req_ip) { 
    303         pj_sockaddr_print(&attr_req_ip->sockaddr, cfg->addr,  
    304                           sizeof(cfg->addr), 0); 
    305     } 
    306  
    307     /* Get REQUESTED-PORT-PROPS attribute, if any */ 
    308     attr_rpp = (pj_stun_uint_attr*) 
    309                pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_PORT_PROPS, 0); 
    310     if (attr_rpp) { 
    311         cfg->rpp_bits = PJ_STUN_GET_RPP_BITS(attr_rpp->value); 
    312         cfg->rpp_port = PJ_STUN_GET_RPP_PORT(attr_rpp->value); 
    313     } else { 
    314         cfg->rpp_bits = 0; 
    315         cfg->rpp_port = 0; 
    316     } 
    317  
    318     /* Get LIFETIME attribute */ 
    319     attr_lifetime = (pj_stun_uint_attr*) 
    320                     pj_stun_msg_find_attr(req, PJ_STUN_ATTR_LIFETIME, 0); 
    321     if (attr_lifetime) { 
    322         cfg->lifetime = attr_lifetime->value; 
    323         if (cfg->lifetime < MIN_LIFETIME || cfg->lifetime > MAX_LIFETIME) { 
    324             respond_error(sess, req, PJ_FALSE,  
    325                           PJ_STUN_SC_BAD_REQUEST,  
    326                           "Invalid LIFETIME value", src_addr,  
    327                           src_addr_len); 
    328             return -1; 
    329         } 
    330     } else { 
    331         cfg->lifetime = DEF_LIFETIME; 
    332     } 
     506    /* Store the credential for future lookup. */ 
     507    if (pj_stun_auth_valid_for_msg(tdata->msg)) { 
     508        pj_turn_srv_put_cred(srv, req, tdata); 
     509    } 
     510 
     511    /* Send the response */ 
     512    return pj_stun_session_send_msg(sess, cache, dst_addr,  addr_len, tdata); 
     513} 
     514 
     515 
     516/* 
     517 * Store the credential to put placed for the specified message for 
     518 * future retrieval. 
     519 */ 
     520PJ_DEF(pj_status_t) pj_turn_srv_put_cred(pj_turn_srv *srv, 
     521                                         const pj_stun_msg *req, 
     522                                         pj_stun_tx_data *response) 
     523{ 
     524    pj_stun_username_attr *user; 
     525    pj_stun_realm_attr *realm; 
     526    pj_stun_nonce_attr *nonce; 
     527    struct saved_cred *saved_cred; 
     528    pj_status_t status; 
     529 
     530    realm = (pj_stun_realm_attr*) 
     531            pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REALM, 0); 
     532    PJ_ASSERT_RETURN(realm != NULL, PJ_EBUG); 
     533 
     534    user = (pj_stun_username_attr*) 
     535           pj_stun_msg_find_attr(req, PJ_STUN_ATTR_USERNAME, 0); 
     536    PJ_ASSERT_RETURN(user != NULL, PJ_EBUG); 
     537 
     538    nonce = (pj_stun_nonce_attr*) 
     539            pj_stun_msg_find_attr(req, PJ_STUN_ATTR_NONCE, 0); 
     540    PJ_ASSERT_RETURN(nonce != NULL, PJ_EBUG); 
     541 
     542    saved_cred = PJ_POOL_ALLOC_T(response->pool, struct saved_cred); 
     543 
     544    /* Lookup the password */ 
     545    status = pj_turn_get_password(response->msg, NULL, &realm->value,  
     546                                  &user->value, response->pool,  
     547                                  &saved_cred->data_type,  
     548                                  &saved_cred->data); 
     549    if (status != PJ_SUCCESS) 
     550        return status; 
     551 
     552    /* Store credential */ 
     553    pj_strdup(response->pool, &saved_cred->username, &user->value); 
     554    pj_strdup(response->pool, &saved_cred->realm, &realm->value); 
     555    pj_strdup(response->pool, &saved_cred->nonce, &nonce->value); 
     556 
     557    pj_thread_local_set(srv->core.tls_key, response->msg); 
     558    pj_thread_local_set(srv->core.tls_data, saved_cred); 
    333559 
    334560    return PJ_SUCCESS; 
    335561} 
    336562 
    337 /* Callback from our own STUN session when incoming request arrives */ 
     563 
     564/** 
     565 * Retrieve previously stored credential for the specified message. 
     566 */ 
     567PJ_DEF(pj_status_t) pj_turn_srv_get_cred(const pj_stun_msg *msg, 
     568                                         void *user_data, 
     569                                         pj_pool_t *pool, 
     570                                         pj_str_t *realm, 
     571                                         pj_str_t *username, 
     572                                         pj_str_t *nonce, 
     573                                         int *data_type, 
     574                                         pj_str_t *data) 
     575{ 
     576    pj_turn_srv *srv; 
     577    const pj_stun_msg *saved_msg; 
     578    struct saved_cred *saved_cred; 
     579 
     580    PJ_UNUSED_ARG(pool); 
     581 
     582    srv = (pj_turn_srv*)user_data; 
     583 
     584    /* Lookup stored message and make sure it's for the same message */ 
     585    saved_msg = (const pj_stun_msg*) 
     586                pj_thread_local_get(srv->core.tls_key); 
     587    PJ_ASSERT_RETURN(saved_msg==msg, PJ_ENOTFOUND); 
     588 
     589    /* Lookup saved credential */ 
     590    saved_cred = (struct saved_cred*)  
     591                 pj_thread_local_get(srv->core.tls_data); 
     592    PJ_ASSERT_RETURN(saved_cred != NULL, PJ_ENOTFOUND); 
     593 
     594 
     595    *realm = saved_cred->realm; 
     596    *username = saved_cred->username; 
     597    *nonce = saved_cred->nonce; 
     598    *data_type = saved_cred->data_type; 
     599    *data = saved_cred->data; 
     600 
     601 
     602    /* Don't clear saved_cred as this may be called more than once */ 
     603 
     604    return PJ_SUCCESS; 
     605} 
     606 
     607 
     608/* Callback from our own STUN session when incoming request arrives. 
     609 * This function is triggered by pj_stun_session_on_rx_pkt() call in 
     610  * pj_turn_srv_on_rx_pkt() function below. 
     611 */ 
    338612static pj_status_t on_rx_stun_request(pj_stun_session *sess, 
    339613                                      const pj_uint8_t *pkt, 
     
    343617                                      unsigned src_addr_len) 
    344618{ 
    345     pjturn_listener *listener; 
    346     pjturn_srv *srv; 
    347     pjturn_allocation_req req; 
    348     pjturn_allocation *alloc; 
    349     pj_stun_tx_data *tdata; 
     619    pj_turn_listener *listener; 
     620    pj_turn_srv *srv; 
     621    pj_turn_allocation *alloc; 
    350622    pj_status_t status; 
    351623 
    352     listener = (pjturn_listener*) pj_stun_session_get_user_data(sess); 
     624    PJ_UNUSED_ARG(pkt); 
     625    PJ_UNUSED_ARG(pkt_len); 
     626 
     627    listener = (pj_turn_listener*) pj_stun_session_get_user_data(sess); 
    353628    srv = listener->server; 
    354629 
    355     /* Handle strayed REFRESH request */ 
    356     if (msg->hdr.type == PJ_STUN_REFRESH_REQUEST) { 
    357         return respond_error(sess, msg, PJ_FALSE,  
    358                              PJ_STUN_SC_ALLOCATION_MISMATCH, 
    359                              NULL, src_addr, src_addr_len); 
    360     } 
    361  
    362     /* Respond any other requests with Bad Request response */ 
     630    /* Respond any requests other than ALLOCATE with 437 response */ 
    363631    if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) { 
    364         return respond_error(sess, msg, PJ_FALSE, PJ_STUN_SC_BAD_REQUEST, 
    365                              NULL, src_addr, src_addr_len); 
    366     } 
    367  
    368     /* We have ALLOCATE request here, and it's authenticated. Parse the 
    369      * request. 
    370      */ 
    371     status = parse_allocate_req(&req, listener, sess, msg, src_addr,  
    372                                 src_addr_len); 
    373     if (status != PJ_SUCCESS) 
    374         return status; 
     632        stun_respond(srv, sess, msg, PJ_STUN_SC_ALLOCATION_MISMATCH, 
     633                     NULL, PJ_FALSE, src_addr, src_addr_len); 
     634        return PJ_SUCCESS; 
     635    } 
    375636 
    376637    /* Create new allocation. The relay resource will be allocated 
    377638     * in this function. 
    378639     */ 
    379     status = pjturn_allocation_create(listener, src_addr, src_addr_len, 
    380                                       msg, &req, &alloc); 
     640    status = pj_turn_allocation_create(listener, src_addr, src_addr_len, 
     641                                       msg, sess, &alloc); 
    381642    if (status != PJ_SUCCESS) { 
    382         char errmsg[PJ_ERR_MSG_SIZE]; 
    383  
    384         pj_strerror(status, errmsg, sizeof(errmsg)); 
    385         return respond_error(sess, msg, PJ_FALSE, PJ_STUN_SC_SERVER_ERROR, 
    386                              errmsg, src_addr, src_addr_len); 
    387     } 
    388  
    389     /* Respond the original ALLOCATE request */ 
    390     status = pj_stun_session_create_res(srv->core.stun_sess[listener->id], 
    391                                         msg, 0, NULL, &tdata); 
    392     if (status != PJ_SUCCESS) { 
    393         char errmsg[PJ_ERR_MSG_SIZE]; 
    394  
    395         pjturn_allocation_destroy(alloc); 
    396  
    397         pj_strerror(status, errmsg, sizeof(errmsg)); 
    398         return respond_error(sess, msg, PJ_FALSE, PJ_STUN_SC_SERVER_ERROR, 
    399                              errmsg, src_addr, src_addr_len); 
    400     } 
    401  
    402     /* Add RELAYED-ADDRESS attribute */ 
    403     pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
    404                                   PJ_STUN_ATTR_RELAY_ADDR, PJ_TRUE, 
    405                                   &alloc->relay.hkey.addr, 
    406                                   pj_sockaddr_get_len(&alloc->relay.hkey.addr)); 
    407  
    408     /* Add LIFETIME. */ 
    409     pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 
    410                               PJ_STUN_ATTR_LIFETIME,  
    411                               (unsigned)alloc->relay.lifetime); 
    412  
    413     /* Add BANDWIDTH */ 
    414     pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 
    415                               PJ_STUN_ATTR_BANDWIDTH, 
    416                               alloc->bandwidth); 
    417  
    418     /* Add RESERVATION-TOKEN */ 
    419     PJ_TODO(ADD_RESERVATION_TOKEN); 
    420  
    421     /* Add XOR-MAPPED-ADDRESS */ 
    422     pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
    423                                   PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE, 
    424                                   &alloc->hkey.clt_addr, 
    425                                   pj_sockaddr_get_len(&alloc->hkey.clt_addr)); 
    426      
    427     /* Send the response */ 
    428     pj_stun_session_send_msg(srv->core.stun_sess[listener->id], PJ_TRUE, 
    429                              src_addr, src_addr_len, tdata); 
     643        /* STUN response has been sent, no need to reply here */ 
     644        return PJ_SUCCESS; 
     645    } 
    430646 
    431647    /* Done. */ 
     
    434650 
    435651 
    436 /* Handle packet from new client address. */ 
    437 static void handle_new_client( pjturn_srv *srv,  
    438                                pjturn_pkt *pkt) 
    439 { 
    440     unsigned options, lis_id; 
    441     pj_status_t status; 
    442  
    443     /* Check that this is a STUN message */ 
    444     options = PJ_STUN_CHECK_PACKET; 
    445     if (pkt->listener->tp_type == PJTURN_TP_UDP) 
    446         options |= PJ_STUN_IS_DATAGRAM; 
    447  
    448     status = pj_stun_msg_check(pkt->pkt, pkt->len, options); 
    449     if (status != PJ_SUCCESS) { 
    450         char errmsg[PJ_ERR_MSG_SIZE]; 
    451         char ip[PJ_INET6_ADDRSTRLEN+10]; 
    452  
    453         pj_strerror(status, errmsg, sizeof(errmsg)); 
    454         PJ_LOG(5,(srv->core.obj_name,  
    455                   "Non STUN packet from %s is dropped: %s", 
    456                   pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 
    457                   errmsg)); 
    458         return; 
    459     } 
    460  
    461     lis_id = pkt->listener->id; 
    462  
    463     /* Hand over processing to STUN session */ 
    464     options &= ~PJ_STUN_CHECK_PACKET; 
    465     status = pj_stun_session_on_rx_pkt(srv->core.stun_sess[lis_id], pkt->pkt,  
    466                                        pkt->len, options, NULL, 
    467                                        &pkt->src.clt_addr,  
    468                                        pkt->src_addr_len); 
    469     if (status != PJ_SUCCESS) { 
    470         char errmsg[PJ_ERR_MSG_SIZE]; 
    471         char ip[PJ_INET6_ADDRSTRLEN+10]; 
    472  
    473         pj_strerror(status, errmsg, sizeof(errmsg)); 
    474         PJ_LOG(5,(srv->core.obj_name,  
    475                   "Error processing STUN packet from %s: %s", 
    476                   pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 
    477                   errmsg)); 
    478         return; 
    479     } 
    480 } 
    481  
    482  
    483 /* 
    484  * This callback is called by UDP listener on incoming packet. 
    485  */ 
    486 PJ_DEF(void) pjturn_srv_on_rx_pkt( pjturn_srv *srv,  
    487                                    pjturn_pkt *pkt) 
    488 { 
    489     pjturn_allocation *alloc; 
     652/* 
     653 * This callback is called by UDP listener on incoming packet. This is 
     654 * the first entry for incoming packet (from client) to the server. From 
     655 * here, the packet may be handed over to an allocation if an allocation 
     656 * is found for the client address, or handed over to owned STUN session 
     657 * if an allocation is not found. 
     658 */ 
     659PJ_DEF(void) pj_turn_srv_on_rx_pkt(pj_turn_srv *srv,  
     660                                   pj_turn_pkt *pkt) 
     661{ 
     662    pj_turn_allocation *alloc; 
    490663 
    491664    /* Get TURN allocation from the source address */ 
     
    498671     */ 
    499672    if (alloc) { 
    500         pjturn_allocation_on_rx_client_pkt(alloc, pkt); 
     673        pj_turn_allocation_on_rx_client_pkt(alloc, pkt); 
    501674    } else { 
    502675        /* Otherwise this is a new client */ 
    503         handle_new_client(srv, pkt); 
    504     } 
    505 } 
    506  
    507  
     676        unsigned options, lis_id; 
     677        pj_status_t status; 
     678 
     679        /* Check that this is a STUN message */ 
     680        options = PJ_STUN_CHECK_PACKET; 
     681        if (pkt->listener->tp_type == PJ_TURN_TP_UDP) 
     682            options |= PJ_STUN_IS_DATAGRAM; 
     683 
     684        status = pj_stun_msg_check(pkt->pkt, pkt->len, options); 
     685        if (status != PJ_SUCCESS) { 
     686            char errmsg[PJ_ERR_MSG_SIZE]; 
     687            char ip[PJ_INET6_ADDRSTRLEN+10]; 
     688 
     689            pj_strerror(status, errmsg, sizeof(errmsg)); 
     690            PJ_LOG(5,(srv->obj_name,  
     691                      "Non STUN packet from %s is dropped: %s", 
     692                      pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 
     693                      errmsg)); 
     694            return; 
     695        } 
     696 
     697        lis_id = pkt->listener->id; 
     698 
     699        /* Hand over processing to STUN session. This will trigger 
     700         * on_rx_stun_request() callback to be called if the STUN 
     701         * message is a request. 
     702         */ 
     703        options &= ~PJ_STUN_CHECK_PACKET; 
     704        status = pj_stun_session_on_rx_pkt(srv->core.stun_sess[lis_id],  
     705                                           pkt->pkt, pkt->len, options, NULL, 
     706                                           &pkt->src.clt_addr,  
     707                                           pkt->src_addr_len); 
     708        if (status != PJ_SUCCESS) { 
     709            char errmsg[PJ_ERR_MSG_SIZE]; 
     710            char ip[PJ_INET6_ADDRSTRLEN+10]; 
     711 
     712            pj_strerror(status, errmsg, sizeof(errmsg)); 
     713            PJ_LOG(5,(srv->obj_name,  
     714                      "Error processing STUN packet from %s: %s", 
     715                      pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 
     716                      errmsg)); 
     717            return; 
     718        } 
     719    } 
     720} 
     721 
     722 
  • pjproject/trunk/pjnath/src/pjturn-srv/turn.h

    r1850 r1852  
    1717 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  
    1818 */ 
    19 #ifndef __PJTURN_SRV_TURN_H__ 
    20 #define __PJTURN_SRV_TURN_H__ 
     19#ifndef __PJ_TURN_SRV_TURN_H__ 
     20#define __PJ_TURN_SRV_TURN_H__ 
    2121 
    2222#include <pjlib.h> 
    2323#include <pjnath.h> 
    2424 
    25 typedef struct pjturn_relay_res     pjturn_relay_res; 
    26 typedef struct pjturn_listener      pjturn_listener; 
    27 typedef struct pjturn_permission    pjturn_permission; 
    28 typedef struct pjturn_allocation    pjturn_allocation; 
    29 typedef struct pjturn_srv           pjturn_srv; 
    30 typedef struct pjturn_pkt           pjturn_pkt; 
    31  
    32  
    33 #define PJTURN_INVALID_CHANNEL      0xFFFF 
    34 #define PJTURN_NO_TIMEOUT           ((long)0x7FFFFFFF) 
    35 #define PJTURN_MAX_PKT_LEN          3000 
    36 #define PJTURN_PERM_TIMEOUT         300 
    37 #define PJTURN_CHANNEL_TIMEOUT      600 
     25typedef struct pj_turn_relay_res            pj_turn_relay_res; 
     26typedef struct pj_turn_listener     pj_turn_listener; 
     27typedef struct pj_turn_permission    pj_turn_permission; 
     28typedef struct pj_turn_allocation    pj_turn_allocation; 
     29typedef struct pj_turn_srv          pj_turn_srv; 
     30typedef struct pj_turn_pkt          pj_turn_pkt; 
     31 
     32 
     33#define PJ_TURN_INVALID_CHANNEL     0xFFFF 
     34#define PJ_TURN_INVALID_LIS_ID      ((unsigned)-1) 
     35#define PJ_TURN_NO_TIMEOUT          ((long)0x7FFFFFFF) 
     36#define PJ_TURN_MAX_PKT_LEN         3000 
     37#define PJ_TURN_PERM_TIMEOUT        300 
     38#define PJ_TURN_CHANNEL_TIMEOUT     600 
    3839 
    3940/** Transport types */ 
    4041enum { 
    41     PJTURN_TP_UDP = 16,     /**< UDP.   */ 
    42     PJTURN_TP_TCP = 6       /**< TCP.   */ 
     42    PJ_TURN_TP_UDP = 16,            /**< UDP.   */ 
     43    PJ_TURN_TP_TCP = 6      /**< TCP.   */ 
    4344}; 
    4445 
     
    4647 * Get transport type name string. 
    4748 */ 
    48 PJ_DECL(const char*) pjturn_tp_type_name(int tp_type); 
     49PJ_DECL(const char*) pj_turn_tp_type_name(int tp_type); 
    4950 
    5051/** 
     
    5253 * one relay resource, and optionally it may reserve another resource. 
    5354 */ 
    54 struct pjturn_relay_res 
     55struct pj_turn_relay_res 
    5556{ 
    5657    /** Hash table key */ 
     
    6465 
    6566    /** Allocation who requested or reserved this resource. */ 
    66     pjturn_allocation *allocation; 
     67    pj_turn_allocation *allocation; 
    6768 
    6869    /** Username used in credential */ 
     
    9394 
    9495        /** The incoming packet buffer */ 
    95         char                rx_pkt[PJTURN_MAX_PKT_LEN]; 
     96        char                rx_pkt[PJ_TURN_MAX_PKT_LEN]; 
    9697 
    9798        /** Source address of the packet. */ 
     
    102103 
    103104        /** The outgoing packet buffer. This must be 3wbit aligned. */ 
    104         char                tx_pkt[PJTURN_MAX_PKT_LEN+4]; 
     105        char                tx_pkt[PJ_TURN_MAX_PKT_LEN+4]; 
    105106    } tp; 
    106107}; 
     
    116117 * allocation hash table. 
    117118 */ 
    118 typedef struct pjturn_allocation_key 
     119typedef struct pj_turn_allocation_key 
    119120{ 
    120121    int             tp_type;    /**< Transport type.        */ 
    121122    pj_sockaddr     clt_addr;   /**< Client's address.      */ 
    122 } pjturn_allocation_key; 
    123  
    124  
    125 /** 
    126  * Allocation request. 
    127  */ 
    128 typedef struct pjturn_allocation_req 
    129 { 
    130     /** Requested transport */ 
    131     unsigned            tp_type; 
    132  
    133     /** Requested IP */ 
    134     char                addr[PJ_INET6_ADDRSTRLEN]; 
     123} pj_turn_allocation_key; 
     124 
     125 
     126/** 
     127 * This structure describes TURN pj_turn_allocation session. 
     128 */ 
     129struct pj_turn_allocation 
     130{ 
     131    /** Hash table key to identify client. */ 
     132    pj_turn_allocation_key hkey; 
     133 
     134    /** Pool for this allocation. */ 
     135    pj_pool_t           *pool; 
     136 
     137    /** Object name for logging identification */ 
     138    char                *obj_name; 
     139 
     140    /** Client info (IP address and port) */ 
     141    char                info[80]; 
     142 
     143    /** Mutex */ 
     144    pj_lock_t           *lock; 
     145 
     146    /** TURN listener. */ 
     147    pj_turn_listener    *listener; 
     148 
     149    /** Client socket, if connection to client is using TCP. */ 
     150    pj_sock_t           clt_sock; 
     151 
     152    /** The relay resource for this allocation. */ 
     153    pj_turn_relay_res   relay; 
     154 
     155    /** Relay resource reserved by this allocation, if any */ 
     156    pj_turn_relay_res   *resv; 
    135157 
    136158    /** Requested bandwidth */ 
    137159    unsigned            bandwidth; 
    138160 
    139     /** Lifetime. */ 
    140     unsigned            lifetime; 
    141  
    142     /** A bits */ 
    143     unsigned            rpp_bits; 
    144  
    145     /** Requested port */ 
    146     unsigned            rpp_port; 
    147  
    148 } pjturn_allocation_req; 
    149  
    150  
    151 /** 
    152  * This structure describes TURN pjturn_allocation session. 
    153  */ 
    154 struct pjturn_allocation 
    155 { 
    156     /** Hash table key to identify client. */ 
    157     pjturn_allocation_key hkey; 
    158  
    159     /** Pool for this allocation. */ 
    160     pj_pool_t           *pool; 
    161  
    162     /** Object name for logging identification */ 
    163     char                *obj_name; 
    164  
    165     /** Client info (IP address and port) */ 
    166     char                info[80]; 
    167  
    168     /** Mutex */ 
    169     pj_lock_t           *lock; 
    170  
    171     /** TURN listener. */ 
    172     pjturn_listener     *listener; 
    173  
    174     /** Client socket, if connection to client is using TCP. */ 
    175     pj_sock_t           clt_sock; 
    176  
    177     /** The relay resource for this allocation. */ 
    178     pjturn_relay_res    relay; 
    179  
    180     /** Relay resource reserved by this allocation, if any */ 
    181     pjturn_relay_res    *resv; 
    182  
    183     /** Requested bandwidth */ 
    184     unsigned            bandwidth; 
    185  
    186161    /** STUN session for this client */ 
    187162    pj_stun_session     *sess; 
    188163 
     164    /** Credential for this STUN session. */ 
     165    pj_stun_auth_cred    cred; 
     166 
    189167    /** Peer hash table (keyed by peer address) */ 
    190168    pj_hash_table_t     *peer_table; 
     
    199177 * permission. 
    200178 */ 
    201 typedef struct pjturn_permission_key 
     179typedef struct pj_turn_permission_key 
    202180{ 
    203181    /** Peer address. */ 
    204182    pj_sockaddr         peer_addr; 
    205183 
    206 } pjturn_permission_key; 
    207  
    208  
    209 /** 
    210  * This structure describes TURN pjturn_permission or channel. 
    211  */ 
    212 struct pjturn_permission 
     184} pj_turn_permission_key; 
     185 
     186 
     187/** 
     188 * This structure describes TURN pj_turn_permission or channel. 
     189 */ 
     190struct pj_turn_permission 
    213191{ 
    214192    /** Hash table key */ 
    215     pjturn_permission_key hkey; 
     193    pj_turn_permission_key hkey; 
    216194 
    217195    /** Transport socket. If TCP is used, the value will be the actual 
     
    221199 
    222200    /** TURN allocation that owns this permission/channel */ 
    223     pjturn_allocation   *allocation; 
    224  
    225     /** Optional channel number, or PJTURN_INVALID_CHANNEL if channel number 
     201    pj_turn_allocation  *allocation; 
     202 
     203    /** Optional channel number, or PJ_TURN_INVALID_CHANNEL if channel number 
    226204     *  is not requested for this permission. 
    227205     */ 
     
    235213 * Create new allocation. 
    236214 */ 
    237 PJ_DECL(pj_status_t) pjturn_allocation_create(pjturn_listener *listener, 
     215PJ_DECL(pj_status_t) pj_turn_allocation_create(pj_turn_listener *listener, 
    238216                                              const pj_sockaddr_t *src_addr, 
    239217                                              unsigned src_addr_len, 
    240218                                              const pj_stun_msg *msg, 
    241                                               const pjturn_allocation_req *req, 
    242                                               pjturn_allocation **p_alloc); 
     219                                              pj_stun_session *srv_sess, 
     220                                              pj_turn_allocation **p_alloc); 
    243221/** 
    244222 * Destroy allocation. 
    245223 */ 
    246 PJ_DECL(void) pjturn_allocation_destroy(pjturn_allocation *alloc); 
    247  
    248 /** 
    249  * Create relay. 
    250  */ 
    251 PJ_DECL(pj_status_t) pjturn_allocation_create_relay(pjturn_srv *srv, 
    252                                                     pjturn_allocation *alloc, 
    253                                                     const pj_stun_msg *msg, 
    254                                                     const pjturn_allocation_req *req, 
    255                                                     pjturn_relay_res *relay); 
     224PJ_DECL(void) pj_turn_allocation_destroy(pj_turn_allocation *alloc); 
     225 
    256226 
    257227/** 
    258228 * Handle incoming packet from client. 
    259229 */ 
    260 PJ_DECL(void) pjturn_allocation_on_rx_client_pkt(pjturn_allocation *alloc, 
    261                                                  pjturn_pkt *pkt); 
     230PJ_DECL(void) pj_turn_allocation_on_rx_client_pkt(pj_turn_allocation *alloc, 
     231                                                 pj_turn_pkt *pkt); 
    262232 
    263233/****************************************************************************/ 
     
    270240 * listens for incoming connections from clients. 
    271241 */ 
    272 struct pjturn_listener 
    273 { 
     242struct pj_turn_listener 
     243{ 
     244    /** Object name/identification */ 
     245    char                *obj_name; 
     246 
     247    /** Slightly longer info about this listener */ 
     248    char                info[80]; 
     249 
    274250    /** TURN server instance. */ 
    275     pjturn_srv          *server; 
     251    pj_turn_srv         *server; 
    276252 
    277253    /** Listener index in the server */ 
     
    294270 
    295271    /** Sendto handler */ 
    296     pj_status_t         (*sendto)(pjturn_listener *listener, 
     272    pj_status_t         (*sendto)(pj_turn_listener *listener, 
    297273                                  const void *packet, 
    298274                                  pj_size_t size, 
     
    302278 
    303279    /** Destroy handler */ 
    304     pj_status_t         (*destroy)(pjturn_listener*); 
     280    pj_status_t         (*destroy)(pj_turn_listener*); 
    305281}; 
    306282 
     
    309285 * An incoming packet. 
    310286 */ 
    311 struct pjturn_pkt 
     287struct pj_turn_pkt 
    312288{ 
    313289    /** Pool for this packet */ 
     
    315291 
    316292    /** Listener that owns this. */ 
    317     pjturn_listener         *listener; 
     293    pj_turn_listener        *listener; 
    318294 
    319295    /** Packet buffer (must be 32bit aligned). */ 
    320     pj_uint8_t              pkt[PJTURN_MAX_PKT_LEN]; 
     296    pj_uint8_t              pkt[PJ_TURN_MAX_PKT_LEN]; 
    321297 
    322298    /** Size of the packet */ 
     
    327303 
    328304    /** Source transport type and source address. */ 
    329     pjturn_allocation_key   src; 
     305    pj_turn_allocation_key   src; 
    330306 
    331307    /** Source address length. */ 
     
    337313 * Create a new listener on the specified port. 
    338314 */ 
    339 PJ_DECL(pj_status_t) pjturn_listener_create_udp(pjturn_srv *srv, 
     315PJ_DECL(pj_status_t) pj_turn_listener_create_udp(pj_turn_srv *srv, 
    340316                                                int af, 
    341317                                                const pj_str_t *bound_addr, 
     
    343319                                                unsigned concurrency_cnt, 
    344320                                                unsigned flags, 
    345                                                 pjturn_listener **p_listener); 
     321                                                pj_turn_listener **p_listener); 
    346322 
    347323/** 
    348324 * Send packet with this listener. 
    349325 */ 
    350 PJ_DECL(pj_status_t) pjturn_listener_sendto(pjturn_listener *listener, 
     326PJ_DECL(pj_status_t) pj_turn_listener_sendto(pj_turn_listener *listener, 
    351327                                            const void *packet, 
    352328                                            pj_size_t size, 
     
    358334 * Destroy listener. 
    359335 */ 
    360 PJ_DECL(pj_status_t) pjturn_listener_destroy(pjturn_listener *listener); 
     336PJ_DECL(pj_status_t) pj_turn_listener_destroy(pj_turn_listener *listener); 
    361337 
    362338 
     
    366342 */ 
    367343/** 
    368  * This structure describes TURN pjturn_srv instance. 
    369  */ 
    370 struct pjturn_srv 
    371 { 
     344 * This structure describes TURN pj_turn_srv instance. 
     345 */ 
     346struct pj_turn_srv 
     347{ 
     348    /** Object name */ 
     349    char        *obj_name; 
     350 
    372351    /** Core settings */ 
    373352    struct { 
    374         /** Object name */ 
    375         char            *obj_name; 
    376  
    377353        /** Pool factory */ 
    378354        pj_pool_factory *pf; 
     
    394370 
    395371        /** Array of listeners. */ 
    396         pjturn_listener **listener; 
     372        pj_turn_listener **listener; 
    397373 
    398374        /** Array of STUN sessions, one for each listeners. */ 
     
    405381        pj_thread_t     **thread; 
    406382 
     383        /** Thread quit signal */ 
     384        pj_bool_t       quit; 
     385 
    407386        /** STUN config. */ 
    408387        pj_stun_config   stun_cfg; 
    409388 
     389        /** STUN auth credential. */ 
     390        pj_stun_auth_cred cred; 
     391 
     392        /** Thread local ID for storing credential */ 
     393        long             tls_key, tls_data; 
    410394 
    411395    } core; 
     
    454438 * Create server. 
    455439 */ 
    456 PJ_DECL(pj_status_t) pjturn_srv_create(pj_pool_factory *pf, 
    457                                        pjturn_srv **p_srv); 
     440PJ_DECL(pj_status_t) pj_turn_srv_create(pj_pool_factory *pf, 
     441                                        pj_turn_srv **p_srv); 
    458442 
    459443/**  
    460444 * Destroy server. 
    461445 */ 
    462 PJ_DECL(pj_status_t) pjturn_srv_destroy(pjturn_srv *srv); 
     446PJ_DECL(pj_status_t) pj_turn_srv_destroy(pj_turn_srv *srv); 
    463447 
    464448/**  
    465449 * Add listener. 
    466450 */ 
    467 PJ_DECL(pj_status_t) pjturn_srv_add_listener(pjturn_srv *srv, 
    468                                              pjturn_listener *lis); 
     451PJ_DECL(pj_status_t) pj_turn_srv_add_listener(pj_turn_srv *srv, 
     452                                              pj_turn_listener *lis); 
    469453 
    470454/** 
    471455 * Register an allocation. 
    472456 */ 
    473 PJ_DECL(pj_status_t) pjturn_srv_register_allocation(pjturn_srv *srv, 
    474                                                     pjturn_allocation *alloc); 
     457PJ_DECL(pj_status_t) pj_turn_srv_register_allocation(pj_turn_srv *srv, 
     458                                                     pj_turn_allocation *alloc); 
    475459 
    476460/** 
    477461 * Unregister an allocation. 
    478462 */ 
    479 PJ_DECL(pj_status_t) pjturn_srv_unregister_allocation(pjturn_srv *srv, 
    480                                                       pjturn_allocation *alloc); 
     463PJ_DECL(pj_status_t) pj_turn_srv_unregister_allocation(pj_turn_srv *srv, 
     464                                                       pj_turn_allocation *alloc); 
    481465 
    482466/** 
    483467 * This callback is called by UDP listener on incoming packet. 
    484468 */ 
    485 PJ_DECL(void) pjturn_srv_on_rx_pkt(pjturn_srv *srv,  
    486                                    pjturn_pkt *pkt); 
    487  
    488  
    489 #endif  /* __PJTURN_SRV_TURN_H__ */ 
    490  
     469PJ_DECL(void) pj_turn_srv_on_rx_pkt(pj_turn_srv *srv,  
     470                                   pj_turn_pkt *pkt); 
     471 
     472 
     473/** 
     474 * Store the credential to put placed for the specified message for 
     475 * future retrieval. 
     476 */ 
     477PJ_DECL(pj_status_t) pj_turn_srv_put_cred(pj_turn_srv *srv, 
     478                                          const pj_stun_msg *request, 
     479                                          pj_stun_tx_data *response); 
     480 
     481/** 
     482 * Retrieve previously stored credential for the specified message. 
     483 */ 
     484PJ_DECL(pj_status_t) pj_turn_srv_get_cred(const pj_stun_msg *msg, 
     485                                          void *user_data, 
     486                                          pj_pool_t *pool, 
     487                                          pj_str_t *realm, 
     488                                          pj_str_t *username, 
     489                                          pj_str_t *nonce, 
     490                                          int *data_type, 
     491                                          pj_str_t *data); 
     492 
     493 
     494#endif  /* __PJ_TURN_SRV_TURN_H__ */ 
     495 
Note: See TracChangeset for help on using the changeset viewer.