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...
28 SalMediaDescription *sal_media_description_new(){
29 SalMediaDescription *md=ms_new0(SalMediaDescription,1);
34 static void sal_media_description_destroy(SalMediaDescription *md){
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;
44 void sal_media_description_ref(SalMediaDescription *md){
48 void sal_media_description_unref(SalMediaDescription *md){
51 sal_media_description_destroy (md);
55 SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
56 SalMediaProto proto, SalStreamType type){
58 for(i=0;i<md->nstreams;++i){
59 SalStreamDescription *ss=&md->streams[i];
60 if (ss->proto==proto && ss->type==type) return ss;
65 bool_t sal_media_description_empty(const SalMediaDescription *md){
67 for(i=0;i<md->nstreams;++i){
68 const SalStreamDescription *ss=&md->streams[i];
69 if (ss->port!=0) return FALSE;
74 void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir){
76 for(i=0;i<md->nstreams;++i){
77 SalStreamDescription *ss=&md->streams[i];
82 bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
86 /* we are looking for at least one stream with requested direction, inactive streams are ignored*/
87 for(i=0;i<md->nstreams;++i){
88 const SalStreamDescription *ss=&md->streams[i];
89 if (ss->dir==stream_dir) found=TRUE;
91 if (ss->dir!=SalStreamInactive) return FALSE;
98 static bool_t fmtp_equals(const char *p1, const char *p2){
99 if (p1 && p2 && strcmp(p1,p2)==0) return TRUE;
100 if (p1==NULL && p2==NULL) return TRUE;
105 static bool_t payload_type_equals(const PayloadType *p1, const PayloadType *p2){
106 if (p1->type!=p2->type) return FALSE;
107 if (strcmp(p1->mime_type,p2->mime_type)!=0) return FALSE;
108 if (p1->clock_rate!=p2->clock_rate) return FALSE;
109 if (p1->channels!=p2->channels) return FALSE;
111 Do not compare fmtp right now: they are modified internally when the call is started
114 if (!fmtp_equals(p1->recv_fmtp,p2->recv_fmtp) ||
115 !fmtp_equals(p1->send_fmtp,p2->send_fmtp))
121 static bool_t payload_list_equals(const MSList *l1, const MSList *l2){
122 const MSList *e1,*e2;
123 for(e1=l1,e2=l2;e1!=NULL && e2!=NULL; e1=e1->next,e2=e2->next){
124 PayloadType *p1=(PayloadType*)e1->data;
125 PayloadType *p2=(PayloadType*)e2->data;
126 if (!payload_type_equals(p1,p2))
129 if (e1!=NULL || e2!=NULL){
130 /*means one list is longer than the other*/
137 bool_t sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2){
138 if (sd1->proto!=sd2->proto) return FALSE;
139 if (sd1->type!=sd2->type) return FALSE;
140 if (strcmp(sd1->addr,sd2->addr)!=0) return FALSE;
141 if (sd1->port!=sd2->port) return FALSE;
142 if (!payload_list_equals(sd1->payloads,sd2->payloads)) return FALSE;
143 if (sd1->bandwidth!=sd2->bandwidth) return FALSE;
144 if (sd1->ptime!=sd2->ptime) return FALSE;
145 /* compare candidates: TODO */
146 if (sd1->dir!=sd2->dir) return FALSE;
150 bool_t sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2){
153 if (strcmp(md1->addr,md2->addr)!=0) return FALSE;
154 if (md1->nstreams!=md2->nstreams) return FALSE;
155 if (md1->bandwidth!=md2->bandwidth) return FALSE;
156 for(i=0;i<md1->nstreams;++i){
157 if (!sal_stream_description_equals(&md1->streams[i],&md2->streams[i]))
163 static void assign_string(char **str, const char *arg){
172 void sal_op_set_contact(SalOp *op, const char *contact){
173 assign_string(&((SalOpBase*)op)->contact,contact);
176 void sal_op_set_route(SalOp *op, const char *route){
177 assign_string(&((SalOpBase*)op)->route,route);
180 void sal_op_set_from(SalOp *op, const char *from){
181 assign_string(&((SalOpBase*)op)->from,from);
184 void sal_op_set_to(SalOp *op, const char *to){
185 assign_string(&((SalOpBase*)op)->to,to);
188 void sal_op_set_user_pointer(SalOp *op, void *up){
189 ((SalOpBase*)op)->user_pointer=up;
192 Sal *sal_op_get_sal(const SalOp *op){
193 return ((SalOpBase*)op)->root;
196 const char *sal_op_get_from(const SalOp *op){
197 return ((SalOpBase*)op)->from;
200 const char *sal_op_get_to(const SalOp *op){
201 return ((SalOpBase*)op)->to;
204 const char *sal_op_get_contact(const SalOp *op){
205 return ((SalOpBase*)op)->contact;
208 const char *sal_op_get_route(const SalOp *op){
209 return ((SalOpBase*)op)->route;
212 const char *sal_op_get_remote_ua(const SalOp *op){
213 return ((SalOpBase*)op)->remote_ua;
216 void *sal_op_get_user_pointer(const SalOp *op){
217 return ((SalOpBase*)op)->user_pointer;
220 const char *sal_op_get_proxy(const SalOp *op){
221 return ((SalOpBase*)op)->route;
224 const char *sal_op_get_network_origin(const SalOp *op){
225 return ((SalOpBase*)op)->origin;
228 void __sal_op_init(SalOp *b, Sal *sal){
229 memset(b,0,sizeof(SalOpBase));
230 ((SalOpBase*)b)->root=sal;
233 void __sal_op_set_network_origin(SalOp *op, const char *origin){
234 assign_string(&((SalOpBase*)op)->origin,origin);
238 void __sal_op_free(SalOp *op){
239 SalOpBase *b=(SalOpBase *)op;
261 ms_free(b->remote_ua);
265 sal_media_description_unref(b->local_media);
267 sal_media_description_unref(b->remote_media);
270 SalAuthInfo* sal_auth_info_new() {
271 return ms_new0(SalAuthInfo,1);
273 SalAuthInfo* sal_auth_info_clone(const SalAuthInfo* auth_info) {
274 SalAuthInfo* new_auth_info=sal_auth_info_new();
275 new_auth_info->username=auth_info->username?ms_strdup(auth_info->username):NULL;
276 new_auth_info->userid=auth_info->userid?ms_strdup(auth_info->userid):NULL;
277 new_auth_info->realm=auth_info->realm?ms_strdup(auth_info->realm):NULL;
278 new_auth_info->password=auth_info->password?ms_strdup(auth_info->password):NULL;
279 return new_auth_info;
281 void sal_auth_info_delete(const SalAuthInfo* auth_info) {
282 if (auth_info->username) ms_free(auth_info->username);
283 if (auth_info->userid) ms_free(auth_info->userid);
284 if (auth_info->realm) ms_free(auth_info->realm);
285 if (auth_info->password) ms_free(auth_info->password);
286 ms_free((void*)auth_info);