source: verona/libeXosip2/src/jrequest.c @ 131:acaf0886270b

Last change on this file since 131:acaf0886270b was 131:acaf0886270b, checked in by Vadim Lebedev <vadim@…>, 2 years ago

BIG patch to bring old verona to the XXX level

File size: 30.8 KB
Line 
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
39extern eXosip_t eXosip;
40
41extern int ipv6_enable;
42
43/* Private functions */
44static 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...   */
49char *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
60int 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
68char *osip_from_tag_new_random(void)
69{
70        return osip_call_id_new_random();
71}
72
73char *osip_to_tag_new_random(void)
74{
75        return osip_call_id_new_random();
76}
77
78unsigned int via_branch_new_random(void)
79{
80        return osip_build_random_number();
81}
82
83
84int _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
182int 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
226int _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
247int
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*/
312int
313generating_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
635int
636generating_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
749int
750generating_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
773static 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
851int
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!! */
1057int 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 */
1069int 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}
Note: See TracBrowser for help on using the repository browser.