| 1 | /* |
|---|
| 2 | eXosip - This is the eXtended osip library. |
|---|
| 3 | Copyright (C) 2002,2003,2004,2005,2006,2007 Aymeric MOIZARD - jack@atosc.org |
|---|
| 4 | |
|---|
| 5 | eXosip is free software; you can redistribute it and/or modify |
|---|
| 6 | it under the terms of the GNU General Public License as published by |
|---|
| 7 | the Free Software Foundation; either version 2 of the License, or |
|---|
| 8 | (at your option) any later version. |
|---|
| 9 | |
|---|
| 10 | eXosip is distributed in the hope that it will be useful, |
|---|
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | GNU General Public License for more details. |
|---|
| 14 | |
|---|
| 15 | You should have received a copy of the GNU General Public License |
|---|
| 16 | along with this program; if not, write to the Free Software |
|---|
| 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 18 | */ |
|---|
| 19 | |
|---|
| 20 | #ifdef ENABLE_MPATROL |
|---|
| 21 | #include <mpatrol.h> |
|---|
| 22 | #endif |
|---|
| 23 | |
|---|
| 24 | #include "eXosip2.h" |
|---|
| 25 | |
|---|
| 26 | #ifndef WIN32 |
|---|
| 27 | #include <sys/types.h> |
|---|
| 28 | #include <sys/socket.h> |
|---|
| 29 | #include <netinet/in.h> |
|---|
| 30 | #include <arpa/inet.h> |
|---|
| 31 | #ifdef __APPLE_CC__ |
|---|
| 32 | #include <unistd.h> |
|---|
| 33 | #endif |
|---|
| 34 | #else |
|---|
| 35 | #include <windows.h> |
|---|
| 36 | #include <iphlpapi.h> |
|---|
| 37 | #endif |
|---|
| 38 | |
|---|
| 39 | extern eXosip_t eXosip; |
|---|
| 40 | |
|---|
| 41 | extern int ipv6_enable; |
|---|
| 42 | |
|---|
| 43 | /* Private functions */ |
|---|
| 44 | static int dialog_fill_route_set(osip_dialog_t * dialog, osip_message_t * request); |
|---|
| 45 | |
|---|
| 46 | /* should use cryptographically random identifier is RECOMMENDED.... */ |
|---|
| 47 | /* by now this should lead to identical call-id when application are |
|---|
| 48 | started at the same time... */ |
|---|
| 49 | char *osip_call_id_new_random() |
|---|
| 50 | { |
|---|
| 51 | char *tmp = (char *) osip_malloc(33); |
|---|
| 52 | unsigned int number = osip_build_random_number(); |
|---|
| 53 | if (tmp == NULL) |
|---|
| 54 | return NULL; |
|---|
| 55 | |
|---|
| 56 | sprintf(tmp, "%u", number); |
|---|
| 57 | return tmp; |
|---|
| 58 | } |
|---|
| 59 | |
|---|
| 60 | int eXosip_generate_random(char *buf, int buf_size) |
|---|
| 61 | { |
|---|
| 62 | unsigned int number = osip_build_random_number(); |
|---|
| 63 | |
|---|
| 64 | snprintf(buf, buf_size, "%u", number); |
|---|
| 65 | return OSIP_SUCCESS; |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | char *osip_from_tag_new_random(void) |
|---|
| 69 | { |
|---|
| 70 | return osip_call_id_new_random(); |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | char *osip_to_tag_new_random(void) |
|---|
| 74 | { |
|---|
| 75 | return osip_call_id_new_random(); |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | unsigned int via_branch_new_random(void) |
|---|
| 79 | { |
|---|
| 80 | return osip_build_random_number(); |
|---|
| 81 | } |
|---|
| 82 | |
|---|
| 83 | |
|---|
| 84 | int _eXosip_build_contact_str(osip_from_t *a_from, osip_uri_t *requri, char **contact_str) |
|---|
| 85 | { |
|---|
| 86 | char *contact = NULL; |
|---|
| 87 | char locip[65]; |
|---|
| 88 | char firewall_ip[65]; |
|---|
| 89 | char firewall_port[10]; |
|---|
| 90 | int len; |
|---|
| 91 | |
|---|
| 92 | if (a_from == NULL || a_from->url == NULL) |
|---|
| 93 | return OSIP_SYNTAXERROR; |
|---|
| 94 | |
|---|
| 95 | if (eXosip.eXtl == NULL) |
|---|
| 96 | return OSIP_NO_NETWORK; |
|---|
| 97 | |
|---|
| 98 | if (!requri) |
|---|
| 99 | requri = a_from->url; |
|---|
| 100 | |
|---|
| 101 | |
|---|
| 102 | firewall_ip[0] = '\0'; |
|---|
| 103 | firewall_port[0] = '\0'; |
|---|
| 104 | if (eXosip.eXtl->tl_get_masquerade_contact != NULL) { |
|---|
| 105 | eXosip.eXtl->tl_get_masquerade_contact(firewall_ip, sizeof(firewall_ip), |
|---|
| 106 | firewall_port, |
|---|
| 107 | sizeof(firewall_port)); |
|---|
| 108 | } |
|---|
| 109 | /*guess the local ip since req uri is known */ |
|---|
| 110 | memset(locip, '\0', sizeof(locip)); |
|---|
| 111 | |
|---|
| 112 | if (a_from->url->username != NULL) |
|---|
| 113 | len = |
|---|
| 114 | 2 + 4 + strlen(a_from->url->username) + 1 + 100 + 6 + 10 + |
|---|
| 115 | strlen(eXosip.transport); |
|---|
| 116 | else |
|---|
| 117 | len = 2 + 4 + 100 + 6 + 10 + strlen(eXosip.transport); |
|---|
| 118 | |
|---|
| 119 | contact = (char *) osip_malloc(len + 1); |
|---|
| 120 | if (contact == NULL) |
|---|
| 121 | return OSIP_NOMEM; |
|---|
| 122 | if (firewall_ip[0] != '\0') { |
|---|
| 123 | char *c_address = requri->host; |
|---|
| 124 | |
|---|
| 125 | struct addrinfo *addrinfo; |
|---|
| 126 | struct __eXosip_sockaddr addr; |
|---|
| 127 | int i; |
|---|
| 128 | |
|---|
| 129 | i = eXosip_get_addrinfo(&addrinfo, requri->host, 5060, |
|---|
| 130 | IPPROTO_TCP); |
|---|
| 131 | if (i == 0) { |
|---|
| 132 | memcpy(&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); |
|---|
| 133 | eXosip_freeaddrinfo(addrinfo); |
|---|
| 134 | c_address = inet_ntoa(((struct sockaddr_in *) &addr)->sin_addr); |
|---|
| 135 | OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL, |
|---|
| 136 | "eXosip: here is the resolved destination host=%s\n", |
|---|
| 137 | c_address)); |
|---|
| 138 | } |
|---|
| 139 | |
|---|
| 140 | if (eXosip_is_public_address(c_address)) { |
|---|
| 141 | memcpy(locip, firewall_ip, sizeof(locip)); |
|---|
| 142 | } |
|---|
| 143 | } |
|---|
| 144 | |
|---|
| 145 | if (locip[0] == '\0') { |
|---|
| 146 | eXosip_guess_ip_for_via(eXosip.eXtl->proto_family, locip, 49); |
|---|
| 147 | if (locip[0] == '\0') { |
|---|
| 148 | OSIP_TRACE(osip_trace |
|---|
| 149 | (__FILE__, __LINE__, OSIP_ERROR, NULL, |
|---|
| 150 | "eXosip: no default interface defined\n")); |
|---|
| 151 | return OSIP_NO_NETWORK; |
|---|
| 152 | } |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | if (eXosip.eXtl->proto_family == AF_INET6) { |
|---|
| 156 | if (a_from->url->username != NULL) |
|---|
| 157 | snprintf(contact, len, "<sip:%s@[%s]:%s>", a_from->url->username, |
|---|
| 158 | locip, firewall_port); |
|---|
| 159 | else |
|---|
| 160 | snprintf(contact, len - strlen(eXosip.transport) - 10, "<sip:[%s]:%s>", |
|---|
| 161 | locip, firewall_port); |
|---|
| 162 | } else { |
|---|
| 163 | if (a_from->url->username != NULL) |
|---|
| 164 | snprintf(contact, len, "<sip:%s@%s:%s>", a_from->url->username, |
|---|
| 165 | locip, firewall_port); |
|---|
| 166 | else |
|---|
| 167 | snprintf(contact, len - strlen(eXosip.transport) - 10, "<sip:%s:%s>", |
|---|
| 168 | locip, firewall_port); |
|---|
| 169 | } |
|---|
| 170 | if (osip_strcasecmp(eXosip.transport, "UDP") != 0) { |
|---|
| 171 | contact[strlen(contact) - 1] = '\0'; |
|---|
| 172 | strcat(contact, ";transport="); |
|---|
| 173 | strcat(contact, eXosip.transport); |
|---|
| 174 | strcat(contact, ">"); |
|---|
| 175 | } |
|---|
| 176 | |
|---|
| 177 | *contact_str = contact; |
|---|
| 178 | return OSIP_SUCCESS; |
|---|
| 179 | |
|---|
| 180 | } |
|---|
| 181 | |
|---|
| 182 | int eXosip_build_contact_str(const char *from, const char* uri, char** str) |
|---|
| 183 | { |
|---|
| 184 | osip_from_t *a_from = 0; |
|---|
| 185 | osip_uri_t *a_uri = 0; |
|---|
| 186 | int ret = OSIP_SUCCESS; |
|---|
| 187 | |
|---|
| 188 | if (!from) |
|---|
| 189 | return OSIP_SYNTAXERROR; |
|---|
| 190 | |
|---|
| 191 | ret = osip_from_init(&a_from); |
|---|
| 192 | if (ret) |
|---|
| 193 | return ret; |
|---|
| 194 | |
|---|
| 195 | ret = osip_from_parse(a_from, from); |
|---|
| 196 | if (ret) { |
|---|
| 197 | osip_from_free(a_from); |
|---|
| 198 | return ret; |
|---|
| 199 | } |
|---|
| 200 | if (uri) { |
|---|
| 201 | ret = osip_uri_init(&a_uri); |
|---|
| 202 | if (ret) { |
|---|
| 203 | osip_from_free(a_from); |
|---|
| 204 | return ret; |
|---|
| 205 | } |
|---|
| 206 | |
|---|
| 207 | ret = osip_uri_parse(a_uri, uri); |
|---|
| 208 | if (ret) { |
|---|
| 209 | osip_uri_free(a_uri); |
|---|
| 210 | osip_from_free(a_from); |
|---|
| 211 | return ret; |
|---|
| 212 | } |
|---|
| 213 | } |
|---|
| 214 | |
|---|
| 215 | |
|---|
| 216 | ret = _eXosip_build_contact_str(a_from, a_uri, str); |
|---|
| 217 | |
|---|
| 218 | if (a_uri) |
|---|
| 219 | osip_uri_free(a_uri); |
|---|
| 220 | if (a_from) |
|---|
| 221 | osip_from_free(a_from); |
|---|
| 222 | |
|---|
| 223 | return ret; |
|---|
| 224 | } |
|---|
| 225 | |
|---|
| 226 | int _eXosip_dialog_add_contact(osip_message_t * request, osip_message_t * answer) |
|---|
| 227 | { |
|---|
| 228 | int ret; |
|---|
| 229 | char *contact = NULL; |
|---|
| 230 | osip_from_t *a_from; |
|---|
| 231 | |
|---|
| 232 | if (answer == NULL) |
|---|
| 233 | a_from = request->from; |
|---|
| 234 | else |
|---|
| 235 | a_from = answer->to; |
|---|
| 236 | |
|---|
| 237 | ret = _eXosip_build_contact_str(a_from, request->req_uri, &contact); |
|---|
| 238 | if (ret != OSIP_SUCCESS) |
|---|
| 239 | return ret; |
|---|
| 240 | |
|---|
| 241 | osip_message_set_contact(request, contact); |
|---|
| 242 | osip_free(contact); |
|---|
| 243 | |
|---|
| 244 | return OSIP_SUCCESS; |
|---|
| 245 | } |
|---|
| 246 | |
|---|
| 247 | int |
|---|
| 248 | _eXosip_request_add_via(osip_message_t * request, const char *transport, |
|---|
| 249 | const char *locip) |
|---|
| 250 | { |
|---|
| 251 | char tmp[200]; |
|---|
| 252 | const char *ip = NULL; |
|---|
| 253 | char firewall_ip[65]; |
|---|
| 254 | char firewall_port[10]; |
|---|
| 255 | |
|---|
| 256 | if (request == NULL) |
|---|
| 257 | return OSIP_BADPARAMETER; |
|---|
| 258 | |
|---|
| 259 | if (request->call_id == NULL) |
|---|
| 260 | return OSIP_SYNTAXERROR; |
|---|
| 261 | |
|---|
| 262 | if (locip == NULL && request->call_id->host == NULL) |
|---|
| 263 | return OSIP_SYNTAXERROR; |
|---|
| 264 | |
|---|
| 265 | if (locip != NULL) |
|---|
| 266 | ip = locip; |
|---|
| 267 | else if (request->call_id->host != NULL) |
|---|
| 268 | ip = request->call_id->host; |
|---|
| 269 | |
|---|
| 270 | firewall_ip[0] = '\0'; |
|---|
| 271 | firewall_port[0] = '\0'; |
|---|
| 272 | if (eXosip.eXtl != NULL && eXosip.eXtl->tl_get_masquerade_contact != NULL) { |
|---|
| 273 | eXosip.eXtl->tl_get_masquerade_contact(firewall_ip, sizeof(firewall_ip), |
|---|
| 274 | firewall_port, |
|---|
| 275 | sizeof(firewall_port)); |
|---|
| 276 | } |
|---|
| 277 | #ifdef MASQUERADE_VIA |
|---|
| 278 | /* this helps to work with a server that don't handle the |
|---|
| 279 | "received" parameter correctly. Some still exists. */ |
|---|
| 280 | if (firewall_ip[0] != '\0') { |
|---|
| 281 | ip = firewall_ip; |
|---|
| 282 | } |
|---|
| 283 | #endif |
|---|
| 284 | |
|---|
| 285 | if (firewall_port[0] == '\0') { |
|---|
| 286 | snprintf(firewall_port, sizeof(firewall_port), "5060"); |
|---|
| 287 | } |
|---|
| 288 | |
|---|
| 289 | if (eXosip.eXtl->proto_family == AF_INET6) |
|---|
| 290 | snprintf(tmp, 200, "SIP/2.0/%s [%s]:%s;branch=z9hG4bK%u", |
|---|
| 291 | eXosip.transport, ip, firewall_port, via_branch_new_random()); |
|---|
| 292 | else { |
|---|
| 293 | if (eXosip.use_rport != 0) |
|---|
| 294 | snprintf(tmp, 200, "SIP/2.0/%s %s:%s;rport;branch=z9hG4bK%u", |
|---|
| 295 | eXosip.transport, ip, firewall_port, via_branch_new_random()); |
|---|
| 296 | else |
|---|
| 297 | snprintf(tmp, 200, "SIP/2.0/%s %s:%s;branch=z9hG4bK%u", |
|---|
| 298 | eXosip.transport, ip, firewall_port, via_branch_new_random()); |
|---|
| 299 | } |
|---|
| 300 | |
|---|
| 301 | osip_message_set_via(request, tmp); |
|---|
| 302 | |
|---|
| 303 | return OSIP_SUCCESS; |
|---|
| 304 | } |
|---|
| 305 | |
|---|
| 306 | /* prepare a minimal request (outside of a dialog) with required headers */ |
|---|
| 307 | /* |
|---|
| 308 | method is the type of request. ("INVITE", "REGISTER"...) |
|---|
| 309 | to is the remote target URI |
|---|
| 310 | transport is either "TCP" or "UDP" (by now, only UDP is implemented!) |
|---|
| 311 | */ |
|---|
| 312 | int |
|---|
| 313 | generating_request_out_of_dialog(osip_message_t ** dest, const char *method, |
|---|
| 314 | const char *to, const char *transport, |
|---|
| 315 | const char *from, const char *proxy) |
|---|
| 316 | { |
|---|
| 317 | /* Section 8.1: |
|---|
| 318 | A valid request contains at a minimum "To, From, Call-iD, Cseq, |
|---|
| 319 | Max-Forwards and Via |
|---|
| 320 | */ |
|---|
| 321 | int i; |
|---|
| 322 | osip_message_t *request; |
|---|
| 323 | char locip[65]; |
|---|
| 324 | int doing_register; |
|---|
| 325 | char *register_callid_number = NULL; |
|---|
| 326 | |
|---|
| 327 | *dest = NULL; |
|---|
| 328 | |
|---|
| 329 | if (eXosip.eXtl == NULL) |
|---|
| 330 | return OSIP_NO_NETWORK; |
|---|
| 331 | |
|---|
| 332 | /*guess the local ip since req uri is known */ |
|---|
| 333 | memset(locip, '\0', sizeof(locip)); |
|---|
| 334 | eXosip_guess_ip_for_via(eXosip.eXtl->proto_family, locip, 49); |
|---|
| 335 | if (locip[0] == '\0') { |
|---|
| 336 | OSIP_TRACE(osip_trace |
|---|
| 337 | (__FILE__, __LINE__, OSIP_ERROR, NULL, |
|---|
| 338 | "eXosip: no default interface defined\n")); |
|---|
| 339 | return OSIP_NO_NETWORK; |
|---|
| 340 | } |
|---|
| 341 | |
|---|
| 342 | i = osip_message_init(&request); |
|---|
| 343 | if (i != 0) |
|---|
| 344 | return i; |
|---|
| 345 | |
|---|
| 346 | /* prepare the request-line */ |
|---|
| 347 | osip_message_set_method(request, osip_strdup(method)); |
|---|
| 348 | osip_message_set_version(request, osip_strdup("SIP/2.0")); |
|---|
| 349 | osip_message_set_status_code(request, 0); |
|---|
| 350 | osip_message_set_reason_phrase(request, NULL); |
|---|
| 351 | |
|---|
| 352 | doing_register = 0 == strcmp("REGISTER", method); |
|---|
| 353 | |
|---|
| 354 | if (doing_register) { |
|---|
| 355 | osip_uri_init(&(request->req_uri)); |
|---|
| 356 | i = osip_uri_parse(request->req_uri, proxy); |
|---|
| 357 | if (i != 0) { |
|---|
| 358 | osip_message_free(request); |
|---|
| 359 | return i; |
|---|
| 360 | } |
|---|
| 361 | i = osip_message_set_to(request, from); |
|---|
| 362 | if (i != 0 || request->to == NULL) { |
|---|
| 363 | if (i >= 0) |
|---|
| 364 | i = OSIP_SYNTAXERROR; |
|---|
| 365 | osip_message_free(request); |
|---|
| 366 | return i; |
|---|
| 367 | } |
|---|
| 368 | |
|---|
| 369 | /* REMOVE ALL URL PARAMETERS from to->url headers and add them as headers */ |
|---|
| 370 | if (request->to != NULL && request->to->url != NULL) { |
|---|
| 371 | osip_uri_t *url = request->to->url; |
|---|
| 372 | while (osip_list_size(&url->url_headers) > 0) { |
|---|
| 373 | osip_uri_header_t *u_header; |
|---|
| 374 | u_header = |
|---|
| 375 | (osip_uri_param_t *) osip_list_get(&url->url_headers, 0); |
|---|
| 376 | if (u_header == NULL) |
|---|
| 377 | break; |
|---|
| 378 | |
|---|
| 379 | if (osip_strcasecmp(u_header->gname, "from") == 0) { |
|---|
| 380 | } else if (osip_strcasecmp(u_header->gname, "to") == 0) { |
|---|
| 381 | } else if (osip_strcasecmp(u_header->gname, "call-id") == 0) { |
|---|
| 382 | } else if (osip_strcasecmp(u_header->gname, "cseq") == 0) { |
|---|
| 383 | } else if (osip_strcasecmp(u_header->gname, "via") == 0) { |
|---|
| 384 | } else if (osip_strcasecmp(u_header->gname, "contact") == 0) { |
|---|
| 385 | //osip_message_set_contact(request, u_header->gvalue); |
|---|
| 386 | } else if (osip_strcasecmp(u_header->gname, "route") == 0) { |
|---|
| 387 | osip_message_set_route(request, u_header->gvalue); |
|---|
| 388 | } else if (osip_strcasecmp(u_header->gname, "content-type") == 0) { |
|---|
| 389 | osip_message_set_content_type(request, u_header->gvalue); |
|---|
| 390 | } else |
|---|
| 391 | osip_message_set_header(request, u_header->gname, |
|---|
| 392 | u_header->gvalue); |
|---|
| 393 | osip_list_remove(&url->url_headers, 0); |
|---|
| 394 | osip_uri_param_free(u_header); |
|---|
| 395 | } |
|---|
| 396 | } |
|---|
| 397 | } else { |
|---|
| 398 | /* in any cases except REGISTER: */ |
|---|
| 399 | i = osip_message_set_to(request, to); |
|---|
| 400 | if (i != 0 || request->to == NULL) { |
|---|
| 401 | if (i >= 0) |
|---|
| 402 | i = OSIP_SYNTAXERROR; |
|---|
| 403 | OSIP_TRACE(osip_trace |
|---|
| 404 | (__FILE__, __LINE__, OSIP_ERROR, NULL, |
|---|
| 405 | "ERROR: callee address does not seems to be a sipurl: %s\n", |
|---|
| 406 | to)); |
|---|
| 407 | osip_message_free(request); |
|---|
| 408 | return i; |
|---|
| 409 | } |
|---|
| 410 | |
|---|
| 411 | /* REMOVE ALL URL PARAMETERS from to->url headers and add them as headers */ |
|---|
| 412 | if (request->to != NULL && request->to->url != NULL) { |
|---|
| 413 | osip_uri_t *url = request->to->url; |
|---|
| 414 | while (osip_list_size(&url->url_headers) > 0) { |
|---|
| 415 | osip_uri_header_t *u_header; |
|---|
| 416 | u_header = |
|---|
| 417 | (osip_uri_param_t *) osip_list_get(&url->url_headers, 0); |
|---|
| 418 | if (u_header == NULL) |
|---|
| 419 | break; |
|---|
| 420 | |
|---|
| 421 | if (osip_strcasecmp(u_header->gname, "from") == 0) { |
|---|
| 422 | } else if (osip_strcasecmp(u_header->gname, "to") == 0) { |
|---|
| 423 | } else if (osip_strcasecmp(u_header->gname, "call-id") == 0) { |
|---|
| 424 | } else if (osip_strcasecmp(u_header->gname, "cseq") == 0) { |
|---|
| 425 | } else if (osip_strcasecmp(u_header->gname, "via") == 0) { |
|---|
| 426 | } else if (osip_strcasecmp(u_header->gname, "contact") == 0) { |
|---|
| 427 | } else if (osip_strcasecmp(u_header->gname, "route") == 0) { |
|---|
| 428 | osip_message_set_route(request, u_header->gvalue); |
|---|
| 429 | } else if (osip_strcasecmp(u_header->gname, "content-type") == 0) { |
|---|
| 430 | osip_message_set_content_type(request, u_header->gvalue); |
|---|
| 431 | } else |
|---|
| 432 | osip_message_set_header(request, u_header->gname, |
|---|
| 433 | u_header->gvalue); |
|---|
| 434 | osip_list_remove(&url->url_headers, 0); |
|---|
| 435 | osip_uri_param_free(u_header); |
|---|
| 436 | } |
|---|
| 437 | } |
|---|
| 438 | |
|---|
| 439 | if (proxy != NULL && proxy[0] != 0) { /* equal to a pre-existing route set */ |
|---|
| 440 | /* if the pre-existing route set contains a "lr" (compliance |
|---|
| 441 | with bis-08) then the req_uri should contains the remote target |
|---|
| 442 | URI */ |
|---|
| 443 | osip_uri_param_t *lr_param; |
|---|
| 444 | osip_route_t *o_proxy; |
|---|
| 445 | |
|---|
| 446 | osip_route_init(&o_proxy); |
|---|
| 447 | i = osip_route_parse(o_proxy, proxy); |
|---|
| 448 | if (i != 0) { |
|---|
| 449 | osip_route_free(o_proxy); |
|---|
| 450 | osip_message_free(request); |
|---|
| 451 | return i; |
|---|
| 452 | } |
|---|
| 453 | |
|---|
| 454 | osip_uri_uparam_get_byname(o_proxy->url, "lr", &lr_param); |
|---|
| 455 | if (lr_param != NULL) { /* to is the remote target URI in this case! */ |
|---|
| 456 | osip_uri_clone(request->to->url, &(request->req_uri)); |
|---|
| 457 | /* "[request] MUST includes a Route header field containing |
|---|
| 458 | the route set values in order." */ |
|---|
| 459 | osip_list_add(&request->routes, o_proxy, 0); |
|---|
| 460 | } else |
|---|
| 461 | /* if the first URI of route set does not contain "lr", the req_uri |
|---|
| 462 | is set to the first uri of route set */ |
|---|
| 463 | { |
|---|
| 464 | request->req_uri = o_proxy->url; |
|---|
| 465 | o_proxy->url = NULL; |
|---|
| 466 | osip_route_free(o_proxy); |
|---|
| 467 | /* add the route set */ |
|---|
| 468 | /* "The UAC MUST add a route header field containing |
|---|
| 469 | the remainder of the route set values in order. |
|---|
| 470 | The UAC MUST then place the remote target URI into |
|---|
| 471 | the route header field as the last value |
|---|
| 472 | */ |
|---|
| 473 | osip_message_set_route(request, to); |
|---|
| 474 | } |
|---|
| 475 | } else { /* No route set (outbound proxy) is used */ |
|---|
| 476 | |
|---|
| 477 | /* The UAC must put the remote target URI (to field) in the req_uri */ |
|---|
| 478 | i = osip_uri_clone(request->to->url, &(request->req_uri)); |
|---|
| 479 | if (i != 0) { |
|---|
| 480 | osip_message_free(request); |
|---|
| 481 | return i; |
|---|
| 482 | } |
|---|
| 483 | } |
|---|
| 484 | } |
|---|
| 485 | |
|---|
| 486 | /* set To and From */ |
|---|
| 487 | i = osip_message_set_from(request, from); |
|---|
| 488 | if (i != 0 || request->from == NULL) { |
|---|
| 489 | if (i >= 0) |
|---|
| 490 | i = OSIP_SYNTAXERROR; |
|---|
| 491 | osip_message_free(request); |
|---|
| 492 | return i; |
|---|
| 493 | } |
|---|
| 494 | |
|---|
| 495 | /* REMOVE ALL URL PARAMETERS from from->url headers and add them as headers */ |
|---|
| 496 | if (doing_register && request->from != NULL && request->from->url != NULL) { |
|---|
| 497 | osip_uri_t *url = request->from->url; |
|---|
| 498 | while (osip_list_size(&url->url_headers) > 0) { |
|---|
| 499 | osip_uri_header_t *u_header; |
|---|
| 500 | u_header = (osip_uri_param_t *) osip_list_get(&url->url_headers, 0); |
|---|
| 501 | if (u_header == NULL) |
|---|
| 502 | break; |
|---|
| 503 | |
|---|
| 504 | osip_list_remove(&url->url_headers, 0); |
|---|
| 505 | osip_uri_param_free(u_header); |
|---|
| 506 | } |
|---|
| 507 | } |
|---|
| 508 | |
|---|
| 509 | if (request->to != NULL && request->to->url != NULL) { |
|---|
| 510 | int pos = 0; |
|---|
| 511 | size_t pname_len; |
|---|
| 512 | osip_uri_param_t *u_param; |
|---|
| 513 | |
|---|
| 514 | pname_len = strlen("method"); |
|---|
| 515 | while (!osip_list_eol(&request->to->url->url_params, pos)) { |
|---|
| 516 | size_t len; |
|---|
| 517 | |
|---|
| 518 | u_param = (osip_uri_param_t *) osip_list_get(&request->to->url->url_params, pos); |
|---|
| 519 | len = strlen(u_param->gname); |
|---|
| 520 | if (pname_len == len |
|---|
| 521 | && osip_strncasecmp(u_param->gname, "method", pname_len) == 0 |
|---|
| 522 | && u_param->gvalue!=NULL) { |
|---|
| 523 | osip_list_remove(&request->to->url->url_params, pos); |
|---|
| 524 | osip_uri_param_free(u_param); |
|---|
| 525 | break; |
|---|
| 526 | } |
|---|
| 527 | pos++; |
|---|
| 528 | } |
|---|
| 529 | } |
|---|
| 530 | |
|---|
| 531 | if (request->from != NULL && request->from->url != NULL) { |
|---|
| 532 | int pos = 0; |
|---|
| 533 | size_t pname_len; |
|---|
| 534 | osip_uri_param_t *u_param; |
|---|
| 535 | |
|---|
| 536 | pname_len = strlen("method"); |
|---|
| 537 | while (!osip_list_eol(&request->from->url->url_params, pos)) { |
|---|
| 538 | size_t len; |
|---|
| 539 | |
|---|
| 540 | u_param = (osip_uri_param_t *) osip_list_get(&request->from->url->url_params, pos); |
|---|
| 541 | len = strlen(u_param->gname); |
|---|
| 542 | if (pname_len == len |
|---|
| 543 | && osip_strncasecmp(u_param->gname, "method", pname_len) == 0 |
|---|
| 544 | && u_param->gvalue!=NULL) { |
|---|
| 545 | osip_list_remove(&request->from->url->url_params, pos); |
|---|
| 546 | osip_uri_param_free(u_param); |
|---|
| 547 | break; |
|---|
| 548 | } |
|---|
| 549 | pos++; |
|---|
| 550 | } |
|---|
| 551 | } |
|---|
| 552 | |
|---|
| 553 | if (request->req_uri) { |
|---|
| 554 | int pos = 0; |
|---|
| 555 | size_t pname_len; |
|---|
| 556 | osip_uri_param_t *u_param; |
|---|
| 557 | |
|---|
| 558 | pname_len = strlen("method"); |
|---|
| 559 | while (!osip_list_eol(&request->req_uri->url_params, pos)) { |
|---|
| 560 | size_t len; |
|---|
| 561 | |
|---|
| 562 | u_param = (osip_uri_param_t *) osip_list_get(&request->req_uri->url_params, pos); |
|---|
| 563 | len = strlen(u_param->gname); |
|---|
| 564 | if (pname_len == len |
|---|
| 565 | && osip_strncasecmp(u_param->gname, "method", pname_len) == 0 |
|---|
| 566 | && u_param->gvalue!=NULL) { |
|---|
| 567 | osip_list_remove(&request->req_uri->url_params, pos); |
|---|
| 568 | osip_uri_param_free(u_param); |
|---|
| 569 | break; |
|---|
| 570 | } |
|---|
| 571 | pos++; |
|---|
| 572 | } |
|---|
| 573 | } |
|---|
| 574 | |
|---|
| 575 | /* add a tag */ |
|---|
| 576 | osip_from_set_tag(request->from, osip_from_tag_new_random()); |
|---|
| 577 | |
|---|
| 578 | /* set the cseq and call_id header */ |
|---|
| 579 | { |
|---|
| 580 | osip_call_id_t *callid; |
|---|
| 581 | osip_cseq_t *cseq; |
|---|
| 582 | char *num; |
|---|
| 583 | char *cidrand; |
|---|
| 584 | |
|---|
| 585 | /* call-id is always the same for REGISTRATIONS */ |
|---|
| 586 | i = osip_call_id_init(&callid); |
|---|
| 587 | if (i != 0) { |
|---|
| 588 | osip_message_free(request); |
|---|
| 589 | return i; |
|---|
| 590 | } |
|---|
| 591 | cidrand = osip_call_id_new_random(); |
|---|
| 592 | osip_call_id_set_number(callid, cidrand); |
|---|
| 593 | if (doing_register) |
|---|
| 594 | register_callid_number = cidrand; |
|---|
| 595 | |
|---|
| 596 | request->call_id = callid; |
|---|
| 597 | |
|---|
| 598 | i = osip_cseq_init(&cseq); |
|---|
| 599 | if (i != 0) { |
|---|
| 600 | osip_message_free(request); |
|---|
| 601 | return i; |
|---|
| 602 | } |
|---|
| 603 | num = osip_strdup(doing_register ? "1" : "20"); |
|---|
| 604 | osip_cseq_set_number(cseq, num); |
|---|
| 605 | osip_cseq_set_method(cseq, osip_strdup(method)); |
|---|
| 606 | request->cseq = cseq; |
|---|
| 607 | |
|---|
| 608 | if (cseq->method == NULL || cseq->number == NULL) { |
|---|
| 609 | osip_message_free(request); |
|---|
| 610 | return OSIP_NOMEM; |
|---|
| 611 | } |
|---|
| 612 | } |
|---|
| 613 | |
|---|
| 614 | i = _eXosip_request_add_via(request, transport, locip); |
|---|
| 615 | if (i != 0) { |
|---|
| 616 | osip_message_free(request); |
|---|
| 617 | return i; |
|---|
| 618 | } |
|---|
| 619 | |
|---|
| 620 | /* always add the Max-Forward header */ |
|---|
| 621 | osip_message_set_max_forwards(request, "70"); /* a UA should start a request with 70 */ |
|---|
| 622 | |
|---|
| 623 | if (0 == strcmp("REGISTER", method)) { |
|---|
| 624 | } else if (0 == strcmp("INFO", method)) { |
|---|
| 625 | } else if (0 == strcmp("OPTIONS", method)) { |
|---|
| 626 | osip_message_set_accept(request, "application/sdp"); |
|---|
| 627 | } |
|---|
| 628 | |
|---|
| 629 | osip_message_set_user_agent(request, eXosip.user_agent); |
|---|
| 630 | /* else if ... */ |
|---|
| 631 | *dest = request; |
|---|
| 632 | return OSIP_SUCCESS; |
|---|
| 633 | } |
|---|
| 634 | |
|---|
| 635 | int |
|---|
| 636 | generating_register(eXosip_reg_t * jreg, osip_message_t ** reg, char *transport, |
|---|
| 637 | char *from, char *proxy, char *contact, int expires) |
|---|
| 638 | { |
|---|
| 639 | int i; |
|---|
| 640 | char locip[65]; |
|---|
| 641 | char firewall_ip[65]; |
|---|
| 642 | char firewall_port[10]; |
|---|
| 643 | if (eXosip.eXtl == NULL) |
|---|
| 644 | return OSIP_NO_NETWORK; |
|---|
| 645 | |
|---|
| 646 | firewall_ip[0] = '\0'; |
|---|
| 647 | firewall_port[0] = '\0'; |
|---|
| 648 | if (eXosip.eXtl->tl_get_masquerade_contact != NULL) { |
|---|
| 649 | eXosip.eXtl->tl_get_masquerade_contact(firewall_ip, sizeof(firewall_ip), |
|---|
| 650 | firewall_port, |
|---|
| 651 | sizeof(firewall_port)); |
|---|
| 652 | } |
|---|
| 653 | |
|---|
| 654 | i = generating_request_out_of_dialog(reg, "REGISTER", NULL, transport, from, |
|---|
| 655 | proxy); |
|---|
| 656 | if (i != 0) |
|---|
| 657 | return i; |
|---|
| 658 | |
|---|
| 659 | memset(locip, '\0', sizeof(locip)); |
|---|
| 660 | eXosip_guess_ip_for_via(eXosip.eXtl->proto_family, locip, 49); |
|---|
| 661 | |
|---|
| 662 | if (locip[0] == '\0') { |
|---|
| 663 | OSIP_TRACE(osip_trace |
|---|
| 664 | (__FILE__, __LINE__, OSIP_ERROR, NULL, |
|---|
| 665 | "eXosip: no default interface defined\n")); |
|---|
| 666 | osip_message_free(*reg); |
|---|
| 667 | *reg = NULL; |
|---|
| 668 | return OSIP_NO_NETWORK; |
|---|
| 669 | } |
|---|
| 670 | |
|---|
| 671 | if (contact == NULL) { |
|---|
| 672 | osip_contact_t *new_contact = NULL; |
|---|
| 673 | osip_uri_t *new_contact_url = NULL; |
|---|
| 674 | |
|---|
| 675 | i = osip_contact_init(&new_contact); |
|---|
| 676 | if (i == 0) |
|---|
| 677 | i = osip_uri_init(&new_contact_url); |
|---|
| 678 | |
|---|
| 679 | new_contact->url = new_contact_url; |
|---|
| 680 | |
|---|
| 681 | if (i == 0 && (*reg)->from != NULL |
|---|
| 682 | && (*reg)->from->url != NULL && (*reg)->from->url->username != NULL) { |
|---|
| 683 | new_contact_url->username = osip_strdup((*reg)->from->url->username); |
|---|
| 684 | } |
|---|
| 685 | |
|---|
| 686 | if (i == 0 && (*reg)->from != NULL && (*reg)->from->url != NULL) { |
|---|
| 687 | /* serach for correct ip */ |
|---|
| 688 | if (firewall_ip[0] != '\0' && (*reg)->req_uri->host != NULL) { |
|---|
| 689 | char *c_address = (*reg)->req_uri->host; |
|---|
| 690 | |
|---|
| 691 | struct addrinfo *addrinfo; |
|---|
| 692 | struct __eXosip_sockaddr addr; |
|---|
| 693 | |
|---|
| 694 | i = eXosip_get_addrinfo(&addrinfo, (*reg)->req_uri->host, 5060, |
|---|
| 695 | IPPROTO_UDP); |
|---|
| 696 | if (i == 0) { |
|---|
| 697 | memcpy(&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); |
|---|
| 698 | eXosip_freeaddrinfo(addrinfo); |
|---|
| 699 | c_address = |
|---|
| 700 | inet_ntoa(((struct sockaddr_in *) &addr)->sin_addr); |
|---|
| 701 | OSIP_TRACE(osip_trace |
|---|
| 702 | (__FILE__, __LINE__, OSIP_INFO1, NULL, |
|---|
| 703 | "eXosip: here is the resolved destination host=%s\n", |
|---|
| 704 | c_address)); |
|---|
| 705 | } |
|---|
| 706 | |
|---|
| 707 | if (eXosip_is_public_address(c_address)) { |
|---|
| 708 | new_contact_url->host = osip_strdup(firewall_ip); |
|---|
| 709 | new_contact_url->port = osip_strdup(firewall_port); |
|---|
| 710 | } else { |
|---|
| 711 | new_contact_url->host = osip_strdup(locip); |
|---|
| 712 | new_contact_url->port = osip_strdup(firewall_port); |
|---|
| 713 | } |
|---|
| 714 | } else { |
|---|
| 715 | new_contact_url->host = osip_strdup(locip); |
|---|
| 716 | new_contact_url->port = osip_strdup(firewall_port); |
|---|
| 717 | } |
|---|
| 718 | |
|---|
| 719 | if (transport != NULL && osip_strcasecmp(transport, "UDP") != 0) { |
|---|
| 720 | osip_uri_uparam_add(new_contact_url, osip_strdup("transport"), |
|---|
| 721 | osip_strdup(transport)); |
|---|
| 722 | } |
|---|
| 723 | |
|---|
| 724 | if (jreg->r_line[0] != '\0') { |
|---|
| 725 | osip_uri_uparam_add(new_contact_url, osip_strdup("line"), |
|---|
| 726 | osip_strdup(jreg->r_line)); |
|---|
| 727 | } |
|---|
| 728 | |
|---|
| 729 | osip_list_add(&(*reg)->contacts, new_contact, -1); |
|---|
| 730 | } |
|---|
| 731 | } else { |
|---|
| 732 | osip_message_set_contact(*reg, contact); |
|---|
| 733 | } |
|---|
| 734 | |
|---|
| 735 | { |
|---|
| 736 | char exp[10]; /* MUST never be ouside 1 and 3600 */ |
|---|
| 737 | |
|---|
| 738 | snprintf(exp, 9, "%i", expires); |
|---|
| 739 | osip_message_set_expires(*reg, exp); |
|---|
| 740 | } |
|---|
| 741 | |
|---|
| 742 | osip_message_set_content_length(*reg, "0"); |
|---|
| 743 | |
|---|
| 744 | return OSIP_SUCCESS; |
|---|
| 745 | } |
|---|
| 746 | |
|---|
| 747 | #ifndef MINISIZE |
|---|
| 748 | |
|---|
| 749 | int |
|---|
| 750 | generating_publish(osip_message_t ** message, const char *to, |
|---|
| 751 | const char *from, const char *route) |
|---|
| 752 | { |
|---|
| 753 | int i; |
|---|
| 754 | |
|---|
| 755 | if (to != NULL && *to == '\0') |
|---|
| 756 | return OSIP_BADPARAMETER; |
|---|
| 757 | |
|---|
| 758 | if (route != NULL && *route == '\0') |
|---|
| 759 | route = NULL; |
|---|
| 760 | |
|---|
| 761 | i = generating_request_out_of_dialog(message, "PUBLISH", to, "UDP", from, |
|---|
| 762 | route); |
|---|
| 763 | if (i != 0) |
|---|
| 764 | return i; |
|---|
| 765 | |
|---|
| 766 | /* osip_message_set_organization(*message, "Jack's Org"); */ |
|---|
| 767 | |
|---|
| 768 | return OSIP_SUCCESS; |
|---|
| 769 | } |
|---|
| 770 | |
|---|
| 771 | #endif |
|---|
| 772 | |
|---|
| 773 | static int dialog_fill_route_set(osip_dialog_t * dialog, osip_message_t * request) |
|---|
| 774 | { |
|---|
| 775 | /* if the pre-existing route set contains a "lr" (compliance |
|---|
| 776 | with bis-08) then the req_uri should contains the remote target |
|---|
| 777 | URI */ |
|---|
| 778 | int i; |
|---|
| 779 | int pos = 0; |
|---|
| 780 | osip_uri_param_t *lr_param; |
|---|
| 781 | osip_route_t *route; |
|---|
| 782 | char *last_route; |
|---|
| 783 | |
|---|
| 784 | /* AMD bug: fixed 17/06/2002 */ |
|---|
| 785 | |
|---|
| 786 | route = (osip_route_t *) osip_list_get(&dialog->route_set, 0); |
|---|
| 787 | |
|---|
| 788 | osip_uri_uparam_get_byname(route->url, "lr", &lr_param); |
|---|
| 789 | if (lr_param != NULL) { /* the remote target URI is the req_uri! */ |
|---|
| 790 | i = osip_uri_clone(dialog->remote_contact_uri->url, &(request->req_uri)); |
|---|
| 791 | if (i != 0) |
|---|
| 792 | return i; |
|---|
| 793 | /* "[request] MUST includes a Route header field containing |
|---|
| 794 | the route set values in order." */ |
|---|
| 795 | /* AMD bug: fixed 17/06/2002 */ |
|---|
| 796 | pos = 0; /* first element is at index 0 */ |
|---|
| 797 | while (!osip_list_eol(&dialog->route_set, pos)) { |
|---|
| 798 | osip_route_t *route2; |
|---|
| 799 | |
|---|
| 800 | route = osip_list_get(&dialog->route_set, pos); |
|---|
| 801 | i = osip_route_clone(route, &route2); |
|---|
| 802 | if (i != 0) |
|---|
| 803 | return i; |
|---|
| 804 | osip_list_add(&request->routes, route2, -1); |
|---|
| 805 | pos++; |
|---|
| 806 | } |
|---|
| 807 | return OSIP_SUCCESS; |
|---|
| 808 | } |
|---|
| 809 | |
|---|
| 810 | /* if the first URI of route set does not contain "lr", the req_uri |
|---|
| 811 | is set to the first uri of route set */ |
|---|
| 812 | |
|---|
| 813 | |
|---|
| 814 | i = osip_uri_clone(route->url, &(request->req_uri)); |
|---|
| 815 | if (i != 0) |
|---|
| 816 | return i; |
|---|
| 817 | /* add the route set */ |
|---|
| 818 | /* "The UAC MUST add a route header field containing |
|---|
| 819 | the remainder of the route set values in order. */ |
|---|
| 820 | pos = 0; /* yes it is */ |
|---|
| 821 | |
|---|
| 822 | while (!osip_list_eol(&dialog->route_set, pos)) { /* not the first one in the list */ |
|---|
| 823 | osip_route_t *route2; |
|---|
| 824 | |
|---|
| 825 | route = osip_list_get(&dialog->route_set, pos); |
|---|
| 826 | i = osip_route_clone(route, &route2); |
|---|
| 827 | if (i != 0) |
|---|
| 828 | return i; |
|---|
| 829 | if (!osip_list_eol(&dialog->route_set, pos + 1)) |
|---|
| 830 | osip_list_add(&request->routes, route2, -1); |
|---|
| 831 | else |
|---|
| 832 | osip_route_free(route2); |
|---|
| 833 | pos++; |
|---|
| 834 | } |
|---|
| 835 | |
|---|
| 836 | /* The UAC MUST then place the remote target URI into |
|---|
| 837 | the route header field as the last value */ |
|---|
| 838 | i = osip_uri_to_str(dialog->remote_contact_uri->url, &last_route); |
|---|
| 839 | if (i != 0) |
|---|
| 840 | return i; |
|---|
| 841 | i = osip_message_set_route(request, last_route); |
|---|
| 842 | osip_free(last_route); |
|---|
| 843 | if (i != 0) { |
|---|
| 844 | return i; |
|---|
| 845 | } |
|---|
| 846 | |
|---|
| 847 | /* route header and req_uri set */ |
|---|
| 848 | return OSIP_SUCCESS; |
|---|
| 849 | } |
|---|
| 850 | |
|---|
| 851 | int |
|---|
| 852 | _eXosip_build_request_within_dialog(osip_message_t ** dest, |
|---|
| 853 | const char *method, |
|---|
| 854 | osip_dialog_t * dialog, const char *transport) |
|---|
| 855 | { |
|---|
| 856 | int i; |
|---|
| 857 | osip_message_t *request; |
|---|
| 858 | char locip[65]; |
|---|
| 859 | char firewall_ip[65]; |
|---|
| 860 | char firewall_port[10]; |
|---|
| 861 | |
|---|
| 862 | *dest = NULL; |
|---|
| 863 | |
|---|
| 864 | if (dialog == NULL) |
|---|
| 865 | return OSIP_BADPARAMETER; |
|---|
| 866 | |
|---|
| 867 | if (eXosip.eXtl == NULL) |
|---|
| 868 | return OSIP_NO_NETWORK; |
|---|
| 869 | |
|---|
| 870 | firewall_ip[0] = '\0'; |
|---|
| 871 | firewall_port[0] = '\0'; |
|---|
| 872 | if (eXosip.eXtl->tl_get_masquerade_contact != NULL) { |
|---|
| 873 | eXosip.eXtl->tl_get_masquerade_contact(firewall_ip, sizeof(firewall_ip), |
|---|
| 874 | firewall_port, |
|---|
| 875 | sizeof(firewall_port)); |
|---|
| 876 | } |
|---|
| 877 | |
|---|
| 878 | i = osip_message_init(&request); |
|---|
| 879 | if (i != 0) |
|---|
| 880 | return i; |
|---|
| 881 | |
|---|
| 882 | if (dialog->remote_contact_uri == NULL) { |
|---|
| 883 | /* this dialog is probably not established! or the remote UA |
|---|
| 884 | is not compliant with the latest RFC |
|---|
| 885 | */ |
|---|
| 886 | osip_message_free(request); |
|---|
| 887 | return OSIP_SYNTAXERROR; |
|---|
| 888 | } |
|---|
| 889 | |
|---|
| 890 | |
|---|
| 891 | memset(locip, '\0', sizeof(locip)); |
|---|
| 892 | eXosip_guess_ip_for_via(eXosip.eXtl->proto_family, locip, 49); |
|---|
| 893 | if (locip[0] == '\0') { |
|---|
| 894 | OSIP_TRACE(osip_trace |
|---|
| 895 | (__FILE__, __LINE__, OSIP_ERROR, NULL, |
|---|
| 896 | "eXosip: no default interface defined\n")); |
|---|
| 897 | osip_message_free(request); |
|---|
| 898 | return OSIP_NO_NETWORK; |
|---|
| 899 | } |
|---|
| 900 | |
|---|
| 901 | /* prepare the request-line */ |
|---|
| 902 | request->sip_method = osip_strdup(method); |
|---|
| 903 | if (request->sip_method == NULL) { |
|---|
| 904 | osip_message_free(request); |
|---|
| 905 | return OSIP_NOMEM; |
|---|
| 906 | } |
|---|
| 907 | request->sip_version = osip_strdup("SIP/2.0"); |
|---|
| 908 | if (request->sip_version == NULL) { |
|---|
| 909 | osip_message_free(request); |
|---|
| 910 | return OSIP_NOMEM; |
|---|
| 911 | } |
|---|
| 912 | request->status_code = 0; |
|---|
| 913 | request->reason_phrase = NULL; |
|---|
| 914 | |
|---|
| 915 | /* and the request uri???? */ |
|---|
| 916 | if (osip_list_eol(&dialog->route_set, 0)) { |
|---|
| 917 | /* The UAC must put the remote target URI (to field) in the req_uri */ |
|---|
| 918 | i = osip_uri_clone(dialog->remote_contact_uri->url, &(request->req_uri)); |
|---|
| 919 | if (i != 0) { |
|---|
| 920 | osip_message_free(request); |
|---|
| 921 | return i; |
|---|
| 922 | } |
|---|
| 923 | } else { |
|---|
| 924 | /* fill the request-uri, and the route headers. */ |
|---|
| 925 | i = dialog_fill_route_set(dialog, request); |
|---|
| 926 | if (i != 0) { |
|---|
| 927 | osip_message_free(request); |
|---|
| 928 | return i; |
|---|
| 929 | } |
|---|
| 930 | } |
|---|
| 931 | |
|---|
| 932 | /* To and From already contains the proper tag! */ |
|---|
| 933 | i = osip_to_clone(dialog->remote_uri, &(request->to)); |
|---|
| 934 | if (i != 0) { |
|---|
| 935 | osip_message_free(request); |
|---|
| 936 | return i; |
|---|
| 937 | } |
|---|
| 938 | i = osip_from_clone(dialog->local_uri, &(request->from)); |
|---|
| 939 | if (i != 0) { |
|---|
| 940 | osip_message_free(request); |
|---|
| 941 | return i; |
|---|
| 942 | } |
|---|
| 943 | |
|---|
| 944 | /* set the cseq and call_id header */ |
|---|
| 945 | osip_message_set_call_id(request, dialog->call_id); |
|---|
| 946 | |
|---|
| 947 | if (0 == strcmp("ACK", method)) { |
|---|
| 948 | osip_cseq_t *cseq; |
|---|
| 949 | char *tmp; |
|---|
| 950 | |
|---|
| 951 | i = osip_cseq_init(&cseq); |
|---|
| 952 | if (i != 0) { |
|---|
| 953 | osip_message_free(request); |
|---|
| 954 | return i; |
|---|
| 955 | } |
|---|
| 956 | tmp = osip_malloc(20); |
|---|
| 957 | if (tmp == NULL) { |
|---|
| 958 | osip_message_free(request); |
|---|
| 959 | return OSIP_NOMEM; |
|---|
| 960 | } |
|---|
| 961 | sprintf(tmp, "%i", dialog->local_cseq); |
|---|
| 962 | osip_cseq_set_number(cseq, tmp); |
|---|
| 963 | osip_cseq_set_method(cseq, osip_strdup(method)); |
|---|
| 964 | request->cseq = cseq; |
|---|
| 965 | } else { |
|---|
| 966 | osip_cseq_t *cseq; |
|---|
| 967 | char *tmp; |
|---|
| 968 | |
|---|
| 969 | i = osip_cseq_init(&cseq); |
|---|
| 970 | if (i != 0) { |
|---|
| 971 | osip_message_free(request); |
|---|
| 972 | return i; |
|---|
| 973 | } |
|---|
| 974 | dialog->local_cseq++; /* we should we do that?? */ |
|---|
| 975 | tmp = osip_malloc(20); |
|---|
| 976 | if (tmp == NULL) { |
|---|
| 977 | osip_message_free(request); |
|---|
| 978 | return OSIP_NOMEM; |
|---|
| 979 | } |
|---|
| 980 | sprintf(tmp, "%i", dialog->local_cseq); |
|---|
| 981 | osip_cseq_set_number(cseq, tmp); |
|---|
| 982 | osip_cseq_set_method(cseq, osip_strdup(method)); |
|---|
| 983 | request->cseq = cseq; |
|---|
| 984 | } |
|---|
| 985 | |
|---|
| 986 | /* always add the Max-Forward header */ |
|---|
| 987 | osip_message_set_max_forwards(request, "70"); /* a UA should start a request with 70 */ |
|---|
| 988 | |
|---|
| 989 | |
|---|
| 990 | i = _eXosip_request_add_via(request, transport, locip); |
|---|
| 991 | if (i != 0) { |
|---|
| 992 | osip_message_free(request); |
|---|
| 993 | return i; |
|---|
| 994 | } |
|---|
| 995 | |
|---|
| 996 | /* add specific headers for each kind of request... */ |
|---|
| 997 | |
|---|
| 998 | #if 0 |
|---|
| 999 | { |
|---|
| 1000 | char contact[200]; |
|---|
| 1001 | |
|---|
| 1002 | if (firewall_ip[0] != '\0') { |
|---|
| 1003 | char *c_address = request->req_uri->host; |
|---|
| 1004 | |
|---|
| 1005 | struct addrinfo *addrinfo; |
|---|
| 1006 | struct __eXosip_sockaddr addr; |
|---|
| 1007 | |
|---|
| 1008 | i = eXosip_get_addrinfo(&addrinfo, request->req_uri->host, 5060, |
|---|
| 1009 | IPPROTO_UDP); |
|---|
| 1010 | if (i == 0) { |
|---|
| 1011 | memcpy(&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); |
|---|
| 1012 | eXosip_freeaddrinfo(addrinfo); |
|---|
| 1013 | c_address = inet_ntoa(((struct sockaddr_in *) &addr)->sin_addr); |
|---|
| 1014 | OSIP_TRACE(osip_trace |
|---|
| 1015 | (__FILE__, __LINE__, OSIP_INFO1, NULL, |
|---|
| 1016 | "eXosip: here is the resolved destination host=%s\n", |
|---|
| 1017 | c_address)); |
|---|
| 1018 | } |
|---|
| 1019 | |
|---|
| 1020 | if (eXosip_is_public_address(c_address)) { |
|---|
| 1021 | sprintf(contact, "<sip:%s@%s:%s>", |
|---|
| 1022 | dialog->local_uri->url->username, firewall_ip, |
|---|
| 1023 | firewall_port); |
|---|
| 1024 | } else { |
|---|
| 1025 | sprintf(contact, "<sip:%s@%s:%s>", |
|---|
| 1026 | dialog->local_uri->url->username, locip, firewall_port); |
|---|
| 1027 | } |
|---|
| 1028 | } else { |
|---|
| 1029 | sprintf(contact, "<sip:%s@%s:%s>", dialog->local_uri->url->username, |
|---|
| 1030 | locip, firewall_port); |
|---|
| 1031 | } |
|---|
| 1032 | osip_message_set_contact(request, contact); |
|---|
| 1033 | /* Here we'll add the supported header if it's needed! */ |
|---|
| 1034 | /* the require header must be added by the upper layer if needed */ |
|---|
| 1035 | } |
|---|
| 1036 | #else |
|---|
| 1037 | _eXosip_dialog_add_contact(request, NULL); |
|---|
| 1038 | #endif |
|---|
| 1039 | |
|---|
| 1040 | if (0 == strcmp("NOTIFY", method)) { |
|---|
| 1041 | } else if (0 == strcmp("INFO", method)) { |
|---|
| 1042 | |
|---|
| 1043 | } else if (0 == strcmp("OPTIONS", method)) { |
|---|
| 1044 | osip_message_set_accept(request, "application/sdp"); |
|---|
| 1045 | } else if (0 == strcmp("ACK", method)) { |
|---|
| 1046 | /* The ACK MUST contains the same credential than the INVITE!! */ |
|---|
| 1047 | /* TODO... */ |
|---|
| 1048 | } |
|---|
| 1049 | |
|---|
| 1050 | osip_message_set_user_agent(request, eXosip.user_agent); |
|---|
| 1051 | /* else if ... */ |
|---|
| 1052 | *dest = request; |
|---|
| 1053 | return OSIP_SUCCESS; |
|---|
| 1054 | } |
|---|
| 1055 | |
|---|
| 1056 | /* this request is only build within a dialog!! */ |
|---|
| 1057 | int generating_bye(osip_message_t ** bye, osip_dialog_t * dialog, char *transport) |
|---|
| 1058 | { |
|---|
| 1059 | int i; |
|---|
| 1060 | |
|---|
| 1061 | i = _eXosip_build_request_within_dialog(bye, "BYE", dialog, transport); |
|---|
| 1062 | if (i != 0) |
|---|
| 1063 | return i; |
|---|
| 1064 | |
|---|
| 1065 | return OSIP_SUCCESS; |
|---|
| 1066 | } |
|---|
| 1067 | |
|---|
| 1068 | /* It is RECOMMENDED to only cancel INVITE request */ |
|---|
| 1069 | int generating_cancel(osip_message_t ** dest, osip_message_t * request_cancelled) |
|---|
| 1070 | { |
|---|
| 1071 | int i; |
|---|
| 1072 | osip_message_t *request; |
|---|
| 1073 | |
|---|
| 1074 | i = osip_message_init(&request); |
|---|
| 1075 | if (i != 0) |
|---|
| 1076 | return i; |
|---|
| 1077 | |
|---|
| 1078 | /* prepare the request-line */ |
|---|
| 1079 | osip_message_set_method(request, osip_strdup("CANCEL")); |
|---|
| 1080 | osip_message_set_version(request, osip_strdup("SIP/2.0")); |
|---|
| 1081 | osip_message_set_status_code(request, 0); |
|---|
| 1082 | osip_message_set_reason_phrase(request, NULL); |
|---|
| 1083 | |
|---|
| 1084 | i = osip_uri_clone(request_cancelled->req_uri, &(request->req_uri)); |
|---|
| 1085 | if (i != 0) { |
|---|
| 1086 | osip_message_free(request); |
|---|
| 1087 | *dest = NULL; |
|---|
| 1088 | return i; |
|---|
| 1089 | } |
|---|
| 1090 | |
|---|
| 1091 | i = osip_to_clone(request_cancelled->to, &(request->to)); |
|---|
| 1092 | if (i != 0) { |
|---|
| 1093 | osip_message_free(request); |
|---|
| 1094 | *dest = NULL; |
|---|
| 1095 | return i; |
|---|
| 1096 | } |
|---|
| 1097 | i = osip_from_clone(request_cancelled->from, &(request->from)); |
|---|
| 1098 | if (i != 0) { |
|---|
| 1099 | osip_message_free(request); |
|---|
| 1100 | *dest = NULL; |
|---|
| 1101 | return i; |
|---|
| 1102 | } |
|---|
| 1103 | |
|---|
| 1104 | /* set the cseq and call_id header */ |
|---|
| 1105 | i = osip_call_id_clone(request_cancelled->call_id, &(request->call_id)); |
|---|
| 1106 | if (i != 0) { |
|---|
| 1107 | osip_message_free(request); |
|---|
| 1108 | *dest = NULL; |
|---|
| 1109 | return i; |
|---|
| 1110 | } |
|---|
| 1111 | i = osip_cseq_clone(request_cancelled->cseq, &(request->cseq)); |
|---|
| 1112 | if (i != 0) { |
|---|
| 1113 | osip_message_free(request); |
|---|
| 1114 | *dest = NULL; |
|---|
| 1115 | return i; |
|---|
| 1116 | } |
|---|
| 1117 | osip_free(request->cseq->method); |
|---|
| 1118 | request->cseq->method = osip_strdup("CANCEL"); |
|---|
| 1119 | if (request->cseq->method == NULL) { |
|---|
| 1120 | osip_message_free(request); |
|---|
| 1121 | *dest = NULL; |
|---|
| 1122 | return OSIP_NOMEM; |
|---|
| 1123 | } |
|---|
| 1124 | |
|---|
| 1125 | /* copy ONLY the top most Via Field (this method is also used by proxy) */ |
|---|
| 1126 | { |
|---|
| 1127 | osip_via_t *via; |
|---|
| 1128 | osip_via_t *via2; |
|---|
| 1129 | |
|---|
| 1130 | i = osip_message_get_via(request_cancelled, 0, &via); |
|---|
| 1131 | if (i < 0) { |
|---|
| 1132 | osip_message_free(request); |
|---|
| 1133 | *dest = NULL; |
|---|
| 1134 | return i; |
|---|
| 1135 | } |
|---|
| 1136 | i = osip_via_clone(via, &via2); |
|---|
| 1137 | if (i != 0) { |
|---|
| 1138 | osip_message_free(request); |
|---|
| 1139 | *dest = NULL; |
|---|
| 1140 | return i; |
|---|
| 1141 | } |
|---|
| 1142 | osip_list_add(&request->vias, via2, -1); |
|---|
| 1143 | } |
|---|
| 1144 | |
|---|
| 1145 | /* add the same route-set than in the previous request */ |
|---|
| 1146 | { |
|---|
| 1147 | int pos = 0; |
|---|
| 1148 | osip_route_t *route; |
|---|
| 1149 | osip_route_t *route2; |
|---|
| 1150 | |
|---|
| 1151 | while (!osip_list_eol(&request_cancelled->routes, pos)) { |
|---|
| 1152 | route = |
|---|
| 1153 | (osip_route_t *) osip_list_get(&request_cancelled->routes, pos); |
|---|
| 1154 | i = osip_route_clone(route, &route2); |
|---|
| 1155 | if (i != 0) { |
|---|
| 1156 | osip_message_free(request); |
|---|
| 1157 | *dest = NULL; |
|---|
| 1158 | return i; |
|---|
| 1159 | } |
|---|
| 1160 | osip_list_add(&request->routes, route2, -1); |
|---|
| 1161 | pos++; |
|---|
| 1162 | } |
|---|
| 1163 | } |
|---|
| 1164 | |
|---|
| 1165 | osip_message_set_max_forwards(request, "70"); /* a UA should start a request with 70 */ |
|---|
| 1166 | osip_message_set_user_agent(request, eXosip.user_agent); |
|---|
| 1167 | |
|---|
| 1168 | *dest = request; |
|---|
| 1169 | return OSIP_SUCCESS; |
|---|
| 1170 | } |
|---|