Changeset 1021 for pjproject/trunk
- Timestamp:
- Mar 1, 2007 12:08:27 AM (18 years ago)
- Location:
- pjproject/trunk/pjlib-util
- Files:
-
- 1 deleted
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/include/pjlib-util/stun_msg.h
r1003 r1021 1175 1175 * the FINGERPRINT CRC attribute for the message. 1176 1176 * 1177 * @param msg The STUN message to be printed. 1177 * @param msg The STUN message to be printed. Upon return, 1178 * some fields in the header (such as message 1179 * length) will be updated. 1178 1180 * @param pkt_buf The buffer to be filled with the packet. 1179 1181 * @param buf_size Size of the buffer. … … 1187 1189 * @return PJ_SUCCESS on success or the appropriate error code. 1188 1190 */ 1189 PJ_DECL(pj_status_t) pj_stun_msg_encode( constpj_stun_msg *msg,1191 PJ_DECL(pj_status_t) pj_stun_msg_encode(pj_stun_msg *msg, 1190 1192 pj_uint8_t *pkt_buf, 1191 1193 unsigned buf_size, … … 1423 1425 * @param xor_ed If non-zero, the port and address will be XOR-ed 1424 1426 * with magic, to make the XOR-MAPPED-ADDRESS attribute. 1427 * @param addr A pj_sockaddr_in or pj_sockaddr_in6 structure. 1425 1428 * @param addr_len Length of \a addr parameter. 1426 * @param addr A pj_sockaddr_in or pj_sockaddr_in6 structure.1427 1429 * @param p_attr Pointer to receive the attribute. 1428 1430 * … … 1433 1435 int attr_type, 1434 1436 pj_bool_t xor_ed, 1437 const pj_sockaddr_t *addr, 1435 1438 unsigned addr_len, 1436 const pj_sockaddr_t *addr,1437 1439 pj_stun_generic_ip_addr_attr **p_attr); 1438 1440 … … 1448 1450 * @param xor_ed If non-zero, the port and address will be XOR-ed 1449 1451 * with magic, to make the XOR-MAPPED-ADDRESS attribute. 1452 * @param addr A pj_sockaddr_in or pj_sockaddr_in6 structure. 1450 1453 * @param addr_len Length of \a addr parameter. 1451 * @param addr A pj_sockaddr_in or pj_sockaddr_in6 structure.1452 1454 * 1453 1455 * @return PJ_SUCCESS on success or the appropriate error code. … … 1458 1460 int attr_type, 1459 1461 pj_bool_t xor_ed, 1460 unsigned addr_len,1461 const pj_sockaddr_t *addr);1462 const pj_sockaddr_t *addr, 1463 unsigned addr_len); 1462 1464 1463 1465 /** -
pjproject/trunk/pjlib-util/include/pjlib-util/stun_session.h
r1008 r1021 25 25 #include <pj/list.h> 26 26 27 PJ_BEGIN_DECL 28 29 30 /* **************************************************************************/ 31 /** 32 * @defgroup PJLIB_UTIL_STUN_SESSION STUN Client/Server Session 33 * @brief STUN client and server session 34 * @ingroup PJLIB_UTIL_STUN 35 * @{ 36 */ 37 27 38 28 39 /** Forward declaration for pj_stun_tx_data */ … … 31 42 /** Forward declaration for pj_stun_session */ 32 43 typedef struct pj_stun_session pj_stun_session; 44 33 45 34 46 /** … … 52 64 * packet sending. 53 65 */ 54 pj_status_t (*on_send_msg)(pj_stun_ tx_data *tdata,66 pj_status_t (*on_send_msg)(pj_stun_session *sess, 55 67 const void *pkt, 56 68 pj_size_t pkt_size, 57 unsigned addr_len, 58 const pj_sockaddr_t *dst_addr); 59 60 /** 61 * Callback to be called when Binding response is received or the 62 * transaction has timed out. 69 const pj_sockaddr_t *dst_addr, 70 unsigned addr_len); 71 72 /** 73 * Callback to be called on incoming STUN request message. In the 74 * callback processing, application MUST create a response by calling 75 * pj_stun_session_create_response() function and send the response 76 * with pj_stun_session_send_msg() function, before returning from 77 * the callback. 78 * 79 * @param sess The STUN session. 80 * @param pkt Pointer to the original STUN packet. 81 * @param pkt_len Length of the STUN packet. 82 * @param msg The parsed STUN request. 83 * @param src_addr Source address of the packet. 84 * @param src_addr_len Length of the source address. 85 * 86 * @return The return value of this callback will be 87 * returned back to pj_stun_session_on_rx_pkt() 88 * function. 89 */ 90 pj_status_t (*on_rx_request)(pj_stun_session *sess, 91 const pj_uint8_t *pkt, 92 unsigned pkt_len, 93 const pj_stun_msg *msg, 94 const pj_sockaddr_t *src_addr, 95 unsigned src_addr_len); 96 97 /** 98 * Callback to be called when response is received or the transaction 99 * has timed out. 63 100 * 64 101 * @param sess The STUN session. … … 70 107 * @param response The response message, on successful transaction. 71 108 */ 72 void (*on_bind_response)(pj_stun_session *sess, 73 pj_status_t status, 74 pj_stun_tx_data *request, 75 const pj_stun_msg *response); 76 77 /** 78 * Callback to be called when Allocate response is received or the 79 * transaction has timed out. 80 * 81 * @param sess The STUN session. 82 * @param status Status of the request. If the value if not 83 * PJ_SUCCESS, the transaction has timed-out 84 * or other error has occurred, and the response 85 * argument may be NULL. 86 * @param request The original STUN request. 87 * @param response The response message, on successful transaction. 88 */ 89 void (*on_allocate_response)(pj_stun_session *sess, 90 pj_status_t status, 91 pj_stun_tx_data *request, 92 const pj_stun_msg *response); 93 94 /** 95 * Callback to be called when Set Active Destination response is received 96 * or the transaction has timed out. 97 * 98 * @param sess The STUN session. 99 * @param status Status of the request. If the value if not 100 * PJ_SUCCESS, the transaction has timed-out 101 * or other error has occurred, and the response 102 * argument may be NULL. 103 * @param request The original STUN request. 104 * @param response The response message, on successful transaction. 105 */ 106 void (*on_set_active_destination_response)(pj_stun_session *sess, 107 pj_status_t status, 108 pj_stun_tx_data *request, 109 const pj_stun_msg *response); 110 111 /** 112 * Callback to be called when Connect response is received or the 113 * transaction has timed out. 114 * 115 * @param sess The STUN session. 116 * @param status Status of the request. If the value if not 117 * PJ_SUCCESS, the transaction has timed-out 118 * or other error has occurred, and the response 119 * argument may be NULL. 120 * @param request The original STUN request. 121 * @param response The response message, on successful transaction. 122 */ 123 void (*on_connect_response)( pj_stun_session *sess, 124 pj_status_t status, 125 pj_stun_tx_data *request, 126 const pj_stun_msg *response); 109 void (*on_request_complete)(pj_stun_session *sess, 110 pj_status_t status, 111 pj_stun_tx_data *tdata, 112 const pj_stun_msg *response); 113 114 115 /** 116 * Type of callback to be called on incoming STUN indication. 117 */ 118 pj_status_t (*on_rx_indication)(pj_stun_session *sess, 119 const pj_uint8_t *pkt, 120 unsigned pkt_len, 121 const pj_stun_msg *msg, 122 const pj_sockaddr_t *src_addr, 123 unsigned src_addr_len); 124 127 125 } pj_stun_session_cb; 128 126 … … 360 358 PJ_DECL(pj_status_t) pj_stun_session_create_data_ind(pj_stun_session *sess, 361 359 pj_stun_tx_data **p_tdata); 360 361 /** 362 * Create a STUN response message. After the message has been 363 * successfully created, application can send the message by calling 364 * pj_stun_session_send_msg(). 365 * 366 * @param sess The STUN session instance. 367 * @param req The STUN request where the response is to be created. 368 * @param err_code Error code to be set in the response, if error response 369 * is to be created, according to pj_stun_status enumeration. 370 * This argument MUST be zero if successful response is 371 * to be created. 372 * @param err_msg Optional pointer for the error message string, when 373 * creating error response. If the value is NULL and the 374 * \a err_code is non-zero, then default error message will 375 * be used. 376 * @param p_tdata Pointer to receive the response message created. 377 * 378 * @return PJ_SUCCESS on success, or the appropriate error code. 379 */ 380 PJ_DECL(pj_status_t) pj_stun_session_create_response(pj_stun_session *sess, 381 const pj_stun_msg *req, 382 unsigned err_code, 383 const pj_str_t *err_msg, 384 pj_stun_tx_data **p_tdata); 385 362 386 363 387 /** … … 373 397 * @param sess The STUN session instance. 374 398 * @param options Optional flags, from pj_stun_session_option. 399 * @param dst_addr The destination socket address. 375 400 * @param addr_len Length of destination address. 376 * @param dst_addr The destination socket address.377 401 * @param tdata The STUN transmit data containing the STUN message to 378 402 * be sent. … … 382 406 PJ_DECL(pj_status_t) pj_stun_session_send_msg(pj_stun_session *sess, 383 407 unsigned options, 408 const pj_sockaddr_t *dst_addr, 384 409 unsigned addr_len, 385 const pj_sockaddr_t *dst_addr,386 410 pj_stun_tx_data *tdata); 387 411 … … 403 427 * @param packet The packet containing STUN message. 404 428 * @param pkt_size Size of the packet. 429 * @param options Options, from pj_stun_options. 405 430 * @param parsed_len Optional pointer to receive the size of the parsed 406 431 * STUN message (useful if packet is received via a … … 412 437 const void *packet, 413 438 pj_size_t pkt_size, 414 unsigned *parsed_len); 415 416 439 unsigned options, 440 unsigned *parsed_len, 441 const pj_sockaddr_t *src_addr, 442 unsigned src_addr_len); 443 444 /** 445 * Destroy the transmit data. Call this function only when tdata has been 446 * created but application doesn't want to send the message (perhaps 447 * because of other error). 448 * 449 * @param sess The STUN session. 450 * @param tdata The transmit data. 451 * 452 * @return PJ_SUCCESS on success, or the appropriate error code. 453 */ 454 PJ_DECL(void) pj_stun_msg_destroy_tdata(pj_stun_session *sess, 455 pj_stun_tx_data *tdata); 456 457 458 /** 459 * @} 460 */ 461 462 463 PJ_END_DECL 417 464 418 465 #endif /* __PJLIB_UTIL_STUN_SESSION_H__ */ -
pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg.c
r1003 r1021 518 518 int attr_type, 519 519 pj_bool_t xor_ed, 520 const pj_sockaddr_t *addr, 520 521 unsigned addr_len, 521 const pj_sockaddr_t *addr,522 522 pj_stun_generic_ip_addr_attr **p_attr) 523 523 { … … 560 560 int attr_type, 561 561 pj_bool_t xor_ed, 562 unsigned addr_len,563 const pj_sockaddr_t *addr)562 const pj_sockaddr_t *addr, 563 unsigned addr_len) 564 564 { 565 565 pj_stun_generic_ip_addr_attr *attr; … … 567 567 568 568 status = pj_stun_generic_ip_addr_attr_create(pool, attr_type, xor_ed, 569 addr _len, addr, &attr);569 addr, addr_len, &attr); 570 570 if (status != PJ_SUCCESS) 571 571 return status; … … 1435 1435 PJ_INLINE(pj_uint16_t) GET_VAL16(const pj_uint8_t *pdu, unsigned pos) 1436 1436 { 1437 pj_uint16_t val = (pj_uint16_t) ((pdu[pos] << 8) + pdu[pos+1]); 1438 return pj_ntohs(val); 1437 return (pj_uint16_t) ((pdu[pos] << 8) + pdu[pos+1]); 1439 1438 } 1440 1439 1441 1440 PJ_INLINE(pj_uint32_t) GET_VAL32(const pj_uint8_t *pdu, unsigned pos) 1442 1441 { 1443 pj_uint32_t val = (pdu[pos+0] << 24) + 1444 (pdu[pos+1] << 16) + 1445 (pdu[pos+2] << 8) + 1446 (pdu[pos+3]); 1447 return pj_ntohl(val); 1442 return (pdu[pos+0] << 24) + 1443 (pdu[pos+1] << 16) + 1444 (pdu[pos+2] << 8) + 1445 (pdu[pos+3]); 1448 1446 } 1449 1447 … … 1466 1464 return PJLIB_UTIL_ESTUNINMSGTYPE; 1467 1465 1466 /* Check the PDU length */ 1467 msg_len = GET_VAL16(pdu, 2); 1468 if ((msg_len + 20 > pdu_len) || 1469 ((options & PJ_STUN_IS_DATAGRAM) && msg_len + 20 != pdu_len)) 1470 { 1471 return PJLIB_UTIL_ESTUNINMSGLEN; 1472 } 1473 1468 1474 /* If magic is set, then there is great possibility that this is 1469 1475 * a STUN message. 1470 1476 */ 1471 if (GET_VAL32(pdu, 4) != PJ_STUN_MAGIC) 1472 return PJLIB_UTIL_ESTUNNOTMAGIC; 1473 1474 /* Check the PDU length */ 1475 msg_len = GET_VAL16(pdu, 2); 1476 if ((msg_len > pdu_len) || 1477 ((options & PJ_STUN_IS_DATAGRAM) && msg_len != pdu_len)) 1478 { 1479 return PJLIB_UTIL_ESTUNINMSGLEN; 1480 } 1481 1482 /* Check if FINGERPRINT attribute is present */ 1483 if (GET_VAL16(pdu, msg_len + 20) == PJ_STUN_ATTR_FINGERPRINT) { 1484 pj_uint16_t attr_len = GET_VAL16(pdu, msg_len + 22); 1485 pj_uint32_t fingerprint = GET_VAL32(pdu, msg_len + 24); 1486 pj_uint32_t crc; 1487 1488 if (attr_len != 4) 1489 return PJLIB_UTIL_ESTUNINATTRLEN; 1490 1491 crc = pj_crc32_calc(pdu, msg_len + 20); 1492 crc ^= STUN_XOR_FINGERPRINT; 1493 1494 if (crc != fingerprint) 1495 return PJLIB_UTIL_ESTUNFINGERPRINT; 1477 if (GET_VAL32(pdu, 4) == PJ_STUN_MAGIC) { 1478 1479 /* Check if FINGERPRINT attribute is present */ 1480 if (GET_VAL16(pdu, msg_len + 20) == PJ_STUN_ATTR_FINGERPRINT) { 1481 pj_uint16_t attr_len = GET_VAL16(pdu, msg_len + 22); 1482 pj_uint32_t fingerprint = GET_VAL32(pdu, msg_len + 24); 1483 pj_uint32_t crc; 1484 1485 if (attr_len != 4) 1486 return PJLIB_UTIL_ESTUNINATTRLEN; 1487 1488 crc = pj_crc32_calc(pdu, msg_len + 20); 1489 crc ^= STUN_XOR_FINGERPRINT; 1490 1491 if (crc != fingerprint) 1492 return PJLIB_UTIL_ESTUNFINGERPRINT; 1493 } 1496 1494 } 1497 1495 … … 1820 1818 * Print the message structure to a buffer. 1821 1819 */ 1822 PJ_DEF(pj_status_t) pj_stun_msg_encode( constpj_stun_msg *msg,1820 PJ_DEF(pj_status_t) pj_stun_msg_encode(pj_stun_msg *msg, 1823 1821 pj_uint8_t *buf, unsigned buf_size, 1824 1822 unsigned options, … … 1834 1832 unsigned printed; 1835 1833 pj_status_t status; 1836 unsigned i , length;1834 unsigned i; 1837 1835 1838 1836 … … 1899 1897 */ 1900 1898 if (amsg_integrity && afingerprint) { 1901 length = (pj_uint16_t)((buf - start) - 20 + 24 + 8);1899 msg->hdr.length = (pj_uint16_t)((buf - start) - 20 + 24 + 8); 1902 1900 } else if (amsg_integrity) { 1903 length = (pj_uint16_t)((buf - start) - 20 + 24);1901 msg->hdr.length = (pj_uint16_t)((buf - start) - 20 + 24); 1904 1902 } else if (afingerprint) { 1905 length = (pj_uint16_t)((buf - start) - 20 + 8);1903 msg->hdr.length = (pj_uint16_t)((buf - start) - 20 + 8); 1906 1904 } else { 1907 length = (pj_uint16_t)((buf - start) - 20);1905 msg->hdr.length = (pj_uint16_t)((buf - start) - 20); 1908 1906 } 1909 1907 1910 1908 /* hdr->length = pj_htons(length); */ 1911 *(buf+2) = (pj_uint8_t)((length >> 8) & 0x00FF);1912 *(buf+3) = (pj_uint8_t)(length & 0x00FF);1909 start[2] = (pj_uint8_t)((msg->hdr.length >> 8) & 0x00FF); 1910 start[3] = (pj_uint8_t)(msg->hdr.length & 0x00FF); 1913 1911 1914 1912 /* Calculate message integrity, if present */ … … 2089 2087 *p_response = NULL; 2090 2088 2091 if ( PJ_STUN_IS_REQUEST(msg->hdr.type))2089 if (!PJ_STUN_IS_REQUEST(msg->hdr.type)) 2092 2090 p_response = NULL; 2093 2091 -
pjproject/trunk/pjlib-util/src/pjlib-util/stun_session.c
r1008 r1021 24 24 pj_stun_endpoint *endpt; 25 25 pj_pool_t *pool; 26 pj_mutex_t *mutex; 26 27 pj_stun_session_cb cb; 27 28 void *user_data; … … 48 49 49 50 #if PJ_LOG_MAX_LEVEL >= 4 50 # define LOG_ERR_(sess, title, rc) 51 # define LOG_ERR_(sess, title, rc) stun_perror(sess, title, rc) 51 52 static void stun_perror(pj_stun_session *sess, const char *title, 52 53 pj_status_t status) … … 60 61 61 62 #else 62 # define ERR_(sess, title, rc)63 # define LOG_ERR_(sess, title, rc) 63 64 #endif 64 65 … … 116 117 117 118 static pj_status_t create_tdata(pj_stun_session *sess, 118 unsigned msg_type,119 119 void *user_data, 120 120 pj_stun_tx_data **p_tdata) 121 121 { 122 122 pj_pool_t *pool; 123 pj_status_t status;124 123 pj_stun_tx_data *tdata; 125 124 … … 134 133 tdata->user_data = user_data; 135 134 135 *p_tdata = tdata; 136 137 return PJ_SUCCESS; 138 } 139 140 static pj_status_t create_request_tdata(pj_stun_session *sess, 141 unsigned msg_type, 142 void *user_data, 143 pj_stun_tx_data **p_tdata) 144 { 145 pj_status_t status; 146 pj_stun_tx_data *tdata; 147 148 status = create_tdata(sess, user_data, &tdata); 149 if (status != PJ_SUCCESS) 150 return status; 151 136 152 /* Create STUN message */ 137 status = pj_stun_msg_create( pool, msg_type, PJ_STUN_MAGIC,153 status = pj_stun_msg_create(tdata->pool, msg_type, PJ_STUN_MAGIC, 138 154 NULL, &tdata->msg); 139 155 if (status != PJ_SUCCESS) { 140 pj_pool_release(pool); 141 return status; 142 } 143 144 /* If this is a request, then copy the request's transaction ID 145 * as the transaction key. 146 */ 147 if (PJ_STUN_IS_REQUEST(msg_type)) { 148 pj_assert(sizeof(tdata->client_key)==sizeof(tdata->msg->hdr.tsx_id)); 149 pj_memcpy(tdata->client_key, tdata->msg->hdr.tsx_id, 150 sizeof(tdata->msg->hdr.tsx_id)); 151 } 156 pj_pool_release(tdata->pool); 157 return status; 158 } 159 160 /* copy the request's transaction ID as the transaction key. */ 161 pj_assert(sizeof(tdata->client_key)==sizeof(tdata->msg->hdr.tsx_id)); 162 pj_memcpy(tdata->client_key, tdata->msg->hdr.tsx_id, 163 sizeof(tdata->msg->hdr.tsx_id)); 152 164 153 165 *p_tdata = tdata; … … 167 179 } 168 180 169 static pj_status_t session_apply_req(pj_stun_session *sess, 181 /* 182 * Destroy the transmit data. 183 */ 184 PJ_DEF(void) pj_stun_msg_destroy_tdata( pj_stun_session *sess, 185 pj_stun_tx_data *tdata) 186 { 187 PJ_UNUSED_ARG(sess); 188 destroy_tdata(tdata); 189 } 190 191 static pj_status_t apply_msg_options(pj_stun_session *sess, 170 192 pj_pool_t *pool, 171 193 unsigned options, 172 pj_stun_msg *msg) 194 pj_stun_msg *msg, 195 pj_str_t **p_passwd) 173 196 { 174 197 pj_status_t status; … … 182 205 pj_stun_generic_string_attr *arealm; 183 206 207 *p_passwd = &sess->l_password; 208 184 209 /* Create and add USERNAME attribute */ 185 status = pj_stun_generic_string_attr_create( sess->pool,210 status = pj_stun_generic_string_attr_create(pool, 186 211 PJ_STUN_ATTR_USERNAME, 187 212 &sess->l_username, … … 193 218 194 219 /* Add REALM only when long term credential is used */ 195 status = pj_stun_generic_string_attr_create( sess->pool,220 status = pj_stun_generic_string_attr_create(pool, 196 221 PJ_STUN_ATTR_REALM, 197 222 &sess->l_realm, … … 203 228 204 229 /* Add MESSAGE-INTEGRITY attribute */ 205 status = pj_stun_msg_integrity_attr_create( sess->pool, &amsgi);230 status = pj_stun_msg_integrity_attr_create(pool, &amsgi); 206 231 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 207 232 208 233 status = pj_stun_msg_add_attr(msg, &amsgi->hdr); 209 234 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 210 211 PJ_TODO(COMPUTE_MESSAGE_INTEGRITY1);212 235 213 236 } else if (options & PJ_STUN_USE_SHORT_TERM_CRED) { … … 215 238 pj_stun_msg_integrity_attr *amsgi; 216 239 240 *p_passwd = &sess->s_password; 241 217 242 /* Create and add USERNAME attribute */ 218 status = pj_stun_generic_string_attr_create( sess->pool,243 status = pj_stun_generic_string_attr_create(pool, 219 244 PJ_STUN_ATTR_USERNAME, 220 245 &sess->s_username, … … 226 251 227 252 /* Add MESSAGE-INTEGRITY attribute */ 228 status = pj_stun_msg_integrity_attr_create( sess->pool, &amsgi);253 status = pj_stun_msg_integrity_attr_create(pool, &amsgi); 229 254 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 230 255 … … 232 257 PJ_ASSERT_RETURN(status==PJ_SUCCESS, status); 233 258 234 PJ_TODO(COMPUTE_MESSAGE_INTEGRITY2); 259 } else { 260 *p_passwd = NULL; 235 261 } 236 262 … … 239 265 pj_stun_fingerprint_attr *af; 240 266 241 status = pj_stun_generic_uint_attr_create( sess->pool,267 status = pj_stun_generic_uint_attr_create(pool, 242 268 PJ_STUN_ATTR_FINGERPRINT, 243 269 0, &af); … … 260 286 tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); 261 287 262 switch (PJ_STUN_GET_METHOD(tdata->msg->hdr.type)) { 263 case PJ_STUN_BINDING_METHOD: 264 tdata->sess->cb.on_bind_response(tdata->sess, status, tdata, response); 265 break; 266 case PJ_STUN_ALLOCATE_METHOD: 267 tdata->sess->cb.on_allocate_response(tdata->sess, status, 268 tdata, response); 269 break; 270 case PJ_STUN_SET_ACTIVE_DESTINATION_METHOD: 271 tdata->sess->cb.on_set_active_destination_response(tdata->sess, status, 272 tdata, response); 273 break; 274 case PJ_STUN_CONNECT_METHOD: 275 tdata->sess->cb.on_connect_response(tdata->sess, status, tdata, 276 response); 277 break; 278 default: 279 pj_assert(!"Unknown method"); 280 break; 288 if (tdata->sess->cb.on_request_complete) { 289 (*tdata->sess->cb.on_request_complete)(tdata->sess, status, tdata, 290 response); 281 291 } 282 292 } … … 290 300 tdata = (pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx); 291 301 292 return tdata->sess->cb.on_send_msg(tdata , stun_pkt, pkt_size,293 tdata-> addr_len, tdata->dst_addr);302 return tdata->sess->cb.on_send_msg(tdata->sess, stun_pkt, pkt_size, 303 tdata->dst_addr, tdata->addr_len); 294 304 } 295 305 … … 303 313 pj_pool_t *pool; 304 314 pj_stun_session *sess; 315 pj_status_t status; 305 316 306 317 PJ_ASSERT_RETURN(endpt && cb && p_sess, PJ_EINVAL); 318 319 if (name==NULL) 320 name = "sess%p"; 307 321 308 322 pool = pj_pool_create(endpt->pf, name, 4000, 4000, NULL); … … 316 330 pj_list_init(&sess->pending_request_list); 317 331 332 status = pj_mutex_create_recursive(pool, name, &sess->mutex); 333 if (status != PJ_SUCCESS) { 334 pj_pool_release(pool); 335 return status; 336 } 337 318 338 *p_sess = sess; 319 339 320 PJ_TODO(MUTEX_PROTECTION);321 322 340 return PJ_SUCCESS; 323 341 } … … 327 345 PJ_ASSERT_RETURN(sess, PJ_EINVAL); 328 346 347 pj_mutex_destroy(sess->mutex); 329 348 pj_pool_release(sess->pool); 330 349 … … 337 356 { 338 357 PJ_ASSERT_RETURN(sess, PJ_EINVAL); 358 pj_mutex_lock(sess->mutex); 339 359 sess->user_data = user_data; 360 pj_mutex_unlock(sess->mutex); 340 361 return PJ_SUCCESS; 341 362 } … … 356 377 357 378 PJ_ASSERT_RETURN(sess, PJ_EINVAL); 379 380 pj_mutex_lock(sess->mutex); 358 381 pj_strdup_with_null(sess->pool, &sess->l_realm, realm ? realm : &nil); 359 382 pj_strdup_with_null(sess->pool, &sess->l_username, user ? user : &nil); 360 383 pj_strdup_with_null(sess->pool, &sess->l_password, passwd ? passwd : &nil); 384 pj_mutex_unlock(sess->mutex); 361 385 362 386 return PJ_SUCCESS; … … 372 396 373 397 PJ_ASSERT_RETURN(sess, PJ_EINVAL); 398 399 pj_mutex_lock(sess->mutex); 374 400 pj_strdup_with_null(sess->pool, &sess->s_username, user ? user : &nil); 375 401 pj_strdup_with_null(sess->pool, &sess->s_password, passwd ? passwd : &nil); 402 pj_mutex_unlock(sess->mutex); 376 403 377 404 return PJ_SUCCESS; … … 387 414 PJ_ASSERT_RETURN(sess && p_tdata, PJ_EINVAL); 388 415 389 status = create_tdata(sess, PJ_STUN_BINDING_REQUEST, NULL, &tdata); 416 status = create_request_tdata(sess, PJ_STUN_BINDING_REQUEST, NULL, 417 &tdata); 390 418 if (status != PJ_SUCCESS) 391 419 return status; … … 398 426 pj_stun_tx_data **p_tdata) 399 427 { 428 PJ_UNUSED_ARG(sess); 429 PJ_UNUSED_ARG(p_tdata); 400 430 PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 401 431 } … … 406 436 pj_stun_tx_data **p_tdata) 407 437 { 438 PJ_UNUSED_ARG(sess); 439 PJ_UNUSED_ARG(p_tdata); 408 440 PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 409 441 } … … 412 444 pj_stun_tx_data **p_tdata) 413 445 { 446 PJ_UNUSED_ARG(sess); 447 PJ_UNUSED_ARG(p_tdata); 414 448 PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 415 449 } … … 419 453 pj_stun_tx_data **p_tdata) 420 454 { 455 PJ_UNUSED_ARG(sess); 456 PJ_UNUSED_ARG(p_tdata); 421 457 PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 422 458 } … … 425 461 pj_stun_tx_data **p_tdata) 426 462 { 463 PJ_UNUSED_ARG(sess); 464 PJ_UNUSED_ARG(p_tdata); 427 465 PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 428 466 } … … 431 469 pj_stun_tx_data **p_tdata) 432 470 { 471 PJ_UNUSED_ARG(sess); 472 PJ_UNUSED_ARG(p_tdata); 433 473 PJ_ASSERT_RETURN(PJ_FALSE, PJ_ENOTSUP); 434 474 } 475 476 477 /* 478 * Create a STUN response message. 479 */ 480 PJ_DEF(pj_status_t) pj_stun_session_create_response( pj_stun_session *sess, 481 const pj_stun_msg *req, 482 unsigned err_code, 483 const pj_str_t *err_msg, 484 pj_stun_tx_data **p_tdata) 485 { 486 pj_status_t status; 487 pj_stun_tx_data *tdata; 488 489 status = create_tdata(sess, NULL, &tdata); 490 if (status != PJ_SUCCESS) 491 return status; 492 493 /* Create STUN response message */ 494 status = pj_stun_msg_create_response(tdata->pool, req, err_code, err_msg, 495 &tdata->msg); 496 if (status != PJ_SUCCESS) { 497 pj_pool_release(tdata->pool); 498 return status; 499 } 500 501 /* copy the request's transaction ID as the transaction key. */ 502 pj_assert(sizeof(tdata->client_key)==sizeof(req->hdr.tsx_id)); 503 pj_memcpy(tdata->client_key, req->hdr.tsx_id, sizeof(req->hdr.tsx_id)); 504 505 *p_tdata = tdata; 506 507 return PJ_SUCCESS; 508 } 509 510 511 /* Print outgoing message to log */ 512 static void dump_tx_msg(pj_stun_session *sess, const pj_stun_msg *msg, 513 unsigned pkt_size, const pj_sockaddr_t *addr) 514 { 515 const char *dst_name; 516 int dst_port; 517 const pj_sockaddr *dst = (const pj_sockaddr*)addr; 518 char buf[512]; 519 520 if (dst->sa_family == PJ_AF_INET) { 521 const pj_sockaddr_in *dst4 = (const pj_sockaddr_in*)dst; 522 dst_name = pj_inet_ntoa(dst4->sin_addr); 523 dst_port = pj_ntohs(dst4->sin_port); 524 } else if (dst->sa_family == PJ_AF_INET6) { 525 const pj_sockaddr_in6 *dst6 = (const pj_sockaddr_in6*)dst; 526 dst_name = "IPv6"; 527 dst_port = pj_ntohs(dst6->sin6_port); 528 } else { 529 LOG_ERR_(sess, "Invalid address family", PJ_EINVAL); 530 return; 531 } 532 533 PJ_LOG(5,(SNAME(sess), 534 "TX %d bytes STUN message to %s:%d:\n" 535 "--- begin STUN message ---\n" 536 "%s" 537 "--- end of STUN message ---\n", 538 pkt_size, dst_name, dst_port, 539 pj_stun_msg_dump(msg, buf, sizeof(buf), NULL))); 540 541 } 542 435 543 436 544 PJ_DEF(pj_status_t) pj_stun_session_send_msg( pj_stun_session *sess, 437 545 unsigned options, 546 const pj_sockaddr_t *server, 438 547 unsigned addr_len, 439 const pj_sockaddr_t *server,440 548 pj_stun_tx_data *tdata) 441 549 { 550 pj_str_t *password; 442 551 pj_status_t status; 443 552 … … 448 557 tdata->pkt = pj_pool_alloc(tdata->pool, tdata->max_len); 449 558 450 if (PJ_LOG_MAX_LEVEL >= 5) { 451 char *buf = (char*) tdata->pkt; 452 const char *dst_name; 453 int dst_port; 454 const pj_sockaddr *dst = (const pj_sockaddr*)server; 455 456 if (dst->sa_family == PJ_AF_INET) { 457 const pj_sockaddr_in *dst4 = (const pj_sockaddr_in*)dst; 458 dst_name = pj_inet_ntoa(dst4->sin_addr); 459 dst_port = pj_ntohs(dst4->sin_port); 460 } else if (dst->sa_family == PJ_AF_INET6) { 461 const pj_sockaddr_in6 *dst6 = (const pj_sockaddr_in6*)dst; 462 dst_name = "IPv6"; 463 dst_port = pj_ntohs(dst6->sin6_port); 464 } else { 465 LOG_ERR_(sess, "Invalid address family", PJ_EINVAL); 466 return PJ_EINVAL; 467 } 468 469 PJ_LOG(5,(SNAME(sess), 470 "Sending STUN message to %s:%d:\n" 471 "--- begin STUN message ---\n" 472 "%s" 473 "--- end of STUN message ---\n", 474 dst_name, dst_port, 475 pj_stun_msg_dump(tdata->msg, buf, tdata->max_len, NULL))); 476 } 559 /* Start locking the session now */ 560 pj_mutex_lock(sess->mutex); 477 561 478 562 /* Apply options */ 479 status = session_apply_req(sess, tdata->pool, options, tdata->msg); 563 status = apply_msg_options(sess, tdata->pool, options, 564 tdata->msg, &password); 480 565 if (status != PJ_SUCCESS) { 566 pj_stun_msg_destroy_tdata(sess, tdata); 567 pj_mutex_unlock(sess->mutex); 481 568 LOG_ERR_(sess, "Error applying options", status); 482 destroy_tdata(tdata);483 569 return status; 484 570 } … … 488 574 0, NULL, &tdata->pkt_size); 489 575 if (status != PJ_SUCCESS) { 576 pj_stun_msg_destroy_tdata(sess, tdata); 577 pj_mutex_unlock(sess->mutex); 490 578 LOG_ERR_(sess, "STUN encode() error", status); 491 destroy_tdata(tdata); 492 return status; 493 } 579 return status; 580 } 581 582 /* Dump packet */ 583 dump_tx_msg(sess, tdata->msg, tdata->pkt_size, server); 494 584 495 585 /* If this is a STUN request message, then send the request with … … 512 602 tdata->pkt, tdata->pkt_size); 513 603 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 604 pj_stun_msg_destroy_tdata(sess, tdata); 605 pj_mutex_unlock(sess->mutex); 514 606 LOG_ERR_(sess, "Error sending STUN request", status); 515 destroy_tdata(tdata);516 607 return status; 517 608 } … … 522 613 } else { 523 614 /* Otherwise for non-request message, send directly to transport. */ 524 status = sess->cb.on_send_msg( tdata, tdata->pkt, tdata->pkt_size,525 addr_len, server);615 status = sess->cb.on_send_msg(sess, tdata->pkt, tdata->pkt_size, 616 server, addr_len); 526 617 527 618 if (status != PJ_SUCCESS && status != PJ_EPENDING) { 528 619 LOG_ERR_(sess, "Error sending STUN request", status); 529 destroy_tdata(tdata);530 return status;531 620 } 532 } 533 534 621 622 /* Destroy */ 623 pj_stun_msg_destroy_tdata(sess, tdata); 624 } 625 626 627 pj_mutex_unlock(sess->mutex); 535 628 return status; 629 } 630 631 632 /* Handle incoming response */ 633 static pj_status_t on_incoming_response(pj_stun_session *sess, 634 pj_stun_msg *msg) 635 { 636 pj_stun_tx_data *tdata; 637 pj_status_t status; 638 639 /* Lookup pending client transaction */ 640 tdata = tsx_lookup(sess, msg); 641 if (tdata == NULL) { 642 LOG_ERR_(sess, "STUN error finding transaction", PJ_ENOTFOUND); 643 return PJ_ENOTFOUND; 644 } 645 646 /* Pass the response to the transaction. 647 * If the message is accepted, transaction callback will be called, 648 * and this will call the session callback too. 649 */ 650 status = pj_stun_client_tsx_on_rx_msg(tdata->client_tsx, msg); 651 if (status != PJ_SUCCESS) { 652 return status; 653 } 654 655 /* If transaction has completed, destroy the transmit data. 656 * This will remove the transaction from the pending list too. 657 */ 658 if (pj_stun_client_tsx_is_complete(tdata->client_tsx)) { 659 pj_stun_msg_destroy_tdata(sess, tdata); 660 tdata = NULL; 661 } 662 663 return PJ_SUCCESS; 664 } 665 666 667 /* Send response */ 668 static pj_status_t send_response(pj_stun_session *sess, unsigned options, 669 pj_pool_t *pool, pj_stun_msg *response, 670 const pj_sockaddr_t *addr, unsigned addr_len) 671 { 672 pj_uint8_t *out_pkt; 673 unsigned out_max_len, out_len; 674 pj_str_t *passwd; 675 pj_status_t status; 676 677 /* Alloc packet buffer */ 678 out_max_len = PJ_STUN_MAX_PKT_LEN; 679 out_pkt = pj_pool_alloc(pool, out_max_len); 680 681 /* Apply options */ 682 apply_msg_options(sess, pool, options, response, &passwd); 683 684 /* Encode */ 685 status = pj_stun_msg_encode(response, out_pkt, out_max_len, 0, 686 passwd, &out_len); 687 if (status != PJ_SUCCESS) { 688 LOG_ERR_(sess, "Error encoding message", status); 689 return status; 690 } 691 692 /* Print log */ 693 dump_tx_msg(sess, response, out_len, addr); 694 695 /* Send packet */ 696 status = sess->cb.on_send_msg(sess, out_pkt, out_len, addr, addr_len); 697 698 return status; 699 } 700 701 /* Handle incoming request */ 702 static pj_status_t on_incoming_request(pj_stun_session *sess, 703 pj_pool_t *tmp_pool, 704 const pj_uint8_t *in_pkt, 705 unsigned in_pkt_len, 706 const pj_stun_msg *msg, 707 const pj_sockaddr_t *src_addr, 708 unsigned src_addr_len) 709 { 710 pj_status_t status; 711 712 /* Distribute to handler, or respond with Bad Request */ 713 if (sess->cb.on_rx_request) { 714 status = (*sess->cb.on_rx_request)(sess, in_pkt, in_pkt_len, msg, 715 src_addr, src_addr_len); 716 } else { 717 pj_stun_msg *response = NULL; 718 719 status = pj_stun_msg_create_response(tmp_pool, msg, 720 PJ_STUN_STATUS_BAD_REQUEST, NULL, 721 &response); 722 if (status == PJ_SUCCESS && response) { 723 status = send_response(sess, 0, tmp_pool, response, 724 src_addr, src_addr_len); 725 } 726 } 727 728 return status; 729 } 730 731 732 /* Handle incoming indication */ 733 static pj_status_t on_incoming_indication(pj_stun_session *sess, 734 pj_pool_t *tmp_pool, 735 const pj_uint8_t *in_pkt, 736 unsigned in_pkt_len, 737 const pj_stun_msg *msg, 738 const pj_sockaddr_t *src_addr, 739 unsigned src_addr_len) 740 { 741 PJ_UNUSED_ARG(tmp_pool); 742 743 /* Distribute to handler */ 744 if (sess->cb.on_rx_indication) { 745 return (*sess->cb.on_rx_indication)(sess, in_pkt, in_pkt_len, msg, 746 src_addr, src_addr_len); 747 } else { 748 return PJ_SUCCESS; 749 } 536 750 } 537 751 … … 540 754 const void *packet, 541 755 pj_size_t pkt_size, 542 unsigned *parsed_len) 756 unsigned options, 757 unsigned *parsed_len, 758 const pj_sockaddr_t *src_addr, 759 unsigned src_addr_len) 543 760 { 544 761 pj_stun_msg *msg, *response; … … 555 772 /* Try to parse the message */ 556 773 status = pj_stun_msg_decode(tmp_pool, (const pj_uint8_t*)packet, 557 pkt_size, 0, &msg, parsed_len,558 & response);774 pkt_size, options, 775 &msg, parsed_len, &response); 559 776 if (status != PJ_SUCCESS) { 560 777 LOG_ERR_(sess, "STUN msg_decode() error", status); 561 778 if (response) { 562 PJ_TODO(SEND_RESPONSE); 779 send_response(sess, 0, tmp_pool, response, 780 src_addr, src_addr_len); 563 781 } 564 782 pj_pool_release(tmp_pool); … … 568 786 dump = pj_pool_alloc(tmp_pool, PJ_STUN_MAX_PKT_LEN); 569 787 570 PJ_LOG(4,(SNAME(sess), 788 PJ_LOG(4,(SNAME(sess), 571 789 "RX STUN message:\n" 572 "--- begin STUN message --- "790 "--- begin STUN message ---\n" 573 791 "%s" 574 792 "--- end of STUN message ---\n", 575 793 pj_stun_msg_dump(msg, dump, PJ_STUN_MAX_PKT_LEN, NULL))); 576 794 795 pj_mutex_lock(sess->mutex); 577 796 578 797 if (PJ_STUN_IS_RESPONSE(msg->hdr.type) || 579 798 PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) 580 799 { 581 pj_stun_tx_data *tdata; 582 583 /* Lookup pending client transaction */ 584 tdata = tsx_lookup(sess, msg); 585 if (tdata == NULL) { 586 LOG_ERR_(sess, "STUN error finding transaction", PJ_ENOTFOUND); 587 pj_pool_release(tmp_pool); 588 return PJ_ENOTFOUND; 589 } 590 591 /* Pass the response to the transaction. 592 * If the message is accepted, transaction callback will be called, 593 * and this will call the session callback too. 594 */ 595 status = pj_stun_client_tsx_on_rx_msg(tdata->client_tsx, msg); 596 if (status != PJ_SUCCESS) { 597 pj_pool_release(tmp_pool); 598 return status; 599 } 600 601 /* If transaction has completed, destroy the transmit data. 602 * This will remove the transaction from the pending list too. 603 */ 604 if (pj_stun_client_tsx_is_complete(tdata->client_tsx)) { 605 destroy_tdata(tdata); 606 tdata = NULL; 607 } 608 609 pj_pool_release(tmp_pool); 610 return PJ_SUCCESS; 800 status = on_incoming_response(sess, msg); 611 801 612 802 } else if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { 613 803 614 PJ_TODO(HANDLE_INCOMING_STUN_REQUEST); 804 status = on_incoming_request(sess, tmp_pool, packet, pkt_size, msg, 805 src_addr, src_addr_len); 615 806 616 807 } else if (PJ_STUN_IS_INDICATION(msg->hdr.type)) { 617 808 618 PJ_TODO(HANDLE_INCOMING_STUN_INDICATION); 809 status = on_incoming_indication(sess, tmp_pool, packet, pkt_size, 810 msg, src_addr, src_addr_len); 619 811 620 812 } else { 621 813 pj_assert(!"Unexpected!"); 622 } 814 status = PJ_EBUG; 815 } 816 817 pj_mutex_unlock(sess->mutex); 623 818 624 819 pj_pool_release(tmp_pool); 625 return PJ_ENOTSUP; 626 } 627 820 return status; 821 } 822 823 -
pjproject/trunk/pjlib-util/src/pjstun-srv-test/server_main.c
r1004 r1021 19 19 #include <pjlib-util.h> 20 20 #include <pjlib.h> 21 #include "server.h"22 21 23 22 #include <stdio.h> … … 27 26 #define THIS_FILE "server_main.c" 28 27 #define MAX_THREADS 8 29 30 struct stun_server_tag server; 31 32 33 pj_status_t server_perror(const char *sender, const char *title, 34 pj_status_t status) 28 #define MAX_SERVICE 16 29 #define MAX_PKT_LEN 512 30 31 struct service 32 { 33 unsigned index; 34 pj_uint16_t port; 35 pj_bool_t is_stream; 36 pj_sock_t sock; 37 pj_ioqueue_key_t *key; 38 pj_ioqueue_op_key_t recv_opkey, 39 send_opkey; 40 41 pj_stun_session *sess; 42 43 int src_addr_len; 44 pj_sockaddr_in src_addr; 45 pj_ssize_t rx_pkt_len; 46 pj_uint8_t rx_pkt[MAX_PKT_LEN]; 47 pj_uint8_t tx_pkt[MAX_PKT_LEN]; 48 }; 49 50 static struct stun_server 51 { 52 pj_caching_pool cp; 53 pj_pool_t *pool; 54 pj_stun_endpoint *endpt; 55 pj_ioqueue_t *ioqueue; 56 pj_timer_heap_t *timer_heap; 57 unsigned service_cnt; 58 struct service services[MAX_SERVICE]; 59 60 pj_bool_t thread_quit_flag; 61 unsigned thread_cnt; 62 pj_thread_t *threads[16]; 63 64 } server; 65 66 67 static pj_status_t server_perror(const char *sender, const char *title, 68 pj_status_t status) 35 69 { 36 70 char errmsg[PJ_ERR_MSG_SIZE]; … … 43 77 44 78 45 static pj_status_t create_response(pj_pool_t *pool, 46 const pj_stun_msg *req_msg, 47 unsigned err_code, 48 unsigned uattr_cnt, 49 pj_uint16_t uattr_types[], 50 pj_stun_msg **p_response) 51 { 52 pj_uint32_t msg_type = req_msg->hdr.type; 53 pj_stun_msg *response; 54 pj_status_t status; 55 56 status = pj_stun_msg_create_response(pool, req_msg, err_code, NULL, 57 &response); 58 if (status != PJ_SUCCESS) 59 return status; 60 61 /* Add unknown_attribute attributes if err_code is 420 */ 62 if (err_code == PJ_STUN_STATUS_UNKNOWN_ATTRIBUTE) { 63 pj_stun_unknown_attr *uattr; 64 65 status = pj_stun_unknown_attr_create(pool, uattr_cnt, uattr_types, 66 &uattr); 67 if (status != PJ_SUCCESS) 68 return status; 69 70 pj_stun_msg_add_attr(response, &uattr->hdr); 71 } 72 73 *p_response = response; 74 return PJ_SUCCESS; 75 } 76 77 78 static pj_status_t send_msg(struct service *svc, const pj_stun_msg *msg) 79 { 80 unsigned tx_pkt_len; 79 /* Callback to be called to send outgoing message */ 80 static pj_status_t on_send_msg(pj_stun_session *sess, 81 const void *pkt, 82 pj_size_t pkt_size, 83 const pj_sockaddr_t *dst_addr, 84 unsigned addr_len) 85 { 86 struct service *svc; 81 87 pj_ssize_t length; 82 88 pj_status_t status; 83 89 84 /* Print to log */ 85 PJ_LOG(4,(THIS_FILE, "TX STUN message: \n" 86 "--- begin STUN message ---\n" 87 "%s" 88 "--- end of STUN message ---\n", 89 pj_stun_msg_dump(msg, svc->tx_pkt, sizeof(svc->tx_pkt), NULL))); 90 91 /* Encode packet */ 92 tx_pkt_len = sizeof(svc->tx_pkt); 93 status = pj_stun_msg_encode(msg, svc->tx_pkt, tx_pkt_len, 0, 94 NULL, &tx_pkt_len); 95 if (status != PJ_SUCCESS) 96 return status; 97 98 length = tx_pkt_len; 90 svc = (struct service*) pj_stun_session_get_user_data(sess); 99 91 100 92 /* Send packet */ 93 length = pkt_size; 101 94 if (svc->is_stream) { 102 status = pj_ioqueue_send(svc->key, &svc->send_opkey, svc->tx_pkt, 103 &length, 0); 95 status = pj_ioqueue_send(svc->key, &svc->send_opkey, pkt, &length, 0); 104 96 } else { 105 status = pj_ioqueue_sendto(svc->key, &svc->send_opkey, svc->tx_pkt, 106 &length, 0, &svc->src_addr, 107 svc->src_addr_len); 108 } 109 110 PJ_LOG(4,(THIS_FILE, "Sending STUN %s %s", 111 pj_stun_get_method_name(msg->hdr.type), 112 pj_stun_get_class_name(msg->hdr.type))); 97 #if 0 98 pj_pool_t *pool; 99 char *buf; 100 pj_stun_msg *msg; 101 102 pool = pj_pool_create(&server.cp.factory, "", 4000, 4000, NULL); 103 status = pj_stun_msg_decode(pool, pkt, pkt_size, PJ_STUN_CHECK_PACKET, &msg, NULL, NULL); 104 buf = pj_pool_alloc(pool, 512); 105 PJ_LOG(3,("", "%s", pj_stun_msg_dump(msg, buf, 512, NULL))); 106 #endif 107 status = pj_ioqueue_sendto(svc->key, &svc->send_opkey, pkt, &length, 108 0, dst_addr, addr_len); 109 } 113 110 114 111 return (status == PJ_SUCCESS || status == PJ_EPENDING) ? … … 117 114 118 115 119 static pj_status_t err_respond(struct service *svc, 120 pj_pool_t *pool, 121 const pj_stun_msg *req_msg, 122 unsigned err_code, 123 unsigned uattr_cnt, 124 pj_uint16_t uattr_types[]) 125 { 126 pj_stun_msg *response; 127 pj_status_t status; 128 129 /* Create the error response */ 130 status = create_response(pool, req_msg, err_code, 131 uattr_cnt, uattr_types, &response); 116 /* Handle STUN binding request */ 117 static pj_status_t on_rx_binding_request(pj_stun_session *sess, 118 const pj_uint8_t *pkt, 119 unsigned pkt_len, 120 const pj_stun_msg *msg, 121 const pj_sockaddr_t *src_addr, 122 unsigned src_addr_len) 123 { 124 struct service *svc = (struct service *) pj_stun_session_get_user_data(sess); 125 pj_stun_tx_data *tdata; 126 pj_stun_auth_policy pol; 127 pj_status_t status; 128 129 /* Create response */ 130 status = pj_stun_session_create_response(sess, msg, 0, NULL, &tdata); 131 if (status != PJ_SUCCESS) 132 return status; 133 134 #if 1 135 pj_memset(&pol, 0, sizeof(pol)); 136 pol.type = PJ_STUN_POLICY_STATIC_LONG_TERM; 137 pol.user_data = NULL; 138 pol.data.static_long_term.realm = pj_str("realm"); 139 pol.data.static_long_term.username = pj_str("user"); 140 pol.data.static_long_term.password = pj_str("password"); 141 pol.data.static_long_term.nonce = pj_str("nonce"); 142 status = pj_stun_verify_credential(pkt, pkt_len, msg, &pol, tdata->pool, 143 &tdata->msg); 144 if (!tdata->msg) 145 return status; 146 #endif 147 148 /* Create MAPPED-ADDRESS attribute */ 149 status = pj_stun_msg_add_generic_ip_addr_attr(tdata->pool, tdata->msg, 150 PJ_STUN_ATTR_MAPPED_ADDR, 151 PJ_FALSE, 152 src_addr, src_addr_len); 132 153 if (status != PJ_SUCCESS) { 133 154 server_perror(THIS_FILE, "Error creating response", status); 155 pj_stun_msg_destroy_tdata(sess, tdata); 134 156 return status; 135 157 } 136 158 137 /* Send response */138 status = send_msg(svc, response);139 if (status != PJ_SUCCESS) {140 server_perror(THIS_FILE, "Error sending response", status);141 return status;142 }143 144 return PJ_SUCCESS;145 }146 147 148 static void handle_binding_request(struct service *svc, pj_pool_t *pool,149 const pj_stun_msg *rx_msg)150 {151 pj_stun_msg *response;152 pj_stun_generic_ip_addr_attr *m_attr;153 pj_status_t status;154 155 status = create_response(pool, rx_msg, 0, 0, NULL, &response);156 if (status != PJ_SUCCESS) {157 server_perror(THIS_FILE, "Error creating response", status);158 return;159 }160 161 /* Create MAPPED-ADDRESS attribute */162 status = pj_stun_generic_ip_addr_attr_create(pool,163 PJ_STUN_ATTR_MAPPED_ADDR,164 PJ_FALSE,165 svc->src_addr_len,166 &svc->src_addr, &m_attr);167 if (status != PJ_SUCCESS) {168 server_perror(THIS_FILE, "Error creating response", status);169 return;170 }171 pj_stun_msg_add_attr(response, &m_attr->hdr);172 173 159 /* On the presence of magic, create XOR-MAPPED-ADDRESS attribute */ 174 if ( rx_msg->hdr.magic == PJ_STUN_MAGIC) {160 if (msg->hdr.magic == PJ_STUN_MAGIC) { 175 161 status = 176 pj_stun_generic_ip_addr_attr_create(pool, 177 PJ_STUN_ATTR_XOR_MAPPED_ADDRESS, 178 PJ_TRUE, 179 svc->src_addr_len, 180 &svc->src_addr, &m_attr); 162 pj_stun_msg_add_generic_ip_addr_attr(tdata->pool, tdata->msg, 163 PJ_STUN_ATTR_XOR_MAPPED_ADDRESS, 164 PJ_TRUE, 165 src_addr, src_addr_len); 181 166 if (status != PJ_SUCCESS) { 182 167 server_perror(THIS_FILE, "Error creating response", status); 183 return; 168 pj_stun_msg_destroy_tdata(sess, tdata); 169 return status; 184 170 } 185 171 } 186 172 187 173 /* Send */ 188 status = send_msg(svc, response); 189 if (status != PJ_SUCCESS) 190 server_perror(THIS_FILE, "Error sending response", status); 191 } 192 193 194 static void handle_unknown_request(struct service *svc, pj_pool_t *pool, 195 pj_stun_msg *rx_msg) 196 { 197 err_respond(svc, pool, rx_msg, PJ_STUN_STATUS_BAD_REQUEST, 0, NULL); 198 } 199 200 174 status = pj_stun_session_send_msg(sess, 0, src_addr, src_addr_len, tdata); 175 return status; 176 } 177 178 179 /* Handle unknown request */ 180 static pj_status_t on_rx_unknown_request(pj_stun_session *sess, 181 const pj_uint8_t *pkt, 182 unsigned pkt_len, 183 const pj_stun_msg *msg, 184 const pj_sockaddr_t *src_addr, 185 unsigned src_addr_len) 186 { 187 pj_stun_tx_data *tdata; 188 pj_status_t status; 189 190 /* Create response */ 191 status = pj_stun_session_create_response(sess, msg, 192 PJ_STUN_STATUS_BAD_REQUEST, 193 NULL, &tdata); 194 if (status != PJ_SUCCESS) 195 return status; 196 197 /* Send */ 198 status = pj_stun_session_send_msg(sess, 0, src_addr, src_addr_len, tdata); 199 return status; 200 } 201 202 /* Callback to be called by STUN session on incoming STUN requests */ 203 static pj_status_t on_rx_request(pj_stun_session *sess, 204 const pj_uint8_t *pkt, 205 unsigned pkt_len, 206 const pj_stun_msg *msg, 207 const pj_sockaddr_t *src_addr, 208 unsigned src_addr_len) 209 { 210 switch (PJ_STUN_GET_METHOD(msg->hdr.type)) { 211 case PJ_STUN_BINDING_METHOD: 212 return on_rx_binding_request(sess, pkt, pkt_len, msg, 213 src_addr, src_addr_len); 214 default: 215 return on_rx_unknown_request(sess, pkt, pkt_len, msg, 216 src_addr, src_addr_len); 217 } 218 } 219 220 221 /* Callback on ioqueue read completion */ 201 222 static void on_read_complete(pj_ioqueue_key_t *key, 202 223 pj_ioqueue_op_key_t *op_key, … … 204 225 { 205 226 struct service *svc = (struct service *) pj_ioqueue_get_user_data(key); 206 pj_pool_t *pool = NULL;207 pj_stun_msg *rx_msg, *response;208 char dump[512];209 227 pj_status_t status; 210 228 … … 212 230 goto next_read; 213 231 214 pool = pj_pool_create(&server.cp.factory, "service", 4000, 4000, NULL); 215 216 rx_msg = NULL; 217 status = pj_stun_msg_decode(pool, svc->rx_pkt, bytes_read, 0, &rx_msg, 218 NULL, &response); 232 /* Handle packet to session */ 233 status = pj_stun_session_on_rx_pkt(svc->sess, svc->rx_pkt, bytes_read, 234 PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET, 235 NULL, &svc->src_addr, svc->src_addr_len); 219 236 if (status != PJ_SUCCESS) { 220 server_perror(THIS_FILE, "STUN msg_decode() error", status); 221 if (response) { 222 send_msg(svc, response); 223 } 224 goto next_read; 225 } 226 227 PJ_LOG(4,(THIS_FILE, "RX STUN message: \n" 228 "--- begin STUN message ---\n" 229 "%s" 230 "--- end of STUN message ---\n", 231 pj_stun_msg_dump(rx_msg, dump, sizeof(dump), NULL))); 232 233 if (PJ_STUN_IS_REQUEST(rx_msg->hdr.type)) { 234 switch (rx_msg->hdr.type) { 235 case PJ_STUN_BINDING_REQUEST: 236 handle_binding_request(svc, pool, rx_msg); 237 break; 238 default: 239 handle_unknown_request(svc, pool, rx_msg); 240 } 241 237 server_perror(THIS_FILE, "Error processing incoming packet", status); 242 238 } 243 239 244 240 next_read: 245 if (pool != NULL)246 pj_pool_release(pool);247 248 241 if (bytes_read < 0) { 249 242 server_perror(THIS_FILE, "on_read_complete()", -bytes_read); … … 266 259 pj_status_t status; 267 260 pj_ioqueue_callback service_callback; 261 pj_stun_session_cb sess_cb; 268 262 pj_sockaddr_in addr; 269 263 … … 279 273 if (status != PJ_SUCCESS) 280 274 goto on_error; 275 276 pj_bzero(&sess_cb, sizeof(sess_cb)); 277 sess_cb.on_send_msg = &on_send_msg; 278 sess_cb.on_rx_request = &on_rx_request; 279 status = pj_stun_session_create(server.endpt, "session", 280 &sess_cb, &svc->sess); 281 if (status != PJ_SUCCESS) 282 goto on_error; 283 284 pj_stun_session_set_user_data(svc->sess, (void*)svc); 281 285 282 286 pj_bzero(&service_callback, sizeof(service_callback)); … … 317 321 while (!server.thread_quit_flag) { 318 322 pj_time_val timeout = { 0, 50 }; 323 pj_timer_heap_poll(server.timer_heap, NULL); 319 324 pj_ioqueue_poll(server.ioqueue, &timeout); 320 325 } … … 347 352 if (status != PJ_SUCCESS) 348 353 return server_perror(THIS_FILE, "pj_ioqueue_create()", status); 354 355 status = pj_timer_heap_create(server.pool, 1024, &server.timer_heap); 356 if (status != PJ_SUCCESS) 357 return server_perror(THIS_FILE, "Error creating timer heap", status); 358 359 status = pj_stun_endpoint_create(&server.cp.factory, 0, 360 server.ioqueue, server.timer_heap, 361 &server.endpt); 362 if (status != PJ_SUCCESS) 363 return server_perror(THIS_FILE, "Error creating endpoint", status); 349 364 350 365 server.service_cnt = 1; … … 362 377 pj_status_t server_main(void) 363 378 { 364 #if 1379 #if 0 365 380 for (;;) { 366 381 pj_time_val timeout = { 0, 50 }; 382 pj_timer_heap_poll(server.timer_heap, NULL); 367 383 pj_ioqueue_poll(server.ioqueue, &timeout); 368 384 … … 414 430 } 415 431 432 pj_stun_session_destroy(server.services[0].sess); 433 pj_stun_endpoint_destroy(server.endpt); 416 434 pj_ioqueue_destroy(server.ioqueue); 417 435 pj_pool_release(server.pool); 436 437 pj_pool_factory_dump(&server.cp.factory, PJ_TRUE); 418 438 pj_caching_pool_destroy(&server.cp); 419 439
Note: See TracChangeset
for help on using the changeset viewer.