]> sjero.net Git - linphone/blob - coreapi/sal.c
Merge branch 'master' of git.sv.gnu.org:/srv/git/linphone
[linphone] / coreapi / sal.c
1 /*
2 linphone
3 Copyright (C) 2010  Simon MORLAT (simon.morlat@free.fr)
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program 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 /** 
21  This header files defines the Signaling Abstraction Layer.
22  The purpose of this layer is too allow experiment different call signaling 
23  protocols and implementations under linphone, for example SIP, JINGLE...
24 **/
25
26 #include "sal.h"
27 const char* sal_transport_to_string(SalTransport transport) {
28     switch (transport) {
29         case SalTransportUDP:return "UDP";
30         case SalTransportTCP: return "TCP";
31         case SalTransportTLS:return "TLS";
32         case SalTransportDTLS:return "DTLS";
33         default: {
34             ms_fatal("Unexpected transport [%i]",transport);
35             return NULL;
36         }
37             
38     }
39 }
40 SalTransport sal_transport_parse(const char* param) {
41     if (strcasecmp("UDP",param)==0) return SalTransportUDP;
42     if (strcasecmp("TCP",param)==0) return SalTransportTCP;
43     if (strcasecmp("TLS",param)==0) return SalTransportTLS;
44     if (strcasecmp("DTLS",param)==0) return SalTransportDTLS;
45     ms_error("Unkown transport type[%s], returning UDP", param);
46     return SalTransportUDP;
47 }
48 SalMediaDescription *sal_media_description_new(){
49         SalMediaDescription *md=ms_new0(SalMediaDescription,1);
50         md->refcount=1;
51         return md;
52 }
53
54 static void sal_media_description_destroy(SalMediaDescription *md){
55         int i;
56         for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;i++){
57                 ms_list_for_each(md->streams[i].payloads,(void (*)(void *))payload_type_destroy);
58                 ms_list_free(md->streams[i].payloads);
59                 md->streams[i].payloads=NULL;
60         }
61         ms_free(md);
62 }
63
64 void sal_media_description_ref(SalMediaDescription *md){
65         md->refcount++;
66 }
67
68 void sal_media_description_unref(SalMediaDescription *md){
69         md->refcount--;
70         if (md->refcount==0){
71                 sal_media_description_destroy (md);
72         }
73 }
74
75 SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
76     SalMediaProto proto, SalStreamType type){
77         int i;
78         for(i=0;i<md->nstreams;++i){
79                 SalStreamDescription *ss=&md->streams[i];
80                 if (ss->proto==proto && ss->type==type) return ss;
81         }
82         return NULL;
83 }
84
85 bool_t sal_media_description_empty(const SalMediaDescription *md){
86         int i;
87         for(i=0;i<md->nstreams;++i){
88                 const SalStreamDescription *ss=&md->streams[i];
89                 if (ss->port!=0) return FALSE;
90         }
91         return TRUE;
92 }
93
94 void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir){
95         int i;
96         for(i=0;i<md->nstreams;++i){
97                 SalStreamDescription *ss=&md->streams[i];
98                 ss->dir=stream_dir;
99         }
100 }
101
102
103 static bool_t is_null_address(const char *addr){
104         return strcmp(addr,"0.0.0.0")==0 || strcmp(addr,"::0")==0;
105 }
106
107 /*check for the presence of at least one stream with requested direction */
108 static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
109         int i;
110
111         /* we are looking for at least one stream with requested direction, inactive streams are ignored*/
112         for(i=0;i<md->nstreams;++i){
113                 const SalStreamDescription *ss=&md->streams[i];
114                 if (ss->dir==stream_dir) return TRUE;
115                 if (stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->addr)))
116                         return TRUE;
117         }
118         return FALSE;
119 }
120
121 bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
122         if (stream_dir==SalStreamRecvOnly){
123                 if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
124                 else return TRUE;
125         }else if (stream_dir==SalStreamSendOnly){
126                 if (has_dir(md,SalStreamRecvOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
127                 else return TRUE;
128         }else if (stream_dir==SalStreamSendRecv){
129                 return has_dir(md,SalStreamSendRecv);
130         }else{
131                 /*SalStreamInactive*/
132                 if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv)  || has_dir(md,SalStreamRecvOnly))
133                         return FALSE;
134                 else return TRUE;
135         }
136         return FALSE;
137 }
138
139 /*
140 static bool_t fmtp_equals(const char *p1, const char *p2){
141         if (p1 && p2 && strcmp(p1,p2)==0) return TRUE;
142         if (p1==NULL && p2==NULL) return TRUE;
143         return FALSE;
144 }
145 */
146
147 static bool_t payload_type_equals(const PayloadType *p1, const PayloadType *p2){
148         if (p1->type!=p2->type) return FALSE;
149         if (strcmp(p1->mime_type,p2->mime_type)!=0) return FALSE;
150         if (p1->clock_rate!=p2->clock_rate) return FALSE;
151         if (p1->channels!=p2->channels) return FALSE;
152         /*
153          Do not compare fmtp right now: they are modified internally when the call is started
154         */
155         /*
156         if (!fmtp_equals(p1->recv_fmtp,p2->recv_fmtp) ||
157             !fmtp_equals(p1->send_fmtp,p2->send_fmtp))
158                 return FALSE;
159         */
160         return TRUE;
161 }
162
163 static bool_t payload_list_equals(const MSList *l1, const MSList *l2){
164         const MSList *e1,*e2;
165         for(e1=l1,e2=l2;e1!=NULL && e2!=NULL; e1=e1->next,e2=e2->next){
166                 PayloadType *p1=(PayloadType*)e1->data;
167                 PayloadType *p2=(PayloadType*)e2->data;
168                 if (!payload_type_equals(p1,p2))
169                         return FALSE;
170         }
171         if (e1!=NULL || e2!=NULL){
172                 /*means one list is longer than the other*/
173                 return FALSE;
174         }
175         return TRUE;
176 }
177
178 bool_t sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2){
179         if (sd1->proto!=sd2->proto) return FALSE;
180         if (sd1->type!=sd2->type) return FALSE;
181         if (strcmp(sd1->addr,sd2->addr)!=0) return FALSE;
182         if (sd1->port!=sd2->port) return FALSE;
183         if (!payload_list_equals(sd1->payloads,sd2->payloads)) return FALSE;
184         if (sd1->bandwidth!=sd2->bandwidth) return FALSE;
185         if (sd1->ptime!=sd2->ptime) return FALSE;
186         /* compare candidates: TODO */
187         if (sd1->dir!=sd2->dir) return FALSE;
188         return TRUE;
189 }
190
191 bool_t sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2){
192         int i;
193         
194         if (strcmp(md1->addr,md2->addr)!=0) return FALSE;
195         if (md1->nstreams!=md2->nstreams) return FALSE;
196         if (md1->bandwidth!=md2->bandwidth) return FALSE;
197         for(i=0;i<md1->nstreams;++i){
198                 if (!sal_stream_description_equals(&md1->streams[i],&md2->streams[i]))
199                         return FALSE;
200         }
201         return TRUE;
202 }
203
204 static void assign_string(char **str, const char *arg){
205         if (*str){
206                 ms_free(*str);
207                 *str=NULL;
208         }
209         if (arg)
210                 *str=ms_strdup(arg);
211 }
212
213 void sal_op_set_contact(SalOp *op, const char *contact){
214         assign_string(&((SalOpBase*)op)->contact,contact);
215 }
216
217 void sal_op_set_route(SalOp *op, const char *route){
218         assign_string(&((SalOpBase*)op)->route,route);
219 }
220
221 void sal_op_set_from(SalOp *op, const char *from){
222         assign_string(&((SalOpBase*)op)->from,from);
223 }
224
225 void sal_op_set_to(SalOp *op, const char *to){
226         assign_string(&((SalOpBase*)op)->to,to);
227 }
228
229 void sal_op_set_user_pointer(SalOp *op, void *up){
230         ((SalOpBase*)op)->user_pointer=up;
231 }
232
233 Sal *sal_op_get_sal(const SalOp *op){
234         return ((SalOpBase*)op)->root;
235 }
236
237 const char *sal_op_get_from(const SalOp *op){
238         return ((SalOpBase*)op)->from;
239 }
240
241 const char *sal_op_get_to(const SalOp *op){
242         return ((SalOpBase*)op)->to;
243 }
244
245 const char *sal_op_get_contact(const SalOp *op){
246         return ((SalOpBase*)op)->contact;
247 }
248
249 const char *sal_op_get_route(const SalOp *op){
250         return ((SalOpBase*)op)->route;
251 }
252
253 const char *sal_op_get_remote_ua(const SalOp *op){
254         return ((SalOpBase*)op)->remote_ua;
255 }
256
257 void *sal_op_get_user_pointer(const SalOp *op){
258         return ((SalOpBase*)op)->user_pointer;
259 }
260
261 const char *sal_op_get_proxy(const SalOp *op){
262         return ((SalOpBase*)op)->route;
263 }
264
265 const char *sal_op_get_network_origin(const SalOp *op){
266         return ((SalOpBase*)op)->origin;
267 }
268
269 void __sal_op_init(SalOp *b, Sal *sal){
270         memset(b,0,sizeof(SalOpBase));
271         ((SalOpBase*)b)->root=sal;
272 }
273
274 void __sal_op_set_network_origin(SalOp *op, const char *origin){
275         assign_string(&((SalOpBase*)op)->origin,origin);
276 }
277
278
279 void __sal_op_free(SalOp *op){
280         SalOpBase *b=(SalOpBase *)op;
281         if (b->from) {
282                 ms_free(b->from);
283                 b->from=NULL;
284         }
285         if (b->to) {
286                 ms_free(b->to);
287                 b->to=NULL;
288         }
289         if (b->route) {
290                 ms_free(b->route);
291                 b->route=NULL;
292         }
293         if (b->contact) {
294                 ms_free(b->contact);
295                 b->contact=NULL;
296         }
297         if (b->origin){
298                 ms_free(b->origin);
299                 b->origin=NULL;
300         }
301         if (b->remote_ua){
302                 ms_free(b->remote_ua);
303                 b->remote_ua=NULL;
304         }
305         if (b->local_media)
306                 sal_media_description_unref(b->local_media);
307         if (b->remote_media)
308                 sal_media_description_unref(b->remote_media);
309         ms_free(op);
310 }
311
312 SalAuthInfo* sal_auth_info_new() {
313         return ms_new0(SalAuthInfo,1);
314 }
315
316 SalAuthInfo* sal_auth_info_clone(const SalAuthInfo* auth_info) {
317         SalAuthInfo* new_auth_info=sal_auth_info_new();
318         new_auth_info->username=auth_info->username?ms_strdup(auth_info->username):NULL;
319         new_auth_info->userid=auth_info->userid?ms_strdup(auth_info->userid):NULL;
320         new_auth_info->realm=auth_info->realm?ms_strdup(auth_info->realm):NULL;
321         new_auth_info->password=auth_info->password?ms_strdup(auth_info->password):NULL;
322         return new_auth_info;
323 }
324
325 void sal_auth_info_delete(const SalAuthInfo* auth_info) {
326         if (auth_info->username) ms_free(auth_info->username);
327         if (auth_info->userid) ms_free(auth_info->userid);
328         if (auth_info->realm) ms_free(auth_info->realm);
329         if (auth_info->password) ms_free(auth_info->password);
330         ms_free((void*)auth_info);
331 }