source: verona/libeXosip2/src/eXconf.c @ 389:ff6d36f17d0d

Last change on this file since 389:ff6d36f17d0d was 389:ff6d36f17d0d, checked in by Vadim Lebedev <vadim@…>, 18 months ago

add support for http and socks tunnel

File size: 29.0 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#include <eXosip2/eXosip.h>
26
27#include <osip2/osip_mt.h>
28#include <osip2/osip_condv.h>
29
30extern eXosip_t eXosip;
31
32int ipv6_enable = 0;
33
34#ifdef OSIP_MT
35static void *_eXosip_thread(void *arg);
36#endif
37static void _eXosip_keep_alive(void);
38
39#ifndef MINISIZE
40
41void eXosip_enable_ipv6(int _ipv6_enable)
42{
43        ipv6_enable = _ipv6_enable;
44}
45
46#endif
47
48const char *eXosip_get_version(void)
49{
50        return EXOSIP_VERSION;
51}
52
53int eXosip_set_cbsip_message(CbSipCallback cbsipCallback)
54{
55        eXosip.cbsipCallback = cbsipCallback;
56        return 0;
57}
58
59int eXosip_set_cbconnection_close (CbConnectionClose cbConnectionClose)
60{
61        eXosip.cbConnectionClose = cbConnectionClose;
62        return 0;
63}
64
65int eXosip_set_keepalive_hook(CbKeepAliveHook cbkeepAliveHook)
66{
67        eXosip.keepAliveHook = cbkeepAliveHook;
68        return 0;
69}
70
71int eXosip_set_keepalive_recv_hook(CbKeepAliveRecvHook cbkeepAliveRecvHook)
72{
73        eXosip.keepAliveRecvHook = cbkeepAliveRecvHook;
74        return 0;
75}
76
77
78void eXosip_masquerade_contact(const char *public_address, int port)
79{
80        eXtl_udp.tl_masquerade_contact(public_address, port);
81        eXtl_tcp.tl_masquerade_contact(public_address, port);
82#ifdef HAVE_OPENSSL_SSL_H
83        eXtl_tls.tl_masquerade_contact(public_address, port);
84#if !(OPENSSL_VERSION_NUMBER < 0x00908000L)
85        eXtl_dtls.tl_masquerade_contact(public_address, port);
86#endif
87#endif
88        return;
89}
90
91int eXosip_guess_localip(int family, char *address, int size)
92{
93        return eXosip_guess_ip_for_via(family, address, size);
94}
95
96int eXosip_is_public_address(const char *c_address)
97{
98        return (0 != strncmp(c_address, "192.168", 7)
99                        && 0 != strncmp(c_address, "10.", 3)
100                        && 0 != strncmp(c_address, "172.16.", 7)
101                        && 0 != strncmp(c_address, "172.17.", 7)
102                        && 0 != strncmp(c_address, "172.18.", 7)
103                        && 0 != strncmp(c_address, "172.19.", 7)
104                        && 0 != strncmp(c_address, "172.20.", 7)
105                        && 0 != strncmp(c_address, "172.21.", 7)
106                        && 0 != strncmp(c_address, "172.22.", 7)
107                        && 0 != strncmp(c_address, "172.23.", 7)
108                        && 0 != strncmp(c_address, "172.24.", 7)
109                        && 0 != strncmp(c_address, "172.25.", 7)
110                        && 0 != strncmp(c_address, "172.26.", 7)
111                        && 0 != strncmp(c_address, "172.27.", 7)
112                        && 0 != strncmp(c_address, "172.28.", 7)
113                        && 0 != strncmp(c_address, "172.29.", 7)
114                        && 0 != strncmp(c_address, "172.30.", 7)
115                        && 0 != strncmp(c_address, "172.31.", 7)
116                        && 0 != strncmp(c_address, "169.254", 7));
117}
118
119void eXosip_set_user_agent(const char *user_agent)
120{
121        osip_free(eXosip.user_agent);
122        eXosip.user_agent = osip_strdup(user_agent);
123}
124
125void eXosip_kill_transaction(osip_list_t * transactions)
126{
127        osip_transaction_t *transaction;
128
129        if (!osip_list_eol(transactions, 0)) {
130                /* some transaction are still used by osip,
131                   transaction should be released by modules! */
132                OSIP_TRACE(osip_trace
133                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
134                                        "module sfp: _osip_kill_transaction transaction should be released by modules!\n"));
135        }
136
137        while (!osip_list_eol(transactions, 0)) {
138                transaction = osip_list_get(transactions, 0);
139
140                __eXosip_delete_jinfo(transaction);
141                osip_transaction_free(transaction);
142        }
143}
144
145void eXosip_quit(void)
146{
147        jauthinfo_t *jauthinfo;
148        eXosip_call_t *jc;
149        eXosip_reg_t *jreg;
150#ifndef MINISIZE
151        eXosip_notify_t *jn;
152        eXosip_subscribe_t *js;
153        eXosip_pub_t *jpub;
154#endif
155#ifdef OSIP_MT
156        int i;
157#endif
158
159        if (eXosip.j_stop_ua == -1) {
160                OSIP_TRACE(osip_trace
161                                   (__FILE__, __LINE__, OSIP_WARNING, NULL,
162                                        "eXosip: already stopped!\n"));
163                return;
164        }
165
166        eXosip.j_stop_ua = 1;           /* ask to quit the application */
167        __eXosip_wakeup();
168        __eXosip_wakeup_event();
169
170#ifdef OSIP_MT
171        if (eXosip.j_thread != NULL) {
172                i = osip_thread_join((struct osip_thread *) eXosip.j_thread);
173                if (i != 0) {
174                        OSIP_TRACE(osip_trace
175                                           (__FILE__, __LINE__, OSIP_ERROR, NULL,
176                                                "eXosip: can't terminate thread!\n"));
177                }
178                osip_free((struct osip_thread *) eXosip.j_thread);
179        }
180
181        jpipe_close(eXosip.j_socketctl);
182        jpipe_close(eXosip.j_socketctl_event);
183#endif
184
185        osip_free(eXosip.user_agent);
186
187        for (jc = eXosip.j_calls; jc != NULL; jc = eXosip.j_calls) {
188                REMOVE_ELEMENT(eXosip.j_calls, jc);
189                eXosip_call_free(jc);
190        }
191
192#ifndef MINISIZE
193        for (js = eXosip.j_subscribes; js != NULL; js = eXosip.j_subscribes) {
194                REMOVE_ELEMENT(eXosip.j_subscribes, js);
195                eXosip_subscribe_free(js);
196        }
197
198        for (jn = eXosip.j_notifies; jn != NULL; jn = eXosip.j_notifies) {
199                REMOVE_ELEMENT(eXosip.j_notifies, jn);
200                eXosip_notify_free(jn);
201        }
202#endif
203
204#ifdef OSIP_MT
205        osip_mutex_destroy((struct osip_mutex *) eXosip.j_mutexlock);
206#if !defined (_WIN32_WCE)
207        osip_cond_destroy((struct osip_cond *) eXosip.j_cond);
208#endif
209#endif
210
211        for (jreg = eXosip.j_reg; jreg != NULL; jreg = eXosip.j_reg) {
212                REMOVE_ELEMENT(eXosip.j_reg, jreg);
213                eXosip_reg_free(jreg);
214        }
215
216#ifndef MINISIZE
217        for (jpub = eXosip.j_pub; jpub != NULL; jpub = eXosip.j_pub) {
218                REMOVE_ELEMENT(eXosip.j_pub, jpub);
219                _eXosip_pub_free(jpub);
220        }
221#endif
222
223        while (!osip_list_eol(&eXosip.j_transactions, 0)) {
224                osip_transaction_t *tr =
225                        (osip_transaction_t *) osip_list_get(&eXosip.j_transactions, 0);
226                if (tr->state == IST_TERMINATED || tr->state == ICT_TERMINATED
227                        || tr->state == NICT_TERMINATED || tr->state == NIST_TERMINATED) {
228                        OSIP_TRACE(osip_trace(__FILE__, __LINE__, OSIP_INFO1, NULL,
229                                                                  "Release a terminated transaction\n"));
230                        osip_list_remove(&eXosip.j_transactions, 0);
231                        __eXosip_delete_jinfo(tr);
232                        osip_transaction_free(tr);
233                } else {
234                        osip_list_remove(&eXosip.j_transactions, 0);
235                        __eXosip_delete_jinfo(tr);
236                        osip_transaction_free(tr);
237                }
238        }
239
240        eXosip_kill_transaction(&eXosip.j_osip->osip_ict_transactions);
241        eXosip_kill_transaction(&eXosip.j_osip->osip_nict_transactions);
242        eXosip_kill_transaction(&eXosip.j_osip->osip_ist_transactions);
243        eXosip_kill_transaction(&eXosip.j_osip->osip_nist_transactions);
244        osip_release(eXosip.j_osip);
245
246        {
247                eXosip_event_t *ev;
248
249                for (ev = osip_fifo_tryget(eXosip.j_events); ev != NULL;
250                         ev = osip_fifo_tryget(eXosip.j_events))
251                        eXosip_event_free(ev);
252        }
253
254        osip_fifo_free(eXosip.j_events);
255
256        for (jauthinfo = eXosip.authinfos; jauthinfo != NULL;
257                 jauthinfo = eXosip.authinfos) {
258                REMOVE_ELEMENT(eXosip.authinfos, jauthinfo);
259                osip_free(jauthinfo);
260        }
261
262        {
263                struct eXosip_http_auth *http_auth;
264                int pos;
265
266                /* update entries with same call_id */
267                for (pos = 0; pos < MAX_EXOSIP_HTTP_AUTH; pos++) {
268                        http_auth = &eXosip.http_auths[pos];
269                        if (http_auth->pszCallId[0] == '\0')
270                                continue;
271                        osip_proxy_authenticate_free(http_auth->wa);
272                        memset(http_auth, 0, sizeof(struct eXosip_http_auth));
273                }
274        }
275
276        eXtl_udp.tl_free();
277        eXtl_tcp.tl_free();
278#ifdef HAVE_OPENSSL_SSL_H
279#if !(OPENSSL_VERSION_NUMBER < 0x00908000L)
280        eXtl_dtls.tl_free();
281#endif
282        eXtl_tls.tl_free();
283#endif
284
285        memset(&eXosip, 0, sizeof(eXosip));
286        eXosip.j_stop_ua = -1;
287        return;
288}
289
290int eXosip_set_socket(int transport, int socket, int port)
291{
292        //FIXME: que fait on dans ce cas la ?
293        eXosip.eXtl = NULL;
294        if (transport == IPPROTO_UDP) {
295                eXtl_udp.proto_port = port;
296                eXtl_udp.tl_set_socket(socket);
297                eXosip.eXtl = &eXtl_udp;
298                snprintf(eXosip.transport, sizeof(eXosip.transport), "%s", "UDP");
299        } else if (transport == IPPROTO_TCP) {
300                eXtl_tcp.proto_port = port;
301                eXtl_tcp.tl_set_socket(socket);
302                eXosip.eXtl = &eXtl_tcp;
303                snprintf(eXosip.transport, sizeof(eXosip.transport), "%s", "TCP");
304        } else
305                return OSIP_BADPARAMETER;
306
307#ifdef OSIP_MT
308        eXosip.j_thread = (void *) osip_thread_create(20000, _eXosip_thread, NULL);
309        if (eXosip.j_thread == NULL) {
310                OSIP_TRACE(osip_trace
311                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
312                                        "eXosip: Cannot start thread!\n"));
313                return OSIP_UNDEFINED_ERROR;
314        }
315#endif
316        return OSIP_SUCCESS;
317}
318
319#ifdef IPV6_V6ONLY
320int setsockopt_ipv6only(int sock)
321{
322        int on = 1;
323
324        return setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &on, sizeof(on));
325}
326#endif                                                  /* IPV6_V6ONLY */
327
328#ifndef MINISIZE
329int eXosip_find_free_port(int free_port, int transport)
330{
331        int res1;
332        int res2;
333        struct addrinfo *addrinfo_rtp = NULL;
334        struct addrinfo *curinfo_rtp;
335        struct addrinfo *addrinfo_rtcp = NULL;
336        struct addrinfo *curinfo_rtcp;
337        int sock;
338        int count;
339
340        for (count = 0; count < 8; count++) {
341                res1 =
342                        eXosip_get_addrinfo(&addrinfo_rtp, "0.0.0.0", free_port + count * 2,
343                                                                transport);
344                if (res1 != 0)
345                        return res1;
346                res2 =
347                        eXosip_get_addrinfo(&addrinfo_rtcp, "0.0.0.0",
348                                                                free_port + count * 2 + 1, transport);
349                if (res2 != 0) {
350                        eXosip_freeaddrinfo(addrinfo_rtp);
351                        return res2;
352                }
353
354                sock = -1;
355                for (curinfo_rtp = addrinfo_rtp; curinfo_rtp;
356                         curinfo_rtp = curinfo_rtp->ai_next) {
357                        if (curinfo_rtp->ai_protocol && curinfo_rtp->ai_protocol != transport) {
358                                OSIP_TRACE(osip_trace
359                                                   (__FILE__, __LINE__, OSIP_INFO3, NULL,
360                                                        "eXosip: Skipping protocol %d\n",
361                                                        curinfo_rtp->ai_protocol));
362                                continue;
363                        }
364
365                        sock = (int) socket(curinfo_rtp->ai_family, curinfo_rtp->ai_socktype,
366                                                                curinfo_rtp->ai_protocol);
367                        if (sock < 0) {
368                                OSIP_TRACE(osip_trace
369                                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
370                                                        "eXosip: Cannot create socket!\n"));
371                                continue;
372                        }
373
374                        if (curinfo_rtp->ai_family == AF_INET6) {
375#ifdef IPV6_V6ONLY
376                                if (setsockopt_ipv6only(sock)) {
377                                        close(sock);
378                                        sock = -1;
379                                        OSIP_TRACE(osip_trace
380                                                           (__FILE__, __LINE__, OSIP_ERROR, NULL,
381                                                                "eXosip: Cannot set socket option!\n"));
382                                        continue;
383                                }
384#endif                                                  /* IPV6_V6ONLY */
385                        }
386
387                        res1 = bind(sock, curinfo_rtp->ai_addr, curinfo_rtp->ai_addrlen);
388                        if (res1 < 0) {
389                                OSIP_TRACE(osip_trace
390                                                   (__FILE__, __LINE__, OSIP_WARNING, NULL,
391                                                        "eXosip: Cannot bind socket node: 0.0.0.0 family:%d\n",
392                                                        curinfo_rtp->ai_family));
393                                close(sock);
394                                sock = -1;
395                                continue;
396                        }
397                        break;
398                }
399
400                eXosip_freeaddrinfo(addrinfo_rtp);
401
402                if (sock == -1) {
403                        eXosip_freeaddrinfo(addrinfo_rtcp);
404                        continue;
405                }
406
407                close(sock);
408                sock = -1;
409                for (curinfo_rtcp = addrinfo_rtcp; curinfo_rtcp;
410                         curinfo_rtcp = curinfo_rtcp->ai_next) {
411                        if (curinfo_rtcp->ai_protocol
412                                && curinfo_rtcp->ai_protocol != transport) {
413                                OSIP_TRACE(osip_trace
414                                                   (__FILE__, __LINE__, OSIP_INFO3, NULL,
415                                                        "eXosip: Skipping protocol %d\n",
416                                                        curinfo_rtcp->ai_protocol));
417                                continue;
418                        }
419
420                        sock = (int) socket(curinfo_rtcp->ai_family, curinfo_rtcp->ai_socktype,
421                                                                curinfo_rtcp->ai_protocol);
422                        if (sock < 0) {
423                                OSIP_TRACE(osip_trace
424                                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
425                                                        "eXosip: Cannot create socket!\n"));
426                                continue;
427                        }
428
429                        if (curinfo_rtcp->ai_family == AF_INET6) {
430#ifdef IPV6_V6ONLY
431                                if (setsockopt_ipv6only(sock)) {
432                                        close(sock);
433                                        sock = -1;
434                                        OSIP_TRACE(osip_trace
435                                                           (__FILE__, __LINE__, OSIP_ERROR, NULL,
436                                                                "eXosip: Cannot set socket option!\n"));
437                                        continue;
438                                }
439#endif                                                  /* IPV6_V6ONLY */
440                        }
441
442                        res1 = bind(sock, curinfo_rtcp->ai_addr, curinfo_rtcp->ai_addrlen);
443                        if (res1 < 0) {
444                                OSIP_TRACE(osip_trace
445                                                   (__FILE__, __LINE__, OSIP_WARNING, NULL,
446                                                        "eXosip: Cannot bind socket node: 0.0.0.0 family:%d\n",
447                                                        curinfo_rtp->ai_family));
448                                close(sock);
449                                sock = -1;
450                                continue;
451                        }
452                        break;
453                }
454
455                eXosip_freeaddrinfo(addrinfo_rtcp);
456
457                /* the pair must be free */
458                if (sock == -1)
459                        continue;
460
461                close(sock);
462                sock = -1;
463                return free_port + count * 2;
464        }
465
466        /* just get a free port */
467        res1 = eXosip_get_addrinfo(&addrinfo_rtp, "0.0.0.0", 0, transport);
468        if (res1)
469                return res1;
470
471        sock = -1;
472        for (curinfo_rtp = addrinfo_rtp; curinfo_rtp;
473                 curinfo_rtp = curinfo_rtp->ai_next) {
474                socklen_t len;
475                struct sockaddr_storage ai_addr;
476
477                if (curinfo_rtp->ai_protocol && curinfo_rtp->ai_protocol != transport) {
478                        OSIP_TRACE(osip_trace
479                                           (__FILE__, __LINE__, OSIP_INFO3, NULL,
480                                                "eXosip: Skipping protocol %d\n",
481                                                curinfo_rtp->ai_protocol));
482                        continue;
483                }
484
485                sock = (int) socket(curinfo_rtp->ai_family, curinfo_rtp->ai_socktype,
486                                                        curinfo_rtp->ai_protocol);
487                if (sock < 0) {
488                        OSIP_TRACE(osip_trace
489                                           (__FILE__, __LINE__, OSIP_ERROR, NULL,
490                                                "eXosip: Cannot create socket!\n"));
491                        continue;
492                }
493
494                if (curinfo_rtp->ai_family == AF_INET6) {
495#ifdef IPV6_V6ONLY
496                        if (setsockopt_ipv6only(sock)) {
497                                close(sock);
498                                sock = -1;
499                                OSIP_TRACE(osip_trace
500                                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
501                                                        "eXosip: Cannot set socket option!\n"));
502                                continue;
503                        }
504#endif                                                  /* IPV6_V6ONLY */
505                }
506
507                res1 = bind(sock, curinfo_rtp->ai_addr, curinfo_rtp->ai_addrlen);
508                if (res1 < 0) {
509                        OSIP_TRACE(osip_trace
510                                           (__FILE__, __LINE__, OSIP_WARNING, NULL,
511                                                "eXosip: Cannot bind socket node: 0.0.0.0 family:%d\n",
512                                                curinfo_rtp->ai_family));
513                        close(sock);
514                        sock = -1;
515                        continue;
516                }
517
518                len = sizeof(ai_addr);
519                res1 = getsockname(sock, (struct sockaddr *) &ai_addr, &len);
520                if (res1 != 0) {
521                        close(sock);
522                        sock = -1;
523                        continue;
524                }
525
526                close(sock);
527                sock = -1;
528                eXosip_freeaddrinfo(addrinfo_rtp);
529
530                if (ipv6_enable == 0)
531                        return ntohs(((struct sockaddr_in *) &ai_addr)->sin_port);
532                else
533                        return ntohs(((struct sockaddr_in6 *) &ai_addr)->sin6_port);
534        }
535
536        eXosip_freeaddrinfo(addrinfo_rtp);
537
538        if (sock != -1) {
539                close(sock);
540                sock = -1;
541        }
542
543        return OSIP_UNDEFINED_ERROR;
544}
545#endif
546
547int
548eXosip_listen_addr(int transport, const char *addr, int port, int family,
549                                   int secure)
550{
551        int i = -1;
552        struct eXtl_protocol *eXtl = NULL;
553
554        if (eXosip.eXtl != NULL) {
555                /* already set */
556                OSIP_TRACE(osip_trace
557                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
558                                        "eXosip: already listening somewhere\n"));
559                return OSIP_WRONG_STATE;
560        }
561
562        if (transport == IPPROTO_UDP && secure == 0)
563                eXtl = &eXtl_udp;
564        else if (transport == IPPROTO_TCP && secure == 0)
565                eXtl = &eXtl_tcp;
566#ifdef HAVE_OPENSSL_SSL_H
567#if !(OPENSSL_VERSION_NUMBER < 0x00908000L)
568        else if (transport == IPPROTO_UDP)
569                eXtl = &eXtl_dtls;
570#endif
571        else if (transport == IPPROTO_TCP)
572                eXtl = &eXtl_tls;
573#endif
574
575
576        if (eXtl == NULL)
577                return OSIP_BADPARAMETER;
578
579        eXtl->proto_family = family;
580        eXtl->proto_port = port;
581        if (addr != NULL)
582                snprintf(eXtl->proto_ifs, sizeof(eXtl->proto_ifs), "%s", addr);
583
584#ifdef  AF_INET6
585        if (family == AF_INET6 && !addr)
586                snprintf(eXtl->proto_ifs, sizeof(eXtl->proto_ifs), "::0");
587#endif
588
589        i = eXtl->tl_open();
590
591        if (i != 0)
592                return i;
593
594        eXosip.eXtl = eXtl;
595
596        if (transport == IPPROTO_UDP && secure == 0)
597                snprintf(eXosip.transport, sizeof(eXosip.transport), "%s", "UDP");
598        else if (transport == IPPROTO_TCP && secure == 0)
599                snprintf(eXosip.transport, sizeof(eXosip.transport), "%s", "TCP");
600        //FIXME: ce n'est peut être pas la meilleur maniÚre de la faire car du coup on ne peut pas avoir openssl et csl en meme temps
601        //utiliser secure == 1 pour openssl et secure == pour CSL
602        else if (transport == IPPROTO_UDP)
603                snprintf(eXosip.transport, sizeof(eXosip.transport), "%s", "DTLS-UDP");
604        else if (transport == IPPROTO_TCP)
605                snprintf(eXosip.transport, sizeof(eXosip.transport), "%s", "TLS");
606
607#ifdef OSIP_MT
608        if (eXosip.j_thread == NULL) {
609                eXosip.j_thread = (void *) osip_thread_create(20000, _eXosip_thread, NULL);
610                if (eXosip.j_thread == NULL) {
611                        OSIP_TRACE(osip_trace
612                                           (__FILE__, __LINE__, OSIP_ERROR, NULL,
613                                                "eXosip: Cannot start thread!\n"));
614                        return OSIP_UNDEFINED_ERROR;
615                }
616        }
617#endif
618
619        return OSIP_SUCCESS;
620}
621#ifdef ENABLE_SOCKS
622static struct eXtl_protocol* socks_proto_tab[] = {
623 &eXtl_socks_tcp,
624 &eXtl_socks_http,
625 &eXtl_socks_tcp2udp,
626 &eXtl_socks_http2udp,
627 0
628};
629#else
630static struct eXtl_protocol* socks_proto_tab[] = { 0 };
631#endif
632
633int
634eXosip_set_tunnel(const char *tuntype, const char* tserver, const char* tport)
635{
636        int i;
637        struct eXtl_protocol* proto;
638
639        for(i = 0; proto = socks_proto_tab[i]; i++)
640                if (!osip_strcasecmp(proto->proto_name, tuntype))
641                        break;
642
643        if (!proto) {
644                OSIP_TRACE(osip_trace
645                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
646                                        "eXosip: Can't find tunnel protocol %s!\n", tuntype));
647
648                return -1;
649        }
650
651        eXosip.eXtl = proto;
652        proto->tl_init();
653        proto->tl_masquerade_contact(tserver, atoi(tport));
654        snprintf(eXosip.transport, sizeof(eXosip.transport), "%s",
655                        proto->proto_num == IPPROTO_UDP ? "UDP" : "TCP");
656
657#ifdef OSIP_MT
658        if (eXosip.j_thread == NULL) {
659                eXosip.j_thread = (void *) osip_thread_create(20000, _eXosip_thread, NULL);
660                if (eXosip.j_thread == NULL) {
661                        OSIP_TRACE(osip_trace
662                                           (__FILE__, __LINE__, OSIP_ERROR, NULL,
663                                                "eXosip: Cannot start thread!\n"));
664                        return OSIP_UNDEFINED_ERROR;
665                }
666        }
667#endif
668
669        return 0;
670}
671
672int eXosip_init(void)
673{
674        osip_t *osip;
675        int i;
676
677        memset(&eXosip, 0, sizeof(eXosip));
678
679        snprintf(eXosip.ipv4_for_gateway, 256, "%s", "217.12.3.11");
680        snprintf(eXosip.ipv6_for_gateway, 256, "%s",
681                         "2001:638:500:101:2e0:81ff:fe24:37c6");
682#ifndef MINISIZE
683        snprintf(eXosip.event_package, 256, "%s", "dialog");
684#endif
685
686#ifdef WIN32
687        /* Initializing windows socket library */
688        {
689                WORD wVersionRequested;
690                WSADATA wsaData;
691
692                wVersionRequested = MAKEWORD(1, 1);
693                i = WSAStartup(wVersionRequested, &wsaData);
694                if (i != 0) {
695                        OSIP_TRACE(osip_trace
696                                           (__FILE__, __LINE__, OSIP_WARNING, NULL,
697                                                "eXosip: Unable to initialize WINSOCK, reason: %d\n", i));
698                        /* return -1; It might be already initilized?? */
699                }
700        }
701#endif
702
703        eXosip.user_agent = osip_strdup("eXosip/" EXOSIP_VERSION);
704        if (eXosip.user_agent == NULL)
705                return OSIP_NOMEM;
706
707        eXosip.j_calls = NULL;
708        eXosip.j_stop_ua = 0;
709#ifdef OSIP_MT
710        eXosip.j_thread = NULL;
711#endif
712        i = osip_list_init(&eXosip.j_transactions);
713        eXosip.j_reg = NULL;
714
715#ifdef OSIP_MT
716#if !defined (_WIN32_WCE)
717        eXosip.j_cond = (struct osip_cond *) osip_cond_init();
718        if (eXosip.j_cond == NULL) {
719                osip_free(eXosip.user_agent);
720                eXosip.user_agent = NULL;
721                return OSIP_NOMEM;
722        }
723#endif
724
725        eXosip.j_mutexlock = (struct osip_mutex *) osip_mutex_init();
726        if (eXosip.j_mutexlock == NULL) {
727                osip_free(eXosip.user_agent);
728                eXosip.user_agent = NULL;
729#if !defined (_WIN32_WCE)
730                osip_cond_destroy((struct osip_cond *) eXosip.j_cond);
731                eXosip.j_cond = NULL;
732#endif
733                return OSIP_NOMEM;
734        }
735#endif
736
737        i = osip_init(&osip);
738        if (i != 0) {
739                OSIP_TRACE(osip_trace
740                                   (__FILE__, __LINE__, OSIP_ERROR, NULL,
741                                        "eXosip: Cannot initialize osip!\n"));
742                return i;
743        }
744
745        osip_set_application_context(osip, &eXosip);
746
747        eXosip_set_callbacks(osip);
748
749        eXosip.j_osip = osip;
750
751#ifdef OSIP_MT
752        /* open a TCP socket to wake up the application when needed. */
753        eXosip.j_socketctl = jpipe();
754        if (eXosip.j_socketctl == NULL)
755                return OSIP_UNDEFINED_ERROR;
756
757        eXosip.j_socketctl_event = jpipe();
758        if (eXosip.j_socketctl_event == NULL)
759                return OSIP_UNDEFINED_ERROR;
760#endif
761
762        /* To be changed in osip! */
763        eXosip.j_events = (osip_fifo_t *) osip_malloc(sizeof(osip_fifo_t));
764        if (eXosip.j_events == NULL)
765                return OSIP_NOMEM;
766        osip_fifo_init(eXosip.j_events);
767
768        eXosip.use_rport = 1;
769        eXosip.dns_capabilities = 2;
770        eXosip.keep_alive = 17000;
771
772        eXtl_udp.tl_init();
773        eXtl_tcp.tl_init();
774#ifdef HAVE_OPENSSL_SSL_H
775#if !(OPENSSL_VERSION_NUMBER < 0x00908000L)
776        eXtl_dtls.tl_init();
777#endif
778        eXtl_tls.tl_init();
779#endif
780        return OSIP_SUCCESS;
781}
782
783
784int eXosip_execute(void)
785{
786        struct timeval lower_tv;
787        int i;
788
789#ifdef OSIP_MT
790        osip_timers_gettimeout(eXosip.j_osip, &lower_tv);
791        if (lower_tv.tv_sec > 10) {
792                lower_tv.tv_sec = 10;
793                OSIP_TRACE(osip_trace
794                                   (__FILE__, __LINE__, OSIP_INFO2, NULL,
795                                        "eXosip: Reseting timer to 10s before waking up!\n"));
796        } else {
797                /*  add a small amount of time on windows to avoid
798                   waking up too early. (probably a bad time precision) */
799                if (lower_tv.tv_usec < 990000)
800                        lower_tv.tv_usec += 10000;      /* add 10ms */
801                else {
802                        lower_tv.tv_usec = 10000;       /* add 10ms */
803                        lower_tv.tv_sec++;
804                }
805                OSIP_TRACE(osip_trace
806                                   (__FILE__, __LINE__, OSIP_INFO2, NULL,
807                                        "eXosip: timer sec:%i usec:%i!\n",
808                                        lower_tv.tv_sec, lower_tv.tv_usec));
809        }
810#else
811        lower_tv.tv_sec = 0;
812        lower_tv.tv_usec = 0;
813#endif
814        i = eXosip_read_message(1, lower_tv.tv_sec, lower_tv.tv_usec);
815
816        if (i == -2000) {
817                return -2000;
818        }
819
820        eXosip_lock();
821        osip_timers_ict_execute(eXosip.j_osip);
822        osip_timers_nict_execute(eXosip.j_osip);
823        osip_timers_ist_execute(eXosip.j_osip);
824        osip_timers_nist_execute(eXosip.j_osip);
825
826        osip_nist_execute(eXosip.j_osip);
827        osip_nict_execute(eXosip.j_osip);
828        osip_ist_execute(eXosip.j_osip);
829        osip_ict_execute(eXosip.j_osip);
830
831        /* free all Calls that are in the TERMINATED STATE? */
832        eXosip_release_terminated_calls();
833        eXosip_release_terminated_registrations();
834        eXosip_release_terminated_publications();
835#ifndef MINISIZE
836        eXosip_release_terminated_subscriptions();
837        eXosip_release_terminated_in_subscriptions();
838#endif
839
840        eXosip_unlock();
841
842
843        if (eXosip.keep_alive > 0) {
844                _eXosip_keep_alive();
845        }
846
847        return OSIP_SUCCESS;
848}
849
850int eXosip_set_option(int opt, const void *value)
851{
852        int val;
853        char *tmp;
854
855        switch (opt) {
856        case EXOSIP_OPT_ADD_ACCOUNT_INFO:
857                {
858                        struct eXosip_account_info *ainfo;
859                        int i;
860                        ainfo = (struct eXosip_account_info *) value;
861                        if (ainfo == NULL || ainfo->proxy[0] == '\0') {
862                                return OSIP_BADPARAMETER;
863                        }
864                        for (i = 0; i < MAX_EXOSIP_ACCOUNT_INFO; i++) {
865                                if (eXosip.account_entries[i].proxy[0] != '\0'
866                                        && 0 == osip_strcasecmp(eXosip.account_entries[i].proxy,
867                                                                                        ainfo->proxy)) {
868                                        /* update ainfo */
869                                        if (ainfo->nat_ip[0] != '\0') {
870                                                snprintf(eXosip.account_entries[i].nat_ip,
871                                                                 sizeof(eXosip.account_entries[i].nat_ip), "%s",
872                                                                 ainfo->nat_ip);
873                                                eXosip.account_entries[i].nat_port = ainfo->nat_port;
874                                                OSIP_TRACE(osip_trace
875                                                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
876                                                                        "eXosip option set: account info updated:%s -> %s:%i\n",
877                                                                        ainfo->proxy, ainfo->nat_ip, ainfo->nat_port));
878                                        } else {
879                                                eXosip.account_entries[i].proxy[0] = '\0';
880                                                OSIP_TRACE(osip_trace
881                                                                   (__FILE__, __LINE__, OSIP_INFO2, NULL,
882                                                                        "eXosip option set: account info deleted :%s\n",
883                                                                        ainfo->proxy));
884                                        }
885                                        return OSIP_SUCCESS;
886                                }
887                        }
888                        if (ainfo->nat_ip[0] == '\0') {
889                                return OSIP_BADPARAMETER;
890                        }
891                        /* not found case: */
892                        for (i = 0; i < MAX_EXOSIP_ACCOUNT_INFO; i++) {
893                                if (eXosip.account_entries[i].proxy[0] == '\0') {
894                                        /* add ainfo */
895                                        snprintf(eXosip.account_entries[i].proxy, sizeof(ainfo->proxy),
896                                                         "%s", ainfo->proxy);
897                                        snprintf(eXosip.account_entries[i].nat_ip,
898                                                         sizeof(ainfo->nat_ip), "%s", ainfo->nat_ip);
899                                        eXosip.account_entries[i].nat_port = ainfo->nat_port;
900                                        OSIP_TRACE(osip_trace
901                                                           (__FILE__, __LINE__, OSIP_INFO1, NULL,
902                                                                "eXosip option set: account info added:%s -> %s:%i\n",
903                                                                ainfo->proxy, ainfo->nat_ip, ainfo->nat_port));
904                                        return OSIP_SUCCESS;
905                                }
906                        }
907                        return OSIP_UNDEFINED_ERROR;
908                }
909                break;
910        case EXOSIP_OPT_ADD_DNS_CACHE:
911                {
912                        struct eXosip_dns_cache *entry;
913                        int i;
914                        entry = (struct eXosip_dns_cache *) value;
915                        if (entry == NULL || entry->host[0] == '\0') {
916                                return OSIP_BADPARAMETER;
917                        }
918                        for (i = 0; i < MAX_EXOSIP_DNS_ENTRY; i++) {
919                                if (eXosip.dns_entries[i].host[0] != '\0'
920                                        && 0 == osip_strcasecmp(eXosip.dns_entries[i].host,
921                                                                                        entry->host)) {
922                                        /* update entry */
923                                        if (entry->ip[0] != '\0') {
924                                                snprintf(eXosip.dns_entries[i].ip,
925                                                                 sizeof(eXosip.dns_entries[i].ip), "%s",
926                                                                 entry->ip);
927                                                OSIP_TRACE(osip_trace
928                                                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
929                                                                        "eXosip option set: dns cache updated:%s -> %s\n",
930                                                                        entry->host, entry->ip));
931                                        } else {
932                                                eXosip.dns_entries[i].host[0] = '\0';
933                                                OSIP_TRACE(osip_trace
934                                                                   (__FILE__, __LINE__, OSIP_INFO2, NULL,
935                                                                        "eXosip option set: dns cache deleted :%s\n",
936                                                                        entry->host));
937                                        }
938                                        return OSIP_SUCCESS;
939                                }
940                        }
941                        if (entry->ip[0] == '\0') {
942                                return OSIP_BADPARAMETER;
943                        }
944                        /* not found case: */
945                        for (i = 0; i < MAX_EXOSIP_DNS_ENTRY; i++) {
946                                if (eXosip.dns_entries[i].host[0] == '\0') {
947                                        /* add entry */
948                                        snprintf(eXosip.dns_entries[i].host, sizeof(entry->host), "%s",
949                                                         entry->host);
950                                        snprintf(eXosip.dns_entries[i].ip, sizeof(entry->ip), "%s",
951                                                         entry->ip);
952                                        OSIP_TRACE(osip_trace
953                                                           (__FILE__, __LINE__, OSIP_INFO2, NULL,
954                                                                "eXosip option set: dns cache added:%s -> %s\n",
955                                                                entry->host, entry->ip));
956                                        return OSIP_SUCCESS;
957                                }
958                        }
959                        return OSIP_UNDEFINED_ERROR;
960                }
961                break;
962        case EXOSIP_OPT_UDP_KEEP_ALIVE:
963                val = *((int *) value);
964                eXosip.keep_alive = val;        /* value in ms */
965                break;
966        case EXOSIP_OPT_UDP_KEEP_ALIVE_ADJUST:
967                val = *((int *) value);
968                eXosip.keep_alive_adjust = val; /* value in ms */
969                eXosip.keep_alive_successed = 0;
970                break;
971        case EXOSIP_OPT_UDP_LEARN_PORT:
972                val = *((int *) value);
973                eXosip.learn_port = val;        /* 1 to learn port */
974                break;
975#ifndef MINISIZE
976        case EXOSIP_OPT_SET_HTTP_TUNNEL_PORT:
977                val = *((int *) value);
978                eXosip.http_port = val; /* value in ms */
979                OSIP_TRACE(osip_trace
980                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
981                                        "eXosip option set: http_port:%i!\n", eXosip.http_port));
982                break;
983        case EXOSIP_OPT_SET_HTTP_TUNNEL_PROXY:
984                tmp = (char *) value;
985                memset(eXosip.http_proxy, '\0', sizeof(eXosip.http_proxy));
986                if (tmp != NULL && tmp[0] != '\0')
987                        osip_strncpy(eXosip.http_proxy, tmp, sizeof(eXosip.http_proxy)-1);      /* value in proxy:port */
988                OSIP_TRACE(osip_trace
989                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
990                                        "eXosip option set: http_proxy:%s!\n", eXosip.http_proxy));
991                break;
992        case EXOSIP_OPT_SET_HTTP_OUTBOUND_PROXY:
993                tmp = (char *) value;
994                memset(eXosip.http_outbound_proxy, '\0',
995                           sizeof(eXosip.http_outbound_proxy));
996                if (tmp != NULL && tmp[0] != '\0')
997                        osip_strncpy(eXosip.http_outbound_proxy, tmp, sizeof(eXosip.http_outbound_proxy)-1);    /* value in proxy:port */
998                OSIP_TRACE(osip_trace
999                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
1000                                        "eXosip option set: http_outbound_proxy:%s!\n",
1001                                        eXosip.http_outbound_proxy));
1002                break;
1003
1004        case EXOSIP_OPT_DONT_SEND_101:
1005                val = *((int *) value);
1006                eXosip.dontsend_101 = val;      /* 0 to disable */
1007                break;
1008#endif
1009
1010        case EXOSIP_OPT_USE_RPORT:
1011                val = *((int *) value);
1012                eXosip.use_rport = val; /* 0 to disable (for broken NAT only?) */
1013                break;
1014
1015        case EXOSIP_OPT_SET_IPV4_FOR_GATEWAY:
1016                tmp = (char *) value;
1017                memset(eXosip.ipv4_for_gateway, '\0', sizeof(eXosip.ipv4_for_gateway));
1018                if (tmp != NULL && tmp[0] != '\0')
1019                        osip_strncpy(eXosip.ipv4_for_gateway, tmp, sizeof(eXosip.ipv4_for_gateway)-1);
1020                OSIP_TRACE(osip_trace
1021                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
1022                                        "eXosip option set: ipv4_for_gateway:%s!\n",
1023                                        eXosip.ipv4_for_gateway));
1024                break;
1025#ifndef MINISIZE
1026        case EXOSIP_OPT_SET_IPV6_FOR_GATEWAY:
1027                tmp = (char *) value;
1028                memset(eXosip.ipv6_for_gateway, '\0', sizeof(eXosip.ipv6_for_gateway));
1029                if (tmp != NULL && tmp[0] != '\0')
1030                        osip_strncpy(eXosip.ipv6_for_gateway, tmp, sizeof(eXosip.ipv6_for_gateway)-1);
1031                OSIP_TRACE(osip_trace
1032                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
1033                                        "eXosip option set: ipv6_for_gateway:%s!\n",
1034                                        eXosip.ipv6_for_gateway));
1035                break;
1036        case EXOSIP_OPT_EVENT_PACKAGE:
1037                tmp = (char *) value;
1038                memset(eXosip.event_package, '\0', sizeof(eXosip.event_package));
1039                if (tmp != NULL && tmp[0] != '\0')
1040                        osip_strncpy(eXosip.event_package, tmp, sizeof(eXosip.event_package)-1);
1041                OSIP_TRACE(osip_trace
1042                                   (__FILE__, __LINE__, OSIP_INFO1, NULL,
1043                                        "eXosip option set: event_package:%s!\n",
1044                                        eXosip.event_package));
1045                break;
1046#endif
1047        case EXOSIP_OPT_DNS_CAPABILITIES:       /*EXOSIP_OPT_SRV_WITH_NAPTR: */
1048                val = *((int *) value);
1049                /* 0: A request, 1: SRV support, 2: NAPTR+SRV support */
1050                eXosip.dns_capabilities = val;
1051                break;
1052        default:
1053                return OSIP_BADPARAMETER;
1054        }
1055        return OSIP_SUCCESS;
1056}
1057
1058static void _eXosip_keep_alive(void)
1059{
1060        static struct timeval mtimer = { 0, 0 };
1061        struct timeval now;
1062        int ret = 0;
1063
1064        osip_gettimeofday(&now, NULL);
1065
1066        if (mtimer.tv_sec == 0 && mtimer.tv_usec == 0) {
1067                /* first init */
1068                osip_gettimeofday(&mtimer, NULL);
1069                add_gettimeofday(&mtimer, eXosip.keep_alive);
1070        }
1071
1072        if (osip_timercmp(&now, &mtimer, <)) {
1073                return;                                 /* not yet time */
1074        }
1075
1076        OSIP_TRACE(osip_trace
1077                           (__FILE__, __LINE__, OSIP_WARNING, NULL,
1078                                "keep alive: %i\n", now.tv_sec - mtimer.tv_sec));
1079
1080        /* reset timer */
1081        osip_gettimeofday(&mtimer, NULL);
1082        add_gettimeofday(&mtimer, eXosip.keep_alive);
1083
1084        ret += eXtl_udp.tl_keepalive();
1085        ret += eXtl_tcp.tl_keepalive();
1086#ifdef HAVE_OPENSSL_SSL_H
1087        ret += eXtl_tls.tl_keepalive();
1088#if !(OPENSSL_VERSION_NUMBER < 0x00908000L)
1089        ret += eXtl_dtls.tl_keepalive();
1090#endif
1091#endif
1092        if (ret < 0)
1093        {
1094                if (eXosip.keep_alive_successed)
1095                        eXosip.keep_alive_adjust /= 2;
1096                eXosip.keep_alive -= eXosip.keep_alive_adjust;
1097        }
1098        else if (ret > 0)
1099        {
1100                eXosip.keep_alive_successed = 1;
1101                eXosip.keep_alive += eXosip.keep_alive_adjust;
1102        }
1103        OSIP_TRACE(osip_trace
1104                                   (__FILE__, __LINE__, OSIP_INFO3, NULL,
1105                                        "keep alive: %i adjust: %i ret %i\n", eXosip.keep_alive, eXosip.keep_alive_adjust, ret));
1106}
1107
1108#ifdef OSIP_MT
1109void *_eXosip_thread(void *arg)
1110{
1111        int i;
1112
1113        while (eXosip.j_stop_ua == 0) {
1114                i = eXosip_execute();
1115                if (i == -2000)
1116                        osip_thread_exit();
1117        }
1118        osip_thread_exit();
1119        return NULL;
1120}
1121
1122#endif
Note: See TracBrowser for help on using the repository browser.