2
The osipua library is a library based on oSIP that implements CallLeg and User Agent
4
Copyright (C) 2001 Simon MORLAT simon.morlat@free.fr
5
Aymeric MOIZARD jack@atosc.org
6
This library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Lesser General Public
8
License as published by the Free Software Foundation; either
9
version 2.1 of the License, or (at your option) any later version.
11
This library is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
Lesser General Public License for more details.
16
You should have received a copy of the GNU Lesser General Public
17
License along with this library; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
#include <sys/types.h>
22
#include <sys/socket.h>
24
#include <netinet/in.h>
25
#include <arpa/inet.h>
28
#include "osipmanager.h"
32
#include <sys/types.h>
33
#include <sys/socket.h>
35
#define STRN_EQ(x,y,l) (strncasecmp((x),(y),(l)) == 0)
38
extern OsipManager *def_manager;
40
int udp_receive (OsipManager * manager);
42
void osipua_execute(OsipManager *manager)
44
long int time_elapsed;
47
osip_ict_execute (manager->config);
48
osip_nict_execute (manager->config);
49
osip_ist_execute (manager->config);
50
osip_nist_execute (manager->config);
53
osip_timers_ict_execute (manager->config);
54
osip_timers_ist_execute (manager->config);
55
osip_timers_nict_execute (manager->config);
56
osip_timers_nist_execute (manager->config);
57
#ifdef OSIP_RETRANSMISSIONS
58
osip_retransmissions_execute(manager->config);
60
/* free killed transaction */
61
while ( (trn=fifo_tryget(&manager->garbage_trn))!=NULL){
62
transaction_free(trn);
67
void osipua_distribute_event(OsipManager *m, sipevent_t *ev)
69
osip_t *config=m->config;
73
smutex_lock(m->mutex);
74
err=osip_find_transaction_and_add_event(config,ev);
76
/* check if it is not an ack for invite (not handled by osip)*/
77
if (ev->type==RCV_REQACK){
78
/* stop the retransmissions of the 200 Ok the ACK matches */
79
#ifdef OSIP_RETRANSMISSIONS
80
osip_stop_200ok_retransmissions(config,ev->sip);
86
else if (ev->type==RCV_STATUS_2XX){
87
/* this a retransmission of 200 Ok */
92
else if (EVT_IS_INCOMINGREQ(ev)){
93
/* not an ack, of course */
94
trn=osip_create_transaction(config,ev);
95
transaction_execute(trn,ev);
98
/* an existing transaction was found */
102
smutex_unlock(m->mutex);
107
sipd_thread (void *managerp)
109
OsipManager *manager = (OsipManager *) managerp;
112
osip_trace (OSIP_INFO1, ("Entering osipua thread.\n"));
113
manager->thread_pid=getpid();
115
while (manager->udp_run_cond)
119
struct timeval timeout;
126
struct sockaddr_storage sa;
128
struct sockaddr_in sa;
131
memcpy (&osipfdset, &manager->udpfdset, sizeof (fd_set));
132
timeout.tv_sec = manager->recv_tout.tv_sec; /* timeout can be modified by linux !! */
133
timeout.tv_usec = manager->recv_tout.tv_usec;
134
nb = select (manager->max_udpfd + 1, &osipfdset, NULL, NULL,&timeout);
135
/* if something to read on the control file descriptor, then exit thread */
138
if (FD_ISSET (manager->udp_unblock_fd, &osipfdset))
140
//printf("Receiving something on unblock_fd\n");
141
read (manager->udp_unblock_fd, manager->udp_buf,
142
SIP_MESSAGE_MAX_LENGTH);
145
//printf("Something to read !!!!!!!!!!!!!!!!!\n");
146
for (j = 0, k = 0; (j < OSIP_MAX_UDP_PORTS) && (k < nb); j++)
148
if (FD_ISSET (manager->udpfds[j], &osipfdset))
152
i = recvfrom (manager->udpfds[j],
154
SIP_MESSAGE_MAX_LENGTH, 0,
155
(struct sockaddr *) &sa, &slen);
158
/* Message might not end with a "\0" but we know the number of */
160
sipevent_t *sipevent;
161
unsigned short int port = 0;
165
char namebuf[BUFSIZ];
166
char sbuf[NI_MAXSERV];
168
manager->udp_buf[i] = '\0';
170
error = getnameinfo((struct sockaddr *)&sa, slen,
171
namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);
173
osip_trace (OSIP_INFO1, ("getnameinfo error\n"));
178
if (STRN_EQ(name, "::ffff:", 7))
180
switch(((struct sockaddr *)&sa)->sa_family){
182
port = ntohs(((struct sockaddr_in*)&sa)->sin_port);
183
osip_trace (OSIP_INFO1,
184
("info: Message from %s:%i\n",
189
port = ntohs(((struct sockaddr_in6*)&sa)->sin6_port);
190
osip_trace (OSIP_INFO1,
191
("info: Message from [%s]:%i\n",
196
osip_trace(OSIP_WARNING,
197
("Cant find port number"));
201
name = inet_ntoa (sa.sin_addr);
204
osip_trace (OSIP_INFO1,
205
("info: RECEIVING UDP MESSAGE:\n%s\n",
208
sipevent = osip_parse (manager->udp_buf);
209
if (sipevent != NULL){
210
if (MSG_IS_REQUEST(sipevent->sip))
212
osipua_fix_via_header(sipevent,
216
osipua_distribute_event(manager,sipevent);
221
osip_trace(OSIP_ERROR,
222
("UDP listener failed while receiving data!\n"));
226
/* messages have been received */
228
smutex_lock(manager->mutex);
229
osipua_execute(manager);
230
smutex_unlock(manager->mutex);
233
osip_trace (OSIP_INFO1, ("Exiting osipua thread.\n"));
238
osipua_fix_via_header(sipevent_t *evt, char *ip_addr, int port)
240
generic_param_t *rport;
242
/* get Top most Via header: */
243
if (evt==NULL||evt->sip==NULL)
245
via = list_get(evt->sip->vias, 0);
246
if (via==NULL||via->host==NULL)
247
/* Hey, we could build it? */
250
via_param_getbyname(via, "rport", &rport);
255
if (rport->gvalue==NULL)
257
rport->gvalue = (char *) smalloc(8);
258
snprintf(rport->gvalue, 8, "%i", port);
262
/* only add the received parameter if the 'sent-by' value does not contains
264
if (0==strcmp(via->host, ip_addr)) /* don't need the received parameter */
266
via_set_received(via, sgetcopy(ip_addr));
272
udp_send (transaction_t * trn, sip_t * sipmsg, char *host, int port, int sock)
275
struct sockaddr_storage addr;
276
struct addrinfo hints, *res;
280
struct sockaddr_in addr;
281
unsigned long int one_inet_addr;
286
osip_trace(OSIP_ERROR,("Null message !!"));
290
msg_2char(sipmsg,&message);
292
osip_trace(OSIP_ERROR,("msg_2char failed !!"));
295
osip_trace(OSIP_INFO1,("Sending message:\n%s",message));
298
/* I add that code for compatibility with older version:
299
This code is not needed anymore with libosip-0.9.2 and >.
300
The "received" parameter IS ALWAYS THERE because linphone
301
add it itself to evry incoming requests.
303
if (MSG_IS_RESPONSE(sipmsg))
308
generic_param_t *maddr;
309
generic_param_t *received;
310
generic_param_t *rport;
311
via = list_get(sipmsg->vias, 0);
312
via_param_getbyname(via, "maddr", &maddr);
313
via_param_getbyname(via, "received", &received);
314
via_param_getbyname(via, "rport", &rport);
315
/* 1: for reliable protocol (not supported)
316
2: check maddr and multicast usage (not supported) */
318
host = maddr->gvalue;
319
/* we should check if this is a multicast address and use
320
set the "ttl" in this case. */
321
else if (received!=NULL)
322
host = received->gvalue;
323
else host = via->host;
325
if (rport==NULL||rport->gvalue==NULL)
327
if (via->port!=NULL) port = satoi(via->port);
331
port = satoi(rport->gvalue);
335
memset(&hints, 0, sizeof(hints));
336
hints.ai_family = PF_UNSPEC;
337
hints.ai_socktype = SOCK_DGRAM;
338
hints.ai_flags = AI_NUMERICHOST;
339
snprintf(num, sizeof(num), "%d", port);
340
error = getaddrinfo(host, num, &hints, &res);
342
osip_trace (OSIP_INFO1,
343
("error: %s: %s\n", host, gai_strerror(error)));
346
if (res->ai_addrlen > sizeof(addr)) {
347
osip_trace (OSIP_INFO1,
348
("error: sockaddr too large\n"));
352
memcpy(&addr, res->ai_addr, res->ai_addrlen);
355
if ((int) (one_inet_addr = inet_addr (host)) == -1)
357
osip_trace (OSIP_INFO1,
358
("error: destination is not an ip address:%s\n",
364
addr.sin_addr.s_addr = one_inet_addr;
367
addr.sin_port = htons ((short) port);
368
addr.sin_family = AF_INET;
371
osip_trace(OSIP_INFO1,("warning: using default manager socket to send a message.\n"));
372
sock=def_manager->send_sock;
375
if (0 > sendto (sock, (const void *) message, strlen (message), 0,
376
(struct sockaddr *) &addr, sizeof (addr)))
378
osip_trace(OSIP_ERROR,("udp_send: could not send message using socket %i: %s\n",sock,strerror(errno)));