int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){ belle_sip_request_t *req=NULL; if (from) sal_op_set_from(op,from); if (to) sal_op_set_to(op,to); if (!op->dialog){ sal_op_subscribe_fill_cbs(op); /*???sal_exosip_fix_route(op); make sure to ha ;lr*/ req=sal_op_build_request(op,"SUBSCRIBE"); if (eventname){ if (op->event) belle_sip_object_unref(op->event); op->event=belle_sip_header_create("Event",eventname); belle_sip_object_ref(op->event); } belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); sal_op_add_body(op,(belle_sip_message_t*)req,body); return sal_op_send_and_create_refresher(op,req,expires,subscribe_refresher_listener); }else if (op->refresher){ const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); /* modify last request to update body*/ sal_op_add_body(op,(belle_sip_message_t*)last_req,body); return belle_sip_refresher_refresh(op->refresher,expires); } ms_warning("sal_subscribe(): no dialog and no refresher ?"); return -1; }
int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg){ belle_sip_request_t* req; char content_type_raw[256]; size_t content_length = msg?strlen(msg):0; time_t curtime=time(NULL); if (op->dialog){ /*for SIP MESSAGE that are sent in call's dialog*/ req=belle_sip_dialog_create_queued_request(op->dialog,"MESSAGE"); }else{ sal_op_message_fill_cbs(op); if (from) sal_op_set_from(op,from); if (to) sal_op_set_to(op,to); op->dir=SalOpDirOutgoing; req=sal_op_build_request(op,"MESSAGE"); if (sal_op_get_contact_address(op)){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); } } snprintf(content_type_raw,sizeof(content_type_raw),BELLE_SIP_CONTENT_TYPE ": %s",content_type); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_type_parse(content_type_raw))); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length))); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); belle_sip_message_set_body(BELLE_SIP_MESSAGE(req),msg,content_length); return sal_op_send_request(op,req); }
/*presence Subscribe/notify*/ int sal_subscribe_presence(SalOp *op, const char *from, const char *to, int expires){ belle_sip_request_t *req=NULL; if (from) sal_op_set_from(op,from); if (to) sal_op_set_to(op,to); sal_op_presence_fill_cbs(op); if (expires==-1){ if (op->refresher){ expires=belle_sip_refresher_get_expires(op->refresher); belle_sip_object_unref(op->refresher); op->refresher=NULL; }else{ ms_error("sal_subscribe_presence(): cannot guess expires from previous refresher."); return -1; } } if (!op->event){ op->event=belle_sip_header_create("Event","presence"); belle_sip_object_ref(op->event); } belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(op->base.from_address),"tag"); belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(op->base.to_address),"tag"); req=sal_op_build_request(op,"SUBSCRIBE"); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); return sal_op_send_request(op,req); }
int sal_call(SalOp *op, const char *from, const char *to){ belle_sip_request_t* invite; op->dir=SalOpDirOutgoing; sal_op_set_from(op,from); sal_op_set_to(op,to); ms_message("[%s] calling [%s] on op [%p]", from, to, op); invite=sal_op_build_request(op,"INVITE"); if( invite == NULL ){ /* can happen if the op has an invalid address */ return -1; } sal_op_fill_invite(op,invite); sal_op_call_fill_cbs(op); if (op->replaces){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(op->replaces)); } if (op->referred_by) belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(op->referred_by)); return sal_op_send_request(op,invite); }
int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){ belle_sip_request_t *req=NULL; if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) { if (from) sal_op_set_from(op,from); if (to) sal_op_set_to(op,to); sal_op_publish_fill_cbs(op); req=sal_op_build_request(op,"PUBLISH"); if (sal_op_get_contact(op)){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); } belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname)); sal_op_add_body(op,BELLE_SIP_MESSAGE(req),body); return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener); } else { /*update status*/ const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher); belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans)); /*update body*/ sal_op_add_body(op,BELLE_SIP_MESSAGE(last_publish),expires!=0 ? body : NULL); return belle_sip_refresher_refresh(op->refresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires); } }
/*presence Subscribe/notify*/ int sal_subscribe_presence(SalOp *op, const char *from, const char *to){ osip_message_t *msg=NULL; if (from) sal_op_set_from(op,from); if (to) sal_op_set_to(op,to); sal_exosip_fix_route(op); 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){ osip_message_free(msg); return -1; } sal_add_out_subscribe(op->base.root,op); return 0; }
static void _sal_exosip_subscription_recv(Sal *sal, eXosip_event_t *ev){ SalOp *op=sal_op_new(sal); char *tmp; op->did=ev->did; op->tid=ev->tid; op->nid=ev->nid; osip_from_to_str(ev->request->from,&tmp); sal_op_set_from(op,tmp); ms_free(tmp); osip_from_to_str(ev->request->to,&tmp); sal_op_set_to(op,tmp); ms_free(tmp); sal_add_in_subscribe(sal,op,ev->request); sal->callbacks.subscribe_received(op,sal_op_get_from(op)); }
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) { /* we are not currently in communication with the destination */ if (from) sal_op_set_from(op,from); 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)); 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 { /* 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_request(op->did,"MESSAGE",&sip); if(sip == NULL) { ms_warning("could not get a build info to send MESSAGE, maybe no previous call established ?"); eXosip_unlock(); return -1; } 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_register(SalOp *op, const char *proxy, const char *from, int expires){ belle_sip_request_t *req; belle_sip_uri_t* req_uri; op->type=SalOpRegister; sal_op_set_from(op,from); sal_op_set_to(op,from); sal_op_set_route(op,proxy); req = sal_op_build_request(op,"REGISTER"); req_uri = belle_sip_request_get_uri(req); belle_sip_uri_set_user(req_uri,NULL); /*remove userinfo if any*/ if (op->base.root->use_dates){ time_t curtime=time(NULL); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); } belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)sal_op_create_contact(op)); return sal_op_send_and_create_refresher(op,req,expires,register_refresher_listener); }
/*presence publish */ int sal_publish_presence(SalOp *op, const char *from, const char *to, int expires, SalPresenceModel *presence){ belle_sip_request_t *req=NULL; if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) { if (from) sal_op_set_from(op,from); if (to) sal_op_set_to(op,to); op->type=SalOpPublish; req=sal_op_build_request(op,"PUBLISH"); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event","presence")); sal_add_presence_info(op,BELLE_SIP_MESSAGE(req),presence); return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener); } else { /*update presence status*/ const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher); belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans)); sal_add_presence_info(op,BELLE_SIP_MESSAGE(last_publish),presence); return belle_sip_refresher_refresh(op->refresher,expires); } }
int sal_register(SalOp *op, const char *proxy, const char *from, int expires,SalAddress* old_contact){ belle_sip_request_t *req; belle_sip_uri_t* req_uri; belle_sip_header_t* accept_header; if (op->refresher){ belle_sip_refresher_stop(op->refresher); belle_sip_object_unref(op->refresher); op->refresher=NULL; } op->type=SalOpRegister; sal_op_set_from(op,from); sal_op_set_to(op,from); sal_op_set_route(op,proxy); req = sal_op_build_request(op,"REGISTER"); req_uri = belle_sip_request_get_uri(req); belle_sip_uri_set_user(req_uri,NULL); /*remove userinfo if any*/ if (op->base.root->use_dates){ time_t curtime=time(NULL); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); } accept_header = belle_sip_header_create("Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), accept_header); belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)sal_op_create_contact(op)); if (old_contact) { belle_sip_header_contact_t *contact=belle_sip_header_contact_create((const belle_sip_header_address_t *)old_contact); if (contact) { char * tmp; belle_sip_header_contact_set_expires(contact,0); /*remove old aor*/ belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(contact)); tmp = belle_sip_object_to_string(contact); ms_message("Clearing contact [%s] for op [%p]",tmp,op); ms_free(tmp); } else { ms_error("Cannot add old contact header to op [%p]",op); } } return sal_op_send_and_create_refresher(op,req,expires,register_refresher_listener); }
void sal_op_set_to_address(SalOp *op, const SalAddress *to){ char* address_string=sal_address_as_string(to); /*can probably be optimized*/ sal_op_set_to(op,address_string); ms_free(address_string); }
/*ping: main purpose is to obtain its own contact address behind firewalls*/ int sal_ping(SalOp *op, const char *from, const char *to){ sal_op_set_from(op,from); sal_op_set_to(op,to); return sal_op_send_request(op,sal_op_build_request(op,"OPTIONS")); }
int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg, const char *peer_uri){ belle_sip_request_t* req; char content_type_raw[256]; size_t content_length = msg?strlen(msg):0; time_t curtime = time(NULL); uint8_t *multipartEncryptedMessage = NULL; int retval; if (op->dialog){ /*for SIP MESSAGE that are sent in call's dialog*/ req = belle_sip_dialog_create_queued_request(op->dialog,"MESSAGE"); }else{ sal_op_message_fill_cbs(op); if (from) sal_op_set_from(op, from); if (to) sal_op_set_to(op, to); op->dir = SalOpDirOutgoing; req = sal_op_build_request(op,"MESSAGE"); if (req == NULL ){ return -1; } if (sal_op_get_contact_address(op)){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(sal_op_create_contact(op))); } } /* shall we try to encrypt the message?*/ if ((strcmp(content_type, "xml/cipher") == 0) || ((strcmp(content_type, "application/cipher.vnd.gsma.rcs-ft-http+xml") == 0))) { /* access the zrtp cache to get keys needed to cipher the message */ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); FILE *CACHEFD = fopen(lc->zrtp_secrets_cache, "rb+"); if (CACHEFD == NULL) { ms_warning("Unable to access ZRTP ZID cache to encrypt message"); /*probably not a good idea to do this:*/ sal_error_info_set(&op->error_info, SalReasonNotAcceptable, 488, "Unable to encrypt IM", NULL); op->base.root->callbacks.text_delivery_update(op,SalTextDeliveryFailed); return -1; } else { size_t cacheSize; char *cacheString; xmlDocPtr cacheXml; int retval; cacheString=ms_load_file_content(CACHEFD, &cacheSize); if (!cacheString){ ms_warning("Unable to load content of ZRTP ZID cache to encrypt message"); return -1; } cacheString[cacheSize] = '\0'; cacheSize += 1; fclose(CACHEFD); cacheXml = xmlParseDoc((xmlChar*)cacheString); ms_free(cacheString); retval = lime_createMultipartMessage(cacheXml, (uint8_t *)msg, (uint8_t *)peer_uri, &multipartEncryptedMessage); if (retval != 0) { ms_warning("Unable to encrypt message for %s : %s - op [%p]", peer_uri, lime_error_code_to_string(retval), op); xmlFreeDoc(cacheXml); free(multipartEncryptedMessage); /*probably not a good idea to do this:*/ sal_error_info_set(&op->error_info, SalReasonNotAcceptable, 488, "Unable to encrypt IM", NULL); op->base.root->callbacks.text_delivery_update(op,SalTextDeliveryFailed); return -1; } else { /* dump updated cache to a string */ xmlChar *xmlStringOutput; int xmlStringLength; xmlDocDumpFormatMemoryEnc(cacheXml, &xmlStringOutput, &xmlStringLength, "UTF-8", 0); /* write it to the cache file */ CACHEFD = fopen(lc->zrtp_secrets_cache, "wb+"); if (fwrite(xmlStringOutput, 1, xmlStringLength, CACHEFD)<=0){ ms_warning("Unable to write zid cache"); } xmlFree(xmlStringOutput); fclose(CACHEFD); content_length = strlen((const char *)multipartEncryptedMessage); } xmlFreeDoc(cacheXml); } } snprintf(content_type_raw,sizeof(content_type_raw),BELLE_SIP_CONTENT_TYPE ": %s",content_type); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_type_parse(content_type_raw))); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length))); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); belle_sip_message_set_body(BELLE_SIP_MESSAGE(req),(multipartEncryptedMessage==NULL)?msg:(const char *)multipartEncryptedMessage,content_length); retval = sal_op_send_request(op,req); free(multipartEncryptedMessage); return retval; }