]> 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
28 SalMediaDescription *sal_media_description_new(){
29         SalMediaDescription *md=ms_new0(SalMediaDescription,1);
30         md->refcount=1;
31         return md;
32 }
33
34 static void sal_media_description_destroy(SalMediaDescription *md){
35         int i;
36         for(i=0;i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS;i++){
37                 ms_list_for_each(md->streams[i].payloads,(void (*)(void *))payload_type_destroy);
38                 ms_list_free(md->streams[i].payloads);
39                 md->streams[i].payloads=NULL;
40         }
41         ms_free(md);
42 }
43
44 void sal_media_description_ref(SalMediaDescription *md){
45         md->refcount++;
46 }
47
48 void sal_media_description_unref(SalMediaDescription *md){
49         md->refcount--;
50         if (md->refcount==0){
51                 sal_media_description_destroy (md);
52         }
53 }
54
55 SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
56     SalMediaProto proto, SalStreamType type){
57         int i;
58         for(i=0;i<md->nstreams;++i){
59                 SalStreamDescription *ss=&md->streams[i];
60                 if (ss->proto==proto && ss->type==type) return ss;
61         }
62         return NULL;
63 }
64
65 bool_t sal_media_description_empty(const SalMediaDescription *md){
66         int i;
67         for(i=0;i<md->nstreams;++i){
68                 const SalStreamDescription *ss=&md->streams[i];
69                 if (ss->port!=0) return FALSE;
70         }
71         return TRUE;
72 }
73
74 void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir){
75         int i;
76         for(i=0;i<md->nstreams;++i){
77                 SalStreamDescription *ss=&md->streams[i];
78                 ss->dir=stream_dir;
79         }
80 }
81
82
83 static bool_t is_null_address(const char *addr){
84         return strcmp(addr,"0.0.0.0")==0 || strcmp(addr,"::0")==0;
85 }
86
87 /*check for the presence of at least one stream with requested direction */
88 static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
89         int i;
90
91         /* we are looking for at least one stream with requested direction, inactive streams are ignored*/
92         for(i=0;i<md->nstreams;++i){
93                 const SalStreamDescription *ss=&md->streams[i];
94                 if (ss->dir==stream_dir) return TRUE;
95                 if (stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->addr)))
96                         return TRUE;
97         }
98         return FALSE;
99 }
100
101 bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
102         if (stream_dir==SalStreamRecvOnly){
103                 if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
104                 else return TRUE;
105         }else if (stream_dir==SalStreamSendOnly){
106                 if (has_dir(md,SalStreamRecvOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
107                 else return TRUE;
108         }else if (stream_dir==SalStreamSendRecv){
109                 return has_dir(md,SalStreamSendRecv);
110         }else{
111                 /*SalStreamInactive*/
112                 if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv)  || has_dir(md,SalStreamRecvOnly))
113                         return FALSE;
114                 else return TRUE;
115         }
116         return FALSE;
117 }
118
119 /*
120 static bool_t fmtp_equals(const char *p1, const char *p2){
121         if (p1 && p2 && strcmp(p1,p2)==0) return TRUE;
122         if (p1==NULL && p2==NULL) return TRUE;
123         return FALSE;
124 }
125 */
126
127 static bool_t payload_type_equals(const PayloadType *p1, const PayloadType *p2){
128         if (p1->type!=p2->type) return FALSE;
129         if (strcmp(p1->mime_type,p2->mime_type)!=0) return FALSE;
130         if (p1->clock_rate!=p2->clock_rate) return FALSE;
131         if (p1->channels!=p2->channels) return FALSE;
132         /*
133          Do not compare fmtp right now: they are modified internally when the call is started
134         */
135         /*
136         if (!fmtp_equals(p1->recv_fmtp,p2->recv_fmtp) ||
137             !fmtp_equals(p1->send_fmtp,p2->send_fmtp))
138                 return FALSE;
139         */
140         return TRUE;
141 }
142
143 static bool_t payload_list_equals(const MSList *l1, const MSList *l2){
144         const MSList *e1,*e2;
145         for(e1=l1,e2=l2;e1!=NULL && e2!=NULL; e1=e1->next,e2=e2->next){
146                 PayloadType *p1=(PayloadType*)e1->data;
147                 PayloadType *p2=(PayloadType*)e2->data;
148                 if (!payload_type_equals(p1,p2))
149                         return FALSE;
150         }
151         if (e1!=NULL || e2!=NULL){
152                 /*means one list is longer than the other*/
153                 abort();
154                 return FALSE;
155         }
156         return TRUE;
157 }
158
159 bool_t sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2){
160         if (sd1->proto!=sd2->proto) return FALSE;
161         if (sd1->type!=sd2->type) return FALSE;
162         if (strcmp(sd1->addr,sd2->addr)!=0) return FALSE;
163         if (sd1->port!=sd2->port) return FALSE;
164         if (!payload_list_equals(sd1->payloads,sd2->payloads)) return FALSE;
165         if (sd1->bandwidth!=sd2->bandwidth) return FALSE;
166         if (sd1->ptime!=sd2->ptime) return FALSE;
167         /* compare candidates: TODO */
168         if (sd1->dir!=sd2->dir) return FALSE;
169         return TRUE;
170 }
171
172 bool_t sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2){
173         int i;
174         
175         if (strcmp(md1->addr,md2->addr)!=0) return FALSE;
176         if (md1->nstreams!=md2->nstreams) return FALSE;
177         if (md1->bandwidth!=md2->bandwidth) return FALSE;
178         for(i=0;i<md1->nstreams;++i){
179                 if (!sal_stream_description_equals(&md1->streams[i],&md2->streams[i]))
180                         return FALSE;
181         }
182         return TRUE;
183 }
184
185 static void assign_string(char **str, const char *arg){
186         if (*str){
187                 ms_free(*str);
188                 *str=NULL;
189         }
190         if (arg)
191                 *str=ms_strdup(arg);
192 }
193
194 void sal_op_set_contact(SalOp *op, const char *contact){
195         assign_string(&((SalOpBase*)op)->contact,contact);
196 }
197
198 void sal_op_set_route(SalOp *op, const char *route){
199         assign_string(&((SalOpBase*)op)->route,route);
200 }
201
202 void sal_op_set_from(SalOp *op, const char *from){
203         assign_string(&((SalOpBase*)op)->from,from);
204 }
205
206 void sal_op_set_to(SalOp *op, const char *to){
207         assign_string(&((SalOpBase*)op)->to,to);
208 }
209
210 void sal_op_set_user_pointer(SalOp *op, void *up){
211         ((SalOpBase*)op)->user_pointer=up;
212 }
213
214 Sal *sal_op_get_sal(const SalOp *op){
215         return ((SalOpBase*)op)->root;
216 }
217
218 const char *sal_op_get_from(const SalOp *op){
219         return ((SalOpBase*)op)->from;
220 }
221
222 const char *sal_op_get_to(const SalOp *op){
223         return ((SalOpBase*)op)->to;
224 }
225
226 const char *sal_op_get_contact(const SalOp *op){
227         return ((SalOpBase*)op)->contact;
228 }
229
230 const char *sal_op_get_route(const SalOp *op){
231         return ((SalOpBase*)op)->route;
232 }
233
234 const char *sal_op_get_remote_ua(const SalOp *op){
235         return ((SalOpBase*)op)->remote_ua;
236 }
237
238 void *sal_op_get_user_pointer(const SalOp *op){
239         return ((SalOpBase*)op)->user_pointer;
240 }
241
242 const char *sal_op_get_proxy(const SalOp *op){
243         return ((SalOpBase*)op)->route;
244 }
245
246 const char *sal_op_get_network_origin(const SalOp *op){
247         return ((SalOpBase*)op)->origin;
248 }
249
250 void __sal_op_init(SalOp *b, Sal *sal){
251         memset(b,0,sizeof(SalOpBase));
252         ((SalOpBase*)b)->root=sal;
253 }
254
255 void __sal_op_set_network_origin(SalOp *op, const char *origin){
256         assign_string(&((SalOpBase*)op)->origin,origin);
257 }
258
259
260 void __sal_op_free(SalOp *op){
261         SalOpBase *b=(SalOpBase *)op;
262         if (b->from) {
263                 ms_free(b->from);
264                 b->from=NULL;
265         }
266         if (b->to) {
267                 ms_free(b->to);
268                 b->to=NULL;
269         }
270         if (b->route) {
271                 ms_free(b->route);
272                 b->route=NULL;
273         }
274         if (b->contact) {
275                 ms_free(b->contact);
276                 b->contact=NULL;
277         }
278         if (b->origin){
279                 ms_free(b->origin);
280                 b->origin=NULL;
281         }
282         if (b->remote_ua){
283                 ms_free(b->remote_ua);
284                 b->remote_ua=NULL;
285         }
286         if (b->local_media)
287                 sal_media_description_unref(b->local_media);
288         if (b->remote_media)
289                 sal_media_description_unref(b->remote_media);
290         ms_free(op);
291 }
292
293 SalAuthInfo* sal_auth_info_new() {
294         return ms_new0(SalAuthInfo,1);
295 }
296
297 SalAuthInfo* sal_auth_info_clone(const SalAuthInfo* auth_info) {
298         SalAuthInfo* new_auth_info=sal_auth_info_new();
299         new_auth_info->username=auth_info->username?ms_strdup(auth_info->username):NULL;
300         new_auth_info->userid=auth_info->userid?ms_strdup(auth_info->userid):NULL;
301         new_auth_info->realm=auth_info->realm?ms_strdup(auth_info->realm):NULL;
302         new_auth_info->password=auth_info->password?ms_strdup(auth_info->password):NULL;
303         return new_auth_info;
304 }
305
306 void sal_auth_info_delete(const SalAuthInfo* auth_info) {
307         if (auth_info->username) ms_free(auth_info->username);
308         if (auth_info->userid) ms_free(auth_info->userid);
309         if (auth_info->realm) ms_free(auth_info->realm);
310         if (auth_info->password) ms_free(auth_info->password);
311         ms_free((void*)auth_info);
312 }