static void register_refresher_listener (belle_sip_refresher_t* refresher ,void* user_pointer ,unsigned int status_code ,const char* reason_phrase) { SalOp* op = (SalOp*)user_pointer; belle_sip_response_t* response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher))); ms_message("Register refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,sal_op_get_proxy(op)); if (belle_sip_refresher_get_auth_events(refresher)) { if (op->auth_info) sal_auth_info_delete(op->auth_info); /*only take first one for now*/ op->auth_info=sal_auth_info_create((belle_sip_auth_event_t*)(belle_sip_refresher_get_auth_events(refresher)->data)); } sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL); if (status_code>=200){ sal_op_assign_recv_headers(op,(belle_sip_message_t*)response); } if(status_code == 200) { /*check service route rfc3608*/ belle_sip_header_service_route_t* service_route; belle_sip_header_address_t* service_route_address=NULL; belle_sip_header_contact_t *contact = belle_sip_refresher_get_contact(refresher); if ((service_route=belle_sip_message_get_header_by_type(response,belle_sip_header_service_route_t))) { service_route_address=belle_sip_header_address_create(NULL,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(service_route))); } sal_op_set_service_route(op,(const SalAddress*)service_route_address); if (service_route_address) belle_sip_object_unref(service_route_address); sal_remove_pending_auth(op->base.root,op); /*just in case*/ if (contact) { sal_op_set_contact_address(op,(SalAddress*)(BELLE_SIP_HEADER_ADDRESS(contact))); /*update contact with real value*/ } op->base.root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->refresher)>0); } else if (status_code>=400) { /* from rfc3608, 6.1. If the UA refreshes the registration, the stored value of the Service- Route is updated according to the Service-Route header field of the latest 200 class response. If there is no Service-Route header field in the response, the UA clears any service route for that address- of-record previously stored by the UA. If the re-registration request is refused or if an existing registration expires and the UA chooses not to re-register, the UA SHOULD discard any stored service route for that address-of-record. */ sal_op_set_service_route(op,NULL); sal_op_ref(op); /*take a ref while invoking the callback to make sure the operations done after are valid*/ op->base.root->callbacks.register_failure(op); if (op->state!=SalOpStateTerminated && op->auth_info) { /*add pending auth*/ sal_add_pending_auth(op->base.root,op); if (status_code==403 || status_code==401 || status_code==407 ) op->base.root->callbacks.auth_failure(op,op->auth_info); } sal_op_unref(op); } }
void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *response){ int code = belle_sip_response_get_status_code(response); const char *reason_phrase=belle_sip_response_get_reason_phrase(response); /*Remark: the reason header is to be used mainly in SIP requests, thus the use and prototype of this function should be changed.*/ belle_sip_header_t* reason_header = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Reason"); belle_sip_header_t *warning=belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Warning"); SalErrorInfo *ei=&op->error_info; const char *warnings; warnings=warning ? belle_sip_header_get_unparsed_value(warning) : NULL; if (warnings==NULL) warnings=reason_header ? belle_sip_header_get_unparsed_value(reason_header) : NULL; sal_error_info_set(ei,SalReasonUnknown,code,reason_phrase,warnings); }
static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { SalOp* op=(SalOp*)user_ctx; if (op->state==SalOpStateTerminated) return; if (!op->dialog) { /*call terminated very early*/ sal_error_info_set(&op->error_info,SalReasonRequestTimeout,408,"Request timeout",NULL); op->base.root->callbacks.call_failure(op); call_set_released(op); } else { /*dialog will terminated shortly, nothing to do*/ } }
static void subscribe_refresher_listener (belle_sip_refresher_t* refresher ,void* user_pointer ,unsigned int status_code ,const char* reason_phrase) { SalOp* op = (SalOp*)user_pointer; belle_sip_transaction_t *tr=BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)); /*belle_sip_response_t* response=belle_sip_transaction_get_response(tr);*/ SalSubscribeStatus sss=SalSubscribeTerminated; ms_message("Subscribe refresher [%i] reason [%s] ",status_code,reason_phrase?reason_phrase:"none"); if (status_code>=200 && status_code<300){ if (status_code==200) sss=SalSubscribeActive; else if (status_code==202) sss=SalSubscribePending; set_or_update_dialog(op,belle_sip_transaction_get_dialog(tr)); } if (status_code>=200){ sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL); op->base.root->callbacks.subscribe_response(op,sss); }else if (status_code==0){ op->base.root->callbacks.on_expire(op); } }
static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { SalOp* op=(SalOp*)user_ctx; sal_error_info_set(&op->error_info,SalReasonRequestTimeout,408,"Request timeout",NULL); process_error(op); }
static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ SalOp* op = (SalOp*)user_ctx; sal_error_info_set(&op->error_info,SalReasonIOError,503,"IO Error",NULL); process_error(op); }
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; }