]> sjero.net Git - linphone/blob - coreapi/sal.c
fix bad free and stupid abort()
[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                 return FALSE;
154         }
155         return TRUE;
156 }
157
158 bool_t sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2){
159         if (sd1->proto!=sd2->proto) return FALSE;
160         if (sd1->type!=sd2->type) return FALSE;
161         if (strcmp(sd1->addr,sd2->addr)!=0) return FALSE;
162         if (sd1->port!=sd2->port) return FALSE;
163         if (!payload_list_equals(sd1->payloads,sd2->payloads)) return FALSE;
164         if (sd1->bandwidth!=sd2->bandwidth) return FALSE;
165         if (sd1->ptime!=sd2->ptime) return FALSE;
166         /* compare candidates: TODO */
167         if (sd1->dir!=sd2->dir) return FALSE;
168         return TRUE;
169 }
170
171 bool_t sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2){
172         int i;
173         
174         if (strcmp(md1->addr,md2->addr)!=0) return FALSE;
175         if (md1->nstreams!=md2->nstreams) return FALSE;
176         if (md1->bandwidth!=md2->bandwidth) return FALSE;
177         for(i=0;i<md1->nstreams;++i){
178                 if (!sal_stream_description_equals(&md1->streams[i],&md2->streams[i]))
179                         return FALSE;
180         }
181         return TRUE;
182 }
183
184 static void assign_string(char **str, const char *arg){
185         if (*str){
186                 ms_free(*str);
187                 *str=NULL;
188         }
189         if (arg)
190                 *str=ms_strdup(arg);
191 }
192
193 void sal_op_set_contact(SalOp *op, const char *contact){
194         assign_string(&((SalOpBase*)op)->contact,contact);
195 }
196
197 void sal_op_set_route(SalOp *op, const char *route){
198         assign_string(&((SalOpBase*)op)->route,route);
199 }
200
201 void sal_op_set_from(SalOp *op, const char *from){
202         assign_string(&((SalOpBase*)op)->from,from);
203 }
204
205 void sal_op_set_to(SalOp *op, const char *to){
206         assign_string(&((SalOpBase*)op)->to,to);
207 }
208
209 void sal_op_set_user_pointer(SalOp *op, void *up){
210         ((SalOpBase*)op)->user_pointer=up;
211 }
212
213 Sal *sal_op_get_sal(const SalOp *op){
214         return ((SalOpBase*)op)->root;
215 }
216
217 const char *sal_op_get_from(const SalOp *op){
218         return ((SalOpBase*)op)->from;
219 }
220
221 const char *sal_op_get_to(const SalOp *op){
222         return ((SalOpBase*)op)->to;
223 }
224
225 const char *sal_op_get_contact(const SalOp *op){
226         return ((SalOpBase*)op)->contact;
227 }
228
229 const char *sal_op_get_route(const SalOp *op){
230         return ((SalOpBase*)op)->route;
231 }
232
233 const char *sal_op_get_remote_ua(const SalOp *op){
234         return ((SalOpBase*)op)->remote_ua;
235 }
236
237 void *sal_op_get_user_pointer(const SalOp *op){
238         return ((SalOpBase*)op)->user_pointer;
239 }
240
241 const char *sal_op_get_proxy(const SalOp *op){
242         return ((SalOpBase*)op)->route;
243 }
244
245 const char *sal_op_get_network_origin(const SalOp *op){
246         return ((SalOpBase*)op)->origin;
247 }
248
249 void __sal_op_init(SalOp *b, Sal *sal){
250         memset(b,0,sizeof(SalOpBase));
251         ((SalOpBase*)b)->root=sal;
252 }
253
254 void __sal_op_set_network_origin(SalOp *op, const char *origin){
255         assign_string(&((SalOpBase*)op)->origin,origin);
256 }
257
258
259 void __sal_op_free(SalOp *op){
260         SalOpBase *b=(SalOpBase *)op;
261         if (b->from) {
262                 ms_free(b->from);
263                 b->from=NULL;
264         }
265         if (b->to) {
266                 ms_free(b->to);
267                 b->to=NULL;
268         }
269         if (b->route) {
270                 ms_free(b->route);
271                 b->route=NULL;
272         }
273         if (b->contact) {
274                 ms_free(b->contact);
275                 b->contact=NULL;
276         }
277         if (b->origin){
278                 ms_free(b->origin);
279                 b->origin=NULL;
280         }
281         if (b->remote_ua){
282                 ms_free(b->remote_ua);
283                 b->remote_ua=NULL;
284         }
285         if (b->local_media)
286                 sal_media_description_unref(b->local_media);
287         if (b->remote_media)
288                 sal_media_description_unref(b->remote_media);
289         ms_free(op);
290 }
291
292 SalAuthInfo* sal_auth_info_new() {
293         return ms_new0(SalAuthInfo,1);
294 }
295
296 SalAuthInfo* sal_auth_info_clone(const SalAuthInfo* auth_info) {
297         SalAuthInfo* new_auth_info=sal_auth_info_new();
298         new_auth_info->username=auth_info->username?ms_strdup(auth_info->username):NULL;
299         new_auth_info->userid=auth_info->userid?ms_strdup(auth_info->userid):NULL;
300         new_auth_info->realm=auth_info->realm?ms_strdup(auth_info->realm):NULL;
301         new_auth_info->password=auth_info->password?ms_strdup(auth_info->password):NULL;
302         return new_auth_info;
303 }
304
305 void sal_auth_info_delete(const SalAuthInfo* auth_info) {
306         if (auth_info->username) ms_free(auth_info->username);
307         if (auth_info->userid) ms_free(auth_info->userid);
308         if (auth_info->realm) ms_free(auth_info->realm);
309         if (auth_info->password) ms_free(auth_info->password);
310         ms_free((void*)auth_info);
311 }