}
}
+static SalOp * sal_find_other(Sal *sal, osip_message_t *response){
+ const MSList *elem;
+ SalOp *op;
+ osip_call_id_t *callid=osip_message_get_call_id(response);
+ if (callid==NULL) {
+ ms_error("There is no call-id in this response !");
+ return NULL;
+ }
+ for(elem=sal->other_transactions;elem!=NULL;elem=elem->next){
+ op=(SalOp*)elem->data;
+ if (osip_call_id_match(callid,op->call_id)==0) return op;
+ }
+ return NULL;
+}
+
+static void sal_add_other(Sal *sal, SalOp *op, osip_message_t *request){
+ osip_call_id_t *callid=osip_message_get_call_id(request);
+ if (callid==NULL) {
+ ms_error("There is no call id in the request !");
+ return;
+ }
+ osip_call_id_clone(callid,&op->call_id);
+ sal->other_transactions=ms_list_append(sal->other_transactions,op);
+}
+
+static void sal_remove_other(Sal *sal, SalOp *op){
+ sal->other_transactions=ms_list_remove(sal->other_transactions,op);
+}
+
+
static void sal_add_pending_auth(Sal *sal, SalOp *op){
sal->pending_auths=ms_list_append(sal->pending_auths,op);
}
op->pending_auth=NULL;
op->sdp_answer=NULL;
op->reinvite=FALSE;
+ op->call_id=NULL;
return op;
}
}
if (op->result)
sal_media_description_unref(op->result);
+ if (op->call_id){
+ sal_remove_other(op->base.root,op);
+ osip_call_id_free(op->call_id);
+ }
__sal_op_free(op);
}
return sal->up;
}
-void sal_masquerade(Sal *ctx, const char *ip){
- ms_message("Masquerading SIP with %s",ip);
- eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,ip);
-}
-
static void unimplemented_stub(){
ms_warning("Unimplemented SAL callback");
}
ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
if (ctx->callbacks.internal_message==NULL)
ctx->callbacks.internal_message=(SalOnInternalMsg)unimplemented_stub;
+ if (ctx->callbacks.ping_reply==NULL)
+ ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub;
}
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure){
return h->result;
}
+int sal_ping(SalOp *op, const char *from, const char *to){
+ osip_message_t *options=NULL;
+
+ sal_op_set_from(op,from);
+ sal_op_set_to(op,to);
+ eXosip_options_build_request (&options, sal_op_get_to(op),
+ sal_op_get_from(op),sal_op_get_route(op));
+ if (options){
+ if (op->base.root->session_expires!=0){
+ osip_message_set_header(options, "Session-expires", "200");
+ osip_message_set_supported(options, "timer");
+ }
+ sal_add_other(sal_op_get_sal(op),op,options);
+ return eXosip_options_send_request(options);
+ }
+ return -1;
+}
+
int sal_refer(SalOp *h, const char *refer_to){
osip_message_t *msg=NULL;
int err=0;
}
}
+static void set_network_origin(SalOp *op, osip_message_t *req){
+ const char *received=NULL;
+ int rport=5060;
+ char origin[64];
+ if (extract_received_rport(req,&received,&rport)!=0){
+ osip_via_t *via=NULL;
+ char *tmp;
+ osip_message_get_via(req,0,&via);
+ received=osip_via_get_host(via);
+ tmp=osip_via_get_port(via);
+ if (tmp) rport=atoi(tmp);
+ }
+ snprintf(origin,sizeof(origin)-1,"sip:%s:%i",received,rport);
+ __sal_op_set_network_origin(op,origin);
+}
+
static void inc_new_call(Sal *sal, eXosip_event_t *ev){
SalOp *op=sal_op_new(sal);
osip_from_t *from,*to;
char *tmp;
sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
+
+ set_network_origin(op,ev->request);
+
if (sdp){
op->sdp_offering=FALSE;
op->base.remote_media=sal_media_description_new();
}
}
-static int call_proceeding(Sal *sal, eXosip_event_t *ev){
- SalOp *op=(SalOp*)ev->external_reference;
+static void update_contact_from_response(SalOp *op, osip_message_t *response){
const char *received;
int rport;
-
- if (op==NULL) {
- ms_warning("This call has been canceled.");
- eXosip_lock();
- eXosip_call_terminate(ev->cid,ev->did);
- eXosip_unlock();
- return -1;
- }
- op->did=ev->did;
- op->tid=ev->tid;
- /* update contact if received and rport are set by the server */
- if (extract_received_rport(ev->response,&received,&rport)==0){
+ if (extract_received_rport(response,&received,&rport)==0){
const char *contact=sal_op_get_contact(op);
if (!contact){
/*no contact given yet, use from instead*/
sal_address_set_domain(addr,received);
sal_address_set_port_int(addr,rport);
tmp=sal_address_as_string(addr);
- ms_message("Contact address automatically updated to %s for this call",tmp);
+ ms_message("Contact address updated to %s for this dialog",tmp);
sal_op_set_contact(op,tmp);
ms_free(tmp);
}
}
+}
+
+static int call_proceeding(Sal *sal, eXosip_event_t *ev){
+ SalOp *op=(SalOp*)ev->external_reference;
+
+ if (op==NULL) {
+ ms_warning("This call has been canceled.");
+ eXosip_lock();
+ eXosip_call_terminate(ev->cid,ev->did);
+ eXosip_unlock();
+ return -1;
+ }
+ op->did=ev->did;
+ op->tid=ev->tid;
+
+ /* update contact if received and rport are set by the server
+ note: will only be used by remote for next INVITE, if any...*/
+ update_contact_from_response(op,ev->response);
return 0;
}
osip_message_t *msg=NULL;
SalOp *op;
const char *contact;
+
op=(SalOp*)ev->external_reference;
if (op==NULL){
ms_error("A closed call is accepted ?");
if (ev->rid>0){
return sal_find_register(sal,ev->rid);
}
+ if (ev->response) return sal_find_other(sal,ev->response);
return NULL;
}
return TRUE;
}
+static void other_request_reply(Sal *sal,eXosip_event_t *ev){
+ SalOp *op=find_op(sal,ev);
+
+ if (op==NULL){
+ ms_warning("other_request_reply(): Receiving response to unknown request.");
+ return;
+ }
+ if (ev->response){
+ update_contact_from_response(op,ev->response);
+ sal->callbacks.ping_reply(op);
+ }
+}
+
static bool_t process_event(Sal *sal, eXosip_event_t *ev){
switch(ev->type){
case EXOSIP_CALL_ANSWERED:
case EXOSIP_MESSAGE_NEW:
other_request(sal,ev);
break;
+ case EXOSIP_MESSAGE_PROCEEDING:
+ case EXOSIP_MESSAGE_ANSWERED:
+ case EXOSIP_MESSAGE_REDIRECTED:
+ case EXOSIP_MESSAGE_SERVERFAILURE:
+ case EXOSIP_MESSAGE_GLOBALFAILURE:
+ other_request_reply(sal,ev);
+ break;
case EXOSIP_MESSAGE_REQUESTFAILURE:
if (ev->response && (ev->response->status_code == 407 || ev->response->status_code == 401)){
return process_authentication(sal,ev);