X-Git-Url: http://sjero.net/git/?p=linphone;a=blobdiff_plain;f=coreapi%2Fsal_eXosip2_presence.c;h=c8191098649343f2bb6ebf8689d06e881efd557f;hp=a38fdf91b8b51f028ba4ec34e50336fbd6c58cb5;hb=bf492b4278d1c68b2da55c65da173a33aec32ea1;hpb=b98bd24e1df6d7f2577481974235a3e789d850fd diff --git a/coreapi/sal_eXosip2_presence.c b/coreapi/sal_eXosip2_presence.c index a38fdf91..c8191098 100644 --- a/coreapi/sal_eXosip2_presence.c +++ b/coreapi/sal_eXosip2_presence.c @@ -20,14 +20,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "sal_eXosip2.h" +typedef enum { + PIDF = 0, + RFCxxxx = 1, + MSOLDPRES = 2 +} presence_type_t; -static SalOp * sal_find_out_subscribe(Sal *sal, int sid){ +/* + * REVISIT: this static variable forces every dialog to use the same presence description type depending + * on what is received on a single dialog... + */ +static presence_type_t presence_style = PIDF; + +SalOp * sal_find_out_subscribe(Sal *sal, int sid){ const MSList *elem; SalOp *op; for(elem=sal->out_subscribes;elem!=NULL;elem=elem->next){ op=(SalOp*)elem->data; if (op->sid==sid) return op; } + ms_message("No op for sid %i",sid); return NULL; } @@ -39,7 +51,7 @@ void sal_remove_out_subscribe(Sal *sal, SalOp *op){ sal->out_subscribes=ms_list_remove(sal->out_subscribes,op); } -static SalOp * sal_find_in_subscribe(Sal *sal, int nid){ +SalOp * sal_find_in_subscribe(Sal *sal, int nid){ const MSList *elem; SalOp *op; for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){ @@ -69,7 +81,27 @@ void sal_remove_in_subscribe(Sal *sal, SalOp *op){ sal->in_subscribes=ms_list_remove(sal->in_subscribes,op); } -int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg){ +static const char *days[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; +static const char *months[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; + +static void msg_add_current_date(osip_message_t *msg){ + char tmp[64]={0}; + time_t curtime=time(NULL); + struct tm *ret; +#ifndef WIN32 + struct tm gmt; + ret=gmtime_r(&curtime,&gmt); +#else + ret=gmtime(&curtime); +#endif + /*cannot use strftime because it is locale dependant*/ + snprintf(tmp,sizeof(tmp)-1,"%s, %i %s %i %02i:%02i:%02i GMT", + days[ret->tm_wday],ret->tm_mday,months[ret->tm_mon],1900+ret->tm_year,ret->tm_hour,ret->tm_min,ret->tm_sec); + osip_message_replace_header(msg,"Date",tmp); +} + + +int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg){ osip_message_t *sip=NULL; if(op->cid == -1) @@ -80,12 +112,20 @@ int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg){ if (to) sal_op_set_to(op,to); + sal_exosip_fix_route(op); eXosip_lock(); eXosip_message_build_request(&sip,"MESSAGE",sal_op_get_to(op), sal_op_get_from(op),sal_op_get_route(op)); - osip_message_set_content_type(sip,"text/plain"); - osip_message_set_body(sip,msg,strlen(msg)); - eXosip_message_send_request(sip); + if (sip!=NULL){ + sal_exosip_add_custom_headers(sip,op->base.custom_headers); + msg_add_current_date(sip); + osip_message_set_content_type(sip,content_type); + if (msg) osip_message_set_body(sip,msg,strlen(msg)); + sal_add_other(op->base.root,op,sip); + eXosip_message_send_request(sip); + }else{ + ms_error("Could not build MESSAGE request !"); + } eXosip_unlock(); } else @@ -93,30 +133,29 @@ int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg){ /* we are currently in communication with the destination */ eXosip_lock(); //First we generate an INFO message to get the current call_id and a good cseq - eXosip_call_build_info(op->did,&sip); + eXosip_call_build_request(op->did,"MESSAGE",&sip); if(sip == NULL) { ms_warning("could not get a build info to send MESSAGE, maybe no previous call established ?"); - osip_message_free(sip); eXosip_unlock(); return -1; } - //change the sip_message to be a MESSAGE ... - osip_free(osip_message_get_method(sip)); - osip_message_set_method(sip,osip_strdup("MESSAGE")); - osip_free(osip_cseq_get_method(osip_message_get_cseq(sip))); - osip_cseq_set_method(osip_message_get_cseq(sip),osip_strdup("MESSAGE")); - osip_message_set_content_type(sip,"text/plain"); - osip_message_set_body(sip,msg,strlen(msg)); - eXosip_message_send_request(sip); + sal_exosip_add_custom_headers(sip,op->base.custom_headers); + msg_add_current_date(sip); + osip_message_set_content_type(sip,content_type); + if (msg) osip_message_set_body(sip,msg,strlen(msg)); + eXosip_call_send_request(op->did,sip); eXosip_unlock(); } return 0; } +int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg) { + return sal_message_send(op,from,to,"text/plain",msg); +} /*presence Subscribe/notify*/ int sal_subscribe_presence(SalOp *op, const char *from, const char *to){ - osip_message_t *msg; + osip_message_t *msg=NULL; if (from) sal_op_set_from(op,from); if (to) @@ -125,6 +164,15 @@ int sal_subscribe_presence(SalOp *op, const char *from, const char *to){ eXosip_lock(); eXosip_subscribe_build_initial_request(&msg,sal_op_get_to(op),sal_op_get_from(op), sal_op_get_route(op),"presence",600); + if (msg==NULL){ + ms_error("Could not build subscribe request to %s",to); + eXosip_unlock(); + return -1; + } + if (op->base.contact){ + _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free); + osip_message_set_contact(msg,op->base.contact); + } op->sid=eXosip_subscribe_send_initial_request(msg); eXosip_unlock(); if (op->sid==-1){ @@ -153,9 +201,18 @@ int sal_unsubscribe(SalOp *op){ } int sal_subscribe_accept(SalOp *op){ - osip_message_t *msg; + osip_message_t *msg=NULL; eXosip_lock(); eXosip_insubscription_build_answer(op->tid,202,&msg); + if (msg==NULL){ + ms_error("Fail to build answer to subscribe."); + eXosip_unlock(); + return -1; + } + if (op->base.contact){ + _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free); + osip_message_set_contact(msg,op->base.contact); + } eXosip_insubscription_send_answer(op->tid,202,msg); eXosip_unlock(); return 0; @@ -168,274 +225,378 @@ int sal_subscribe_decline(SalOp *op){ return 0; } +static void mk_presence_body (const SalPresenceStatus online_status, const char *contact_info, + char *buf, size_t buflen, presence_type_t ptype) { + switch (ptype) { + case RFCxxxx: { + /* definition from http://msdn.microsoft.com/en-us/library/cc246202%28PROT.10%29.aspx */ + int atom_id = 1000; + + if (online_status==SalPresenceOnline) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n" +"
", contact_info, atom_id, contact_info); + + } + else if (online_status == SalPresenceBusy || + online_status == SalPresenceDonotdisturb) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n
", contact_info, atom_id, contact_info); + + } + else if (online_status==SalPresenceBerightback) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n" +"
", contact_info, atom_id, contact_info); + + } + else if (online_status == SalPresenceAway || + online_status == SalPresenceMoved) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n" +"
", contact_info, atom_id, contact_info); + + } + else if (online_status==SalPresenceOnthephone) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n" +"
", contact_info, atom_id, contact_info); + + } + else if (online_status==SalPresenceOuttolunch) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n" +"
", contact_info, atom_id, contact_info); + + } + else + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n" +"
", contact_info, atom_id, contact_info); + } + break; + } + case MSOLDPRES: { + /* Couldn't find schema http://schemas.microsoft.com/2002/09/sip/presence + * so messages format has been taken from Communigate that can send notify + * requests with this schema + */ + int atom_id = 1000; + + if (online_status==SalPresenceOnline) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n" +"
", contact_info, atom_id, contact_info); + + } + else if (online_status == SalPresenceBusy || + online_status == SalPresenceDonotdisturb) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n
", contact_info, atom_id, contact_info); + + } + else if (online_status==SalPresenceBerightback) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n" +"
", contact_info, atom_id, contact_info); + + } + else if (online_status == SalPresenceAway || + online_status == SalPresenceMoved) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n" +"
", contact_info, atom_id, contact_info); + + } + else if (online_status==SalPresenceOnthephone) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n" +"
", contact_info, atom_id, contact_info); + + } + else if (online_status==SalPresenceOuttolunch) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n" +"
", contact_info, atom_id, contact_info); + + } + else + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"\n" +"\n" +"
\n" +"\n" +"\n" +"
\n" +"
\n" +"
", contact_info, atom_id, contact_info); + } + break; + } + default: { /* use pidf+xml as default format, rfc4479, rfc4480, rfc3863 */ + + if (online_status==SalPresenceOnline) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"open\n" +"%s\n" +"\n" +"", +contact_info, contact_info); + } + else if (online_status == SalPresenceBusy || + online_status == SalPresenceDonotdisturb) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"open\n" +"%s\n" +"\n" +"\n" +"\n" +"\n" +"", +contact_info, contact_info); + } + else if (online_status==SalPresenceBerightback) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"open\n" +"%s\n" +"\n" +"\n" +"\n" +"\n" +"", +contact_info, contact_info); + } + else if (online_status == SalPresenceAway || + online_status == SalPresenceMoved) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"open\n" +"%s\n" +"\n" +"\n" +"\n" +"\n" +"", +contact_info, contact_info); + } + else if (online_status==SalPresenceOnthephone) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"open\n" +"%s\n" +"\n" +"\n" +"\n" +"\n" +"", +contact_info, contact_info); + } + else if (online_status==SalPresenceOuttolunch) + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"open\n" +"%s\n" +"\n" +"\n" +"\n" +"Out to lunch \n" +"\n" +"", +contact_info, contact_info); + } + else + { + snprintf(buf, buflen, "\n" +"\n" +"\n" +"closed\n" +"%s\n" +"\n" +"\n", contact_info, contact_info); + } + break; + } + } // switch + +} + static void add_presence_body(osip_message_t *notify, SalPresenceStatus online_status) { char buf[1000]; -#ifdef SUPPORT_MSN - int atom_id = 1000; -#endif char *contact_info; osip_from_t *from=NULL; from=osip_message_get_from(notify); osip_uri_to_str(from->url,&contact_info); -#ifdef SUPPORT_MSN - - if (online_status==SalPresenceOnline) - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -\n\ -
\n\ -\n\ -\n\ -
\n\ -
\n\ -
", contact_info, atom_id, contact_info); + mk_presence_body (online_status, contact_info, buf, sizeof (buf), presence_style); - } - else if (online_status==SalPresenceBusy) - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -\n\ -
\n\ -\n\ -\n\ -
\n\ -
\n\ -
", contact_info, atom_id, contact_info); + osip_message_set_body(notify, buf, strlen(buf)); + osip_message_set_content_type(notify, + presence_style ? "application/xpidf+xml" : "application/pidf+xml"); - } - else if (online_status==SalPresenceBerightback) - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -\n\ -
\n\ -\n\ -\n\ -
\n\ -
\n\ -
", contact_info, atom_id, contact_info); - - } - else if (online_status==SalPresenceAway) - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -\n\ -
\n\ -\n\ -\n\ -
\n\ -
\n\ -
", contact_info, atom_id, contact_info); - - } - else if (online_status==SalPresenceOnthephone) - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -\n\ -
\n\ -\n\ -\n\ -
\n\ -
\n\ -
", contact_info, atom_id, contact_info); - - } - else if (online_status==SalPresenceOuttolunch) - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -\n\ -
\n\ -\n\ -\n\ -
\n\ -
\n\ -
", contact_info, atom_id, contact_info); - - } - else - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -\n\ -
\n\ -\n\ -\n\ -
\n\ -
\n\ -
", contact_info, atom_id, contact_info); - } - - osip_message_set_body(notify, buf, strlen(buf)); - osip_message_set_content_type(notify, "application/xpidf+xml"); -#else - - if (online_status==SalPresenceOnline) - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -open\n\ -\n\ -%s\n\ -online\n\ -\n\ -", - contact_info, contact_info); - } - else if (online_status==SalPresenceBusy) - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -open\n\ -\n\ - busy\n\ -\n\ -\n\ -%s\n\ -busy\n\ -\n\ -", - contact_info, contact_info); - } - else if (online_status==SalPresenceBerightback) - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -open\n\ -\n\ - in-transit\n\ -\n\ -\n\ -%s\n\ -be right back\n\ -\n\ -", - contact_info, contact_info); - } - else if (online_status==SalPresenceAway) - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -open\n\ -\n\ - away\n\ -\n\ -\n\ -%s\n\ -away\n\ -\n\ -", - contact_info, contact_info); - } - else if (online_status==SalPresenceOnthephone) - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -open\n\ -\n\ - on-the-phone\n\ -\n\ -\n\ -%s\n\ -on the phone\n\ -\n\ -", - contact_info, contact_info); - } - else if (online_status==SalPresenceOuttolunch) - { - sprintf(buf, "\n\ -\n\ -\n\ -\n\ -open\n\ -\n\ - meal\n\ -\n\ -\n\ -%s\n\ -out to lunch\n\ -\n\ -", - contact_info, contact_info); - } - else - { - /* */ - sprintf(buf, "\n\ -\n%s", - contact_info, -"\n\ -\n\ -closed\n\ -\n\ - permanent-absence\n\ -\n\ -\n\ -\n\ -\n\n"); - } - osip_message_set_body(notify, buf, strlen(buf)); - osip_message_set_content_type(notify, "application/pidf+xml"); - -#endif osip_free(contact_info); } int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message){ - osip_message_t *msg; + osip_message_t *msg=NULL; eXosip_ss_t ss=EXOSIP_SUBCRSTATE_ACTIVE; if (op->nid==-1){ ms_warning("Cannot notify, subscription was closed."); @@ -447,6 +608,7 @@ int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_ if (msg!=NULL){ const char *identity=sal_op_get_contact(op); if (identity==NULL) identity=sal_op_get_to(op); + _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free); osip_message_set_contact(msg,identity); add_presence_body(msg,status); eXosip_insubscription_send_request(op->did,msg); @@ -475,151 +637,28 @@ int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus p osip_message_t *pub; int i; char buf[1024]; + const char *route=sal_op_get_route(op); - if (presence_mode==SalPresenceOnline) - { - snprintf(buf, sizeof(buf), "\n\ - \n\ - \n\ - \n\ - open\n\ - \n\ - %s\n\ - online\n\ - \n\ - ", - from, from); - } - else if (presence_mode==SalPresenceBusy - ||presence_mode==SalPresenceDonotdisturb) - { - snprintf(buf, sizeof(buf), "\n\ - \n\ - \n\ - \n\ - open\n\ - \n\ - busy\n\ - \n\ - \n\ - %s\n\ - busy\n\ - \n\ - ", - from, from); - } - else if (presence_mode==SalPresenceBerightback) - { - snprintf(buf, sizeof(buf), "\n\ - \n\ - \n\ - \n\ - open\n\ - \n\ - in-transit\n\ - \n\ - \n\ - %s\n\ - be right back\n\ - \n\ - ", - from,from); - } - else if (presence_mode==SalPresenceAway - ||presence_mode==SalPresenceMoved) - { - snprintf(buf, sizeof(buf), "\n\ - \n\ - \n\ - \n\ - open\n\ - \n\ - away\n\ - \n\ - \n\ - %s\n\ - away\n\ - \n\ - ", - from, from); - } - else if (presence_mode==SalPresenceOnthephone) - { - snprintf(buf, sizeof(buf), "\n\ - \n\ - \n\ - \n\ - open\n\ - \n\ - on-the-phone\n\ - \n\ - \n\ - %s\n\ - on the phone\n\ - \n\ - ", - from, from); - } - else if (presence_mode==SalPresenceOuttolunch) - { - snprintf(buf, sizeof(buf), "\n\ - \n\ - \n\ - \n\ - open\n\ - \n\ - meal\n\ - \n\ - \n\ - %s\n\ - out to lunch\n\ - \n\ - ", - from, from); - } - else{ - /* offline */ - snprintf(buf, sizeof(buf), "\n\ - \n%s", - from, - "\n\ - \n\ - closed\n\ - \n\ - permanent-absence\n\ - \n\ - \n\ - \n\ - \n\n"); - } + mk_presence_body (presence_mode, from, buf, sizeof (buf), presence_style); - i = eXosip_build_publish(&pub,from, to, NULL, "presence", "1800", "application/pidf+xml", buf); + i = eXosip_build_publish(&pub,to, from, NULL, "presence", "600", + presence_style ? "application/xpidf+xml" : "application/pidf+xml", buf); if (i<0){ ms_warning("Failed to build publish request."); return -1; } - + if (route) + sal_message_add_route(pub,route); + eXosip_lock(); i = eXosip_publish(pub, to); /* should update the sip-if-match parameter from sip-etag from last 200ok of PUBLISH */ eXosip_unlock(); if (i<0){ - ms_message("Failed to send publish request."); - return -1; + ms_message("Failed to send publish request."); + return -1; } + sal_add_other(sal_op_get_sal(op),op,pub); return 0; } @@ -691,7 +730,8 @@ void sal_exosip_notify_recv(Sal *sal, eXosip_event_t *ev){ }else if (strstr(body->body,"berightback")!=NULL || strstr(body->body,"in-transit")!=NULL ){ estatus=SalPresenceBerightback; - }else if (strstr(body->body,"away")!=NULL){ + }else if (strstr(body->body,"away")!=NULL + || strstr(body->body,"idle")){ estatus=SalPresenceAway; }else if (strstr(body->body,"onthephone")!=NULL || strstr(body->body,"on-the-phone")!=NULL){ @@ -714,6 +754,15 @@ void sal_exosip_notify_recv(Sal *sal, eXosip_event_t *ev){ ms_message("And outgoing subscription terminated by remote."); } sal->callbacks.notify_presence(op,op->sid!=-1 ? SalSubscribeActive : SalSubscribeTerminated, estatus,NULL); + + /* try to detect presence message style used by server, + * and switch our presence messages to servers style */ + if (strstr (body->body, "//IETF//DTD RFCxxxx XPIDF 1.0//EN") != NULL) { + presence_style = RFCxxxx; + } else if (strstr(body->body,"http://schemas.microsoft.com/2002/09/sip/presence")!=NULL) { + presence_style = MSOLDPRES; + } + osip_free(tmp); }