- Timestamp:
- Mar 9, 2008 12:55:00 PM (17 years ago)
- Location:
- pjproject/trunk/pjnath
- Files:
-
- 2 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjnath/build/pjturn_srv.dsp
r1850 r1852 43 43 # PROP Target_Dir "" 44 44 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 45 # ADD CPP /nologo /MD /W 3/GX /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c45 # ADD CPP /nologo /MD /W4 /GX /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c 46 46 # ADD BASE RSC /l 0x409 /d "NDEBUG" 47 47 # ADD RSC /l 0x409 /d "NDEBUG" … … 67 67 # PROP Target_Dir "" 68 68 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c 69 # ADD CPP /nologo /MTd /W 3/Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c69 # ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c 70 70 # ADD BASE RSC /l 0x409 /d "_DEBUG" 71 71 # ADD RSC /l 0x409 /d "_DEBUG" … … 92 92 # Begin Source File 93 93 94 SOURCE="..\src\pjturn-srv\auth.c" 95 # End Source File 96 # Begin Source File 97 94 98 SOURCE="..\src\pjturn-srv\listener_udp.c" 95 99 # End Source File … … 108 112 # Begin Source File 109 113 114 SOURCE="..\src\pjturn-srv\auth.h" 115 # End Source File 116 # Begin Source File 117 110 118 SOURCE="..\src\pjturn-srv\turn.h" 111 119 # End Source File -
pjproject/trunk/pjnath/include/pjnath/stun_msg.h
r1850 r1852 298 298 PJ_STUN_ATTR_RELAY_ADDR = 0x0016,/**< RELAY-ADDRESS attribute. */ 299 299 PJ_STUN_ATTR_REQ_ADDR_TYPE = 0x0017,/**< REQUESTED-ADDRESS-TYPE */ 300 PJ_STUN_ATTR_REQ_P ORT_PROPS = 0x0018,/**< REQUESTED-PORT-PROPS */300 PJ_STUN_ATTR_REQ_PROPS = 0x0018,/**< REQUESTED-PROPS */ 301 301 PJ_STUN_ATTR_REQ_TRANSPORT = 0x0019,/**< REQUESTED-TRANSPORT */ 302 302 PJ_STUN_ATTR_XOR_MAPPED_ADDR = 0x0020,/**< XOR-MAPPED-ADDRESS */ 303 303 PJ_STUN_ATTR_TIMER_VAL = 0x0021,/**< TIMER-VAL attribute. */ 304 PJ_STUN_ATTR_RE Q_IP = 0x0022,/**< REQUESTED-IP attribute*/304 PJ_STUN_ATTR_RESERVATION_TOKEN = 0x0022,/**< TURN RESERVATION-TOKEN */ 305 305 PJ_STUN_ATTR_XOR_REFLECTED_FROM = 0x0023,/**< XOR-REFLECTED-FROM */ 306 306 PJ_STUN_ATTR_PRIORITY = 0x0024,/**< PRIORITY */ … … 359 359 PJ_STUN_SC_INSUFFICIENT_CAPACITY = 507, /**< Insufficient Capacity 360 360 (TURN) */ 361 PJ_STUN_SC_INSUFFICIENT_PORT_CAPACITY=508, /**< Insufficient Port Capacity 362 (TURN) */ 361 363 PJ_STUN_SC_GLOBAL_FAILURE = 600 /**< Global Failure */ 362 364 } pj_stun_status; … … 946 948 947 949 /** 948 * This describes the TURN REQUESTED-P ORT-PROPS attribute, encoded as950 * This describes the TURN REQUESTED-PROPS attribute, encoded as 949 951 * STUN 32bit integer attribute. Few macros are provided to manipulate 950 952 * the values in this attribute: #PJ_STUN_GET_RPP_BITS(), 951 953 * #PJ_STUN_SET_RPP_BITS(), #PJ_STUN_GET_RPP_PORT(), and 952 954 * #PJ_STUN_SET_RPP_PORT(). 953 * 955 * 954 956 * This attribute allows the client to request certain properties for 955 * the port that is allocated by the server. The attribute can be used 956 * with any transport protocol that has the notion of a 16 bit port 957 * space (including TCP and UDP). The attribute is 32 bits long. Its 958 * format is: 957 * the relayed transport address that is allocated by the server. The 958 * attribute is 32 bits long. Its format is: 959 959 960 960 \verbatim … … 963 963 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 964 964 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 965 | Reserved = 0 | A | Specific Port Number|965 | Prop-type | Reserved = 0 | 966 966 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 967 967 968 968 \endverbatim 969 969 970 * The two bits labeled A in the diagram above are for requested port 971 * alignment and have the following meaning: 972 * 973 * - 00 no specific port alignment 974 * - 01 odd port number 975 * - 10 even port number 976 * - 11 even port number; reserve next higher port 977 */ 978 typedef struct pj_stun_uint_attr pj_stun_req_port_props_attr; 979 980 /** 981 * Get the 2 bits requested port alignment value from a 32bit integral 982 * value of TURN REQUESTED-PORT-PROPS attribute. 983 */ 984 #define PJ_STUN_GET_RPP_BITS(u32) ((u32 >> 16) & 0x03) 985 986 /** 987 * Convert 2 bits requested port alignment value to a 32bit integral 988 * value of TURN REQUESTED-PORT-PROPS attribute. 989 */ 990 #define PJ_STUN_SET_RPP_BITS(A) (A << 16) 991 992 /** 993 * Get the port number in TURN REQUESTED-PORT-PROPS attribute. The port 994 * number is returned in host byte order. 995 */ 996 #define PJ_STUN_GET_RPP_PORT(u32) pj_ntohs((pj_uint16_t)(u32 & 0x0000FFFFL)) 997 998 /** 999 * Convert port number in host byte order to 32bit value to be encoded in 1000 * TURN REQUESTED-PORT-PROPS attribute. 1001 */ 1002 #define PJ_STUN_SET_RPP_PORT(port) ((pj_uint32_t)pj_htons((pj_uint16_t)(port))) 970 * The field labeled "Prop-type" is an 8-bit field specifying the 971 * desired property. The rest of the attribute is RFFU (Reserved For 972 * Future Use) and MUST be set to 0 on transmission and ignored on 973 * reception. The values of the "Prop-type" field are: 974 * 975 * 0x00 (Reserved) 976 * 0x01 Even port number 977 * 0x02 Pair of ports 978 */ 979 typedef struct pj_stun_uint_attr pj_stun_req_props_attr; 980 981 /** 982 * Get the 8bit Prop-type value from a 32bit integral value of TURN 983 * TURN REQUESTED-PROPS attribute. 984 */ 985 #define PJ_STUN_GET_PROP_TYPE(u32) (u32 >> 24) 986 987 /** 988 * Convert 8bit Prop-type value to a 32bit integral value of TURN 989 * REQUESTED-PROPS attribute. 990 */ 991 #define PJ_STUN_SET_PROP_TYPE(PropType) (PropType << 24) 1003 992 1004 993 … … 1047 1036 1048 1037 /** 1049 * This describes the TURN REQUESTED-IP attribute. 1050 * The REQUESTED-IP attribute is used by the client to request that a 1051 * specific IP address be allocated by the TURN server. This attribute 1052 * is needed since it is anticipated that TURN servers will be multi- 1053 * homed so as to be able to allocate more than 64k transport addresses. 1054 * As a consequence, a client needing a second transport address on the 1055 * same interface as a previous one can use this attribute to request a 1056 * remote address from the same TURN server interface as the TURN 1057 * client's previous remote address. 1038 * This describes the TURN RESERVATION-TOKEN attribute. 1039 * The RESERVATION-TOKEN attribute contains a token that uniquely 1040 * identifies a relayed transport address being held in reserve by the 1041 * server. The server includes this attribute in a success response to 1042 * tell the client about the token, and the client includes this 1043 * attribute in a subsequent Allocate request to request the server use 1044 * that relayed transport address for the allocation. 1058 1045 * 1059 * The format of this attribute is identical to XOR-MAPPED-ADDRESS. 1060 * However, the port component of the attribute MUST be ignored by the 1061 * server. If a client wishes to request a specific IP address and 1062 * port, it uses both the REQUESTED-IP and REQUESTED-PORT-PROPS 1063 * attributes. 1064 */ 1065 typedef struct pj_stun_sockaddr_attr pj_stun_req_ip_attr; 1046 * The attribute value is a 64-bit-long field containing the token 1047 * value. 1048 */ 1049 typedef struct pj_stun_uint64_attr pj_stun_res_token_attr; 1066 1050 1067 1051 /** -
pjproject/trunk/pjnath/include/pjnath/stun_session.h
r1498 r1852 294 294 * Create a STUN response message. After the message has been 295 295 * successfully created, application can send the message by calling 296 * pj_stun_session_send_msg(). 296 * pj_stun_session_send_msg(). Alternatively application may use 297 * pj_stun_session_respond() to create and send response in one function 298 * call. 297 299 * 298 300 * @param sess The STUN session instance. … … 316 318 pj_stun_tx_data **p_tdata); 317 319 318 319 320 /** 320 321 * Send STUN message to the specified destination. This function will encode … … 341 342 unsigned addr_len, 342 343 pj_stun_tx_data *tdata); 344 345 /** 346 * Create and send STUN response message. 347 * 348 * @param sess The STUN session instance. 349 * @param req The STUN request message to be responded. 350 * @param err_code Error code to be set in the response, if error response 351 * is to be created, according to pj_stun_status enumeration. 352 * This argument MUST be zero if successful response is 353 * to be created. 354 * @param err_msg Optional pointer for the error message string, when 355 * creating error response. If the value is NULL and the 356 * \a err_code is non-zero, then default error message will 357 * be used. 358 * @param cache Specify whether session should cache this response for 359 * future request retransmission. If TRUE, subsequent request 360 * retransmission will be handled by the session and it 361 * will not call request callback. 362 * @param dst_addr Destination address of the response (or equal to the 363 * source address of the original request). 364 * @param addr_len Address length. 365 * 366 * @return PJ_SUCCESS on success, or the appropriate error code. 367 */ 368 PJ_DECL(pj_status_t) pj_stun_session_respond(pj_stun_session *sess, 369 const pj_stun_msg *req, 370 unsigned code, 371 const char *err_msg, 372 pj_bool_t cache, 373 const pj_sockaddr_t *dst_addr, 374 unsigned addr_len); 343 375 344 376 /** -
pjproject/trunk/pjnath/src/pjnath/stun_msg.c
r1850 r1852 78 78 { PJ_STUN_SC_SERVER_ERROR, "Server Error"}, 79 79 { PJ_STUN_SC_INSUFFICIENT_CAPACITY, "Insufficient Capacity"}, 80 { PJ_STUN_SC_INSUFFICIENT_PORT_CAPACITY,"Insufficient Port Capacity"}, 80 81 { PJ_STUN_SC_GLOBAL_FAILURE, "Global Failure"} 81 82 }; … … 290 291 }, 291 292 { 292 /* PJ_STUN_ATTR_REQUESTED_P ORT_PROPS, */293 "REQUESTED-P ORT-PROPS",293 /* PJ_STUN_ATTR_REQUESTED_PROPS, */ 294 "REQUESTED-PROPS", 294 295 &decode_uint_attr, 295 296 &encode_uint_attr … … 350 351 }, 351 352 { 352 /* PJ_STUN_ATTR_RE QUESTED_IP, */353 "RE QUESTED-IP",354 &decode_ xored_sockaddr_attr,355 &encode_ sockaddr_attr353 /* PJ_STUN_ATTR_RESERVATION_TOKEN, */ 354 "RESERVATION-TOKEN", 355 &decode_uint64_attr, 356 &encode_uint64_attr 356 357 }, 357 358 { -
pjproject/trunk/pjnath/src/pjnath/stun_msg_dump.c
r1811 r1852 75 75 case PJ_STUN_ATTR_RELAY_ADDR: 76 76 case PJ_STUN_ATTR_XOR_MAPPED_ADDR: 77 case PJ_STUN_ATTR_REQ_IP:78 77 case PJ_STUN_ATTR_XOR_REFLECTED_FROM: 79 78 case PJ_STUN_ATTR_XOR_INTERNAL_ADDR: … … 118 117 case PJ_STUN_ATTR_BANDWIDTH: 119 118 case PJ_STUN_ATTR_REQ_ADDR_TYPE: 120 case PJ_STUN_ATTR_REQ_P ORT_PROPS:119 case PJ_STUN_ATTR_REQ_PROPS: 121 120 case PJ_STUN_ATTR_REQ_TRANSPORT: 122 121 case PJ_STUN_ATTR_TIMER_VAL: … … 208 207 case PJ_STUN_ATTR_ICE_CONTROLLED: 209 208 case PJ_STUN_ATTR_ICE_CONTROLLING: 209 case PJ_STUN_ATTR_RESERVATION_TOKEN: 210 210 { 211 211 const pj_stun_uint64_attr *attr; -
pjproject/trunk/pjnath/src/pjnath/stun_session.c
r1654 r1852 712 712 } 713 713 714 715 /* 716 * Create and send STUN response message. 717 */ 718 PJ_DEF(pj_status_t) pj_stun_session_respond( pj_stun_session *sess, 719 const pj_stun_msg *req, 720 unsigned code, 721 const char *errmsg, 722 pj_bool_t cache, 723 const pj_sockaddr_t *dst_addr, 724 unsigned addr_len) 725 { 726 pj_status_t status; 727 pj_str_t reason; 728 pj_stun_tx_data *tdata; 729 730 status = pj_stun_session_create_res(sess, req, code, 731 (errmsg?pj_cstr(&reason,errmsg):NULL), 732 &tdata); 733 if (status != PJ_SUCCESS) 734 return status; 735 736 return pj_stun_session_send_msg(sess, cache, dst_addr, addr_len, tdata); 737 } 738 739 714 740 /* 715 741 * Cancel outgoing STUN transaction. -
pjproject/trunk/pjnath/src/pjturn-srv/allocation.c
r1850 r1852 18 18 */ 19 19 #include "turn.h" 20 #include "auth.h" 21 20 22 21 23 #define THIS_FILE "allocation.c" … … 31 33 #define PEER_TABLE_SIZE 32 32 34 35 #define MAX_CLIENT_BANDWIDTH 128 /* In Kbps */ 36 #define DEFA_CLIENT_BANDWIDTH 64 37 38 #define MIN_LIFETIME 30 39 #define MAX_LIFETIME 600 40 #define DEF_LIFETIME 300 41 42 43 33 44 /* ChannelData header */ 34 45 typedef struct channel_data_hdr … … 39 50 40 51 52 /* Parsed Allocation request. */ 53 typedef struct alloc_request 54 { 55 unsigned tp_type; /* Requested transport */ 56 char addr[PJ_INET6_ADDRSTRLEN]; /* Requested IP */ 57 unsigned bandwidth; /* Requested bandwidth */ 58 unsigned lifetime; /* Lifetime. */ 59 unsigned rpp_bits; /* A bits */ 60 unsigned rpp_port; /* Requested port */ 61 } alloc_request; 62 63 64 41 65 /* Prototypes */ 42 static pj_status_t create_relay(pjturn_allocation *alloc, 43 const pjturn_allocation_req *req); 66 static void destroy_allocation(pj_turn_allocation *alloc); 67 static pj_status_t create_relay(pj_turn_srv *srv, 68 pj_turn_allocation *alloc, 69 const pj_stun_msg *msg, 70 const alloc_request *req, 71 pj_turn_relay_res *relay); 72 static void destroy_relay(pj_turn_relay_res *relay); 44 73 static void on_rx_from_peer(pj_ioqueue_key_t *key, 45 74 pj_ioqueue_op_key_t *op_key, 46 75 pj_ssize_t bytes_read); 47 static void destroy_relay(pjturn_relay_res *relay);48 76 static pj_status_t stun_on_send_msg(pj_stun_session *sess, 49 77 const void *pkt, … … 65 93 66 94 /* Log allocation error */ 67 static void alloc_err(pj turn_allocation *alloc, const char *title,95 static void alloc_err(pj_turn_allocation *alloc, const char *title, 68 96 pj_status_t status) 69 97 { … … 75 103 } 76 104 105 106 /* Parse ALLOCATE request */ 107 static pj_status_t parse_allocate_req(alloc_request *cfg, 108 pj_stun_session *sess, 109 const pj_stun_msg *req, 110 const pj_sockaddr_t *src_addr, 111 unsigned src_addr_len) 112 { 113 pj_stun_bandwidth_attr *attr_bw; 114 pj_stun_req_transport_attr *attr_req_tp; 115 pj_stun_res_token_attr *attr_res_token; 116 pj_stun_req_props_attr *attr_rpp; 117 pj_stun_lifetime_attr *attr_lifetime; 118 119 pj_bzero(cfg, sizeof(*cfg)); 120 121 /* Get BANDWIDTH attribute, if any. */ 122 attr_bw = (pj_stun_uint_attr*) 123 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_BANDWIDTH, 0); 124 if (attr_bw) { 125 cfg->bandwidth = attr_bw->value; 126 } else { 127 cfg->bandwidth = DEFA_CLIENT_BANDWIDTH; 128 } 129 130 /* Check if we can satisfy the bandwidth */ 131 if (cfg->bandwidth > MAX_CLIENT_BANDWIDTH) { 132 pj_stun_session_respond(sess, req, PJ_STUN_SC_ALLOCATION_QUOTA_REACHED, 133 "Invalid bandwidth", PJ_TRUE, 134 src_addr, src_addr_len); 135 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_ALLOCATION_QUOTA_REACHED); 136 } 137 138 /* MUST have REQUESTED-TRANSPORT attribute */ 139 attr_req_tp = (pj_stun_uint_attr*) 140 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_TRANSPORT, 0); 141 if (attr_req_tp == NULL) { 142 pj_stun_session_respond(sess, req, PJ_STUN_SC_BAD_REQUEST, 143 "Missing REQUESTED-TRANSPORT attribute", 144 PJ_TRUE, src_addr, src_addr_len); 145 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); 146 } 147 148 cfg->tp_type = PJ_STUN_GET_RT_PROTO(attr_req_tp->value); 149 150 /* Can only support UDP for now */ 151 if (cfg->tp_type != PJ_TURN_TP_UDP) { 152 pj_stun_session_respond(sess, req, PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, 153 NULL, PJ_TRUE, src_addr, src_addr_len); 154 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO); 155 } 156 157 /* Get RESERVATION-TOKEN attribute, if any */ 158 attr_res_token = (pj_stun_res_token_attr*) 159 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_RESERVATION_TOKEN, 160 0); 161 if (attr_res_token) { 162 /* We don't support RESERVATION-TOKEN for now */ 163 pj_stun_session_respond(sess, req, 164 PJ_STUN_SC_BAD_REQUEST, 165 "RESERVATION-TOKEN is not supported", PJ_TRUE, 166 src_addr, src_addr_len); 167 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); 168 } 169 170 /* Get REQUESTED-PROPS attribute, if any */ 171 attr_rpp = (pj_stun_req_props_attr*) 172 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_PROPS, 0); 173 if (attr_rpp) { 174 /* We don't support REQUESTED-PROPS for now */ 175 pj_stun_session_respond(sess, req, 176 PJ_STUN_SC_BAD_REQUEST, 177 "REQUESTED-PROPS is not supported", PJ_TRUE, 178 src_addr, src_addr_len); 179 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); 180 } 181 182 /* Get LIFETIME attribute */ 183 attr_lifetime = (pj_stun_uint_attr*) 184 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_LIFETIME, 0); 185 if (attr_lifetime) { 186 cfg->lifetime = attr_lifetime->value; 187 if (cfg->lifetime < MIN_LIFETIME) { 188 pj_stun_session_respond(sess, req, PJ_STUN_SC_BAD_REQUEST, 189 "LIFETIME too short", PJ_TRUE, 190 src_addr, src_addr_len); 191 return PJ_STATUS_FROM_STUN_CODE(PJ_STUN_SC_BAD_REQUEST); 192 } 193 if (cfg->lifetime > MAX_LIFETIME) 194 cfg->lifetime = MAX_LIFETIME; 195 } else { 196 cfg->lifetime = DEF_LIFETIME; 197 } 198 199 return PJ_SUCCESS; 200 } 201 202 203 /* Respond to ALLOCATE request */ 204 static pj_status_t send_allocate_response(pj_turn_allocation *alloc, 205 pj_stun_session *srv_sess, 206 const pj_stun_msg *msg) 207 { 208 pj_stun_tx_data *tdata; 209 pj_status_t status; 210 211 /* Respond the original ALLOCATE request */ 212 status = pj_stun_session_create_res(srv_sess, msg, 0, NULL, &tdata); 213 if (status != PJ_SUCCESS) 214 return status; 215 216 /* Add RELAYED-ADDRESS attribute */ 217 pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 218 PJ_STUN_ATTR_RELAY_ADDR, PJ_TRUE, 219 &alloc->relay.hkey.addr, 220 pj_sockaddr_get_len(&alloc->relay.hkey.addr)); 221 222 /* Add LIFETIME. */ 223 pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 224 PJ_STUN_ATTR_LIFETIME, 225 (unsigned)alloc->relay.lifetime); 226 227 /* Add BANDWIDTH */ 228 pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 229 PJ_STUN_ATTR_BANDWIDTH, 230 alloc->bandwidth); 231 232 /* Add RESERVATION-TOKEN */ 233 PJ_TODO(ADD_RESERVATION_TOKEN); 234 235 /* Add XOR-MAPPED-ADDRESS */ 236 pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 237 PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE, 238 &alloc->hkey.clt_addr, 239 pj_sockaddr_get_len(&alloc->hkey.clt_addr)); 240 241 /* Send the response */ 242 return pj_stun_session_send_msg(srv_sess, PJ_TRUE, 243 &alloc->hkey.clt_addr, 244 pj_sockaddr_get_len(&alloc->hkey.clt_addr), 245 tdata); 246 } 247 248 249 /* 250 * Init credential for the allocation. We use static credential, meaning that 251 * the user's password must not change during allocation. 252 */ 253 static pj_status_t init_cred(pj_turn_allocation *alloc, const pj_stun_msg *req) 254 { 255 const pj_stun_username_attr *user; 256 const pj_stun_realm_attr *realm; 257 const pj_stun_nonce_attr *nonce; 258 pj_status_t status; 259 260 realm = (const pj_stun_realm_attr*) 261 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REALM, 0); 262 PJ_ASSERT_RETURN(realm != NULL, PJ_EBUG); 263 264 user = (const pj_stun_username_attr*) 265 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_USERNAME, 0); 266 PJ_ASSERT_RETURN(user != NULL, PJ_EBUG); 267 268 nonce = (const pj_stun_nonce_attr*) 269 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_NONCE, 0); 270 PJ_ASSERT_RETURN(nonce != NULL, PJ_EBUG); 271 272 /* Lookup the password */ 273 status = pj_turn_get_password(NULL, NULL, &realm->value, 274 &user->value, alloc->pool, 275 &alloc->cred.data.static_cred.data_type, 276 &alloc->cred.data.static_cred.data); 277 if (status != PJ_SUCCESS) 278 return status; 279 280 /* Save credential */ 281 alloc->cred.type = PJ_STUN_AUTH_CRED_STATIC; 282 pj_strdup(alloc->pool, &alloc->cred.data.static_cred.realm, &realm->value); 283 pj_strdup(alloc->pool, &alloc->cred.data.static_cred.username, &user->value); 284 pj_strdup(alloc->pool, &alloc->cred.data.static_cred.nonce, &nonce->value); 285 286 return PJ_SUCCESS; 287 } 288 289 77 290 /* 78 291 * Create new allocation. 79 292 */ 80 PJ_DEF(pj_status_t) pj turn_allocation_create(pjturn_listener *listener,81 const pj_sockaddr_t *src_addr,82 unsigned src_addr_len,83 const pj_stun_msg *msg,84 const pjturn_allocation_req *req,85 pjturn_allocation **p_alloc)86 { 87 pj turn_srv *srv = listener->server;293 PJ_DEF(pj_status_t) pj_turn_allocation_create(pj_turn_listener *listener, 294 const pj_sockaddr_t *src_addr, 295 unsigned src_addr_len, 296 const pj_stun_msg *msg, 297 pj_stun_session *srv_sess, 298 pj_turn_allocation **p_alloc) 299 { 300 pj_turn_srv *srv = listener->server; 88 301 pj_pool_t *pool; 89 pjturn_allocation *alloc; 302 alloc_request req; 303 pj_turn_allocation *alloc; 90 304 pj_stun_session_cb sess_cb; 91 char relay_info[80];305 char str_tmp[80]; 92 306 pj_status_t status; 93 307 308 /* Parse ALLOCATE request */ 309 status = parse_allocate_req(&req, srv_sess, msg, src_addr, src_addr_len); 310 if (status != PJ_SUCCESS) 311 return status; 312 94 313 pool = pj_pool_create(srv->core.pf, "alloc%p", 1000, 1000, NULL); 95 314 96 315 /* Init allocation structure */ 97 alloc = PJ_POOL_ZALLOC_T(pool, pj turn_allocation);316 alloc = PJ_POOL_ZALLOC_T(pool, pj_turn_allocation); 98 317 alloc->pool = pool; 99 318 alloc->obj_name = pool->obj_name; … … 102 321 alloc->relay.tp.sock = PJ_INVALID_SOCKET; 103 322 104 alloc->bandwidth = req ->bandwidth;323 alloc->bandwidth = req.bandwidth; 105 324 106 325 alloc->hkey.tp_type = listener->tp_type; … … 110 329 &alloc->lock); 111 330 if (status != PJ_SUCCESS) { 112 pjturn_allocation_destroy(alloc); 113 return status; 331 goto on_error; 114 332 } 115 333 … … 121 339 122 340 /* Print info */ 123 pj_ansi_strcpy(alloc->info, pj turn_tp_type_name(listener->tp_type));341 pj_ansi_strcpy(alloc->info, pj_turn_tp_type_name(listener->tp_type)); 124 342 alloc->info[3] = ':'; 125 343 pj_sockaddr_print(src_addr, alloc->info+4, sizeof(alloc->info)-4, 3); … … 133 351 &sess_cb, PJ_FALSE, &alloc->sess); 134 352 if (status != PJ_SUCCESS) { 135 pjturn_allocation_destroy(alloc); 136 return status; 353 goto on_error; 137 354 } 138 355 … … 140 357 pj_stun_session_set_user_data(alloc->sess, alloc); 141 358 359 /* Init authentication credential */ 360 status = init_cred(alloc, msg); 361 if (status != PJ_SUCCESS) { 362 goto on_error; 363 } 364 365 /* Attach authentication credential to STUN session */ 366 pj_stun_session_set_credential(alloc->sess, &alloc->cred); 367 142 368 /* Create the relay resource */ 143 status = pjturn_allocation_create_relay(srv, alloc, msg, req, 144 &alloc->relay); 369 status = create_relay(srv, alloc, msg, &req, &alloc->relay); 145 370 if (status != PJ_SUCCESS) { 146 pjturn_allocation_destroy(alloc); 147 return status; 371 goto on_error; 148 372 } 149 373 150 374 /* Register this allocation */ 151 pjturn_srv_register_allocation(srv, alloc); 152 153 pj_sockaddr_print(&alloc->relay.hkey.addr, relay_info, 154 sizeof(relay_info), 3); 375 pj_turn_srv_register_allocation(srv, alloc); 376 377 /* Respond to ALLOCATE request */ 378 status = send_allocate_response(alloc, srv_sess, msg); 379 if (status != PJ_SUCCESS) 380 goto on_error; 381 382 /* Done */ 383 pj_sockaddr_print(&alloc->relay.hkey.addr, str_tmp, 384 sizeof(str_tmp), 3); 155 385 PJ_LOG(4,(alloc->obj_name, "Client %s created, relay addr=%s:%s", 156 alloc->info, pj turn_tp_type_name(req->tp_type), relay_info));386 alloc->info, pj_turn_tp_type_name(req.tp_type), str_tmp)); 157 387 158 388 /* Success */ 159 389 *p_alloc = alloc; 160 390 return PJ_SUCCESS; 161 } 162 163 164 /* 165 * Destroy allocation. 166 */ 167 PJ_DECL(void) pjturn_allocation_destroy(pjturn_allocation *alloc) 168 { 169 pj_pool_t *pool; 170 171 /* Unregister this allocation */ 172 pjturn_srv_unregister_allocation(alloc->listener->server, alloc); 173 174 /* Destroy relay */ 175 destroy_relay(&alloc->relay); 176 177 /* Must lock only after destroying relay otherwise deadlock */ 178 if (alloc->lock) { 179 pj_lock_acquire(alloc->lock); 180 } 181 182 /* Destroy STUN session */ 183 if (alloc->sess) { 184 pj_stun_session_destroy(alloc->sess); 185 alloc->sess = NULL; 186 } 187 188 /* Destroy lock */ 189 if (alloc->lock) { 190 pj_lock_release(alloc->lock); 191 pj_lock_destroy(alloc->lock); 192 alloc->lock = NULL; 193 } 194 195 /* Destroy pool */ 196 pool = alloc->pool; 197 if (pool) { 198 alloc->pool = NULL; 199 pj_pool_release(pool); 200 } 391 392 on_error: 393 /* Send reply to the ALLOCATE request */ 394 pj_strerror(status, str_tmp, sizeof(str_tmp)); 395 pj_stun_session_respond(srv_sess, msg, PJ_STUN_SC_BAD_REQUEST, str_tmp, 396 PJ_TRUE, src_addr, src_addr_len); 397 398 /* Cleanup */ 399 destroy_allocation(alloc); 400 return status; 201 401 } 202 402 203 403 204 404 /* Destroy relay resource */ 205 static void destroy_relay(pj turn_relay_res *relay)405 static void destroy_relay(pj_turn_relay_res *relay) 206 406 { 207 407 if (relay->timer.id) { … … 224 424 } 225 425 226 /* Initiate shutdown sequence for this allocation */ 227 static void alloc_shutdown(pjturn_allocation *alloc) 426 427 /* 428 * Really destroy allocation. 429 */ 430 static void destroy_allocation(pj_turn_allocation *alloc) 431 { 432 pj_pool_t *pool; 433 434 /* Unregister this allocation */ 435 pj_turn_srv_unregister_allocation(alloc->listener->server, alloc); 436 437 /* Destroy relay */ 438 destroy_relay(&alloc->relay); 439 440 /* Must lock only after destroying relay otherwise deadlock */ 441 if (alloc->lock) { 442 pj_lock_acquire(alloc->lock); 443 } 444 445 /* Destroy STUN session */ 446 if (alloc->sess) { 447 pj_stun_session_destroy(alloc->sess); 448 alloc->sess = NULL; 449 } 450 451 /* Destroy lock */ 452 if (alloc->lock) { 453 pj_lock_release(alloc->lock); 454 pj_lock_destroy(alloc->lock); 455 alloc->lock = NULL; 456 } 457 458 /* Destroy pool */ 459 pool = alloc->pool; 460 if (pool) { 461 alloc->pool = NULL; 462 pj_pool_release(pool); 463 } 464 } 465 466 467 PJ_DECL(void) pj_turn_allocation_destroy(pj_turn_allocation *alloc) 468 { 469 destroy_allocation(alloc); 470 } 471 472 473 /* Initiate shutdown sequence for this allocation and start destroy timer. 474 * Once allocation is marked as shutting down, any packets will be 475 * rejected/discarded 476 */ 477 static void alloc_shutdown(pj_turn_allocation *alloc) 228 478 { 229 479 pj_time_val destroy_delay = DESTROY_DELAY; … … 231 481 /* Work with existing schedule */ 232 482 if (alloc->relay.timer.id == TIMER_ID_TIMEOUT) { 233 /* Cancel existing timer */483 /* Cancel existing shutdown timer */ 234 484 pj_timer_heap_cancel(alloc->listener->server->core.timer_heap, 235 485 &alloc->relay.timer); … … 258 508 } 259 509 510 260 511 /* Reschedule timeout using current lifetime setting */ 261 static pj_status_t resched_timeout(pj turn_allocation *alloc)512 static pj_status_t resched_timeout(pj_turn_allocation *alloc) 262 513 { 263 514 pj_time_val delay; … … 292 543 static void relay_timeout_cb(pj_timer_heap_t *heap, pj_timer_entry *e) 293 544 { 294 pjturn_relay_res *rel; 295 pjturn_allocation *alloc; 296 297 rel = (pjturn_relay_res*) e->user_data; 545 pj_turn_relay_res *rel; 546 pj_turn_allocation *alloc; 547 548 PJ_UNUSED_ARG(heap); 549 550 rel = (pj_turn_relay_res*) e->user_data; 298 551 alloc = rel->allocation; 299 552 … … 314 567 alloc->info)); 315 568 316 pjturn_allocation_destroy(alloc);569 destroy_allocation(alloc); 317 570 } 318 571 } … … 322 575 * Create relay. 323 576 */ 324 PJ_DEF(pj_status_t) pjturn_allocation_create_relay(pjturn_srv *srv,325 pjturn_allocation *alloc,326 327 const pjturn_allocation_req*req,328 pjturn_relay_res *relay)577 static pj_status_t create_relay(pj_turn_srv *srv, 578 pj_turn_allocation *alloc, 579 const pj_stun_msg *msg, 580 const alloc_request *req, 581 pj_turn_relay_res *relay) 329 582 { 330 583 enum { RETRY = 40 }; … … 366 619 367 620 /* Create the socket */ 368 if (req->tp_type == PJ TURN_TP_UDP) {621 if (req->tp_type == PJ_TURN_TP_UDP) { 369 622 sock_type = pj_SOCK_DGRAM(); 370 } else if (req->tp_type == PJ TURN_TP_TCP) {623 } else if (req->tp_type == PJ_TURN_TP_TCP) { 371 624 sock_type = pj_SOCK_STREAM(); 372 625 } else { … … 396 649 if (req->rpp_port) { 397 650 port = (pj_uint16_t) req->rpp_port; 398 } else if (req->tp_type == PJ TURN_TP_UDP) {651 } else if (req->tp_type == PJ_TURN_TP_UDP) { 399 652 port = (pj_uint16_t) srv->ports.next_udp++; 400 653 if (srv->ports.next_udp > srv->ports.max_udp) 401 654 srv->ports.next_udp = srv->ports.min_udp; 402 } else if (req->tp_type == PJ TURN_TP_TCP) {655 } else if (req->tp_type == PJ_TURN_TP_TCP) { 403 656 port = (pj_uint16_t) srv->ports.next_tcp++; 404 657 if (srv->ports.next_tcp > srv->ports.max_tcp) … … 406 659 } else { 407 660 pj_assert(!"Invalid transport"); 661 port = 0; 408 662 } 409 663 … … 464 718 465 719 /* Create and send error response */ 466 static void send_reply_err(pj turn_allocation *alloc,720 static void send_reply_err(pj_turn_allocation *alloc, 467 721 const pj_stun_msg *req, 468 722 pj_bool_t cache, … … 470 724 { 471 725 pj_status_t status; 472 pj_str_t reason; 473 pj_stun_tx_data *tdata; 474 475 status = pj_stun_session_create_res(alloc->sess, req, 476 code, (errmsg?pj_cstr(&reason,errmsg):NULL), 477 &tdata); 478 if (status != PJ_SUCCESS) { 479 alloc_err(alloc, "Error creating STUN error response", status); 480 return; 481 } 482 483 status = pj_stun_session_send_msg(alloc->sess, cache, 484 &alloc->hkey.clt_addr, 485 pj_sockaddr_get_len(&alloc->hkey.clt_addr), 486 tdata); 726 727 status = pj_stun_session_respond(alloc->sess, req, code, errmsg, cache, 728 &alloc->hkey.clt_addr, 729 pj_sockaddr_get_len(&alloc->hkey.clt_addr.addr)); 487 730 if (status != PJ_SUCCESS) { 488 731 alloc_err(alloc, "Error sending STUN error response", status); … … 492 735 493 736 /* Create and send successful response */ 494 static void send_reply_ok(pj turn_allocation *alloc,737 static void send_reply_ok(pj_turn_allocation *alloc, 495 738 const pj_stun_msg *req) 496 739 { … … 535 778 536 779 /* Create new permission */ 537 static pj turn_permission *create_permission(pjturn_allocation *alloc,780 static pj_turn_permission *create_permission(pj_turn_allocation *alloc, 538 781 const pj_sockaddr_t *peer_addr, 539 782 unsigned addr_len) 540 783 { 541 pj turn_permission *perm;542 543 perm = PJ_POOL_ZALLOC_T(alloc->pool, pj turn_permission);784 pj_turn_permission *perm; 785 786 perm = PJ_POOL_ZALLOC_T(alloc->pool, pj_turn_permission); 544 787 pj_memcpy(&perm->hkey.peer_addr, peer_addr, addr_len); 545 788 546 if (alloc->listener->tp_type == PJ TURN_TP_UDP) {789 if (alloc->listener->tp_type == PJ_TURN_TP_UDP) { 547 790 perm->sock = alloc->listener->sock; 548 791 } else { … … 552 795 553 796 perm->allocation = alloc; 554 perm->channel = PJ TURN_INVALID_CHANNEL;797 perm->channel = PJ_TURN_INVALID_CHANNEL; 555 798 556 799 pj_gettimeofday(&perm->expiry); 557 perm->expiry.sec += PJ TURN_PERM_TIMEOUT;800 perm->expiry.sec += PJ_TURN_PERM_TIMEOUT; 558 801 559 802 return perm; … … 561 804 562 805 /* Check if a permission isn't expired. Return NULL if expired. */ 563 static pj turn_permission *check_permission_expiry(pjturn_permission *perm)564 { 565 pj turn_allocation *alloc = perm->allocation;806 static pj_turn_permission *check_permission_expiry(pj_turn_permission *perm) 807 { 808 pj_turn_allocation *alloc = perm->allocation; 566 809 pj_time_val now; 567 810 … … 577 820 578 821 /* Remove from channel hash table, if assigned a channel number */ 579 if (perm->channel != PJ TURN_INVALID_CHANNEL) {822 if (perm->channel != PJ_TURN_INVALID_CHANNEL) { 580 823 pj_hash_set(NULL, alloc->ch_table, &perm->channel, 581 824 sizeof(perm->channel), 0, NULL); … … 586 829 587 830 /* Lookup permission in hash table by the peer address */ 588 static pj turn_permission*589 lookup_permission_by_addr(pj turn_allocation *alloc,831 static pj_turn_permission* 832 lookup_permission_by_addr(pj_turn_allocation *alloc, 590 833 const pj_sockaddr_t *peer_addr, 591 834 unsigned addr_len) 592 835 { 593 pj turn_permission_key key;594 pj turn_permission *perm;836 pj_turn_permission_key key; 837 pj_turn_permission *perm; 595 838 596 839 pj_bzero(&key, sizeof(key)); … … 598 841 599 842 /* Lookup in peer hash table */ 600 perm = (pj turn_permission*) pj_hash_get(alloc->peer_table, &key,843 perm = (pj_turn_permission*) pj_hash_get(alloc->peer_table, &key, 601 844 sizeof(key), NULL); 602 845 return check_permission_expiry(perm); … … 604 847 605 848 /* Lookup permission in hash table by the channel number */ 606 static pj turn_permission*607 lookup_permission_by_chnum(pj turn_allocation *alloc,849 static pj_turn_permission* 850 lookup_permission_by_chnum(pj_turn_allocation *alloc, 608 851 unsigned chnum) 609 852 { 610 853 pj_uint16_t chnum16 = (pj_uint16_t)chnum; 611 pj turn_permission *perm;854 pj_turn_permission *perm; 612 855 613 856 /* Lookup in peer hash table */ 614 perm = (pj turn_permission*) pj_hash_get(alloc->peer_table, &chnum16,857 perm = (pj_turn_permission*) pj_hash_get(alloc->peer_table, &chnum16, 615 858 sizeof(chnum16), NULL); 616 859 return check_permission_expiry(perm); … … 620 863 * Return PJ_TRUE is permission is found. 621 864 */ 622 static pj_bool_t refresh_permission(pj turn_permission *perm)865 static pj_bool_t refresh_permission(pj_turn_permission *perm) 623 866 { 624 867 pj_gettimeofday(&perm->expiry); 625 if (perm->channel == PJ TURN_INVALID_CHANNEL)626 perm->expiry.sec += PJ TURN_PERM_TIMEOUT;868 if (perm->channel == PJ_TURN_INVALID_CHANNEL) 869 perm->expiry.sec += PJ_TURN_PERM_TIMEOUT; 627 870 else 628 perm->expiry.sec += PJ TURN_CHANNEL_TIMEOUT;871 perm->expiry.sec += PJ_TURN_CHANNEL_TIMEOUT; 629 872 return PJ_TRUE; 630 873 } 631 874 632 875 /* 633 * Handle incoming packet from client. 876 * Handle incoming packet from client. This would have been called by 877 * server upon receiving packet from a listener. 634 878 */ 635 PJ_DEF(void) pj turn_allocation_on_rx_client_pkt( pjturn_allocation *alloc,636 pj turn_pkt *pkt)879 PJ_DEF(void) pj_turn_allocation_on_rx_client_pkt(pj_turn_allocation *alloc, 880 pj_turn_pkt *pkt) 637 881 { 638 882 pj_bool_t is_stun; 639 883 pj_status_t status; 884 885 /* Lock this allocation */ 886 pj_lock_acquire(alloc->lock); 640 887 641 888 /* Quickly check if this is STUN message */ … … 650 897 */ 651 898 unsigned options = PJ_STUN_CHECK_PACKET; 652 if (pkt->listener->tp_type == PJ TURN_TP_UDP)899 if (pkt->listener->tp_type == PJ_TURN_TP_UDP) 653 900 options |= PJ_STUN_IS_DATAGRAM; 654 901 … … 659 906 if (status != PJ_SUCCESS) { 660 907 alloc_err(alloc, "Error handling STUN packet", status); 661 return;908 goto on_return; 662 909 } 663 910 … … 667 914 */ 668 915 channel_data_hdr *cd = (channel_data_hdr*)pkt->pkt; 669 pj turn_permission *perm;916 pj_turn_permission *perm; 670 917 pj_ssize_t len; 671 918 672 919 /* For UDP check the packet length */ 673 if (alloc->listener->tp_type == PJ TURN_TP_UDP) {920 if (alloc->listener->tp_type == PJ_TURN_TP_UDP) { 674 921 if (pkt->len < pj_ntohs(cd->length)+sizeof(*cd)) { 675 922 PJ_LOG(4,(alloc->obj_name, 676 923 "ChannelData from %s discarded: UDP size error", 677 924 alloc->info)); 678 return;925 goto on_return; 679 926 } 680 927 } else { 681 928 pj_assert(!"Unsupported transport"); 682 return;929 goto on_return; 683 930 } 684 931 … … 689 936 "ChannelData from %s discarded: not found", 690 937 alloc->info)); 691 return;938 goto on_return; 692 939 } 693 940 … … 701 948 refresh_permission(perm); 702 949 } 703 } 950 951 on_return: 952 /* Release lock */ 953 pj_lock_release(alloc->lock); 954 } 955 704 956 705 957 /* … … 707 959 * on_rx_from_peer(). 708 960 */ 709 static void on_rx_peer_pkt(pjturn_allocation *alloc,710 pjturn_relay_res *rel,711 char *pkt, pj_size_t len,712 const pj_sockaddr *src_addr)713 { 714 pj turn_permission *perm;961 static void handle_peer_pkt(pj_turn_allocation *alloc, 962 pj_turn_relay_res *rel, 963 char *pkt, pj_size_t len, 964 const pj_sockaddr *src_addr) 965 { 966 pj_turn_permission *perm; 715 967 716 968 /* Lookup permission */ … … 725 977 * this permission is attached to a channel number. 726 978 */ 727 if (perm->channel != PJ TURN_INVALID_CHANNEL) {979 if (perm->channel != PJ_TURN_INVALID_CHANNEL) { 728 980 /* Send ChannelData */ 729 981 channel_data_hdr *cd = (channel_data_hdr*)rel->tp.tx_pkt; 730 982 731 if (len > PJ TURN_MAX_PKT_LEN) {983 if (len > PJ_TURN_MAX_PKT_LEN) { 732 984 char peer_addr[80]; 733 985 pj_sockaddr_print(src_addr, peer_addr, sizeof(peer_addr), 3); 734 PJ_LOG( 1,(alloc->obj_name, "Client %s: discarded data from %s "986 PJ_LOG(4,(alloc->obj_name, "Client %s: discarded data from %s " 735 987 "because it's too long (%d bytes)", 736 988 alloc->info, peer_addr, len)); … … 746 998 747 999 /* Send to client */ 748 pj turn_listener_sendto(alloc->listener, rel->tp.tx_pkt,1000 pj_turn_listener_sendto(alloc->listener, rel->tp.tx_pkt, 749 1001 len+sizeof(channel_data_hdr), 0, 750 1002 &alloc->hkey.clt_addr, … … 771 1023 pj_ssize_t bytes_read) 772 1024 { 773 pj turn_relay_res *rel;1025 pj_turn_relay_res *rel; 774 1026 pj_status_t status; 775 1027 776 rel = (pjturn_relay_res*) pj_ioqueue_get_user_data(key); 1028 rel = (pj_turn_relay_res*) pj_ioqueue_get_user_data(key); 1029 1030 /* Lock the allocation */ 1031 pj_lock_acquire(rel->allocation->lock); 777 1032 778 1033 do { 779 1034 if (bytes_read > 0) { 780 on_rx_peer_pkt(rel->allocation, rel, rel->tp.rx_pkt,781 bytes_read, &rel->tp.src_addr);1035 handle_peer_pkt(rel->allocation, rel, rel->tp.rx_pkt, 1036 bytes_read, &rel->tp.src_addr); 782 1037 } 783 1038 … … 795 1050 } while (status != PJ_EPENDING && status != PJ_ECANCELLED); 796 1051 1052 /* Release allocation lock */ 1053 pj_lock_release(rel->allocation->lock); 797 1054 } 798 1055 … … 807 1064 unsigned addr_len) 808 1065 { 809 pj turn_allocation *alloc;810 811 alloc = (pj turn_allocation*) pj_stun_session_get_user_data(sess);812 813 return pj turn_listener_sendto(alloc->listener, pkt, pkt_size, 0,1066 pj_turn_allocation *alloc; 1067 1068 alloc = (pj_turn_allocation*) pj_stun_session_get_user_data(sess); 1069 1070 return pj_turn_listener_sendto(alloc->listener, pkt, pkt_size, 0, 814 1071 dst_addr, addr_len); 815 1072 } … … 818 1075 * Callback notification from STUN session when it receives STUN 819 1076 * requests. This callback was trigger by STUN incoming message 820 * processing in pj turn_allocation_on_rx_client_pkt().1077 * processing in pj_turn_allocation_on_rx_client_pkt(). 821 1078 */ 822 1079 static pj_status_t stun_on_rx_request(pj_stun_session *sess, … … 827 1084 unsigned src_addr_len) 828 1085 { 829 pjturn_allocation *alloc; 830 831 alloc = (pjturn_allocation*) pj_stun_session_get_user_data(sess); 1086 pj_turn_allocation *alloc; 1087 1088 PJ_UNUSED_ARG(pkt); 1089 PJ_UNUSED_ARG(pkt_len); 1090 PJ_UNUSED_ARG(src_addr); 1091 PJ_UNUSED_ARG(src_addr_len); 1092 1093 alloc = (pj_turn_allocation*) pj_stun_session_get_user_data(sess); 832 1094 833 1095 /* Refuse to serve any request if we've been shutdown */ 834 1096 if (alloc->relay.lifetime == 0) { 1097 /* Reject with 437 if we're shutting down */ 835 1098 send_reply_err(alloc, msg, PJ_TRUE, 836 1099 PJ_STUN_SC_ALLOCATION_MISMATCH, NULL); … … 895 1158 pj_stun_channel_number_attr *ch_attr; 896 1159 pj_stun_peer_addr_attr *peer_attr; 897 pj turn_permission *p1, *p2;1160 pj_turn_permission *p1, *p2; 898 1161 899 1162 ch_attr = (pj_stun_channel_number_attr*) … … 934 1197 p2 = lookup_permission_by_addr(alloc, &peer_attr->sockaddr, 935 1198 pj_sockaddr_get_len(&peer_attr->sockaddr)); 936 if (p2 && p2->channel != PJ TURN_INVALID_CHANNEL) {1199 if (p2 && p2->channel != PJ_TURN_INVALID_CHANNEL) { 937 1200 send_reply_err(alloc, msg, PJ_TRUE, PJ_STUN_SC_BAD_REQUEST, 938 1201 "Peer address already assigned a channel number"); … … 977 1240 * Callback notification from STUN session when it receives STUN 978 1241 * indications. This callback was trigger by STUN incoming message 979 * processing in pj turn_allocation_on_rx_client_pkt().1242 * processing in pj_turn_allocation_on_rx_client_pkt(). 980 1243 */ 981 1244 static pj_status_t stun_on_rx_indication(pj_stun_session *sess, … … 988 1251 pj_stun_peer_addr_attr *peer_attr; 989 1252 pj_stun_data_attr *data_attr; 990 pjturn_allocation *alloc; 991 pjturn_permission *perm; 992 993 alloc = (pjturn_allocation*) pj_stun_session_get_user_data(sess); 1253 pj_turn_allocation *alloc; 1254 pj_turn_permission *perm; 1255 1256 PJ_UNUSED_ARG(pkt); 1257 PJ_UNUSED_ARG(pkt_len); 1258 PJ_UNUSED_ARG(src_addr); 1259 PJ_UNUSED_ARG(src_addr_len); 1260 1261 alloc = (pj_turn_allocation*) pj_stun_session_get_user_data(sess); 994 1262 995 1263 /* Only expect Send Indication */ … … 1025 1293 1026 1294 /* Relay the data to client */ 1027 if (alloc->hkey.tp_type == PJ TURN_TP_UDP) {1295 if (alloc->hkey.tp_type == PJ_TURN_TP_UDP) { 1028 1296 pj_ssize_t len = data_attr->length; 1029 1297 pj_sock_sendto(alloc->listener->sock, data_attr->data, -
pjproject/trunk/pjnath/src/pjturn-srv/listener_udp.c
r1812 r1852 22 22 { 23 23 pj_ioqueue_op_key_t op_key; 24 pj turn_pkt pkt;24 pj_turn_pkt pkt; 25 25 }; 26 26 27 27 struct udp_listener 28 28 { 29 pj turn_listener base;29 pj_turn_listener base; 30 30 pj_ioqueue_key_t *key; 31 31 unsigned read_cnt; … … 34 34 35 35 36 static pj_status_t udp_sendto(pj turn_listener *listener,36 static pj_status_t udp_sendto(pj_turn_listener *listener, 37 37 const void *packet, 38 38 pj_size_t size, … … 40 40 const pj_sockaddr_t *addr, 41 41 int addr_len); 42 static pj_status_t udp_destroy(pj turn_listener *udp);42 static pj_status_t udp_destroy(pj_turn_listener *udp); 43 43 static void on_read_complete(pj_ioqueue_key_t *key, 44 44 pj_ioqueue_op_key_t *op_key, … … 49 49 * Create a new listener on the specified port. 50 50 */ 51 PJ_DEF(pj_status_t) pj turn_listener_create_udp( pjturn_srv *srv,51 PJ_DEF(pj_status_t) pj_turn_listener_create_udp( pj_turn_srv *srv, 52 52 int af, 53 53 const pj_str_t *bound_addr, … … 55 55 unsigned concurrency_cnt, 56 56 unsigned flags, 57 pj turn_listener **p_listener)57 pj_turn_listener **p_listener) 58 58 { 59 59 pj_pool_t *pool; … … 64 64 65 65 /* Create structure */ 66 pool = pj_pool_create(srv->core.pf, "udp lis%p", 1000, 1000, NULL);66 pool = pj_pool_create(srv->core.pf, "udp%p", 1000, 1000, NULL); 67 67 udp = PJ_POOL_ZALLOC_T(pool, struct udp_listener); 68 68 udp->base.pool = pool; 69 udp->base.obj_name = pool->obj_name; 69 70 udp->base.server = srv; 70 udp->base.tp_type = PJ TURN_TP_UDP;71 udp->base.tp_type = PJ_TURN_TP_UDP; 71 72 udp->base.sock = PJ_INVALID_SOCKET; 72 73 udp->base.sendto = &udp_sendto; … … 86 87 goto on_error; 87 88 89 /* Create info */ 90 pj_ansi_strcpy(udp->base.info, "UDP:"); 91 pj_sockaddr_print(&udp->base.addr, udp->base.info+4, 92 sizeof(udp->base.info)-4, 3); 93 88 94 /* Bind socket */ 89 95 status = pj_sock_bind(udp->base.sock, &udp->base.addr, … … 105 111 for (i=0; i<concurrency_cnt; ++i) { 106 112 pj_pool_t *rpool = pj_pool_create(srv->core.pf, "rop%p", 107 1000, 1000, NULL); 113 sizeof(struct read_op)+1000, 114 1000, NULL); 108 115 109 116 udp->read_op[i] = PJ_POOL_ZALLOC_T(rpool, struct read_op); … … 114 121 115 122 /* Done */ 123 PJ_LOG(4,(udp->base.obj_name, "Listener %s created", udp->base.info)); 124 116 125 *p_listener = &udp->base; 117 126 return PJ_SUCCESS; … … 127 136 * Destroy listener. 128 137 */ 129 static pj_status_t udp_destroy(pj turn_listener *listener)138 static pj_status_t udp_destroy(pj_turn_listener *listener) 130 139 { 131 140 struct udp_listener *udp = (struct udp_listener *)listener; … … 150 159 151 160 if (udp->base.pool) { 152 pj_pool_release(udp->base.pool); 161 pj_pool_t *pool = udp->base.pool; 162 163 PJ_LOG(4,(udp->base.obj_name, "Listener %s destroyed", 164 udp->base.info)); 165 153 166 udp->base.pool = NULL; 167 pj_pool_release(pool); 154 168 } 155 169 return PJ_SUCCESS; … … 159 173 * Callback to send packet. 160 174 */ 161 static pj_status_t udp_sendto(pj turn_listener *listener,175 static pj_status_t udp_sendto(pj_turn_listener *listener, 162 176 const void *packet, 163 177 pj_size_t size, … … 167 181 { 168 182 pj_ssize_t len = size; 169 return pj_sock_sendto(listener->sock, packet, &len, flag, addr, 170 pj_sockaddr_get_len(addr)); 183 return pj_sock_sendto(listener->sock, packet, &len, flag, addr, addr_len); 171 184 } 172 185 … … 192 205 pj_gettimeofday(&read_op->pkt.rx_time); 193 206 194 pj turn_srv_on_rx_pkt(udp->base.server, &read_op->pkt);207 pj_turn_srv_on_rx_pkt(udp->base.server, &read_op->pkt); 195 208 } 196 209 -
pjproject/trunk/pjnath/src/pjturn-srv/main.c
r1812 r1852 1 1 #include "turn.h" 2 3 int err(const char *title, pj_status_t status) 4 { 5 char errmsg[PJ_ERR_MSG_SIZE]; 6 pj_strerror(status, errmsg, sizeof(errmsg)); 7 8 printf("%s: %s\n", title, errmsg); 9 return 1; 10 } 11 12 int main() 13 { 14 pj_caching_pool cp; 15 pj_turn_srv *srv; 16 pj_turn_listener *listener; 17 pj_status_t status; 18 19 status = pj_init(); 20 if (status != PJ_SUCCESS) 21 return err("pj_init() error", status); 22 23 pj_caching_pool_init(&cp, NULL, 0); 24 25 status = pj_turn_srv_create(&cp.factory, &srv); 26 if (status != PJ_SUCCESS) 27 return err("Error creating server", status); 28 29 status = pj_turn_listener_create_udp(srv, pj_AF_INET(), NULL, 3478, 1, 0, &listener); 30 if (status != PJ_SUCCESS) 31 return err("Error creating listener", status); 32 33 status = pj_turn_srv_add_listener(srv, listener); 34 if (status != PJ_SUCCESS) 35 return err("Error adding listener", status); 36 37 puts("Server is running"); 38 puts("Press <ENTER> to quit"); 39 40 { 41 char line[10]; 42 fgets(line, sizeof(line), stdin); 43 } 44 45 pj_turn_srv_destroy(srv); 46 pj_caching_pool_destroy(&cp); 47 pj_shutdown(); 48 49 return 0; 50 } 51 -
pjproject/trunk/pjnath/src/pjturn-srv/server.c
r1850 r1852 18 18 */ 19 19 #include "turn.h" 20 #include "auth.h" 20 21 21 22 #define MAX_CLIENTS 32 22 23 #define MAX_PEERS_PER_CLIENT 8 23 #define MAX_HANDLES (MAX_CLIENTS*MAX_PEERS_PER_CLIENT+MAX_LISTENERS) 24 //#define MAX_HANDLES (MAX_CLIENTS*MAX_PEERS_PER_CLIENT+MAX_LISTENERS) 25 #define MAX_HANDLES PJ_IOQUEUE_MAX_HANDLES 24 26 #define MAX_TIMER (MAX_HANDLES * 2) 25 27 #define MIN_PORT 49152 … … 27 29 #define MAX_LISTENERS 16 28 30 #define MAX_THREADS 2 29 30 #define MAX_CLIENT_BANDWIDTH 128 /* In Kbps */ 31 #define DEFA_CLIENT_BANDWIDTH 64 32 33 #define MIN_LIFETIME 32 34 #define MAX_LIFETIME 600 35 #define DEF_LIFETIME 300 36 31 #define MAX_NET_EVENTS 10 37 32 38 33 /* Prototypes */ 34 static int server_thread_proc(void *arg); 39 35 static pj_status_t on_tx_stun_msg( pj_stun_session *sess, 40 36 const void *pkt, … … 49 45 unsigned src_addr_len); 50 46 51 /* 52 * Get transport type name. 53 */ 54 PJ_DEF(const char*) pjturn_tp_type_name(int tp_type) 47 struct saved_cred 48 { 49 pj_str_t realm; 50 pj_str_t username; 51 pj_str_t nonce; 52 int data_type; 53 pj_str_t data; 54 }; 55 56 57 /* 58 * Get transport type name, normally for logging purpose only. 59 */ 60 PJ_DEF(const char*) pj_turn_tp_type_name(int tp_type) 55 61 { 56 62 /* Must be 3 characters long! */ 57 if (tp_type == PJ TURN_TP_UDP)63 if (tp_type == PJ_TURN_TP_UDP) { 58 64 return "UDP"; 59 else if (tp_type == PJTURN_TP_TCP)65 } else if (tp_type == PJ_TURN_TP_TCP) { 60 66 return "TCP"; 61 else 67 } else { 68 pj_assert(!"Unsupported transport"); 62 69 return "???"; 70 } 63 71 } 64 72 … … 66 74 * Create server. 67 75 */ 68 PJ_DEF(pj_status_t) pj turn_srv_create( pj_pool_factory *pf,69 pj turn_srv **p_srv)76 PJ_DEF(pj_status_t) pj_turn_srv_create(pj_pool_factory *pf, 77 pj_turn_srv **p_srv) 70 78 { 71 79 pj_pool_t *pool; 72 pjturn_srv *srv; 80 pj_turn_srv *srv; 81 unsigned i; 73 82 pj_status_t status; 74 83 … … 77 86 /* Create server and init core settings */ 78 87 pool = pj_pool_create(pf, "srv%p", 1000, 1000, NULL); 79 srv = PJ_POOL_ZALLOC_T(pool, pj turn_srv);80 srv-> core.obj_name = pool->obj_name;88 srv = PJ_POOL_ZALLOC_T(pool, pj_turn_srv); 89 srv->obj_name = pool->obj_name; 81 90 srv->core.pf = pf; 82 91 srv->core.pool = pool; 92 srv->core.tls_key = srv->core.tls_data = -1; 83 93 94 /* Create ioqueue */ 84 95 status = pj_ioqueue_create(pool, MAX_HANDLES, &srv->core.ioqueue); 85 96 if (status != PJ_SUCCESS) 86 97 goto on_error; 87 98 99 /* Server mutex */ 100 status = pj_lock_create_recursive_mutex(pool, srv->obj_name, 101 &srv->core.lock); 102 if (status != PJ_SUCCESS) 103 goto on_error; 104 105 /* Allocate TLS */ 106 status = pj_thread_local_alloc(&srv->core.tls_key); 107 if (status != PJ_SUCCESS) 108 goto on_error; 109 110 status = pj_thread_local_alloc(&srv->core.tls_data); 111 if (status != PJ_SUCCESS) 112 goto on_error; 113 114 /* Create timer heap */ 88 115 status = pj_timer_heap_create(pool, MAX_TIMER, &srv->core.timer_heap); 89 116 if (status != PJ_SUCCESS) 90 117 goto on_error; 91 118 92 srv->core.listener = pj_pool_calloc(pool, MAX_LISTENERS, 119 /* Configure lock for the timer heap */ 120 pj_timer_heap_set_lock(srv->core.timer_heap, srv->core.lock, PJ_FALSE); 121 122 /* Array of listeners */ 123 srv->core.listener = (pj_turn_listener**) 124 pj_pool_calloc(pool, MAX_LISTENERS, 93 125 sizeof(srv->core.listener[0])); 94 srv->core.stun_sess = pj_pool_calloc(pool, MAX_LISTENERS, 126 127 /* Array of STUN sessions, one for each listener */ 128 srv->core.stun_sess = (pj_stun_session**) 129 pj_pool_calloc(pool, MAX_LISTENERS, 95 130 (sizeof(srv->core.stun_sess[0]))); 96 97 srv->core.thread_cnt = MAX_THREADS;98 srv->core.thread = pj_pool_calloc(pool, srv->core.thread_cnt,99 sizeof(pj_thread_t*));100 101 status = pj_lock_create_recursive_mutex(pool, "srv%p", &srv->core.lock);102 if (status != PJ_SUCCESS)103 goto on_error;104 131 105 132 /* Create hash tables */ … … 117 144 srv->core.timer_heap); 118 145 146 /* Init STUN credential */ 147 srv->core.cred.type = PJ_STUN_AUTH_CRED_DYNAMIC; 148 srv->core.cred.data.dyn_cred.user_data = srv; 149 srv->core.cred.data.dyn_cred.get_auth = &pj_turn_get_auth; 150 srv->core.cred.data.dyn_cred.get_cred = &pj_turn_srv_get_cred; 151 srv->core.cred.data.dyn_cred.get_password = &pj_turn_get_password; 152 srv->core.cred.data.dyn_cred.verify_nonce = &pj_turn_verify_nonce; 153 154 /* Array of worker threads */ 155 srv->core.thread_cnt = MAX_THREADS; 156 srv->core.thread = (pj_thread_t**) 157 pj_pool_calloc(pool, srv->core.thread_cnt, 158 sizeof(pj_thread_t*)); 159 160 /* Start the worker threads */ 161 for (i=0; i<srv->core.thread_cnt; ++i) { 162 status = pj_thread_create(pool, srv->obj_name, &server_thread_proc, 163 srv, 0, 0, &srv->core.thread[i]); 164 if (status != PJ_SUCCESS) 165 goto on_error; 166 } 167 168 /* We're done. Application should add listeners now */ 169 PJ_LOG(4,(srv->obj_name, "TURN server v%s is running", 170 pj_get_version())); 171 119 172 *p_srv = srv; 120 173 return PJ_SUCCESS; 121 174 122 175 on_error: 123 pj turn_srv_destroy(srv);176 pj_turn_srv_destroy(srv); 124 177 return status; 125 178 } 126 179 127 /** 128 * Create server. 129 */ 130 PJ_DEF(pj_status_t) pjturn_srv_destroy(pjturn_srv *srv) 131 { 180 181 /* 182 * Handle timer and network events 183 */ 184 static void srv_handle_events(pj_turn_srv *srv, const pj_time_val *max_timeout) 185 { 186 /* timeout is 'out' var. This just to make compiler happy. */ 187 pj_time_val timeout = { 0, 0}; 188 unsigned net_event_count = 0; 189 int c; 190 191 /* Poll the timer. The timer heap has its own mutex for better 192 * granularity, so we don't need to lock the server. 193 */ 194 timeout.sec = timeout.msec = 0; 195 c = pj_timer_heap_poll( srv->core.timer_heap, &timeout ); 196 197 /* timer_heap_poll should never ever returns negative value, or otherwise 198 * ioqueue_poll() will block forever! 199 */ 200 pj_assert(timeout.sec >= 0 && timeout.msec >= 0); 201 if (timeout.msec >= 1000) timeout.msec = 999; 202 203 /* If caller specifies maximum time to wait, then compare the value with 204 * the timeout to wait from timer, and use the minimum value. 205 */ 206 if (max_timeout && PJ_TIME_VAL_GT(timeout, *max_timeout)) { 207 timeout = *max_timeout; 208 } 209 210 /* Poll ioqueue. 211 * Repeat polling the ioqueue while we have immediate events, because 212 * timer heap may process more than one events, so if we only process 213 * one network events at a time (such as when IOCP backend is used), 214 * the ioqueue may have trouble keeping up with the request rate. 215 * 216 * For example, for each send() request, one network event will be 217 * reported by ioqueue for the send() completion. If we don't poll 218 * the ioqueue often enough, the send() completion will not be 219 * reported in timely manner. 220 */ 221 do { 222 c = pj_ioqueue_poll( srv->core.ioqueue, &timeout); 223 if (c < 0) { 224 pj_thread_sleep(PJ_TIME_VAL_MSEC(timeout)); 225 return; 226 } else if (c == 0) { 227 break; 228 } else { 229 net_event_count += c; 230 timeout.sec = timeout.msec = 0; 231 } 232 } while (c > 0 && net_event_count < MAX_NET_EVENTS); 233 234 } 235 236 /* 237 * Server worker thread proc. 238 */ 239 static int server_thread_proc(void *arg) 240 { 241 pj_turn_srv *srv = (pj_turn_srv*)arg; 242 243 while (!srv->core.quit) { 244 pj_time_val timeout_max = {0, 500}; 245 srv_handle_events(srv, &timeout_max); 246 } 247 248 return 0; 249 } 250 251 /* 252 * Destroy the server. 253 */ 254 PJ_DEF(pj_status_t) pj_turn_srv_destroy(pj_turn_srv *srv) 255 { 256 pj_hash_iterator_t itbuf, *it; 257 unsigned i; 258 259 /* Stop all worker threads */ 260 srv->core.quit = PJ_TRUE; 261 for (i=0; i<srv->core.thread_cnt; ++i) { 262 if (srv->core.thread[i]) { 263 pj_thread_join(srv->core.thread[i]); 264 pj_thread_destroy(srv->core.thread[i]); 265 srv->core.thread[i] = NULL; 266 } 267 } 268 269 /* Destroy all listeners and STUN sessions associated with them. */ 270 for (i=0; i<srv->core.lis_cnt; ++i) { 271 if (srv->core.listener[i]) { 272 pj_turn_listener_destroy(srv->core.listener[i]); 273 srv->core.listener[i] = NULL; 274 } 275 if (srv->core.stun_sess[i]) { 276 pj_stun_session_destroy(srv->core.stun_sess[i]); 277 srv->core.stun_sess[i] = NULL; 278 } 279 } 280 281 /* Destroy all allocations */ 282 if (srv->tables.alloc) { 283 it = pj_hash_first(srv->tables.alloc, &itbuf); 284 while (it != NULL) { 285 pj_turn_allocation *alloc = (pj_turn_allocation*) 286 pj_hash_this(srv->tables.alloc, it); 287 pj_turn_allocation_destroy(alloc); 288 it = pj_hash_next(srv->tables.alloc, it); 289 } 290 } 291 292 293 /* Destroy hash tables (well, sort of) */ 294 if (srv->tables.alloc) { 295 srv->tables.alloc = NULL; 296 srv->tables.res = NULL; 297 } 298 299 /* Destroy timer heap */ 300 if (srv->core.timer_heap) { 301 pj_timer_heap_destroy(srv->core.timer_heap); 302 srv->core.timer_heap = NULL; 303 } 304 305 /* Destroy ioqueue */ 306 if (srv->core.ioqueue) { 307 pj_ioqueue_destroy(srv->core.ioqueue); 308 srv->core.ioqueue = NULL; 309 } 310 311 /* Destroy thread local IDs */ 312 if (srv->core.tls_key != -1) { 313 pj_thread_local_free(srv->core.tls_key); 314 srv->core.tls_key = -1; 315 } 316 if (srv->core.tls_data != -1) { 317 pj_thread_local_free(srv->core.tls_data); 318 srv->core.tls_data = -1; 319 } 320 321 /* Destroy server lock */ 322 if (srv->core.lock) { 323 pj_lock_destroy(srv->core.lock); 324 srv->core.lock = NULL; 325 } 326 327 /* Release pool */ 328 if (srv->core.pool) { 329 pj_pool_t *pool = srv->core.pool; 330 srv->core.pool = NULL; 331 pj_pool_release(pool); 332 } 333 334 /* Done */ 132 335 return PJ_SUCCESS; 133 336 } 134 337 135 /** 338 339 /* 136 340 * Add listener. 137 341 */ 138 PJ_DEF(pj_status_t) pj turn_srv_add_listener(pjturn_srv *srv,139 pjturn_listener *lis)342 PJ_DEF(pj_status_t) pj_turn_srv_add_listener(pj_turn_srv *srv, 343 pj_turn_listener *lis) 140 344 { 141 345 pj_stun_session_cb sess_cb; … … 157 361 sess_cb.on_send_msg = &on_tx_stun_msg; 158 362 159 status = pj_stun_session_create(&srv->core.stun_cfg, "lis%p", &sess_cb,160 PJ_FALSE, &sess);363 status = pj_stun_session_create(&srv->core.stun_cfg, lis->obj_name, 364 &sess_cb, PJ_FALSE, &sess); 161 365 if (status != PJ_SUCCESS) { 162 366 srv->core.listener[index] = NULL; … … 165 369 166 370 pj_stun_session_set_user_data(sess, lis); 371 pj_stun_session_set_credential(sess, &srv->core.cred); 167 372 168 373 srv->core.stun_sess[index] = sess; … … 170 375 srv->core.lis_cnt++; 171 376 377 PJ_LOG(4,(srv->obj_name, "Listener %s/%s added at index %d", 378 lis->obj_name, lis->info, lis->id)); 379 172 380 return PJ_SUCCESS; 173 381 } 174 382 175 /** 176 * Register an allocation. 177 */ 178 PJ_DEF(pj_status_t) pjturn_srv_register_allocation(pjturn_srv *srv, 179 pjturn_allocation *alloc) 383 384 /* 385 * Send packet with this listener. 386 */ 387 PJ_DEF(pj_status_t) pj_turn_listener_sendto(pj_turn_listener *listener, 388 const void *packet, 389 pj_size_t size, 390 unsigned flag, 391 const pj_sockaddr_t *addr, 392 int addr_len) 393 { 394 pj_assert(listener->id != PJ_TURN_INVALID_LIS_ID); 395 return listener->sendto(listener, packet, size, flag, addr, addr_len); 396 } 397 398 399 /* 400 * Destroy listener. 401 */ 402 PJ_DEF(pj_status_t) pj_turn_listener_destroy(pj_turn_listener *listener) 403 { 404 pj_turn_srv *srv = listener->server; 405 unsigned i; 406 407 /* Remove from our listener list */ 408 pj_lock_acquire(srv->core.lock); 409 for (i=0; i<srv->core.lis_cnt; ++i) { 410 if (srv->core.listener[i] == listener) { 411 srv->core.listener[i] = NULL; 412 srv->core.lis_cnt--; 413 listener->id = PJ_TURN_INVALID_LIS_ID; 414 if (srv->core.stun_sess[i]) { 415 pj_stun_session_destroy(srv->core.stun_sess[i]); 416 srv->core.stun_sess[i] = NULL; 417 } 418 break; 419 } 420 } 421 pj_lock_release(srv->core.lock); 422 423 /* Destroy */ 424 return listener->destroy(listener); 425 } 426 427 428 /* 429 * Register an allocation to the hash tables. 430 */ 431 PJ_DEF(pj_status_t) pj_turn_srv_register_allocation(pj_turn_srv *srv, 432 pj_turn_allocation *alloc) 180 433 { 181 434 /* Add to hash tables */ … … 191 444 } 192 445 193 /** 194 * Unregister an allocation. 195 */ 196 PJ_DEF(pj_status_t) pjturn_srv_unregister_allocation(pjturn_srv *srv, 197 pjturn_allocation *alloc) 446 447 /* 448 * Unregister an allocation from the hash tables. 449 */ 450 PJ_DEF(pj_status_t) pj_turn_srv_unregister_allocation(pj_turn_srv *srv, 451 pj_turn_allocation *alloc) 198 452 { 199 453 /* Unregister from hash tables */ … … 209 463 210 464 211 /* Callback from our own STUN session to send packet */ 465 /* Callback from our own STUN session whenever it needs to send 466 * outgoing STUN packet. 467 */ 212 468 static pj_status_t on_tx_stun_msg( pj_stun_session *sess, 213 469 const void *pkt, … … 216 472 unsigned addr_len) 217 473 { 218 pj turn_listener *listener;474 pj_turn_listener *listener; 219 475 220 listener = (pj turn_listener*) pj_stun_session_get_user_data(sess);476 listener = (pj_turn_listener*) pj_stun_session_get_user_data(sess); 221 477 222 478 PJ_ASSERT_RETURN(listener!=NULL, PJ_EINVALIDOP); 223 479 224 return pjturn_listener_sendto(listener, pkt, pkt_size, 0, 225 dst_addr, addr_len); 226 } 227 228 /* Create and send error response */ 229 static pj_status_t respond_error(pj_stun_session *sess, const pj_stun_msg *req, 230 pj_bool_t cache, int code, const char *errmsg, 231 const pj_sockaddr_t *dst_addr, 232 unsigned addr_len) 480 return pj_turn_listener_sendto(listener, pkt, pkt_size, 0, 481 dst_addr, addr_len); 482 } 483 484 485 /* Respond to STUN request */ 486 static pj_status_t stun_respond(pj_turn_srv *srv, 487 pj_stun_session *sess, 488 const pj_stun_msg *req, 489 unsigned code, 490 const char *errmsg, 491 pj_bool_t cache, 492 const pj_sockaddr_t *dst_addr, 493 unsigned addr_len) 233 494 { 234 495 pj_status_t status; … … 236 497 pj_stun_tx_data *tdata; 237 498 238 status = pj_stun_session_create_res(sess, req, 239 code, (errmsg?pj_cstr(&reason,errmsg):NULL), 499 /* Create response */ 500 status = pj_stun_session_create_res(sess, req, code, 501 (errmsg?pj_cstr(&reason,errmsg):NULL), 240 502 &tdata); 241 503 if (status != PJ_SUCCESS) 242 504 return status; 243 505 244 status = pj_stun_session_send_msg(sess, cache, dst_addr, addr_len, tdata); 245 return status; 246 247 } 248 249 /* Parse ALLOCATE request */ 250 static pj_status_t parse_allocate_req(pjturn_allocation_req *cfg, 251 pjturn_listener *listener, 252 pj_stun_session *sess, 253 const pj_stun_msg *req, 254 const pj_sockaddr_t *src_addr, 255 unsigned src_addr_len) 256 { 257 pj_stun_bandwidth_attr *attr_bw; 258 pj_stun_req_transport_attr *attr_req_tp; 259 pj_stun_req_ip_attr *attr_req_ip; 260 pj_stun_req_port_props_attr *attr_rpp; 261 pj_stun_lifetime_attr *attr_lifetime; 262 263 pj_bzero(cfg, sizeof(*cfg)); 264 265 /* Get BANDWIDTH attribute, if any. */ 266 attr_bw = (pj_stun_uint_attr*) 267 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_BANDWIDTH, 0); 268 if (attr_bw) { 269 cfg->bandwidth = attr_bw->value; 270 } else { 271 cfg->bandwidth = DEFA_CLIENT_BANDWIDTH; 272 } 273 274 /* Check if we can satisfy the bandwidth */ 275 if (cfg->bandwidth > MAX_CLIENT_BANDWIDTH) { 276 respond_error(sess, req, PJ_FALSE, 277 PJ_STUN_SC_ALLOCATION_QUOTA_REACHED, 278 "Invalid bandwidth", src_addr, src_addr_len); 279 return -1; 280 } 281 282 /* Get REQUESTED-TRANSPORT attribute, is any */ 283 attr_req_tp = (pj_stun_uint_attr*) 284 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_TRANSPORT, 0); 285 if (attr_req_tp) { 286 cfg->tp_type = PJ_STUN_GET_RT_PROTO(attr_req_tp->value); 287 } else { 288 cfg->tp_type = listener->tp_type; 289 } 290 291 /* Can only support UDP for now */ 292 if (cfg->tp_type != PJTURN_TP_UDP) { 293 respond_error(sess, req, PJ_FALSE, 294 PJ_STUN_SC_UNSUPP_TRANSPORT_PROTO, 295 NULL, src_addr, src_addr_len); 296 return -1; 297 } 298 299 /* Get REQUESTED-IP attribute, if any */ 300 attr_req_ip = (pj_stun_sockaddr_attr*) 301 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_IP, 0); 302 if (attr_req_ip) { 303 pj_sockaddr_print(&attr_req_ip->sockaddr, cfg->addr, 304 sizeof(cfg->addr), 0); 305 } 306 307 /* Get REQUESTED-PORT-PROPS attribute, if any */ 308 attr_rpp = (pj_stun_uint_attr*) 309 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REQ_PORT_PROPS, 0); 310 if (attr_rpp) { 311 cfg->rpp_bits = PJ_STUN_GET_RPP_BITS(attr_rpp->value); 312 cfg->rpp_port = PJ_STUN_GET_RPP_PORT(attr_rpp->value); 313 } else { 314 cfg->rpp_bits = 0; 315 cfg->rpp_port = 0; 316 } 317 318 /* Get LIFETIME attribute */ 319 attr_lifetime = (pj_stun_uint_attr*) 320 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_LIFETIME, 0); 321 if (attr_lifetime) { 322 cfg->lifetime = attr_lifetime->value; 323 if (cfg->lifetime < MIN_LIFETIME || cfg->lifetime > MAX_LIFETIME) { 324 respond_error(sess, req, PJ_FALSE, 325 PJ_STUN_SC_BAD_REQUEST, 326 "Invalid LIFETIME value", src_addr, 327 src_addr_len); 328 return -1; 329 } 330 } else { 331 cfg->lifetime = DEF_LIFETIME; 332 } 506 /* Store the credential for future lookup. */ 507 if (pj_stun_auth_valid_for_msg(tdata->msg)) { 508 pj_turn_srv_put_cred(srv, req, tdata); 509 } 510 511 /* Send the response */ 512 return pj_stun_session_send_msg(sess, cache, dst_addr, addr_len, tdata); 513 } 514 515 516 /* 517 * Store the credential to put placed for the specified message for 518 * future retrieval. 519 */ 520 PJ_DEF(pj_status_t) pj_turn_srv_put_cred(pj_turn_srv *srv, 521 const pj_stun_msg *req, 522 pj_stun_tx_data *response) 523 { 524 pj_stun_username_attr *user; 525 pj_stun_realm_attr *realm; 526 pj_stun_nonce_attr *nonce; 527 struct saved_cred *saved_cred; 528 pj_status_t status; 529 530 realm = (pj_stun_realm_attr*) 531 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_REALM, 0); 532 PJ_ASSERT_RETURN(realm != NULL, PJ_EBUG); 533 534 user = (pj_stun_username_attr*) 535 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_USERNAME, 0); 536 PJ_ASSERT_RETURN(user != NULL, PJ_EBUG); 537 538 nonce = (pj_stun_nonce_attr*) 539 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_NONCE, 0); 540 PJ_ASSERT_RETURN(nonce != NULL, PJ_EBUG); 541 542 saved_cred = PJ_POOL_ALLOC_T(response->pool, struct saved_cred); 543 544 /* Lookup the password */ 545 status = pj_turn_get_password(response->msg, NULL, &realm->value, 546 &user->value, response->pool, 547 &saved_cred->data_type, 548 &saved_cred->data); 549 if (status != PJ_SUCCESS) 550 return status; 551 552 /* Store credential */ 553 pj_strdup(response->pool, &saved_cred->username, &user->value); 554 pj_strdup(response->pool, &saved_cred->realm, &realm->value); 555 pj_strdup(response->pool, &saved_cred->nonce, &nonce->value); 556 557 pj_thread_local_set(srv->core.tls_key, response->msg); 558 pj_thread_local_set(srv->core.tls_data, saved_cred); 333 559 334 560 return PJ_SUCCESS; 335 561 } 336 562 337 /* Callback from our own STUN session when incoming request arrives */ 563 564 /** 565 * Retrieve previously stored credential for the specified message. 566 */ 567 PJ_DEF(pj_status_t) pj_turn_srv_get_cred(const pj_stun_msg *msg, 568 void *user_data, 569 pj_pool_t *pool, 570 pj_str_t *realm, 571 pj_str_t *username, 572 pj_str_t *nonce, 573 int *data_type, 574 pj_str_t *data) 575 { 576 pj_turn_srv *srv; 577 const pj_stun_msg *saved_msg; 578 struct saved_cred *saved_cred; 579 580 PJ_UNUSED_ARG(pool); 581 582 srv = (pj_turn_srv*)user_data; 583 584 /* Lookup stored message and make sure it's for the same message */ 585 saved_msg = (const pj_stun_msg*) 586 pj_thread_local_get(srv->core.tls_key); 587 PJ_ASSERT_RETURN(saved_msg==msg, PJ_ENOTFOUND); 588 589 /* Lookup saved credential */ 590 saved_cred = (struct saved_cred*) 591 pj_thread_local_get(srv->core.tls_data); 592 PJ_ASSERT_RETURN(saved_cred != NULL, PJ_ENOTFOUND); 593 594 595 *realm = saved_cred->realm; 596 *username = saved_cred->username; 597 *nonce = saved_cred->nonce; 598 *data_type = saved_cred->data_type; 599 *data = saved_cred->data; 600 601 602 /* Don't clear saved_cred as this may be called more than once */ 603 604 return PJ_SUCCESS; 605 } 606 607 608 /* Callback from our own STUN session when incoming request arrives. 609 * This function is triggered by pj_stun_session_on_rx_pkt() call in 610 * pj_turn_srv_on_rx_pkt() function below. 611 */ 338 612 static pj_status_t on_rx_stun_request(pj_stun_session *sess, 339 613 const pj_uint8_t *pkt, … … 343 617 unsigned src_addr_len) 344 618 { 345 pjturn_listener *listener; 346 pjturn_srv *srv; 347 pjturn_allocation_req req; 348 pjturn_allocation *alloc; 349 pj_stun_tx_data *tdata; 619 pj_turn_listener *listener; 620 pj_turn_srv *srv; 621 pj_turn_allocation *alloc; 350 622 pj_status_t status; 351 623 352 listener = (pjturn_listener*) pj_stun_session_get_user_data(sess); 624 PJ_UNUSED_ARG(pkt); 625 PJ_UNUSED_ARG(pkt_len); 626 627 listener = (pj_turn_listener*) pj_stun_session_get_user_data(sess); 353 628 srv = listener->server; 354 629 355 /* Handle strayed REFRESH request */ 356 if (msg->hdr.type == PJ_STUN_REFRESH_REQUEST) { 357 return respond_error(sess, msg, PJ_FALSE, 358 PJ_STUN_SC_ALLOCATION_MISMATCH, 359 NULL, src_addr, src_addr_len); 360 } 361 362 /* Respond any other requests with Bad Request response */ 630 /* Respond any requests other than ALLOCATE with 437 response */ 363 631 if (msg->hdr.type != PJ_STUN_ALLOCATE_REQUEST) { 364 return respond_error(sess, msg, PJ_FALSE, PJ_STUN_SC_BAD_REQUEST, 365 NULL, src_addr, src_addr_len); 366 } 367 368 /* We have ALLOCATE request here, and it's authenticated. Parse the 369 * request. 370 */ 371 status = parse_allocate_req(&req, listener, sess, msg, src_addr, 372 src_addr_len); 373 if (status != PJ_SUCCESS) 374 return status; 632 stun_respond(srv, sess, msg, PJ_STUN_SC_ALLOCATION_MISMATCH, 633 NULL, PJ_FALSE, src_addr, src_addr_len); 634 return PJ_SUCCESS; 635 } 375 636 376 637 /* Create new allocation. The relay resource will be allocated 377 638 * in this function. 378 639 */ 379 status = pj turn_allocation_create(listener, src_addr, src_addr_len,380 msg, &req, &alloc);640 status = pj_turn_allocation_create(listener, src_addr, src_addr_len, 641 msg, sess, &alloc); 381 642 if (status != PJ_SUCCESS) { 382 char errmsg[PJ_ERR_MSG_SIZE]; 383 384 pj_strerror(status, errmsg, sizeof(errmsg)); 385 return respond_error(sess, msg, PJ_FALSE, PJ_STUN_SC_SERVER_ERROR, 386 errmsg, src_addr, src_addr_len); 387 } 388 389 /* Respond the original ALLOCATE request */ 390 status = pj_stun_session_create_res(srv->core.stun_sess[listener->id], 391 msg, 0, NULL, &tdata); 392 if (status != PJ_SUCCESS) { 393 char errmsg[PJ_ERR_MSG_SIZE]; 394 395 pjturn_allocation_destroy(alloc); 396 397 pj_strerror(status, errmsg, sizeof(errmsg)); 398 return respond_error(sess, msg, PJ_FALSE, PJ_STUN_SC_SERVER_ERROR, 399 errmsg, src_addr, src_addr_len); 400 } 401 402 /* Add RELAYED-ADDRESS attribute */ 403 pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 404 PJ_STUN_ATTR_RELAY_ADDR, PJ_TRUE, 405 &alloc->relay.hkey.addr, 406 pj_sockaddr_get_len(&alloc->relay.hkey.addr)); 407 408 /* Add LIFETIME. */ 409 pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 410 PJ_STUN_ATTR_LIFETIME, 411 (unsigned)alloc->relay.lifetime); 412 413 /* Add BANDWIDTH */ 414 pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 415 PJ_STUN_ATTR_BANDWIDTH, 416 alloc->bandwidth); 417 418 /* Add RESERVATION-TOKEN */ 419 PJ_TODO(ADD_RESERVATION_TOKEN); 420 421 /* Add XOR-MAPPED-ADDRESS */ 422 pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg, 423 PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE, 424 &alloc->hkey.clt_addr, 425 pj_sockaddr_get_len(&alloc->hkey.clt_addr)); 426 427 /* Send the response */ 428 pj_stun_session_send_msg(srv->core.stun_sess[listener->id], PJ_TRUE, 429 src_addr, src_addr_len, tdata); 643 /* STUN response has been sent, no need to reply here */ 644 return PJ_SUCCESS; 645 } 430 646 431 647 /* Done. */ … … 434 650 435 651 436 /* Handle packet from new client address. */ 437 static void handle_new_client( pjturn_srv *srv, 438 pjturn_pkt *pkt) 439 { 440 unsigned options, lis_id; 441 pj_status_t status; 442 443 /* Check that this is a STUN message */ 444 options = PJ_STUN_CHECK_PACKET; 445 if (pkt->listener->tp_type == PJTURN_TP_UDP) 446 options |= PJ_STUN_IS_DATAGRAM; 447 448 status = pj_stun_msg_check(pkt->pkt, pkt->len, options); 449 if (status != PJ_SUCCESS) { 450 char errmsg[PJ_ERR_MSG_SIZE]; 451 char ip[PJ_INET6_ADDRSTRLEN+10]; 452 453 pj_strerror(status, errmsg, sizeof(errmsg)); 454 PJ_LOG(5,(srv->core.obj_name, 455 "Non STUN packet from %s is dropped: %s", 456 pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 457 errmsg)); 458 return; 459 } 460 461 lis_id = pkt->listener->id; 462 463 /* Hand over processing to STUN session */ 464 options &= ~PJ_STUN_CHECK_PACKET; 465 status = pj_stun_session_on_rx_pkt(srv->core.stun_sess[lis_id], pkt->pkt, 466 pkt->len, options, NULL, 467 &pkt->src.clt_addr, 468 pkt->src_addr_len); 469 if (status != PJ_SUCCESS) { 470 char errmsg[PJ_ERR_MSG_SIZE]; 471 char ip[PJ_INET6_ADDRSTRLEN+10]; 472 473 pj_strerror(status, errmsg, sizeof(errmsg)); 474 PJ_LOG(5,(srv->core.obj_name, 475 "Error processing STUN packet from %s: %s", 476 pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 477 errmsg)); 478 return; 479 } 480 } 481 482 483 /* 484 * This callback is called by UDP listener on incoming packet. 485 */ 486 PJ_DEF(void) pjturn_srv_on_rx_pkt( pjturn_srv *srv, 487 pjturn_pkt *pkt) 488 { 489 pjturn_allocation *alloc; 652 /* 653 * This callback is called by UDP listener on incoming packet. This is 654 * the first entry for incoming packet (from client) to the server. From 655 * here, the packet may be handed over to an allocation if an allocation 656 * is found for the client address, or handed over to owned STUN session 657 * if an allocation is not found. 658 */ 659 PJ_DEF(void) pj_turn_srv_on_rx_pkt(pj_turn_srv *srv, 660 pj_turn_pkt *pkt) 661 { 662 pj_turn_allocation *alloc; 490 663 491 664 /* Get TURN allocation from the source address */ … … 498 671 */ 499 672 if (alloc) { 500 pj turn_allocation_on_rx_client_pkt(alloc, pkt);673 pj_turn_allocation_on_rx_client_pkt(alloc, pkt); 501 674 } else { 502 675 /* Otherwise this is a new client */ 503 handle_new_client(srv, pkt); 504 } 505 } 506 507 676 unsigned options, lis_id; 677 pj_status_t status; 678 679 /* Check that this is a STUN message */ 680 options = PJ_STUN_CHECK_PACKET; 681 if (pkt->listener->tp_type == PJ_TURN_TP_UDP) 682 options |= PJ_STUN_IS_DATAGRAM; 683 684 status = pj_stun_msg_check(pkt->pkt, pkt->len, options); 685 if (status != PJ_SUCCESS) { 686 char errmsg[PJ_ERR_MSG_SIZE]; 687 char ip[PJ_INET6_ADDRSTRLEN+10]; 688 689 pj_strerror(status, errmsg, sizeof(errmsg)); 690 PJ_LOG(5,(srv->obj_name, 691 "Non STUN packet from %s is dropped: %s", 692 pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 693 errmsg)); 694 return; 695 } 696 697 lis_id = pkt->listener->id; 698 699 /* Hand over processing to STUN session. This will trigger 700 * on_rx_stun_request() callback to be called if the STUN 701 * message is a request. 702 */ 703 options &= ~PJ_STUN_CHECK_PACKET; 704 status = pj_stun_session_on_rx_pkt(srv->core.stun_sess[lis_id], 705 pkt->pkt, pkt->len, options, NULL, 706 &pkt->src.clt_addr, 707 pkt->src_addr_len); 708 if (status != PJ_SUCCESS) { 709 char errmsg[PJ_ERR_MSG_SIZE]; 710 char ip[PJ_INET6_ADDRSTRLEN+10]; 711 712 pj_strerror(status, errmsg, sizeof(errmsg)); 713 PJ_LOG(5,(srv->obj_name, 714 "Error processing STUN packet from %s: %s", 715 pj_sockaddr_print(&pkt->src.clt_addr, ip, sizeof(ip), 3), 716 errmsg)); 717 return; 718 } 719 } 720 } 721 722 -
pjproject/trunk/pjnath/src/pjturn-srv/turn.h
r1850 r1852 17 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 18 */ 19 #ifndef __PJ TURN_SRV_TURN_H__20 #define __PJ TURN_SRV_TURN_H__19 #ifndef __PJ_TURN_SRV_TURN_H__ 20 #define __PJ_TURN_SRV_TURN_H__ 21 21 22 22 #include <pjlib.h> 23 23 #include <pjnath.h> 24 24 25 typedef struct pjturn_relay_res pjturn_relay_res; 26 typedef struct pjturn_listener pjturn_listener; 27 typedef struct pjturn_permission pjturn_permission; 28 typedef struct pjturn_allocation pjturn_allocation; 29 typedef struct pjturn_srv pjturn_srv; 30 typedef struct pjturn_pkt pjturn_pkt; 31 32 33 #define PJTURN_INVALID_CHANNEL 0xFFFF 34 #define PJTURN_NO_TIMEOUT ((long)0x7FFFFFFF) 35 #define PJTURN_MAX_PKT_LEN 3000 36 #define PJTURN_PERM_TIMEOUT 300 37 #define PJTURN_CHANNEL_TIMEOUT 600 25 typedef struct pj_turn_relay_res pj_turn_relay_res; 26 typedef struct pj_turn_listener pj_turn_listener; 27 typedef struct pj_turn_permission pj_turn_permission; 28 typedef struct pj_turn_allocation pj_turn_allocation; 29 typedef struct pj_turn_srv pj_turn_srv; 30 typedef struct pj_turn_pkt pj_turn_pkt; 31 32 33 #define PJ_TURN_INVALID_CHANNEL 0xFFFF 34 #define PJ_TURN_INVALID_LIS_ID ((unsigned)-1) 35 #define PJ_TURN_NO_TIMEOUT ((long)0x7FFFFFFF) 36 #define PJ_TURN_MAX_PKT_LEN 3000 37 #define PJ_TURN_PERM_TIMEOUT 300 38 #define PJ_TURN_CHANNEL_TIMEOUT 600 38 39 39 40 /** Transport types */ 40 41 enum { 41 PJ TURN_TP_UDP = 16, /**< UDP. */42 PJ TURN_TP_TCP = 6 /**< TCP. */42 PJ_TURN_TP_UDP = 16, /**< UDP. */ 43 PJ_TURN_TP_TCP = 6 /**< TCP. */ 43 44 }; 44 45 … … 46 47 * Get transport type name string. 47 48 */ 48 PJ_DECL(const char*) pj turn_tp_type_name(int tp_type);49 PJ_DECL(const char*) pj_turn_tp_type_name(int tp_type); 49 50 50 51 /** … … 52 53 * one relay resource, and optionally it may reserve another resource. 53 54 */ 54 struct pj turn_relay_res55 struct pj_turn_relay_res 55 56 { 56 57 /** Hash table key */ … … 64 65 65 66 /** Allocation who requested or reserved this resource. */ 66 pj turn_allocation *allocation;67 pj_turn_allocation *allocation; 67 68 68 69 /** Username used in credential */ … … 93 94 94 95 /** The incoming packet buffer */ 95 char rx_pkt[PJ TURN_MAX_PKT_LEN];96 char rx_pkt[PJ_TURN_MAX_PKT_LEN]; 96 97 97 98 /** Source address of the packet. */ … … 102 103 103 104 /** The outgoing packet buffer. This must be 3wbit aligned. */ 104 char tx_pkt[PJ TURN_MAX_PKT_LEN+4];105 char tx_pkt[PJ_TURN_MAX_PKT_LEN+4]; 105 106 } tp; 106 107 }; … … 116 117 * allocation hash table. 117 118 */ 118 typedef struct pj turn_allocation_key119 typedef struct pj_turn_allocation_key 119 120 { 120 121 int tp_type; /**< Transport type. */ 121 122 pj_sockaddr clt_addr; /**< Client's address. */ 122 } pjturn_allocation_key; 123 124 125 /** 126 * Allocation request. 127 */ 128 typedef struct pjturn_allocation_req 129 { 130 /** Requested transport */ 131 unsigned tp_type; 132 133 /** Requested IP */ 134 char addr[PJ_INET6_ADDRSTRLEN]; 123 } pj_turn_allocation_key; 124 125 126 /** 127 * This structure describes TURN pj_turn_allocation session. 128 */ 129 struct pj_turn_allocation 130 { 131 /** Hash table key to identify client. */ 132 pj_turn_allocation_key hkey; 133 134 /** Pool for this allocation. */ 135 pj_pool_t *pool; 136 137 /** Object name for logging identification */ 138 char *obj_name; 139 140 /** Client info (IP address and port) */ 141 char info[80]; 142 143 /** Mutex */ 144 pj_lock_t *lock; 145 146 /** TURN listener. */ 147 pj_turn_listener *listener; 148 149 /** Client socket, if connection to client is using TCP. */ 150 pj_sock_t clt_sock; 151 152 /** The relay resource for this allocation. */ 153 pj_turn_relay_res relay; 154 155 /** Relay resource reserved by this allocation, if any */ 156 pj_turn_relay_res *resv; 135 157 136 158 /** Requested bandwidth */ 137 159 unsigned bandwidth; 138 160 139 /** Lifetime. */140 unsigned lifetime;141 142 /** A bits */143 unsigned rpp_bits;144 145 /** Requested port */146 unsigned rpp_port;147 148 } pjturn_allocation_req;149 150 151 /**152 * This structure describes TURN pjturn_allocation session.153 */154 struct pjturn_allocation155 {156 /** Hash table key to identify client. */157 pjturn_allocation_key hkey;158 159 /** Pool for this allocation. */160 pj_pool_t *pool;161 162 /** Object name for logging identification */163 char *obj_name;164 165 /** Client info (IP address and port) */166 char info[80];167 168 /** Mutex */169 pj_lock_t *lock;170 171 /** TURN listener. */172 pjturn_listener *listener;173 174 /** Client socket, if connection to client is using TCP. */175 pj_sock_t clt_sock;176 177 /** The relay resource for this allocation. */178 pjturn_relay_res relay;179 180 /** Relay resource reserved by this allocation, if any */181 pjturn_relay_res *resv;182 183 /** Requested bandwidth */184 unsigned bandwidth;185 186 161 /** STUN session for this client */ 187 162 pj_stun_session *sess; 188 163 164 /** Credential for this STUN session. */ 165 pj_stun_auth_cred cred; 166 189 167 /** Peer hash table (keyed by peer address) */ 190 168 pj_hash_table_t *peer_table; … … 199 177 * permission. 200 178 */ 201 typedef struct pj turn_permission_key179 typedef struct pj_turn_permission_key 202 180 { 203 181 /** Peer address. */ 204 182 pj_sockaddr peer_addr; 205 183 206 } pj turn_permission_key;207 208 209 /** 210 * This structure describes TURN pj turn_permission or channel.211 */ 212 struct pj turn_permission184 } pj_turn_permission_key; 185 186 187 /** 188 * This structure describes TURN pj_turn_permission or channel. 189 */ 190 struct pj_turn_permission 213 191 { 214 192 /** Hash table key */ 215 pj turn_permission_key hkey;193 pj_turn_permission_key hkey; 216 194 217 195 /** Transport socket. If TCP is used, the value will be the actual … … 221 199 222 200 /** TURN allocation that owns this permission/channel */ 223 pj turn_allocation *allocation;224 225 /** Optional channel number, or PJ TURN_INVALID_CHANNEL if channel number201 pj_turn_allocation *allocation; 202 203 /** Optional channel number, or PJ_TURN_INVALID_CHANNEL if channel number 226 204 * is not requested for this permission. 227 205 */ … … 235 213 * Create new allocation. 236 214 */ 237 PJ_DECL(pj_status_t) pj turn_allocation_create(pjturn_listener *listener,215 PJ_DECL(pj_status_t) pj_turn_allocation_create(pj_turn_listener *listener, 238 216 const pj_sockaddr_t *src_addr, 239 217 unsigned src_addr_len, 240 218 const pj_stun_msg *msg, 241 const pjturn_allocation_req *req,242 pj turn_allocation **p_alloc);219 pj_stun_session *srv_sess, 220 pj_turn_allocation **p_alloc); 243 221 /** 244 222 * Destroy allocation. 245 223 */ 246 PJ_DECL(void) pjturn_allocation_destroy(pjturn_allocation *alloc); 247 248 /** 249 * Create relay. 250 */ 251 PJ_DECL(pj_status_t) pjturn_allocation_create_relay(pjturn_srv *srv, 252 pjturn_allocation *alloc, 253 const pj_stun_msg *msg, 254 const pjturn_allocation_req *req, 255 pjturn_relay_res *relay); 224 PJ_DECL(void) pj_turn_allocation_destroy(pj_turn_allocation *alloc); 225 256 226 257 227 /** 258 228 * Handle incoming packet from client. 259 229 */ 260 PJ_DECL(void) pj turn_allocation_on_rx_client_pkt(pjturn_allocation *alloc,261 pj turn_pkt *pkt);230 PJ_DECL(void) pj_turn_allocation_on_rx_client_pkt(pj_turn_allocation *alloc, 231 pj_turn_pkt *pkt); 262 232 263 233 /****************************************************************************/ … … 270 240 * listens for incoming connections from clients. 271 241 */ 272 struct pjturn_listener 273 { 242 struct pj_turn_listener 243 { 244 /** Object name/identification */ 245 char *obj_name; 246 247 /** Slightly longer info about this listener */ 248 char info[80]; 249 274 250 /** TURN server instance. */ 275 pj turn_srv *server;251 pj_turn_srv *server; 276 252 277 253 /** Listener index in the server */ … … 294 270 295 271 /** Sendto handler */ 296 pj_status_t (*sendto)(pj turn_listener *listener,272 pj_status_t (*sendto)(pj_turn_listener *listener, 297 273 const void *packet, 298 274 pj_size_t size, … … 302 278 303 279 /** Destroy handler */ 304 pj_status_t (*destroy)(pj turn_listener*);280 pj_status_t (*destroy)(pj_turn_listener*); 305 281 }; 306 282 … … 309 285 * An incoming packet. 310 286 */ 311 struct pj turn_pkt287 struct pj_turn_pkt 312 288 { 313 289 /** Pool for this packet */ … … 315 291 316 292 /** Listener that owns this. */ 317 pj turn_listener *listener;293 pj_turn_listener *listener; 318 294 319 295 /** Packet buffer (must be 32bit aligned). */ 320 pj_uint8_t pkt[PJ TURN_MAX_PKT_LEN];296 pj_uint8_t pkt[PJ_TURN_MAX_PKT_LEN]; 321 297 322 298 /** Size of the packet */ … … 327 303 328 304 /** Source transport type and source address. */ 329 pj turn_allocation_key src;305 pj_turn_allocation_key src; 330 306 331 307 /** Source address length. */ … … 337 313 * Create a new listener on the specified port. 338 314 */ 339 PJ_DECL(pj_status_t) pj turn_listener_create_udp(pjturn_srv *srv,315 PJ_DECL(pj_status_t) pj_turn_listener_create_udp(pj_turn_srv *srv, 340 316 int af, 341 317 const pj_str_t *bound_addr, … … 343 319 unsigned concurrency_cnt, 344 320 unsigned flags, 345 pj turn_listener **p_listener);321 pj_turn_listener **p_listener); 346 322 347 323 /** 348 324 * Send packet with this listener. 349 325 */ 350 PJ_DECL(pj_status_t) pj turn_listener_sendto(pjturn_listener *listener,326 PJ_DECL(pj_status_t) pj_turn_listener_sendto(pj_turn_listener *listener, 351 327 const void *packet, 352 328 pj_size_t size, … … 358 334 * Destroy listener. 359 335 */ 360 PJ_DECL(pj_status_t) pj turn_listener_destroy(pjturn_listener *listener);336 PJ_DECL(pj_status_t) pj_turn_listener_destroy(pj_turn_listener *listener); 361 337 362 338 … … 366 342 */ 367 343 /** 368 * This structure describes TURN pjturn_srv instance. 369 */ 370 struct pjturn_srv 371 { 344 * This structure describes TURN pj_turn_srv instance. 345 */ 346 struct pj_turn_srv 347 { 348 /** Object name */ 349 char *obj_name; 350 372 351 /** Core settings */ 373 352 struct { 374 /** Object name */375 char *obj_name;376 377 353 /** Pool factory */ 378 354 pj_pool_factory *pf; … … 394 370 395 371 /** Array of listeners. */ 396 pj turn_listener **listener;372 pj_turn_listener **listener; 397 373 398 374 /** Array of STUN sessions, one for each listeners. */ … … 405 381 pj_thread_t **thread; 406 382 383 /** Thread quit signal */ 384 pj_bool_t quit; 385 407 386 /** STUN config. */ 408 387 pj_stun_config stun_cfg; 409 388 389 /** STUN auth credential. */ 390 pj_stun_auth_cred cred; 391 392 /** Thread local ID for storing credential */ 393 long tls_key, tls_data; 410 394 411 395 } core; … … 454 438 * Create server. 455 439 */ 456 PJ_DECL(pj_status_t) pj turn_srv_create(pj_pool_factory *pf,457 pjturn_srv **p_srv);440 PJ_DECL(pj_status_t) pj_turn_srv_create(pj_pool_factory *pf, 441 pj_turn_srv **p_srv); 458 442 459 443 /** 460 444 * Destroy server. 461 445 */ 462 PJ_DECL(pj_status_t) pj turn_srv_destroy(pjturn_srv *srv);446 PJ_DECL(pj_status_t) pj_turn_srv_destroy(pj_turn_srv *srv); 463 447 464 448 /** 465 449 * Add listener. 466 450 */ 467 PJ_DECL(pj_status_t) pj turn_srv_add_listener(pjturn_srv *srv,468 pjturn_listener *lis);451 PJ_DECL(pj_status_t) pj_turn_srv_add_listener(pj_turn_srv *srv, 452 pj_turn_listener *lis); 469 453 470 454 /** 471 455 * Register an allocation. 472 456 */ 473 PJ_DECL(pj_status_t) pj turn_srv_register_allocation(pjturn_srv *srv,474 pjturn_allocation *alloc);457 PJ_DECL(pj_status_t) pj_turn_srv_register_allocation(pj_turn_srv *srv, 458 pj_turn_allocation *alloc); 475 459 476 460 /** 477 461 * Unregister an allocation. 478 462 */ 479 PJ_DECL(pj_status_t) pj turn_srv_unregister_allocation(pjturn_srv *srv,480 pjturn_allocation *alloc);463 PJ_DECL(pj_status_t) pj_turn_srv_unregister_allocation(pj_turn_srv *srv, 464 pj_turn_allocation *alloc); 481 465 482 466 /** 483 467 * This callback is called by UDP listener on incoming packet. 484 468 */ 485 PJ_DECL(void) pjturn_srv_on_rx_pkt(pjturn_srv *srv, 486 pjturn_pkt *pkt); 487 488 489 #endif /* __PJTURN_SRV_TURN_H__ */ 490 469 PJ_DECL(void) pj_turn_srv_on_rx_pkt(pj_turn_srv *srv, 470 pj_turn_pkt *pkt); 471 472 473 /** 474 * Store the credential to put placed for the specified message for 475 * future retrieval. 476 */ 477 PJ_DECL(pj_status_t) pj_turn_srv_put_cred(pj_turn_srv *srv, 478 const pj_stun_msg *request, 479 pj_stun_tx_data *response); 480 481 /** 482 * Retrieve previously stored credential for the specified message. 483 */ 484 PJ_DECL(pj_status_t) pj_turn_srv_get_cred(const pj_stun_msg *msg, 485 void *user_data, 486 pj_pool_t *pool, 487 pj_str_t *realm, 488 pj_str_t *username, 489 pj_str_t *nonce, 490 int *data_type, 491 pj_str_t *data); 492 493 494 #endif /* __PJ_TURN_SRV_TURN_H__ */ 495
Note: See TracChangeset
for help on using the changeset viewer.