Changeset 217 for pjproject/trunk/pjlib-util/src/pjlib-util/stun_client.c
- Timestamp:
- Feb 22, 2006 10:10:42 PM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib-util/src/pjlib-util/stun_client.c
r185 r217 18 18 */ 19 19 #include <pjlib-util/stun.h> 20 #include <pjlib-util/errno.h> 21 #include <pj/os.h> 20 22 #include <pj/pool.h> 21 #include <pj/log.h> 23 #include <pj/rand.h> 24 #include <pj/sock_select.h> 22 25 #include <pj/string.h> 23 #include <pj/os.h> 24 #include <pj/sock_select.h> 26 25 27 26 28 enum { MAX_REQUEST = 3 }; 27 29 static int stun_timer[] = {1600, 1600, 1600 }; 28 30 29 #define THIS_FILE "stun client"31 #define THIS_FILE "stun_client.c" 30 32 #define LOG_ADDR(addr) pj_inet_ntoa(addr.sin_addr), pj_ntohs(addr.sin_port) 31 33 … … 38 40 { 39 41 pj_sockaddr_in srv_addr[2]; 40 int i, j, rc,send_cnt = 0;42 int i, j, send_cnt = 0; 41 43 pj_pool_t *pool; 42 44 struct { … … 49 51 pj_size_t out_msg_len; 50 52 int wait_resp = 0; 51 int mapped_status = 0;53 pj_status_t status; 52 54 53 55 PJ_CHECK_STACK(); … … 55 57 /* Create pool. */ 56 58 pool = pj_pool_create(pf, "stun%p", 1024, 1024, NULL); 57 if (!pool) { 58 mapped_status = PJ_STUN_ERR_MEMORY; 59 return -1; 60 } 59 if (!pool) 60 return PJ_ENOMEM; 61 61 62 62 63 /* Allocate client records */ 63 64 rec = pj_pool_calloc(pool, sock_cnt, sizeof(*rec)); 64 65 if (!rec) { 65 mapped_status = PJ_STUN_ERR_MEMORY;66 status = PJ_ENOMEM; 66 67 goto on_error; 67 68 } 68 69 70 69 71 /* Create the outgoing BIND REQUEST message template */ 70 rc = pj_stun_create_bind_req( pool, &out_msg, &out_msg_len, 0, 0); 71 if (rc != 0) { 72 mapped_status = -1; 73 goto on_error; 74 } 72 status = pj_stun_create_bind_req( pool, &out_msg, &out_msg_len, 73 pj_rand(), pj_rand()); 74 if (status != PJ_SUCCESS) 75 goto on_error; 75 76 76 77 /* Resolve servers. */ 77 if (pj_sockaddr_in_init(&srv_addr[0], srv1, (pj_uint16_t)port1) != 0) { 78 mapped_status = PJ_STUN_ERR_RESOLVE; 79 goto on_error; 80 } 81 if (pj_sockaddr_in_init(&srv_addr[1], srv2, (pj_uint16_t)port2) != 0) { 82 mapped_status = PJ_STUN_ERR_RESOLVE; 83 goto on_error; 84 } 78 status = pj_sockaddr_in_init(&srv_addr[0], srv1, (pj_uint16_t)port1); 79 if (status != PJ_SUCCESS) 80 goto on_error; 81 82 status = pj_sockaddr_in_init(&srv_addr[1], srv2, (pj_uint16_t)port2); 83 if (status != PJ_SUCCESS) 84 goto on_error; 85 85 86 86 /* Init mapped addresses to zero */ … … 93 93 int select_rc; 94 94 95 PJ_LOG(4,(THIS_FILE, "STUN retransmit %d, wait_resp=%d",96 send_cnt, wait_resp));97 98 95 PJ_FD_ZERO(&r); 99 96 100 97 /* Send messages to servers that has not given us response. */ 101 for (i=0; i<sock_cnt && mapped_status==0; ++i) {102 for (j=0; j<2 && mapped_status==0; ++j) {98 for (i=0; i<sock_cnt && status==PJ_SUCCESS; ++i) { 99 for (j=0; j<2 && status==PJ_SUCCESS; ++j) { 103 100 pj_stun_msg_hdr *msg_hdr = out_msg; 104 101 pj_ssize_t sent_len; … … 113 110 /* Send! */ 114 111 sent_len = out_msg_len; 115 rc = pj_sock_sendto(sock[i], out_msg, &sent_len, 0, 116 (pj_sockaddr_t*)&srv_addr[j], 117 sizeof(pj_sockaddr_in)); 118 if (sent_len != (int)out_msg_len) { 119 PJ_LOG(4,(THIS_FILE, 120 "Error sending STUN request to %s:%d", 121 LOG_ADDR(srv_addr[j]))); 122 mapped_status = PJ_STUN_ERR_TRANSPORT; 123 } else { 112 status = pj_sock_sendto(sock[i], out_msg, &sent_len, 0, 113 (pj_sockaddr_t*)&srv_addr[j], 114 sizeof(pj_sockaddr_in)); 115 if (status == PJ_SUCCESS) 124 116 ++wait_resp; 125 }126 117 } 127 118 } … … 140 131 141 132 for (pj_gettimeofday(&now), select_rc=1; 142 mapped_status==0 && select_rc==1 && wait_resp>0 && PJ_TIME_VAL_LT(now, next_tx); 133 status==PJ_SUCCESS && select_rc==1 && wait_resp>0 134 && PJ_TIME_VAL_LT(now, next_tx); 143 135 pj_gettimeofday(&now)) 144 136 { … … 169 161 170 162 len = sizeof(recv_buf); 171 pj_sock_recvfrom( sock[i], recv_buf,172 &len, 0,173 (pj_sockaddr_t*)&addr,174 &addrlen);163 status = pj_sock_recvfrom( sock[i], recv_buf, 164 &len, 0, 165 (pj_sockaddr_t*)&addr, 166 &addrlen); 175 167 176 168 --wait_resp; 177 169 178 if (len < 1) { 179 mapped_status = PJ_STUN_ERR_TRANSPORT; 180 continue; 181 } 182 183 if (pj_stun_parse_msg(recv_buf, len, &msg) != 0) { 184 PJ_LOG(4,(THIS_FILE, 185 "Error parsing STUN response from %s:%d", 186 LOG_ADDR(addr))); 187 mapped_status = PJ_STUN_ERR_INVALID_MSG; 188 continue; 189 } 170 if (status != PJ_SUCCESS) 171 continue; 172 173 status = pj_stun_parse_msg(recv_buf, len, &msg); 174 if (status != PJ_SUCCESS) { 175 continue; 176 } 177 190 178 191 179 sock_idx = pj_ntohl(msg.hdr->tsx[2]); … … 193 181 194 182 if (sock_idx<0 || sock_idx>=sock_cnt || srv_idx<0 || srv_idx>=2) { 195 PJ_LOG(4,(THIS_FILE, 196 "Invalid transaction ID from %s:%d", 197 LOG_ADDR(addr))); 198 mapped_status = PJ_STUN_ERR_INVALID_MSG; 183 status = PJLIB_UTIL_ESTUNININDEX; 199 184 continue; 200 185 } 201 186 202 187 if (pj_ntohs(msg.hdr->type) != PJ_STUN_BINDING_RESPONSE) { 203 PJ_LOG(4,(THIS_FILE, 204 "Non binding response %d from %s:%d", 205 pj_ntohs(msg.hdr->type), LOG_ADDR(addr))); 206 mapped_status = PJ_STUN_ERR_INVALID_MSG; 188 status = PJLIB_UTIL_ESTUNNOBINDRES; 207 189 continue; 208 190 } 209 191 210 192 if (pj_stun_msg_find_attr(&msg, PJ_STUN_ATTR_ERROR_CODE) != NULL) { 211 PJ_LOG(4,(THIS_FILE, 212 "Got STUN error attribute from %s:%d", 213 LOG_ADDR(addr))); 214 mapped_status = PJ_STUN_ERR_INVALID_MSG; 193 status = PJLIB_UTIL_ESTUNRECVERRATTR; 215 194 continue; 216 195 } … … 218 197 attr = (void*)pj_stun_msg_find_attr(&msg, PJ_STUN_ATTR_MAPPED_ADDR); 219 198 if (!attr) { 220 PJ_LOG(4,(THIS_FILE, 221 "No mapped address in response from %s:%d", 222 LOG_ADDR(addr))); 223 mapped_status = PJ_STUN_ERR_INVALID_MSG; 199 status = PJLIB_UTIL_ESTUNNOMAP; 224 200 continue; 225 201 } … … 237 213 } 238 214 239 for (i=0; i<sock_cnt && mapped_status==0; ++i) {215 for (i=0; i<sock_cnt && status==PJ_SUCCESS; ++i) { 240 216 if (rec[i].srv[0].mapped_addr == rec[i].srv[1].mapped_addr && 241 217 rec[i].srv[0].mapped_port == rec[i].srv[1].mapped_port) … … 246 222 247 223 if (rec[i].srv[0].mapped_addr == 0 || rec[i].srv[0].mapped_port == 0) { 248 mapped_status = PJ_STUN_ERR_NO_RESPONSE;224 status = PJLIB_UTIL_ESTUNNOTRESPOND; 249 225 break; 250 226 } 251 227 } else { 252 mapped_status = PJ_STUN_ERR_SYMETRIC;228 status = PJLIB_UTIL_ESTUNSYMMETRIC; 253 229 break; 254 230 } … … 257 233 pj_pool_release(pool); 258 234 259 return mapped_status;235 return status; 260 236 261 237 on_error: 262 238 if (pool) pj_pool_release(pool); 263 return -1;239 return status; 264 240 } 265 241 266 PJ_DEF(const char*) pj_stun_get_err_msg(pj_status_t status)267 {268 switch (status) {269 case 0: return "No error";270 case -1: return "General error";271 case PJ_STUN_ERR_MEMORY: return "Memory allocation failed";272 case PJ_STUN_ERR_RESOLVE: return "Invalid IP or unable to resolve STUN server";273 case PJ_STUN_ERR_TRANSPORT: return "Unable to contact STUN server";274 case PJ_STUN_ERR_INVALID_MSG: return "Invalid response from STUN server";275 case PJ_STUN_ERR_NO_RESPONSE: return "No response from STUN server";276 case PJ_STUN_ERR_SYMETRIC: return "Different mappings are returned from servers";277 }278 return "Unknown error";279 }
Note: See TracChangeset
for help on using the changeset viewer.