3 Copyright (C) 2010 Simon MORLAT (simon.morlat@free.fr)
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.
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.
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.
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...
27 const char* sal_transport_to_string(SalTransport transport) {
29 case SalTransportUDP:return "udp";
30 case SalTransportTCP: return "tcp";
31 case SalTransportTLS:return "tls";
32 case SalTransportDTLS:return "dtls";
34 ms_fatal("Unexpected transport [%i]",transport);
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;
48 SalMediaDescription *sal_media_description_new(){
49 SalMediaDescription *md=ms_new0(SalMediaDescription,1);
54 static void sal_media_description_destroy(SalMediaDescription *md){
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;
64 void sal_media_description_ref(SalMediaDescription *md){
68 void sal_media_description_unref(SalMediaDescription *md){
71 sal_media_description_destroy (md);
75 SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
76 SalMediaProto proto, SalStreamType type){
78 for(i=0;i<md->nstreams;++i){
79 SalStreamDescription *ss=&md->streams[i];
80 if (ss->proto==proto && ss->type==type) return ss;
85 bool_t sal_media_description_empty(const SalMediaDescription *md){
87 for(i=0;i<md->nstreams;++i){
88 const SalStreamDescription *ss=&md->streams[i];
89 if (ss->port!=0) return FALSE;
94 void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir){
96 for(i=0;i<md->nstreams;++i){
97 SalStreamDescription *ss=&md->streams[i];
103 static bool_t is_null_address(const char *addr){
104 return strcmp(addr,"0.0.0.0")==0 || strcmp(addr,"::0")==0;
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){
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)))
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;
125 }else if (stream_dir==SalStreamSendOnly){
126 if (has_dir(md,SalStreamRecvOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
128 }else if (stream_dir==SalStreamSendRecv){
129 return has_dir(md,SalStreamSendRecv);
131 /*SalStreamInactive*/
132 if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv) || has_dir(md,SalStreamRecvOnly))
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;
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;
153 Do not compare fmtp right now: they are modified internally when the call is started
156 if (!fmtp_equals(p1->recv_fmtp,p2->recv_fmtp) ||
157 !fmtp_equals(p1->send_fmtp,p2->send_fmtp))
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))
171 if (e1!=NULL || e2!=NULL){
172 /*means one list is longer than the other*/
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;
191 bool_t sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2){
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]))
204 static void assign_string(char **str, const char *arg){
213 void sal_op_set_contact(SalOp *op, const char *contact){
214 assign_string(&((SalOpBase*)op)->contact,contact);
217 void sal_op_set_route(SalOp *op, const char *route){
218 assign_string(&((SalOpBase*)op)->route,route);
221 void sal_op_set_from(SalOp *op, const char *from){
222 assign_string(&((SalOpBase*)op)->from,from);
225 void sal_op_set_to(SalOp *op, const char *to){
226 assign_string(&((SalOpBase*)op)->to,to);
229 void sal_op_set_user_pointer(SalOp *op, void *up){
230 ((SalOpBase*)op)->user_pointer=up;
233 Sal *sal_op_get_sal(const SalOp *op){
234 return ((SalOpBase*)op)->root;
237 const char *sal_op_get_from(const SalOp *op){
238 return ((SalOpBase*)op)->from;
241 const char *sal_op_get_to(const SalOp *op){
242 return ((SalOpBase*)op)->to;
245 const char *sal_op_get_contact(const SalOp *op){
246 return ((SalOpBase*)op)->contact;
249 const char *sal_op_get_route(const SalOp *op){
250 return ((SalOpBase*)op)->route;
253 const char *sal_op_get_remote_ua(const SalOp *op){
254 return ((SalOpBase*)op)->remote_ua;
257 void *sal_op_get_user_pointer(const SalOp *op){
258 return ((SalOpBase*)op)->user_pointer;
261 const char *sal_op_get_proxy(const SalOp *op){
262 return ((SalOpBase*)op)->route;
265 const char *sal_op_get_network_origin(const SalOp *op){
266 return ((SalOpBase*)op)->origin;
269 void __sal_op_init(SalOp *b, Sal *sal){
270 memset(b,0,sizeof(SalOpBase));
271 ((SalOpBase*)b)->root=sal;
274 void __sal_op_set_network_origin(SalOp *op, const char *origin){
275 assign_string(&((SalOpBase*)op)->origin,origin);
279 void __sal_op_free(SalOp *op){
280 SalOpBase *b=(SalOpBase *)op;
302 ms_free(b->remote_ua);
306 sal_media_description_unref(b->local_media);
308 sal_media_description_unref(b->remote_media);
312 SalAuthInfo* sal_auth_info_new() {
313 return ms_new0(SalAuthInfo,1);
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;
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);