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