Changeset 2589


Ignore:
Timestamp:
Apr 13, 2009 8:54:10 AM (15 years ago)
Author:
bennylp
Message:

Ticket #780: Update TURN from draft 09 to draft 13:

  • new rules for permissions:
    • permission must be created and refreshed explicitly with CreatePermission?
    • transmitting data does not refresh permission
  • attributes changed/added: XOR-PEER-ADDRESS, XOR-RELAYED-ADDRESS, EVEN-PORT, DONT-FRAGMENT
  • attribute(s) removed: REQUESTED-PROPS
  • new status codes: 401 (Forbidden), 507 (Insufficient Capacity)
  • removed status codes: 443 (Invalid IP address), 444 (Invalid Port), 508 (Insufficient Port Capacity)
Location:
pjproject/trunk/pjnath
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjnath/include/pjnath/stun_msg.h

    r2394 r2589  
    8484 
    8585    /** 
     86     * STUN/TURN CreatePermission method as defined by draft-ietf-behave-turn 
     87     */ 
     88    PJ_STUN_CREATE_PERM_METHOD              = 8, 
     89 
     90    /** 
    8691     * STUN/TURN ChannelBind as defined by draft-ietf-behave-turn 
    8792     */ 
     
    252257     */ 
    253258    PJ_STUN_DATA_INDICATION                 = 0x0017, 
     259 
     260 
     261    /** 
     262     * TURN CreatePermission request 
     263     */ 
     264    PJ_STUN_CREATE_PERM_REQUEST             = 0x0008, 
     265 
     266    /** 
     267     * TURN CreatePermission successful response. 
     268     */ 
     269    PJ_STUN_CREATE_PERM_RESPONSE            = 0x0108, 
     270 
     271    /** 
     272     * TURN CreatePermission failure response 
     273     */ 
     274    PJ_STUN_CREATE_PERM_ERROR_RESPONSE      = 0x0118, 
    254275 
    255276 
     
    293314    PJ_STUN_ATTR_MAGIC_COOKIE       = 0x000F,/**< MAGIC-COOKIE attr (deprec)*/ 
    294315    PJ_STUN_ATTR_BANDWIDTH          = 0x0010,/**< TURN BANDWIDTH (deprec)   */ 
    295     PJ_STUN_ATTR_PEER_ADDR          = 0x0012,/**< TURN PEER-ADDRESS attr.   */ 
     316    PJ_STUN_ATTR_XOR_PEER_ADDR      = 0x0012,/**< TURN XOR-PEER-ADDRESS     */ 
    296317    PJ_STUN_ATTR_DATA               = 0x0013,/**< DATA attribute.           */ 
    297318    PJ_STUN_ATTR_REALM              = 0x0014,/**< REALM attribute.          */ 
    298319    PJ_STUN_ATTR_NONCE              = 0x0015,/**< NONCE attribute.          */ 
    299     PJ_STUN_ATTR_RELAYED_ADDR       = 0x0016,/**< RELAYED-ADDRESS attribute.*/ 
     320    PJ_STUN_ATTR_XOR_RELAYED_ADDR   = 0x0016,/**< TURN XOR-RELAYED-ADDRESS  */ 
    300321    PJ_STUN_ATTR_REQ_ADDR_TYPE      = 0x0017,/**< REQUESTED-ADDRESS-TYPE    */ 
    301     PJ_STUN_ATTR_REQ_PROPS          = 0x0018,/**< REQUESTED-PROPS           */ 
    302     PJ_STUN_ATTR_REQ_TRANSPORT      = 0x0019,/**< REQUESTED-TRANSPORT       */ 
     322    PJ_STUN_ATTR_EVEN_PORT          = 0x0018,/**< TURN EVEN-PORT            */ 
     323    PJ_STUN_ATTR_REQ_TRANSPORT      = 0x0019,/**< TURN REQUESTED-TRANSPORT  */ 
     324    PJ_STUN_ATTR_DONT_FRAGMENT      = 0x001A,/**< TURN DONT-FRAGMENT        */ 
    303325    PJ_STUN_ATTR_XOR_MAPPED_ADDR    = 0x0020,/**< XOR-MAPPED-ADDRESS        */ 
    304326    PJ_STUN_ATTR_TIMER_VAL          = 0x0021,/**< TIMER-VAL attribute.      */ 
     
    333355    PJ_STUN_SC_BAD_REQUEST              = 400,  /**< Bad Request            */ 
    334356    PJ_STUN_SC_UNAUTHORIZED             = 401,  /**< Unauthorized           */ 
     357    PJ_STUN_SC_FORBIDDEN                = 403,  /**< Forbidden (TURN)       */ 
    335358    PJ_STUN_SC_UNKNOWN_ATTRIBUTE        = 420,  /**< Unknown Attribute      */ 
    336359#if 0 
     
    350373    PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO   = 442,  /**< Unsupported Transport or 
    351374                                                     Protocol (TURN) */ 
    352     PJ_STUN_SC_INVALID_IP_ADDR          = 443,  /**< Invalid IP Address(TURN)*/ 
    353     PJ_STUN_SC_INVALID_PORT             = 444,  /**< Invalid Port (TURN)    */ 
    354375    PJ_STUN_SC_OPER_TCP_ONLY            = 445,  /**< Operation for TCP Only */ 
    355376    PJ_STUN_SC_CONNECTION_FAILURE       = 446,  /**< Connection Failure     */ 
     
    359380    PJ_STUN_SC_ROLE_CONFLICT            = 487,  /**< Role Conflict          */ 
    360381    PJ_STUN_SC_SERVER_ERROR             = 500,  /**< Server Error           */ 
    361     PJ_STUN_SC_INSUFFICIENT_CAPACITY    = 507,  /**< Insufficient Capacity  
    362                                                      (TURN) */ 
    363     PJ_STUN_SC_INSUFFICIENT_PORT_CAPACITY=508,  /**< Insufficient Port Capacity  
     382    PJ_STUN_SC_INSUFFICIENT_CAPACITY    = 508,  /**< Insufficient Capacity  
    364383                                                     (TURN) */ 
    365384    PJ_STUN_SC_GLOBAL_FAILURE           = 600   /**< Global Failure         */ 
     
    913932 
    914933/** 
    915  * This describes the STUN PEER-ADDRESS attribute. 
    916  * The PEER-ADDRESS specifies the address and port of the peer as seen 
     934 * This describes the STUN XOR-PEER-ADDRESS attribute. 
     935 * The XOR-PEER-ADDRESS specifies the address and port of the peer as seen 
    917936 * from the TURN server.  It is encoded in the same way as XOR-MAPPED- 
    918937 * ADDRESS.  
    919938 */ 
    920 typedef struct pj_stun_sockaddr_attr pj_stun_peer_addr_attr; 
     939typedef struct pj_stun_sockaddr_attr pj_stun_xor_peer_addr_attr; 
    921940 
    922941 
     
    932951 
    933952/** 
    934  * This describes the STUN RELAYED-ADDRESS attribute. 
    935  * The RELAYED-ADDRESS is present in Allocate responses.  It specifies the 
     953 * This describes the STUN XOR-RELAYED-ADDRESS attribute. The  
     954 * XOR-RELAYED-ADDRESS is present in Allocate responses.  It specifies the 
    936955 * address and port that the server allocated to the client.  It is 
    937956 * encoded in the same way as XOR-MAPPED-ADDRESS. 
    938957 */ 
    939 typedef struct pj_stun_sockaddr_attr pj_stun_relayed_addr_attr; 
     958typedef struct pj_stun_sockaddr_attr pj_stun_xor_relayed_addr_attr; 
    940959 
    941960 
     
    956975 \endverbatim 
    957976 */ 
    958 typedef struct pj_stun_uint_attr pj_stun_req_addr_type; 
    959  
    960 /** 
    961  * This describes the TURN REQUESTED-PROPS attribute, encoded as 
    962  * STUN 32bit integer attribute. Few macros are provided to manipulate 
    963  * the values in this attribute: #PJ_STUN_GET_PROP_TYPE(), and 
    964  * #PJ_STUN_SET_PROP_TYPE(). 
     977typedef struct pj_stun_uint_attr pj_stun_req_addr_type_attr; 
     978 
     979 
     980/** 
     981 * This describes the TURN REQUESTED-TRANSPORT attribute, encoded in 
     982 * STUN generic integer attribute. 
     983 * 
     984 * This attribute allows the client to request that the port in the 
     985 * relayed-transport-address be even, and (optionally) that the server 
     986 * reserve the next-higher port number.  The attribute is 8 bits long. 
     987 * Its format is: 
     988 
     989\verbatim 
     990      0 
     991      0 1 2 3 4 5 6 7 
     992     +-+-+-+-+-+-+-+-+ 
     993     |R|    RFFU     | 
     994     +-+-+-+-+-+-+-+-+ 
     995 
     996\endverbatim 
     997 
     998 * The attribute contains a single 1-bit flag: 
    965999 *  
    966  * This attribute allows the client to request that the allocation have 
    967  * certain properties, and by the server to indicate which properties 
    968  * are supported.  The attribute is 32 bits long.  Its format is: 
    969  
    970  \verbatim 
    971  
    972       0                   1                   2                   3 
    973       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 
    974      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
    975      |   Prop-type   |                  Reserved = 0                 | 
    976      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
    977  
    978  \endverbatim 
    979  
    980  * The field labeled "Prop-type" is an 8-bit field specifying the 
    981  * desired property.  The rest of the attribute is RFFU (Reserved For 
    982  * Future Use) and MUST be set to 0 on transmission and ignored on 
    983  * reception. 
    984  * 
    985  * The "Prop-type" field is formatted as follows: 
    986  
    987  \verbatim 
    988  
    989       0 1 2 3 4 5 6 7  
    990      +-+-+-+-+-+-+-+-+ 
    991      |E|R|P|         | 
    992      +-+-+-+-+-+-+-+-+ 
    993  
    994  \endverbatim 
    995  
    996    The bits in "Prop-type" are: 
    997  
    998    E: If 1, the port number for the relayed-transport-address must be 
    999       even.  If 0, the port number can be even or odd. 
    1000  
    1001    R: If 1, the server must reserve the next highest port for a 
    1002       subsequent allocation.  If 0, no such reservation is requested. 
    1003       If the client sets the R bit to 1, it MUST also set the E bit to 1 
    1004       (however, the E bit may be 1 when the R bit is 0). 
    1005  
    1006    P: If 1, the allocation must be a Preserving allocation.  If 0, the 
    1007       allocation can be either Preserving or Non-Preserving. 
    1008  
    1009  */ 
    1010 typedef struct pj_stun_uint_attr pj_stun_req_props_attr; 
    1011  
    1012 /** 
    1013  * Get the 8bit Prop-type value from a 32bit integral value of TURN  
    1014  * TURN REQUESTED-PROPS attribute. 
    1015  */ 
    1016 #define PJ_STUN_GET_PROP_TYPE(u32)      (u32 >> 24) 
    1017  
    1018 /** 
    1019  * Convert 8bit Prop-type value to a 32bit integral value of TURN  
    1020  * REQUESTED-PROPS attribute. 
    1021  */ 
    1022 #define PJ_STUN_SET_PROP_TYPE(PropType) (PropType << 24) 
     1000 * R: If 1, the server is requested to reserve the next higher port 
     1001 *    number (on the same IP address) for a subsequent allocation.  If 
     1002 *    0, no such reservation is requested. 
     1003 *  
     1004 * The other 7 bits of the attribute must be set to zero on transmission 
     1005 * and ignored on reception. 
     1006 */ 
     1007typedef struct pj_stun_uint_attr pj_stun_even_port_attr; 
    10231008 
    10241009 
     
    10641049#define PJ_STUN_SET_RT_PROTO(proto)   (((pj_uint32_t)(proto)) << 24) 
    10651050 
     1051 
     1052/** 
     1053 * This describes the TURN DONT-FRAGMENT attribute. 
     1054 * 
     1055 * This attribute is used by the client to request that the server set 
     1056 * the DF (Don't Fragment) bit in the IP header when relaying the 
     1057 * application data onward to the peer.  This attribute has no value 
     1058 * part and thus the attribute length field is 0. 
     1059 */ 
     1060typedef struct pj_stun_empty_attr pj_stun_use_candidate_attr; 
    10661061 
    10671062 
  • pjproject/trunk/pjnath/include/pjnath/stun_session.h

    r2394 r2589  
    328328 
    329329/** 
    330  * Set server name to be included in all response. 
    331  * 
    332  * @param sess      The STUN session instance. 
    333  * @param srv_name  Server name string. 
    334  * 
    335  * @return          The user data associated with this STUN session. 
    336  */ 
    337 PJ_DECL(pj_status_t) pj_stun_session_set_server_name(pj_stun_session *sess, 
    338                                                      const pj_str_t *srv_name); 
     330 * Set SOFTWARE name to be included in all requests and responses. 
     331 * 
     332 * @param sess      The STUN session instance. 
     333 * @param sw        Software name string. If this argument is NULL or 
     334 *                  empty, the session will not include SOFTWARE attribute 
     335 *                  in STUN requests and responses. 
     336 * 
     337 * @return          PJ_SUCCESS on success, or the appropriate error code. 
     338 */ 
     339PJ_DECL(pj_status_t) pj_stun_session_set_software_name(pj_stun_session *sess, 
     340                                                       const pj_str_t *sw); 
    339341 
    340342/** 
  • pjproject/trunk/pjnath/include/pjnath/turn_session.h

    r2394 r2589  
    435435PJ_DECL(void) pj_turn_session_set_log(pj_turn_session *sess, 
    436436                                      unsigned flags); 
     437 
     438 
     439/** 
     440 * Configure the SOFTWARE name to be sent in all STUN requests by the 
     441 * TURN session. 
     442 * 
     443 * @param sess      The TURN client session. 
     444 * @param sw        Software name string. If this argument is NULL or 
     445 *                  empty, the session will not include SOFTWARE attribute 
     446 *                  in STUN requests and responses. 
     447 * 
     448 * @return          PJ_SUCCESS on success, or the appropriate error code. 
     449 */ 
     450PJ_DECL(pj_status_t) pj_turn_session_set_software_name(pj_turn_session *sess, 
     451                                                       const pj_str_t *sw); 
    437452 
    438453 
     
    520535 
    521536/** 
     537 * Create or renew permission in the TURN server for the specified peer IP 
     538 * addresses. Application must install permission for a particular (peer) 
     539 * IP address before it sends any data to that IP address, or otherwise 
     540 * the TURN server will drop the data. 
     541 * 
     542 * @param sess          The TURN client session. 
     543 * @param addr_cnt      Number of IP addresses. 
     544 * @param addr          Array of peer IP addresses. Only the address family 
     545 *                      and IP address portion of the socket address matter. 
     546 * @param options       Specify 1 to let the TURN client session automatically 
     547 *                      renew the permission later when they are about to 
     548 *                      expire. 
     549 * 
     550 * @return              PJ_SUCCESS if the operation has been successfully 
     551 *                      issued, or the appropriate error code. Note that 
     552 *                      the operation itself will complete asynchronously. 
     553 */ 
     554PJ_DECL(pj_status_t) pj_turn_session_set_perm(pj_turn_session *sess, 
     555                                              unsigned addr_cnt, 
     556                                              const pj_sockaddr addr[], 
     557                                              unsigned options); 
     558 
     559 
     560/** 
    522561 * Send a data to the specified peer address via the TURN relay. This  
    523562 * function will encapsulate the data as STUN Send Indication or TURN 
  • pjproject/trunk/pjnath/include/pjnath/turn_sock.h

    r2394 r2589  
    249249 
    250250/** 
     251 * Create or renew permission in the TURN server for the specified peer IP 
     252 * addresses. Application must install permission for a particular (peer) 
     253 * IP address before it sends any data to that IP address, or otherwise 
     254 * the TURN server will drop the data. 
     255 * 
     256 * @param turn_sock     The TURN transport instance. 
     257 * @param addr_cnt      Number of IP addresses. 
     258 * @param addr          Array of peer IP addresses. Only the address family 
     259 *                      and IP address portion of the socket address matter. 
     260 * @param options       Specify 1 to let the TURN client session automatically 
     261 *                      renew the permission later when they are about to 
     262 *                      expire. 
     263 * 
     264 * @return              PJ_SUCCESS if the operation has been successfully 
     265 *                      issued, or the appropriate error code. Note that 
     266 *                      the operation itself will complete asynchronously. 
     267 */ 
     268PJ_DECL(pj_status_t) pj_turn_sock_set_perm(pj_turn_sock *turn_sock, 
     269                                           unsigned addr_cnt, 
     270                                           const pj_sockaddr addr[], 
     271                                           unsigned options); 
     272 
     273/** 
    251274 * Send a data to the specified peer address via the TURN relay. This  
    252275 * function will encapsulate the data as STUN Send Indication or TURN 
  • pjproject/trunk/pjnath/include/pjnath/types.h

    r2580 r2589  
    108108operation of the relay and to exchange packets with its peers using the relay. 
    109109 
    110 This version of PJNATH implements both TCP and UDP client transport and it 
    111 complies with the following TURN draft: 
    112  - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-turn-09.txt"> 
    113    <B>draft-ietf-behave-turn-09</B></A>: Obtaining Relay Addresses  
     110Features: 
     111 - <A HREF="http://www.ietf.org/internet-drafts/draft-ietf-behave-turn-13.txt"> 
     112   <B>draft-ietf-behave-turn-13</B></A>: Obtaining Relay Addresses  
    114113   from Simple Traversal Underneath NAT (STUN) 
     114 - DNS SRV resolution 
     115 - Fallback to DNS A resolution if SRV record is not found 
     116 - UDP and TCP connection to TURN server 
     117 - automatic management of allocation refresh 
     118 
    115119 
    116120 
  • pjproject/trunk/pjnath/src/pjnath-test/server.c

    r2394 r2589  
    311311    pj_stun_msg_add_uint_attr(pool, resp, PJ_STUN_ATTR_LIFETIME, lifetime); 
    312312    if (lifetime != 0) { 
    313         /* Add RELAYED-ADDRESS */ 
    314         pj_stun_msg_add_sockaddr_attr(pool, resp, PJ_STUN_ATTR_RELAYED_ADDR, PJ_TRUE, &alloc->alloc_addr, 
     313        /* Add XOR-RELAYED-ADDRESS */ 
     314        pj_stun_msg_add_sockaddr_attr(pool, resp, PJ_STUN_ATTR_XOR_RELAYED_ADDR, PJ_TRUE, &alloc->alloc_addr, 
    315315                                      pj_sockaddr_get_len(&alloc->alloc_addr)); 
    316316        /* Add XOR-MAPPED-ADDRESS */ 
  • pjproject/trunk/pjnath/src/pjnath/stun_msg.c

    r2580 r2589  
    4444    "Send",                     /* 6 */ 
    4545    "Data",                     /* 7 */ 
    46     "???",                      /* 8 */ 
     46    "CreatePermission",         /* 8 */ 
    4747    "ChannelBind",              /* 9 */ 
    4848}; 
     
    5757    { PJ_STUN_SC_BAD_REQUEST,               "Bad Request"}, 
    5858    { PJ_STUN_SC_UNAUTHORIZED,              "Unauthorized"}, 
     59    { PJ_STUN_SC_FORBIDDEN,                 "Forbidden"}, 
    5960    { PJ_STUN_SC_UNKNOWN_ATTRIBUTE,         "Unknown Attribute"}, 
    6061    //{ PJ_STUN_SC_STALE_CREDENTIALS,       "Stale Credentials"}, 
     
    7071    { PJ_STUN_SC_WRONG_CREDENTIALS,         "Wrong Credentials"}, 
    7172    { PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO,    "Unsupported Transport Protocol"}, 
    72     { PJ_STUN_SC_INVALID_IP_ADDR,           "Invalid IP Address"}, 
    73     { PJ_STUN_SC_INVALID_PORT,              "Invalid Port"}, 
    7473    { PJ_STUN_SC_OPER_TCP_ONLY,             "Operation for TCP Only"}, 
    7574    { PJ_STUN_SC_CONNECTION_FAILURE,        "Connection Failure"}, 
     
    7978    { PJ_STUN_SC_SERVER_ERROR,              "Server Error"}, 
    8079    { PJ_STUN_SC_INSUFFICIENT_CAPACITY,     "Insufficient Capacity"}, 
    81     { PJ_STUN_SC_INSUFFICIENT_PORT_CAPACITY,"Insufficient Port Capacity"}, 
    8280    { PJ_STUN_SC_GLOBAL_FAILURE,            "Global Failure"} 
    8381}; 
     
    311309    }, 
    312310    { 
    313         /* PJ_STUN_ATTR_PEER_ADDRESS, */ 
    314         "PEER-ADDRESS", 
     311        /* PJ_STUN_ATTR_XOR_PEER_ADDRESS, */ 
     312        "XOR-PEER-ADDRESS", 
    315313        &decode_xored_sockaddr_attr, 
    316314        &encode_sockaddr_attr, 
     
    339337    }, 
    340338    { 
    341         /* PJ_STUN_ATTR_RELAY_ADDRESS, */ 
    342         "RELAYED-ADDRESS", 
     339        /* PJ_STUN_ATTR_XOR_RELAYED_ADDR, */ 
     340        "XOR-RELAYED-ADDRESS", 
    343341        &decode_xored_sockaddr_attr, 
    344342        &encode_sockaddr_attr, 
     
    353351    }, 
    354352    { 
    355         /* PJ_STUN_ATTR_REQUESTED_PROPS, */ 
    356         "REQUESTED-PROPS", 
     353        /* PJ_STUN_ATTR_EVEN_PORT, */ 
     354        "EVEN-PORT", 
    357355        &decode_uint_attr, 
    358356        &encode_uint_attr, 
     
    367365    }, 
    368366    { 
    369         /* ID 0x001A is not assigned */ 
    370         NULL, 
    371         NULL, 
    372         NULL, 
    373         NULL 
     367        /* PJ_STUN_ATTR_DONT_FRAGMENT */ 
     368        "DONT-FRAGMENT", 
     369        &decode_empty_attr, 
     370        &encode_empty_attr, 
     371        &clone_empty_attr 
    374372    }, 
    375373    { 
  • pjproject/trunk/pjnath/src/pjnath/stun_msg_dump.c

    r2394 r2589  
    7373    case PJ_STUN_ATTR_CHANGED_ADDR: 
    7474    case PJ_STUN_ATTR_REFLECTED_FROM: 
    75     case PJ_STUN_ATTR_PEER_ADDR: 
    76     case PJ_STUN_ATTR_RELAYED_ADDR: 
     75    case PJ_STUN_ATTR_XOR_PEER_ADDR: 
     76    case PJ_STUN_ATTR_XOR_RELAYED_ADDR: 
    7777    case PJ_STUN_ATTR_XOR_MAPPED_ADDR: 
    7878    case PJ_STUN_ATTR_XOR_REFLECTED_FROM: 
     
    117117    case PJ_STUN_ATTR_BANDWIDTH: 
    118118    case PJ_STUN_ATTR_REQ_ADDR_TYPE: 
    119     case PJ_STUN_ATTR_REQ_PROPS: 
     119    case PJ_STUN_ATTR_EVEN_PORT: 
    120120    case PJ_STUN_ATTR_REQ_TRANSPORT: 
    121121    case PJ_STUN_ATTR_TIMER_VAL: 
     
    224224        break; 
    225225    case PJ_STUN_ATTR_USE_CANDIDATE: 
     226    case PJ_STUN_ATTR_DONT_FRAGMENT: 
    226227    default: 
    227228        len = pj_ansi_snprintf(p, end-p, "\n"); 
  • pjproject/trunk/pjnath/src/pjnath/stun_session.c

    r2394 r2589  
    218218    pj_str_t realm, username, nonce, auth_key; 
    219219 
    220     /* The server SHOULD include a SOFTWARE attribute in all responses */ 
    221     if (sess->srv_name.slen && PJ_STUN_IS_RESPONSE(msg->hdr.type)) { 
     220    /* If the agent is sending a request, it SHOULD add a SOFTWARE attribute 
     221     * to the request. The server SHOULD include a SOFTWARE attribute in all  
     222     * responses  
     223     */ 
     224    if (sess->srv_name.slen && !PJ_STUN_IS_INDICATION(msg->hdr.type) && 
     225        pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_SOFTWARE, 0)==NULL)  
     226    { 
    222227        pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SOFTWARE, 
    223228                                    &sess->srv_name); 
     
    487492    sess->srv_name.ptr = (char*) pj_pool_alloc(pool, 32); 
    488493    sess->srv_name.slen = pj_ansi_snprintf(sess->srv_name.ptr, 32, 
    489                                            "pj_stun-%s", pj_get_version()); 
     494                                           "pjnath-%s", pj_get_version()); 
    490495 
    491496    sess->rx_pool = pj_pool_create(sess->cfg->pf, name,  
     
    591596} 
    592597 
    593 PJ_DEF(pj_status_t) pj_stun_session_set_server_name(pj_stun_session *sess, 
    594                                                     const pj_str_t *srv_name) 
     598PJ_DEF(pj_status_t) pj_stun_session_set_software_name(pj_stun_session *sess, 
     599                                                      const pj_str_t *sw) 
    595600{ 
    596601    PJ_ASSERT_RETURN(sess, PJ_EINVAL); 
    597     if (srv_name) 
    598         pj_strdup(sess->pool, &sess->srv_name, srv_name); 
     602    if (sw && sw->slen) 
     603        pj_strdup(sess->pool, &sess->srv_name, sw); 
    599604    else 
    600605        sess->srv_name.slen = 0; 
  • pjproject/trunk/pjnath/src/pjnath/turn_session.c

    r2407 r2589  
    2929#include <pj/os.h> 
    3030#include <pj/pool.h> 
     31#include <pj/rand.h> 
    3132#include <pj/sock.h> 
    3233 
    3334#define PJ_TURN_CHANNEL_MIN         0x4000 
    34 #define PJ_TURN_CHANNEL_MAX         0xFFFE  /* inclusive */ 
    35 #define PJ_TURN_PEER_HTABLE_SIZE    8 
     35#define PJ_TURN_CHANNEL_MAX         0x7FFF  /* inclusive */ 
     36#define PJ_TURN_CHANNEL_HTABLE_SIZE 8 
     37#define PJ_TURN_PERM_HTABLE_SIZE    8 
     38#define PJ_TURN_RENEWAL_BEFORE      10  /* seconds before renewals */ 
    3639 
    3740static const char *state_names[] =  
     
    5457}; 
    5558 
    56  
    57 struct peer 
    58 { 
    59     pj_uint16_t     ch_id; 
     59/* This structure describes a channel binding. A channel binding is index by 
     60 * the channel number or IP address and port number of the peer. 
     61 */ 
     62struct ch_t 
     63{ 
     64    /* The channel number */ 
     65    pj_uint16_t     num; 
     66 
     67    /* PJ_TRUE if we've received successful response to ChannelBind request 
     68     * for this channel. 
     69     */ 
    6070    pj_bool_t       bound; 
     71 
     72    /* The peer IP address and port */ 
    6173    pj_sockaddr     addr; 
     74 
     75    /* The channel binding expiration */ 
    6276    pj_time_val     expiry; 
    6377}; 
    6478 
     79 
     80/* This structure describes a permission. A permission is identified by the 
     81 * IP address only. 
     82 */ 
     83struct perm_t 
     84{ 
     85    /* Cache of hash value to speed-up lookup */ 
     86    pj_uint32_t     hval; 
     87 
     88    /* The permission IP address. The port number MUST be zero */ 
     89    pj_sockaddr     addr; 
     90 
     91    /* Number of peers that uses this permission. */ 
     92    unsigned        peer_cnt; 
     93 
     94    /* Automatically renew this permission once it expires? */ 
     95    pj_bool_t       renew; 
     96 
     97    /* The permission expiration */ 
     98    pj_time_val     expiry; 
     99 
     100    /* Arbitrary/random pointer value (token) to map this perm with the  
     101     * request to create it. It is used to invalidate this perm when the  
     102     * request fails. 
     103     */ 
     104    void           *req_token; 
     105}; 
     106 
     107 
     108/* The TURN client session structure */ 
    65109struct pj_turn_session 
    66110{ 
     
    103147    pj_sockaddr          relay_addr; 
    104148 
    105     pj_hash_table_t     *peer_table; 
     149    pj_hash_table_t     *ch_table; 
     150    pj_hash_table_t     *perm_table; 
    106151 
    107152    pj_uint32_t          send_ind_tsx_id[3]; 
     
    143188                                pj_status_t status, 
    144189                                const pj_dns_srv_record *rec); 
    145 static struct peer *lookup_peer_by_addr(pj_turn_session *sess, 
    146                                         const pj_sockaddr_t *addr, 
    147                                         unsigned addr_len, 
    148                                         pj_bool_t update, 
    149                                         pj_bool_t bind_channel); 
    150 static struct peer *lookup_peer_by_chnum(pj_turn_session *sess, 
    151                                          pj_uint16_t chnum); 
     190static struct ch_t *lookup_ch_by_addr(pj_turn_session *sess, 
     191                                      const pj_sockaddr_t *addr, 
     192                                      unsigned addr_len, 
     193                                      pj_bool_t update, 
     194                                      pj_bool_t bind_channel); 
     195static struct ch_t *lookup_ch_by_chnum(pj_turn_session *sess, 
     196                                       pj_uint16_t chnum); 
     197static struct perm_t *lookup_perm(pj_turn_session *sess, 
     198                                  const pj_sockaddr_t *addr, 
     199                                  unsigned addr_len, 
     200                                  pj_bool_t update); 
     201static void invalidate_perm(pj_turn_session *sess, 
     202                            struct perm_t *perm); 
    152203static void on_timer_event(pj_timer_heap_t *th, pj_timer_entry *e); 
    153204 
     
    225276 
    226277    /* Peer hash table */ 
    227     sess->peer_table = pj_hash_create(pool, PJ_TURN_PEER_HTABLE_SIZE); 
     278    sess->ch_table = pj_hash_create(pool, PJ_TURN_CHANNEL_HTABLE_SIZE); 
     279 
     280    /* Permission hash table */ 
     281    sess->perm_table = pj_hash_create(pool, PJ_TURN_PERM_HTABLE_SIZE); 
    228282 
    229283    /* Session lock */ 
     
    483537 
    484538 
     539/* 
     540 * Set software name 
     541 */ 
     542PJ_DEF(pj_status_t) pj_turn_session_set_software_name( pj_turn_session *sess, 
     543                                                       const pj_str_t *sw) 
     544{ 
     545    pj_status_t status; 
     546 
     547    pj_lock_acquire(sess->lock); 
     548    status = pj_stun_session_set_software_name(sess->stun, sw); 
     549    pj_lock_release(sess->lock); 
     550 
     551    return status; 
     552} 
     553 
     554 
    485555/** 
    486556 * Set the server or domain name of the server. 
     
    705775 
    706776/* 
     777 * Install or renew permissions 
     778 */ 
     779PJ_DEF(pj_status_t) pj_turn_session_set_perm( pj_turn_session *sess, 
     780                                              unsigned addr_cnt, 
     781                                              const pj_sockaddr addr[], 
     782                                              unsigned options) 
     783{ 
     784    pj_stun_tx_data *tdata; 
     785    pj_hash_iterator_t it_buf, *it; 
     786    void *req_token; 
     787    unsigned i, attr_added=0; 
     788    pj_status_t status; 
     789 
     790    PJ_ASSERT_RETURN(sess && addr_cnt && addr, PJ_EINVAL); 
     791 
     792    pj_lock_acquire(sess->lock); 
     793 
     794    /* Create a bare CreatePermission request */ 
     795    status = pj_stun_session_create_req(sess->stun,  
     796                                        PJ_STUN_CREATE_PERM_REQUEST, 
     797                                        PJ_STUN_MAGIC, NULL, &tdata); 
     798    if (status != PJ_SUCCESS) { 
     799        pj_lock_release(sess->lock); 
     800        return status; 
     801    } 
     802 
     803    /* Create request token to map the request to the perm structures 
     804     * which the request belongs. 
     805     */ 
     806    req_token = (void*)(long)pj_rand(); 
     807 
     808    /* Process the addresses */ 
     809    for (i=0; i<addr_cnt; ++i) { 
     810        struct perm_t *perm; 
     811 
     812        /* Lookup the perm structure and create if it doesn't exist */ 
     813        perm = lookup_perm(sess, &addr[i], pj_sockaddr_get_len(&addr[i]), 
     814                           PJ_TRUE); 
     815        perm->renew = (options & 0x01); 
     816 
     817        /* Only add to the request if the request doesn't contain this 
     818         * address yet. 
     819         */ 
     820        if (perm->req_token != req_token) { 
     821            perm->req_token = req_token; 
     822 
     823            /* Add XOR-PEER-ADDRESS */ 
     824            status = pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
     825                                                   PJ_STUN_ATTR_XOR_PEER_ADDR, 
     826                                                   PJ_TRUE, 
     827                                                   &addr[i], 
     828                                                   sizeof(addr[i])); 
     829            if (status != PJ_SUCCESS) 
     830                goto on_error; 
     831 
     832            ++attr_added; 
     833        } 
     834    } 
     835 
     836    pj_assert(attr_added != 0); 
     837 
     838    /* Send the request */ 
     839    status = pj_stun_session_send_msg(sess->stun, req_token, PJ_FALSE,  
     840                                      (sess->conn_type==PJ_TURN_TP_UDP), 
     841                                      sess->srv_addr, 
     842                                      pj_sockaddr_get_len(sess->srv_addr),  
     843                                      tdata); 
     844    if (status != PJ_SUCCESS) { 
     845        /* tdata is already destroyed */ 
     846        tdata = NULL; 
     847        goto on_error; 
     848    } 
     849 
     850    pj_lock_release(sess->lock); 
     851    return PJ_SUCCESS; 
     852 
     853on_error: 
     854    /* destroy tdata */ 
     855    if (tdata) { 
     856        pj_stun_msg_destroy_tdata(sess->stun, tdata); 
     857    } 
     858    /* invalidate perm structures associated with this request */ 
     859    it = pj_hash_first(sess->perm_table, &it_buf); 
     860    while (it) { 
     861        struct perm_t *perm = (struct perm_t*) 
     862                              pj_hash_this(sess->perm_table, it); 
     863        it = pj_hash_next(sess->perm_table, it); 
     864        if (perm->req_token == req_token) 
     865            invalidate_perm(sess, perm); 
     866    } 
     867    pj_lock_release(sess->lock); 
     868    return status; 
     869} 
     870 
     871/* 
    707872 * Send REFRESH 
    708873 */ 
     
    758923                                            unsigned addr_len) 
    759924{ 
    760     struct peer *peer; 
     925    struct ch_t *ch; 
     926    struct perm_t *perm; 
    761927    pj_status_t status; 
    762928 
     
    772938    pj_lock_acquire(sess->lock); 
    773939 
    774     /* Lookup peer to see whether we've assigned a channel number 
    775      * to this peer. 
    776      */ 
    777     peer = lookup_peer_by_addr(sess, addr, addr_len, PJ_TRUE, PJ_FALSE); 
    778     pj_assert(peer != NULL); 
    779  
    780     if (peer->ch_id != PJ_TURN_INVALID_CHANNEL && peer->bound) { 
    781         /* Peer is assigned Channel number, we can use ChannelData */ 
     940    /* Lookup permission first */ 
     941    perm = lookup_perm(sess, addr, pj_sockaddr_get_len(addr), PJ_FALSE); 
     942    if (perm == NULL) { 
     943        /* Permission doesn't exist, install it first */ 
     944        char ipstr[PJ_INET6_ADDRSTRLEN+2]; 
     945 
     946        PJ_LOG(4,(sess->obj_name,  
     947                  "sendto(): IP %s has no permission, requesting it first..", 
     948                  pj_sockaddr_print(addr, ipstr, sizeof(ipstr), 2))); 
     949 
     950        status = pj_turn_session_set_perm(sess, 1, (const pj_sockaddr*)addr,  
     951                                          0); 
     952        if (status != PJ_SUCCESS) { 
     953            pj_lock_release(sess->lock); 
     954            return status; 
     955        } 
     956    } 
     957 
     958    /* See if the peer is bound to a channel number */ 
     959    ch = lookup_ch_by_addr(sess, addr, pj_sockaddr_get_len(addr),  
     960                           PJ_FALSE, PJ_FALSE); 
     961    if (ch && ch->num != PJ_TURN_INVALID_CHANNEL && ch->bound) { 
     962        /* Peer is assigned a channel number, we can use ChannelData */ 
    782963        pj_turn_channel_data *cd = (pj_turn_channel_data*)sess->tx_pkt; 
    783964         
     
    789970        } 
    790971 
    791         cd->ch_number = pj_htons((pj_uint16_t)peer->ch_id); 
     972        cd->ch_number = pj_htons((pj_uint16_t)ch->num); 
    792973        cd->length = pj_htons((pj_uint16_t)pkt_len); 
    793974        pj_memcpy(cd+1, pkt, pkt_len); 
     
    800981 
    801982    } else { 
    802         /* Peer has not been assigned Channel number, must use Send 
    803          * Indication. 
    804          */ 
     983        /* Use Send Indication. */ 
    805984        pj_stun_sockaddr_attr peer_attr; 
    806985        pj_stun_binary_attr data_attr; 
     
    818997            goto on_return; 
    819998 
    820         /* Add PEER-ADDRESS */ 
    821         pj_stun_sockaddr_attr_init(&peer_attr, PJ_STUN_ATTR_PEER_ADDR, 
     999        /* Add XOR-PEER-ADDRESS */ 
     1000        pj_stun_sockaddr_attr_init(&peer_attr, PJ_STUN_ATTR_XOR_PEER_ADDR, 
    8221001                                   PJ_TRUE, addr, addr_len); 
    8231002        pj_stun_msg_add_attr(&send_ind, (pj_stun_attr_hdr*)&peer_attr); 
     
    8551034                                                 unsigned addr_len) 
    8561035{ 
    857     struct peer *peer; 
     1036    struct ch_t *ch; 
    8581037    pj_stun_tx_data *tdata; 
    8591038    pj_uint16_t ch_num; 
     
    8721051        goto on_return; 
    8731052 
    874     /* Lookup peer */ 
    875     peer = lookup_peer_by_addr(sess, peer_adr, addr_len, PJ_TRUE, PJ_FALSE); 
    876     pj_assert(peer); 
    877  
    878     if (peer->ch_id != PJ_TURN_INVALID_CHANNEL) { 
     1053    /* Lookup if this peer has already been assigned a number */ 
     1054    ch = lookup_ch_by_addr(sess, peer_adr, pj_sockaddr_get_len(peer_adr), 
     1055                           PJ_TRUE, PJ_FALSE); 
     1056    pj_assert(ch); 
     1057 
     1058    if (ch->num != PJ_TURN_INVALID_CHANNEL) { 
    8791059        /* Channel is already bound. This is a refresh request. */ 
    880         ch_num = peer->ch_id; 
     1060        ch_num = ch->num; 
    8811061    } else { 
    8821062        PJ_ASSERT_ON_FAIL(sess->next_ch <= PJ_TURN_CHANNEL_MAX,  
    8831063                            {status=PJ_ETOOMANY; goto on_return;}); 
    884         peer->ch_id = ch_num = sess->next_ch++; 
     1064        ch->num = ch_num = sess->next_ch++; 
    8851065    } 
    8861066 
     
    8901070                              PJ_STUN_SET_CH_NB(ch_num)); 
    8911071 
    892     /* Add PEER-ADDRESS attribute */ 
     1072    /* Add XOR-PEER-ADDRESS attribute */ 
    8931073    pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
    894                                   PJ_STUN_ATTR_PEER_ADDR, PJ_TRUE, 
     1074                                  PJ_STUN_ATTR_XOR_PEER_ADDR, PJ_TRUE, 
    8951075                                  peer_adr, addr_len); 
    8961076 
     
    8981078     * for future reference when we receive the ChannelBind response. 
    8991079     */ 
    900     status = pj_stun_session_send_msg(sess->stun, peer, PJ_FALSE,  
     1080    status = pj_stun_session_send_msg(sess->stun, ch, PJ_FALSE,  
    9011081                                      (sess->conn_type==PJ_TURN_TP_UDP), 
    9021082                                      sess->srv_addr, 
     
    9501130        /* This must be ChannelData. */ 
    9511131        pj_turn_channel_data cd; 
    952         struct peer *peer; 
     1132        struct ch_t *ch; 
    9531133 
    9541134        if (pkt_len < 4) { 
     
    9811161        } 
    9821162 
    983         /* Lookup peer */ 
    984         peer = lookup_peer_by_chnum(sess, cd.ch_number); 
    985         if (!peer || !peer->bound) { 
     1163        /* Lookup channel */ 
     1164        ch = lookup_ch_by_chnum(sess, cd.ch_number); 
     1165        if (!ch || !ch->bound) { 
    9861166            status = PJ_ENOTFOUND; 
    9871167            goto on_return; 
     
    9911171        if (sess->cb.on_rx_data) { 
    9921172            (*sess->cb.on_rx_data)(sess, ((pj_uint8_t*)pkt)+sizeof(cd),  
    993                                    cd.length, &peer->addr, 
    994                                    pj_sockaddr_get_len(&peer->addr)); 
     1173                                   cd.length, &ch->addr, 
     1174                                   pj_sockaddr_get_len(&ch->addr)); 
    9951175        } 
    9961176 
     
    10901270{ 
    10911271    const pj_stun_lifetime_attr *lf_attr; 
    1092     const pj_stun_relayed_addr_attr *raddr_attr; 
     1272    const pj_stun_xor_relayed_addr_attr *raddr_attr; 
    10931273    const pj_stun_sockaddr_attr *mapped_attr; 
    10941274    pj_str_t s; 
     
    11381318     * address family. 
    11391319     */ 
    1140     raddr_attr = (const pj_stun_relayed_addr_attr*) 
    1141                  pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_RELAYED_ADDR, 0); 
     1320    raddr_attr = (const pj_stun_xor_relayed_addr_attr*) 
     1321                 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_RELAYED_ADDR, 0); 
    11421322    if (raddr_attr == NULL && method==PJ_STUN_ALLOCATE_METHOD) { 
    11431323        on_session_fail(sess, method, PJNATH_EINSTUNMSG, 
     
    13021482        { 
    13031483            /* Successful ChannelBind response */ 
    1304             struct peer *peer = (struct peer*)token; 
    1305  
    1306             pj_assert(peer->ch_id != PJ_TURN_INVALID_CHANNEL); 
    1307             peer->bound = PJ_TRUE; 
     1484            struct ch_t *ch = (struct ch_t*)token; 
     1485 
     1486            pj_assert(ch->num != PJ_TURN_INVALID_CHANNEL); 
     1487            ch->bound = PJ_TRUE; 
    13081488 
    13091489            /* Update hash table */ 
    1310             lookup_peer_by_addr(sess, &peer->addr, 
    1311                                 pj_sockaddr_get_len(&peer->addr), 
    1312                                 PJ_TRUE, PJ_TRUE); 
     1490            lookup_ch_by_addr(sess, &ch->addr, 
     1491                              pj_sockaddr_get_len(&ch->addr), 
     1492                              PJ_TRUE, PJ_TRUE); 
    13131493 
    13141494        } else { 
     
    13331513        } 
    13341514 
     1515    } else if (method == PJ_STUN_CREATE_PERM_METHOD) { 
     1516        /* Handle CreatePermission response */ 
     1517        if (status==PJ_SUCCESS &&  
     1518            PJ_STUN_IS_SUCCESS_RESPONSE(response->hdr.type))  
     1519        { 
     1520            /* No special handling when the request is successful. */ 
     1521        } else { 
     1522            /* Iterate the permission table and invalidate all permissions 
     1523             * that are related to this request. 
     1524             */ 
     1525            pj_hash_iterator_t it_buf, *it; 
     1526            char ipstr[PJ_INET6_ADDRSTRLEN+10]; 
     1527            int err_code; 
     1528            char errbuf[PJ_ERR_MSG_SIZE]; 
     1529            pj_str_t reason; 
     1530 
     1531            if (status != PJ_SUCCESS) { 
     1532                err_code = status; 
     1533                reason = pj_strerror(status, errbuf, sizeof(errbuf)); 
     1534            } else { 
     1535                const pj_stun_errcode_attr *eattr; 
     1536 
     1537                eattr = (const pj_stun_errcode_attr*) 
     1538                        pj_stun_msg_find_attr(response,  
     1539                                              PJ_STUN_ATTR_ERROR_CODE, 0); 
     1540                if (eattr) { 
     1541                    err_code = eattr->err_code; 
     1542                    reason = eattr->reason; 
     1543                } else { 
     1544                    err_code = -1; 
     1545                    reason = pj_str("?"); 
     1546                } 
     1547            } 
     1548 
     1549            it = pj_hash_first(sess->perm_table, &it_buf); 
     1550            while (it) { 
     1551                struct perm_t *perm = (struct perm_t*) 
     1552                                      pj_hash_this(sess->perm_table, it); 
     1553                it = pj_hash_next(sess->perm_table, it); 
     1554 
     1555                if (perm->req_token == token) { 
     1556                    PJ_LOG(1,(sess->obj_name,  
     1557                              "CreatePermission failed for IP %s: %d/%.*s", 
     1558                              pj_sockaddr_print(&perm->addr, ipstr,  
     1559                                                sizeof(ipstr), 2), 
     1560                              err_code, (int)reason.slen, reason.ptr)); 
     1561 
     1562                    invalidate_perm(sess, perm); 
     1563                } 
     1564            } 
     1565        } 
     1566 
    13351567    } else { 
    13361568        PJ_LOG(4,(sess->obj_name, "Unexpected STUN %s response", 
     
    13531585{ 
    13541586    pj_turn_session *sess; 
    1355     pj_stun_peer_addr_attr *peer_attr; 
     1587    pj_stun_xor_peer_addr_attr *peer_attr; 
    13561588    pj_stun_icmp_attr *icmp; 
    13571589    pj_stun_data_attr *data_attr; 
     
    13801612    } 
    13811613 
    1382     /* Get PEER-ADDRESS attribute */ 
    1383     peer_attr = (pj_stun_peer_addr_attr*) 
    1384                 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_PEER_ADDR, 0); 
     1614    /* Get XOR-PEER-ADDRESS attribute */ 
     1615    peer_attr = (pj_stun_xor_peer_addr_attr*) 
     1616                pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_PEER_ADDR, 0); 
    13851617 
    13861618    /* Get DATA attribute */ 
     
    13881620                pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_DATA, 0); 
    13891621 
    1390     /* Must have both PEER-ADDRESS and DATA attributes */ 
     1622    /* Must have both XOR-PEER-ADDRESS and DATA attributes */ 
    13911623    if (!peer_attr || !data_attr) { 
    13921624        PJ_LOG(4,(sess->obj_name,  
     
    14731705 * Lookup peer descriptor from its address. 
    14741706 */ 
    1475 static struct peer *lookup_peer_by_addr(pj_turn_session *sess, 
    1476                                         const pj_sockaddr_t *addr, 
    1477                                         unsigned addr_len, 
    1478                                         pj_bool_t update, 
    1479                                         pj_bool_t bind_channel) 
    1480 { 
    1481     unsigned hval = 0; 
    1482     struct peer *peer; 
    1483  
    1484     peer = (struct peer*) pj_hash_get(sess->peer_table, addr, addr_len, &hval); 
    1485     if (peer == NULL && update) { 
    1486         peer = PJ_POOL_ZALLOC_T(sess->pool, struct peer); 
    1487         peer->ch_id = PJ_TURN_INVALID_CHANNEL; 
    1488         pj_memcpy(&peer->addr, addr, addr_len); 
     1707static struct ch_t *lookup_ch_by_addr(pj_turn_session *sess, 
     1708                                      const pj_sockaddr_t *addr, 
     1709                                      unsigned addr_len, 
     1710                                      pj_bool_t update, 
     1711                                      pj_bool_t bind_channel) 
     1712{ 
     1713    pj_uint32_t hval = 0; 
     1714    struct ch_t *ch; 
     1715 
     1716    ch = (struct ch_t*)  
     1717         pj_hash_get(sess->ch_table, addr, addr_len, &hval); 
     1718    if (ch == NULL && update) { 
     1719        ch = PJ_POOL_ZALLOC_T(sess->pool, struct ch_t); 
     1720        ch->num = PJ_TURN_INVALID_CHANNEL; 
     1721        pj_memcpy(&ch->addr, addr, addr_len); 
    14891722 
    14901723        /* Register by peer address */ 
    1491         pj_hash_set(sess->pool, sess->peer_table, &peer->addr, addr_len, 
    1492                     hval, peer); 
    1493     } 
    1494  
    1495     if (peer && update) { 
    1496         pj_gettimeofday(&peer->expiry); 
    1497         if (peer->bound) { 
    1498             peer->expiry.sec += PJ_TURN_CHANNEL_TIMEOUT - 10; 
    1499         } else { 
    1500             peer->expiry.sec += PJ_TURN_PERM_TIMEOUT - 10; 
    1501         } 
     1724        pj_hash_set(sess->pool, sess->ch_table, &ch->addr, addr_len, 
     1725                    hval, ch); 
     1726    } 
     1727 
     1728    if (ch && update) { 
     1729        pj_gettimeofday(&ch->expiry); 
     1730        ch->expiry.sec += PJ_TURN_PERM_TIMEOUT - PJ_TURN_RENEWAL_BEFORE; 
    15021731 
    15031732        if (bind_channel) { 
    15041733            pj_uint32_t hval = 0; 
    15051734            /* Register by channel number */ 
    1506             pj_assert(peer->ch_id != PJ_TURN_INVALID_CHANNEL && peer->bound); 
    1507  
    1508             if (pj_hash_get(sess->peer_table, &peer->ch_id,  
    1509                             sizeof(peer->ch_id), &hval)==0) { 
    1510                 pj_hash_set(sess->pool, sess->peer_table, &peer->ch_id, 
    1511                             sizeof(peer->ch_id), hval, peer); 
     1735            pj_assert(ch->num != PJ_TURN_INVALID_CHANNEL && ch->bound); 
     1736 
     1737            if (pj_hash_get(sess->ch_table, &ch->num,  
     1738                            sizeof(ch->num), &hval)==0) { 
     1739                pj_hash_set(sess->pool, sess->ch_table, &ch->num, 
     1740                            sizeof(ch->num), hval, ch); 
    15121741            } 
    15131742        } 
    15141743    } 
    15151744 
    1516     return peer; 
    1517 } 
    1518  
    1519  
    1520 /* 
    1521  * Lookup peer descriptor from its channel number. 
    1522  */ 
    1523 static struct peer *lookup_peer_by_chnum(pj_turn_session *sess, 
     1745    return ch; 
     1746} 
     1747 
     1748 
     1749/* 
     1750 * Lookup channel descriptor from its channel number. 
     1751 */ 
     1752static struct ch_t *lookup_ch_by_chnum(pj_turn_session *sess, 
    15241753                                         pj_uint16_t chnum) 
    15251754{ 
    1526     return (struct peer*) pj_hash_get(sess->peer_table, &chnum,  
     1755    return (struct ch_t*) pj_hash_get(sess->ch_table, &chnum,  
    15271756                                      sizeof(chnum), NULL); 
    15281757} 
    15291758 
     1759 
     1760/* 
     1761 * Lookup permission and optionally create if it doesn't exist. 
     1762 */ 
     1763static struct perm_t *lookup_perm(pj_turn_session *sess, 
     1764                                  const pj_sockaddr_t *addr, 
     1765                                  unsigned addr_len, 
     1766                                  pj_bool_t update) 
     1767{ 
     1768    pj_uint32_t hval = 0; 
     1769    pj_sockaddr perm_addr; 
     1770    struct perm_t *perm; 
     1771 
     1772    /* make sure port number if zero */ 
     1773    if (pj_sockaddr_get_port(addr) != 0) { 
     1774        pj_memcpy(&perm_addr, addr, addr_len); 
     1775        pj_sockaddr_set_port(&perm_addr, 0); 
     1776        addr = &perm_addr; 
     1777    } 
     1778 
     1779    /* lookup and create if it doesn't exist and wanted */ 
     1780    perm = (struct perm_t*)  
     1781           pj_hash_get(sess->perm_table, addr, addr_len, &hval); 
     1782    if (perm == NULL && update) { 
     1783        perm = PJ_POOL_ZALLOC_T(sess->pool, struct perm_t); 
     1784        pj_memcpy(&perm->addr, addr, addr_len); 
     1785        perm->hval = hval; 
     1786 
     1787        pj_hash_set(sess->pool, sess->perm_table, &perm->addr, addr_len, 
     1788                    perm->hval, perm); 
     1789    } 
     1790 
     1791    if (perm && update) { 
     1792        pj_gettimeofday(&perm->expiry); 
     1793        perm->expiry.sec += PJ_TURN_PERM_TIMEOUT - PJ_TURN_RENEWAL_BEFORE; 
     1794 
     1795    } 
     1796 
     1797    return perm; 
     1798} 
     1799 
     1800/* 
     1801 * Delete permission 
     1802 */ 
     1803static void invalidate_perm(pj_turn_session *sess, 
     1804                            struct perm_t *perm) 
     1805{ 
     1806    pj_hash_set(NULL, sess->perm_table, &perm->addr, 
     1807                pj_sockaddr_get_len(&perm->addr), perm->hval, NULL); 
     1808} 
    15301809 
    15311810/* 
     
    15651844 
    15661845        /* Scan hash table to refresh bound channels */ 
    1567         it = pj_hash_first(sess->peer_table, &itbuf); 
     1846        it = pj_hash_first(sess->ch_table, &itbuf); 
    15681847        while (it) { 
    1569             struct peer *peer = (struct peer*)  
    1570                                 pj_hash_this(sess->peer_table, it); 
    1571             if (peer->bound && PJ_TIME_VAL_LTE(peer->expiry, now)) { 
     1848            struct ch_t *ch = (struct ch_t*)  
     1849                              pj_hash_this(sess->ch_table, it); 
     1850            if (ch->bound && PJ_TIME_VAL_LTE(ch->expiry, now)) { 
    15721851 
    15731852                /* Send ChannelBind to refresh channel binding and  
    15741853                 * permission. 
    15751854                 */ 
    1576                 pj_turn_session_bind_channel(sess, &peer->addr, 
    1577                                              pj_sockaddr_get_len(&peer->addr)); 
     1855                pj_turn_session_bind_channel(sess, &ch->addr, 
     1856                                             pj_sockaddr_get_len(&ch->addr)); 
    15781857                pkt_sent = PJ_TRUE; 
    15791858            } 
    15801859 
    1581             it = pj_hash_next(sess->peer_table, it); 
     1860            it = pj_hash_next(sess->ch_table, it); 
    15821861        } 
    15831862 
  • pjproject/trunk/pjnath/src/pjnath/turn_sock.c

    r2394 r2589  
    388388 
    389389/* 
     390 * Install permission 
     391 */ 
     392PJ_DEF(pj_status_t) pj_turn_sock_set_perm( pj_turn_sock *turn_sock, 
     393                                           unsigned addr_cnt, 
     394                                           const pj_sockaddr addr[], 
     395                                           unsigned options) 
     396{ 
     397    if (turn_sock->sess == NULL) 
     398        return PJ_EINVALIDOP; 
     399 
     400    return pj_turn_session_set_perm(turn_sock->sess, addr_cnt, addr, options); 
     401} 
     402 
     403/* 
    390404 * Send packet. 
    391405 */  
  • pjproject/trunk/pjnath/src/pjturn-client/client_main.c

    r2408 r2589  
    139139        char name[] = "peer0"; 
    140140        pj_uint16_t port; 
     141        pj_stun_sock_cfg ss_cfg; 
    141142        pj_str_t server; 
    142143 
     
    147148        g.peer[i].mapped_addr.addr.sa_family = pj_AF_INET(); 
    148149 
     150        pj_stun_sock_cfg_default(&ss_cfg); 
     151#if 1 
     152        /* make reading the log easier */ 
     153        ss_cfg.ka_interval = 300; 
     154#endif 
     155 
    149156        name[strlen(name)-1] = '0'+i; 
    150157        status = pj_stun_sock_create(&g.stun_config, name, pj_AF_INET(),  
    151                                      &stun_sock_cb, NULL, 
     158                                     &stun_sock_cb, &ss_cfg, 
    152159                                     &g.peer[i], &g.peer[i].stun_sock); 
    153160        if (status != PJ_SUCCESS) { 
     
    416423 
    417424    puts("\n"); 
    418     puts("+====================================================================+"); 
    419     puts("|             CLIENT                |             PEER-0             |"); 
    420     puts("|                                   |                                |"); 
    421     printf("| State     : %-12s          | Address: %-21s |\n", 
     425    puts("+=====================================================================+"); 
     426    puts("|             CLIENT                 |             PEER-0             |"); 
     427    puts("|                                    |                                |"); 
     428    printf("| State     : %-12s           | Address: %-21s |\n", 
    422429           client_state, peer0_addr); 
    423     printf("| Relay addr: %-21s |                                |\n", 
     430    printf("| Relay addr: %-21s  |                                |\n", 
    424431           relay_addr); 
    425     puts("|                                   | 0  Send data to relay address  |"); 
    426     puts("| a      Allocate relay             +--------------------------------+        "); 
    427     puts("| s,ss   Send data to peer 0/1      |             PEER-1             |"); 
    428     puts("| b,bb   BindChannel to peer 0/1    |                                |"); 
    429     printf("| x      Delete allocation          | Address: %-21s |\n", 
     432    puts("|                                    | 0  Send data to relay address  |"); 
     433    puts("| a      Allocate relay              |                                |"); 
     434    puts("| p,pp   Set permission for peer 0/1 +--------------------------------+"); 
     435    puts("| s,ss   Send data to peer 0/1       |             PEER-1             |"); 
     436    puts("| b,bb   BindChannel to peer 0/1     |                                |"); 
     437    printf("| x      Delete allocation           | Address: %-21s |\n", 
    430438          peer1_addr); 
    431     puts("+-----------------------------------+                                |"); 
    432     puts("| q  Quit                  d  Dump  | 1  Send data to relay adderss  |"); 
    433     puts("+-----------------------------------+--------------------------------+"); 
     439    puts("+------------------------------------+                                |"); 
     440    puts("| q  Quit                  d  Dump   | 1  Send data to relay adderss  |"); 
     441    puts("+------------------------------------+--------------------------------+"); 
    434442    printf(">>> "); 
    435443    fflush(stdout); 
     
    488496            if (status != PJ_SUCCESS) 
    489497                my_perror("turn_udp_bind_channel() failed", status); 
     498            break; 
     499        case 'p': 
     500            if (g.relay == NULL) { 
     501                puts("Error: no relay"); 
     502                continue; 
     503            } 
     504            if (input[1]!='p') 
     505                peer = &g.peer[0]; 
     506            else 
     507                peer = &g.peer[1]; 
     508 
     509            status = pj_turn_sock_set_perm(g.relay, 1, &peer->mapped_addr, 1); 
     510            if (status != PJ_SUCCESS) 
     511                my_perror("pj_turn_sock_set_perm() failed", status); 
    490512            break; 
    491513        case 'x': 
  • pjproject/trunk/pjnath/src/pjturn-srv/allocation.c

    r2394 r2589  
    110110    pj_stun_req_transport_attr *attr_req_tp; 
    111111    pj_stun_res_token_attr *attr_res_token; 
    112     pj_stun_req_props_attr *attr_rpp; 
    113112    pj_stun_lifetime_attr *attr_lifetime; 
    114113 
     
    165164    } 
    166165 
    167     /* Get REQUESTED-PROPS attribute, if any */ 
    168     attr_rpp = (pj_stun_req_props_attr*) 
    169                pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_PROPS, 0); 
    170     if (attr_rpp) { 
    171         /* We don't support REQUESTED-PROPS for now */ 
    172         pj_stun_session_respond(sess, rdata,  
    173                                 PJ_STUN_SC_BAD_REQUEST, 
    174                                 "REQUESTED-PROPS is not supported",  
    175                                 NULL, PJ_TRUE, src_addr, src_addr_len); 
    176         return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); 
    177     } 
    178  
    179166    /* Get LIFETIME attribute */ 
    180167    attr_lifetime = (pj_stun_uint_attr*) 
     
    212199        return status; 
    213200 
    214     /* Add RELAYED-ADDRESS attribute */ 
     201    /* Add XOR-RELAYED-ADDRESS attribute */ 
    215202    pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 
    216                                   PJ_STUN_ATTR_RELAYED_ADDR, PJ_TRUE, 
     203                                  PJ_STUN_ATTR_XOR_RELAYED_ADDR, PJ_TRUE, 
    217204                                  &alloc->relay.hkey.addr, 
    218205                                  pj_sockaddr_get_len(&alloc->relay.hkey.addr)); 
     
    10711058 
    10721059        pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,  
    1073                                       PJ_STUN_ATTR_PEER_ADDR, PJ_TRUE, 
     1060                                      PJ_STUN_ATTR_XOR_PEER_ADDR, PJ_TRUE, 
    10741061                                      src_addr, pj_sockaddr_get_len(src_addr)); 
    10751062        pj_stun_msg_add_binary_attr(tdata->pool, tdata->msg, 
     
    12311218         */ 
    12321219        pj_stun_channel_number_attr *ch_attr; 
    1233         pj_stun_peer_addr_attr *peer_attr; 
     1220        pj_stun_xor_peer_addr_attr *peer_attr; 
    12341221        pj_turn_permission *p1, *p2; 
    12351222 
    12361223        ch_attr = (pj_stun_channel_number_attr*) 
    12371224                  pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_CHANNEL_NUMBER, 0); 
    1238         peer_attr = (pj_stun_peer_addr_attr*) 
    1239                     pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_PEER_ADDR, 0); 
     1225        peer_attr = (pj_stun_xor_peer_addr_attr*) 
     1226                    pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_PEER_ADDR, 0); 
    12401227 
    12411228        if (!ch_attr || !peer_attr) { 
     
    13341321                                         unsigned src_addr_len) 
    13351322{ 
    1336     pj_stun_peer_addr_attr *peer_attr; 
     1323    pj_stun_xor_peer_addr_attr *peer_attr; 
    13371324    pj_stun_data_attr *data_attr; 
    13381325    pj_turn_allocation *alloc; 
     
    13541341    } 
    13551342 
    1356     /* Get PEER-ADDRESS attribute */ 
    1357     peer_attr = (pj_stun_peer_addr_attr*) 
    1358                 pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_PEER_ADDR, 0); 
    1359  
    1360     /* MUST have PEER-ADDRESS attribute */ 
     1343    /* Get XOR-PEER-ADDRESS attribute */ 
     1344    peer_attr = (pj_stun_xor_peer_addr_attr*) 
     1345                pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_XOR_PEER_ADDR, 0); 
     1346 
     1347    /* MUST have XOR-PEER-ADDRESS attribute */ 
    13611348    if (!peer_attr) 
    13621349        return PJ_SUCCESS; 
Note: See TracChangeset for help on using the changeset viewer.