bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody){ const char *body = NULL; belle_sip_header_content_type_t *content_type; belle_sip_header_content_length_t *clen=NULL; belle_sip_header_t *content_encoding; content_type=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_type_t); if (content_type){ body=belle_sip_message_get_body(msg); clen=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_length_t); } content_encoding=belle_sip_message_get_header(msg,"Content-encoding"); memset(salbody,0,sizeof(SalBody)); if (content_type && body && clen) { salbody->type=belle_sip_header_content_type_get_type(content_type); salbody->subtype=belle_sip_header_content_type_get_subtype(content_type); salbody->data=body; salbody->size=belle_sip_header_content_length_get_content_length(clen); if (content_encoding) salbody->encoding=belle_sip_header_get_unparsed_value(content_encoding); return TRUE; } return FALSE; }
static void handle_notify(SalOp *op, belle_sip_request_t *req, belle_sip_dialog_t *dialog){ belle_sip_response_t* resp=NULL; belle_sip_server_transaction_t* server_transaction=op->pending_server_trans; belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); SalSubscribeStatus sub_state; if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) { SalPresenceModel *presence_model = NULL; const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); if (op->dialog !=NULL && dialog != op->dialog){ ms_warning("Receiving a NOTIFY from a dialog we haven't stored (op->dialog=%p dialog=%p)", op->dialog, dialog); } if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) { sub_state=SalSubscribeTerminated; ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op)); } else { sub_state=SalSubscribeActive; } presence_model = process_presence_notification(op, req); if (presence_model != NULL || body==NULL) { /* Presence notification body parsed successfully. */ resp = sal_op_create_response_from_request(op, req, 200); /*create first because the op may be destroyed by notify_presence */ op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL); } else if (body){ /* Formatting error in presence notification body. */ ms_warning("Wrongly formatted presence document."); resp = sal_op_create_response_from_request(op, req, 488); } if (resp) belle_sip_server_transaction_send_response(server_transaction,resp); } }
static void handle_notify(SalOp *op, belle_sip_request_t *req){ belle_sip_response_t* resp; belle_sip_server_transaction_t* server_transaction=op->pending_server_trans; belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); SalSubscribeStatus sub_state; if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) { SalPresenceModel *presence_model = NULL; const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); if (body==NULL){ ms_error("No body in NOTIFY received from [%s]",sal_op_get_from(op)); resp = sal_op_create_response_from_request(op, req, 415); belle_sip_server_transaction_send_response(server_transaction,resp); return; } presence_model = process_presence_notification(op, req); if (presence_model != NULL) { /* Presence notification body parsed successfully. */ if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) { sub_state=SalSubscribeTerminated; ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op)); } else { sub_state=SalSubscribeActive; } resp = sal_op_create_response_from_request(op, req, 200); /*create first because the op may be destroyed by notify_presence */ op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL); } else { /* Formatting error in presence notification body. */ ms_error("Wrongly formatted presence notification received"); resp = sal_op_create_response_from_request(op, req, 400); } belle_sip_server_transaction_send_response(server_transaction,resp); } }
static belle_sip_request_t *_belle_sip_dialog_create_request_from(belle_sip_dialog_t *obj, const belle_sip_request_t *initial_req, int queued){ belle_sip_request_t* req; const char *method=belle_sip_request_get_method(initial_req); belle_sip_header_content_length_t* content_lenth; belle_sip_list_t* headers; if (queued) req=belle_sip_dialog_create_queued_request(obj,method); else req=belle_sip_dialog_create_request(obj,method); if (req==NULL) return NULL; content_lenth = belle_sip_message_get_header_by_type(initial_req,belle_sip_header_content_length_t); /*first copy non system headers*/ headers = belle_sip_message_get_all_headers(BELLE_SIP_MESSAGE(initial_req)); belle_sip_list_for_each2(headers,(void (*)(void *, void *))copy_non_system_headers,req); belle_sip_list_free(headers); /*replicate via user parameters, if any, useful for 'alias' parameter in SUBSCRIBE requests*/ { belle_sip_header_via_t *orig_via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(initial_req),belle_sip_header_via_t); belle_sip_header_via_t *new_via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_via_t); belle_sip_parameters_copy_parameters_from(BELLE_SIP_PARAMETERS(new_via),BELLE_SIP_PARAMETERS(orig_via)); } /*copy body*/ if (content_lenth && belle_sip_header_content_length_get_content_length(content_lenth)>0) { belle_sip_message_set_body(BELLE_SIP_MESSAGE(req),belle_sip_message_get_body(BELLE_SIP_MESSAGE(initial_req)),belle_sip_header_content_length_get_content_length(content_lenth)); } return req; }
static void process_response(void *data, const belle_http_response_event_t *event){ belle_http_response_t *resp=event->response; const char *body=belle_sip_message_get_body(BELLE_SIP_MESSAGE(resp)); if (body){ fprintf(stdout,"%s",body); } belle_sip_main_loop_quit(belle_sip_stack_get_main_loop(stack)); }
static void belle_request_process_response_event(void *ctx, const belle_http_response_event_t *event) { LinphoneCore *lc = (LinphoneCore *)ctx; belle_sip_message_t *message = BELLE_SIP_MESSAGE(event->response); const char *body = belle_sip_message_get_body(message); if (belle_http_response_get_status_code(event->response) == 200) { linphone_remote_provisioning_apply(lc, body); } else { linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "http error"); } }
static void process_response_from_post_xml_rpc_request(void *data, const belle_http_response_event_t *event) { LinphoneXmlRpcRequest *request = (LinphoneXmlRpcRequest *)data; /* Check the answer code */ if (event->response) { int code = belle_http_response_get_status_code(event->response); if (code == 200) { /* Valid response from the server. */ parse_valid_xml_rpc_response(request, belle_sip_message_get_body((belle_sip_message_t *)event->response)); } else { notify_xml_rpc_error(request); } } linphone_xml_rpc_request_unref(request); }
static void process_response(void *data, const belle_http_response_event_t *event){ http_counters_t *counters=(http_counters_t*)data; counters->response_count++; CU_ASSERT_PTR_NOT_NULL(event->response); if (event->response){ int code=belle_http_response_get_status_code(event->response); const char *body=belle_sip_message_get_body(BELLE_SIP_MESSAGE(event->response)); if (code>=200 && code <300) counters->two_hundred++; else if (code>=300 && code <400) counters->three_hundred++; else if (code>=300 && code <400) counters->four_hundred++; CU_ASSERT_PTR_NOT_NULL(body); } }
static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_request_t *req) { belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t); belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_length_t); const char *body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); SalPresenceModel *result = NULL; if ((content_type == NULL) || (content_length == NULL)) return NULL; if (belle_sip_header_content_length_get_content_length(content_length) == 0) return NULL; op->base.root->callbacks.parse_presence_requested(op, belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type), body, &result); return result; }
/* * Extract the sdp from a sip message. * If there is no body in the message, the session_desc is set to null, 0 is returned. * If body was present is not a SDP or parsing of SDP failed, -1 is returned and SalReason is set appropriately. * **/ static int extract_sdp(SalOp *op, belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error) { const char *body; belle_sip_header_content_type_t* content_type; if (op&&op->sdp_handling == SalOpSDPSimulateError){ ms_error("Simulating SDP parsing error for op %p", op); *session_desc=NULL; *error=SalReasonNotAcceptable; return -1; } else if( op && op->sdp_handling == SalOpSDPSimulateRemove){ ms_error("Simulating no SDP for op %p", op); *session_desc = NULL; return 0; } body = belle_sip_message_get_body(message); if(body == NULL) { *session_desc = NULL; return 0; } content_type = belle_sip_message_get_header_by_type(message,belle_sip_header_content_type_t); if (content_type){ if (strcmp("application",belle_sip_header_content_type_get_type(content_type))==0 && strcmp("sdp",belle_sip_header_content_type_get_subtype(content_type))==0) { *session_desc=belle_sdp_session_description_parse(body); if (*session_desc==NULL) { ms_error("Failed to parse SDP message."); *error=SalReasonNotAcceptable; return -1; } }else{ *error=SalReasonUnsupportedContent; return -1; } }else *session_desc=NULL; return 0; }
void sal_op_call_process_notify(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t* server_transaction){ belle_sip_request_t* req = belle_sip_request_event_get_request(event); const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); belle_sip_header_t* header_event=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"); belle_sip_header_content_type_t* content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t); belle_sip_response_t* resp; ms_message("Receiving NOTIFY request on op [%p]",op); if (header_event && strncasecmp(belle_sip_header_get_unparsed_value(header_event),"refer",strlen("refer"))==0 && content_type && strcmp(belle_sip_header_content_type_get_type(content_type),"message")==0 && strcmp(belle_sip_header_content_type_get_subtype(content_type),"sipfrag")==0 && body){ belle_sip_response_t* sipfrag=BELLE_SIP_RESPONSE(belle_sip_message_parse(body)); if (sipfrag){ int code=belle_sip_response_get_status_code(sipfrag); SalReferStatus status=SalReferFailed; if (code<200){ status=SalReferTrying; }else if (code<300){ status=SalReferSuccess; }else if (code>=400){ status=SalReferFailed; } belle_sip_object_unref(sipfrag); resp = sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); op->base.root->callbacks.notify_refer(op,status); } }else{ ms_error("Notify without sipfrag, trashing"); resp = sal_op_create_response_from_request(op,req,501); belle_sip_server_transaction_send_response(server_transaction,resp); } }
static void server_process_request_event(void *obj, const belle_sip_request_event_t *event){ endpoint_t* endpoint = (endpoint_t*)obj; belle_sip_server_transaction_t* server_transaction =belle_sip_provider_create_server_transaction(endpoint->provider,belle_sip_request_event_get_request(event)); belle_sip_request_t* req = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)); belle_sip_response_t* resp; belle_sip_header_contact_t* contact; belle_sip_header_expires_t* expires; belle_sip_header_authorization_t* authorization; belle_sip_header_via_t* via; const char* raw_authenticate_digest = "WWW-Authenticate: Digest " "algorithm=MD5, realm=\"" SIPDOMAIN "\", opaque=\"1bc7f9097684320\""; belle_sip_header_www_authenticate_t* www_authenticate=NULL; const char* auth_uri; const char* qop; unsigned char auth_ok=0; char local_resp[33]; belle_sip_message("caller_process_request_event received [%s] message",belle_sip_request_get_method(belle_sip_request_event_get_request(event))); switch (endpoint->auth) { case none: { auth_ok=1; break; } case digest_auth: case digest: { if ((authorization=belle_sip_message_get_header_by_type(req,belle_sip_header_authorization_t)) != NULL){ qop=belle_sip_header_authorization_get_qop(authorization); if (qop && strcmp(qop,"auth")==0) { compute_response_auth_qop( belle_sip_header_authorization_get_username(authorization) ,belle_sip_header_authorization_get_realm(authorization) ,PASSWD ,endpoint->nonce ,endpoint->nonce_count ,belle_sip_header_authorization_get_cnonce(authorization) ,belle_sip_header_authorization_get_qop(authorization) ,belle_sip_request_get_method(req) ,auth_uri=belle_sip_uri_to_string(belle_sip_header_authorization_get_uri(authorization)) ,local_resp); } else { /*digest*/ compute_response(belle_sip_header_authorization_get_username(authorization) ,belle_sip_header_authorization_get_realm(authorization) ,PASSWD ,endpoint->nonce ,belle_sip_request_get_method(req) ,auth_uri=belle_sip_uri_to_string(belle_sip_header_authorization_get_uri(authorization)) ,local_resp); } belle_sip_free((void*)auth_uri); auth_ok=strcmp(belle_sip_header_authorization_get_response(authorization),local_resp)==0; } if (auth_ok && endpoint->nonce_count<MAX_NC_COUNT ) {/*revoke nonce after MAX_NC_COUNT uses*/ if (endpoint->auth == digest ) { sprintf(endpoint->nonce,"%p",authorization); //*change the nonce for next auth*/ } else { endpoint->nonce_count++; } } else { auth_ok=0; www_authenticate=belle_sip_header_www_authenticate_parse(raw_authenticate_digest); sprintf(endpoint->nonce,"%p",authorization); //*change the nonce for next auth*/ belle_sip_header_www_authenticate_set_nonce(www_authenticate,endpoint->nonce); if (endpoint->auth == digest_auth) { belle_sip_header_www_authenticate_add_qop(www_authenticate,"auth"); if (endpoint->nonce_count>=MAX_NC_COUNT) { belle_sip_header_www_authenticate_set_stale(www_authenticate,1); endpoint->nonce_count=1; } } } } break; default: break; } if (auth_ok) { resp=belle_sip_response_create_from_request(belle_sip_request_event_get_request(event),200); if (!endpoint->expire_in_contact) { belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(expires=belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t))); } if (strcmp(belle_sip_request_get_method(req),"REGISTER")==0) { contact=belle_sip_message_get_header_by_type(req,belle_sip_header_contact_t); } else { contact=belle_sip_header_contact_new(); } if(endpoint->unreconizable_contact) { /*put an unexpected address*/ belle_sip_uri_set_host(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact)),"nimportequoi.com"); } belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(contact)); if (strcmp(belle_sip_request_get_method(req),"PUBLISH")==0) { belle_sip_header_t* sip_if_match=belle_sip_message_get_header(BELLE_SIP_MESSAGE(resp),"SIP-If-Match"); if (sip_if_match) { CU_ASSERT_STRING_EQUAL(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(sip_if_match)),"blablietag"); } /*check for body*/ CU_ASSERT_PTR_NOT_NULL(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))); if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) { CU_ASSERT_STRING_EQUAL(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),publish_body); } CU_ASSERT_PTR_NOT_NULL(belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t)); CU_ASSERT_PTR_NOT_NULL(belle_sip_message_get_header_by_type(req,belle_sip_header_content_length_t)); belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),belle_sip_header_create("SIP-ETag","blablietag")); } } else { resp=belle_sip_response_create_from_request(belle_sip_request_event_get_request(event),401); if (www_authenticate) belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(www_authenticate)); } if (endpoint->received) { via=belle_sip_message_get_header_by_type(req,belle_sip_header_via_t); belle_sip_header_via_set_received(via,endpoint->received); } belle_sip_server_transaction_send_response(server_transaction,resp); }
static void process_request_event(void *op_base, const belle_sip_request_event_t *event) { SalOp* op = (SalOp*)op_base; belle_sip_server_transaction_t* server_transaction=NULL; belle_sdp_session_description_t* sdp; belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_dialog_state_t dialog_state; belle_sip_response_t* resp; belle_sip_header_t* call_info; const char *method=belle_sip_request_get_method(req); bool_t is_update=FALSE; if (strcmp("ACK",method)!=0){ /*ACK does'nt create srv transaction*/ server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event)); belle_sip_object_ref(server_transaction); belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),sal_op_ref(op)); } if (strcmp("INVITE",method)==0) { if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); /*updating pending invite transaction*/ op->pending_server_trans=server_transaction; belle_sip_object_ref(op->pending_server_trans); } if (strcmp("UPDATE",method)==0) { if (op->pending_update_server_trans) belle_sip_object_unref(op->pending_update_server_trans); /*updating pending update transaction*/ op->pending_update_server_trans=server_transaction; belle_sip_object_ref(op->pending_update_server_trans); } if (!op->dialog) { set_or_update_dialog(op,belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(op->pending_server_trans))); ms_message("new incoming call from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op)); } dialog_state=belle_sip_dialog_get_state(op->dialog); switch(dialog_state) { case BELLE_SIP_DIALOG_NULL: { if (strcmp("INVITE",method)==0) { if (!op->replaces && (op->replaces=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_replaces_t))) { belle_sip_object_ref(op->replaces); } else if(op->replaces) { ms_warning("replace header already set"); } if (process_sdp_for_invite(op,req) == 0) { if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) { if( strstr(belle_sip_header_get_unparsed_value(call_info),"answer-after=") != NULL) { op->auto_answer_asked=TRUE; ms_message("The caller asked to automatically answer the call(Emergency?)\n"); } } op->base.root->callbacks.call_received(op); } break; } /* else same behavior as for EARLY state*/ } case BELLE_SIP_DIALOG_EARLY: { //hmm probably a cancel if (strcmp("CANCEL",method)==0) { if(belle_sip_request_event_get_server_transaction(event)) { /*first answer 200 ok to cancel*/ belle_sip_server_transaction_send_response(server_transaction ,sal_op_create_response_from_request(op,req,200)); /*terminate invite transaction*/ call_terminated(op ,op->pending_server_trans ,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),487); } else { /*call leg does not exist*/ belle_sip_server_transaction_send_response(server_transaction ,sal_op_create_response_from_request(op,req,481)); } } else if (strcmp("PRACK",method)==0) { resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); } else if (strcmp("UPDATE",method)==0) { sal_op_reset_descriptions(op); if (process_sdp_for_invite(op,req)==0) op->base.root->callbacks.call_updating(op,TRUE); } else { belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req)); unsupported_method(server_transaction,req); } break; } case BELLE_SIP_DIALOG_CONFIRMED: /*great ACK received*/ if (strcmp("ACK",method)==0) { if (op->sdp_offering){ SalReason reason; if (extract_sdp(op,BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){ if (sdp){ if (op->base.remote_media) sal_media_description_unref(op->base.remote_media); op->base.remote_media=sal_media_description_new(); sdp_to_media_description(sdp,op->base.remote_media); sdp_process(op); belle_sip_object_unref(sdp); }else{ ms_warning("SDP expected in ACK but not found."); } } } op->base.root->callbacks.call_ack(op); } else if(strcmp("BYE",method)==0) { resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op)); op->state=SalOpStateTerminating; /*call end not notified by dialog deletion because transaction can end before dialog*/ } else if(strcmp("INVITE",method)==0 || (is_update=(strcmp("UPDATE",method)==0)) ) { if (is_update && !belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) { /*session timer case*/ /*session expire should be handled. to be done when real session timer (rfc4028) will be implemented*/ resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); belle_sip_object_unref(op->pending_update_server_trans); op->pending_update_server_trans=NULL; } else { /*re-invite*/ sal_op_reset_descriptions(op); if (process_sdp_for_invite(op,req)==0) op->base.root->callbacks.call_updating(op,is_update); } } else if (strcmp("INFO",method)==0){ if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)) && strstr(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),"picture_fast_update")) { /*vfu request*/ ms_message("Receiving VFU request on op [%p]",op); if (op->base.root->callbacks.vfu_request){ op->base.root->callbacks.vfu_request(op); } }else{ SalBody salbody; if (sal_op_get_body(op,(belle_sip_message_t*)req,&salbody)) { if (sal_body_has_type(&salbody,"application","dtmf-relay")){ char tmp[10]; if (sal_lines_get_value(salbody.data, "Signal",tmp, sizeof(tmp))){ op->base.root->callbacks.dtmf_received(op,tmp[0]); } }else op->base.root->callbacks.info_received(op,&salbody); } else { op->base.root->callbacks.info_received(op,NULL); } } resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); }else if (strcmp("REFER",method)==0) { sal_op_process_refer(op,event,server_transaction); } else if (strcmp("NOTIFY",method)==0) { sal_op_call_process_notify(op,event,server_transaction); } else if (strcmp("OPTIONS",method)==0) { resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); } else if (strcmp("CANCEL",method)==0) { /*call leg does not exist because 200ok already sent*/ belle_sip_server_transaction_send_response(server_transaction,sal_op_create_response_from_request(op,req,481)); } else if (strcmp("MESSAGE",method)==0){ sal_process_incoming_message(op,event); }else{ ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog); unsupported_method(server_transaction,req); } break; default: ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); break; } if (server_transaction) belle_sip_object_unref(server_transaction); }
void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *event){ belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,req); belle_sip_header_address_t* address; belle_sip_header_from_t* from_header; belle_sip_header_content_type_t* content_type; belle_sip_response_t* resp; int errcode=500; belle_sip_header_call_id_t* call_id = belle_sip_message_get_header_by_type(req,belle_sip_header_call_id_t); belle_sip_header_cseq_t* cseq = belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t); belle_sip_header_date_t *date=belle_sip_message_get_header_by_type(req,belle_sip_header_date_t); char* from; bool_t plain_text=FALSE; bool_t external_body=FALSE; bool_t cipher_xml=FALSE; bool_t rcs_filetransfer=FALSE; uint8_t *decryptedMessage = NULL; from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t); /* check if we have a xml/cipher message to be decrypted */ if (content_type && (cipher_xml=is_cipher_xml(content_type))) { /* access the zrtp cache to get keys needed to decipher 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 decrypt message"); goto error; } else { size_t cacheSize; char *cacheString; int retval; xmlDocPtr cacheXml; cacheString=ms_load_file_content(CACHEFD, &cacheSize); if (!cacheString){ ms_warning("Unable to load content of ZRTP ZID cache to decrypt message"); goto error; } cacheString[cacheSize] = '\0'; cacheSize += 1; fclose(CACHEFD); cacheXml = xmlParseDoc((xmlChar*)cacheString); ms_free(cacheString); retval = lime_decryptMultipartMessage(cacheXml, (uint8_t *)belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)), &decryptedMessage); if (retval != 0) { ms_warning("Unable to decrypt message, reason : %s - op [%p]", lime_error_code_to_string(retval), op); free(decryptedMessage); xmlFreeDoc(cacheXml); errcode = 488; goto error; } 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("Fail to write cache"); } xmlFree(xmlStringOutput); fclose(CACHEFD); } xmlFreeDoc(cacheXml); } } rcs_filetransfer=is_rcs_filetransfer(content_type); if (content_type && ((plain_text=is_plain_text(content_type)) || (external_body=is_external_body(content_type)) || (decryptedMessage!=NULL) || rcs_filetransfer)) { SalMessage salmsg; char message_id[256]={0}; if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); op->pending_server_trans=server_transaction; belle_sip_object_ref(op->pending_server_trans); address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); snprintf(message_id,sizeof(message_id)-1,"%s%i" ,belle_sip_header_call_id_get_call_id(call_id) ,belle_sip_header_cseq_get_seq_number(cseq)); salmsg.from=from; /* if we just deciphered a message, use the deciphered part(which can be a rcs xml body pointing to the file to retreive from server)*/ if (cipher_xml) { salmsg.text = (char *)decryptedMessage; } else { /* message body wasn't ciphered */ salmsg.text=(plain_text||rcs_filetransfer)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL; } salmsg.url=NULL; salmsg.content_type = NULL; if (rcs_filetransfer) { /* if we have a rcs file transfer, set the type, message body (stored in salmsg.text) contains all needed information to retrieve the file */ salmsg.content_type = "application/vnd.gsma.rcs-ft-http+xml"; } if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) { size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")); salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/ ((char*)salmsg.url)[url_length-2]='\0'; /*remove trailing "*/ } salmsg.message_id=message_id; salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL); op->base.root->callbacks.text_received(op,&salmsg); free(decryptedMessage); belle_sip_object_unref(address); belle_sip_free(from); if (salmsg.url) ms_free((char*)salmsg.url); } else if (content_type && is_im_iscomposing(content_type)) { SalIsComposing saliscomposing; address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); saliscomposing.from=from; saliscomposing.text=belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); op->base.root->callbacks.is_composing_received(op,&saliscomposing); resp = belle_sip_response_create_from_request(req,200); belle_sip_server_transaction_send_response(server_transaction,resp); belle_sip_object_unref(address); belle_sip_free(from); } else { ms_error("Unsupported MESSAGE (content-type not recognized)"); resp = belle_sip_response_create_from_request(req,415); add_message_accept((belle_sip_message_t*)resp); belle_sip_server_transaction_send_response(server_transaction,resp); sal_op_release(op); return; } return; error: resp = belle_sip_response_create_from_request(req, errcode); belle_sip_server_transaction_send_response(server_transaction,resp); sal_op_release(op); }
static void process_request_event(void *op_base, const belle_sip_request_event_t *event) { SalOp* op = (SalOp*)op_base; belle_sip_server_transaction_t* server_transaction=NULL; belle_sdp_session_description_t* sdp; belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_dialog_state_t dialog_state; belle_sip_response_t* resp; belle_sip_header_t* call_info; if (strcmp("ACK",belle_sip_request_get_method(req))!=0){ /*ACK does'nt create srv transaction*/ server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event)); belle_sip_object_ref(server_transaction); belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),op); sal_op_ref(op); } if (strcmp("INVITE",belle_sip_request_get_method(req))==0) { if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); /*updating pending invite transaction*/ op->pending_server_trans=server_transaction; belle_sip_object_ref(op->pending_server_trans); } if (!op->dialog) { set_or_update_dialog(op,belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(op->pending_server_trans))); ms_message("new incoming call from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op)); } dialog_state=belle_sip_dialog_get_state(op->dialog); switch(dialog_state) { case BELLE_SIP_DIALOG_NULL: { if (strcmp("INVITE",belle_sip_request_get_method(req))==0) { if (!op->replaces && (op->replaces=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_replaces_t))) { belle_sip_object_ref(op->replaces); } else if(op->replaces) { ms_warning("replace header already set"); } process_sdp_for_invite(op,req); if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) { if( strstr(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(call_info)),"answer-after=") != NULL) { op->auto_answer_asked=TRUE; ms_message("The caller asked to automatically answer the call(Emergency?)\n"); } } op->base.root->callbacks.call_received(op); break; } /* else same behavior as for EARLY state*/ } case BELLE_SIP_DIALOG_EARLY: { //hmm probably a cancel if (strcmp("CANCEL",belle_sip_request_get_method(req))==0) { if(belle_sip_request_event_get_server_transaction(event)) { /*first answer 200 ok to cancel*/ belle_sip_server_transaction_send_response(server_transaction ,sal_op_create_response_from_request(op,req,200)); /*terminate invite transaction*/ call_terminated(op ,op->pending_server_trans ,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),487); } else { /*call leg does not exist*/ belle_sip_server_transaction_send_response(server_transaction ,sal_op_create_response_from_request(op,req,481)); } } else if (strcmp("PRACK",belle_sip_request_get_method(req))==0) { resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); } else { belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req)); unsupported_method(server_transaction,req); } break; } case BELLE_SIP_DIALOG_CONFIRMED: /*great ACK received*/ if (strcmp("ACK",belle_sip_request_get_method(req))==0) { if (op->sdp_offering){ if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(req)))){ if (op->base.remote_media) sal_media_description_unref(op->base.remote_media); op->base.remote_media=sal_media_description_new(); sdp_to_media_description(sdp,op->base.remote_media); sdp_process(op); belle_sip_object_unref(sdp); } } /*FIXME if (op->reinvite){ op->reinvite=FALSE; }*/ op->base.root->callbacks.call_ack(op); } else if(strcmp("BYE",belle_sip_request_get_method(req))==0) { resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op)); op->state=SalOpStateTerminating; /*call end not notified by dialog deletion because transaction can end before dialog*/ } else if(strcmp("INVITE",belle_sip_request_get_method(req))==0) { /*re-invite*/ if (op->base.remote_media){ sal_media_description_unref(op->base.remote_media); op->base.remote_media=NULL; } if (op->result){ sal_media_description_unref(op->result); op->result=NULL; } process_sdp_for_invite(op,req); op->base.root->callbacks.call_updating(op); } else if (strcmp("INFO",belle_sip_request_get_method(req))==0){ if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)) && strstr(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),"picture_fast_update")) { /*vfu request*/ ms_message("Receiving VFU request on op [%p]",op); if (op->base.root->callbacks.vfu_request){ op->base.root->callbacks.vfu_request(op); } }else{ SalBody salbody; if (sal_op_get_body(op,(belle_sip_message_t*)req,&salbody)) { op->base.root->callbacks.info_received(op,&salbody); } else { op->base.root->callbacks.info_received(op,NULL); } } resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); }else if (strcmp("REFER",belle_sip_request_get_method(req))==0) { sal_op_process_refer(op,event,server_transaction); } else if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) { sal_op_call_process_notify(op,event,server_transaction); } else if (strcmp("OPTIONS",belle_sip_request_get_method(req))==0) { resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); } else if (strcmp("CANCEL",belle_sip_request_get_method(req))==0) { /*call leg does not exist because 200ok already sent*/ belle_sip_server_transaction_send_response( server_transaction ,sal_op_create_response_from_request(op,req,481)); } else{ ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog); unsupported_method(server_transaction,req); } break; default: { ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); } /* no break */ } if (server_transaction) belle_sip_object_unref(server_transaction); }
void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *event){ belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,req); belle_sip_header_address_t* address; belle_sip_header_from_t* from_header; belle_sip_header_content_type_t* content_type; belle_sip_response_t* resp; belle_sip_header_call_id_t* call_id = belle_sip_message_get_header_by_type(req,belle_sip_header_call_id_t); belle_sip_header_cseq_t* cseq = belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t); belle_sip_header_date_t *date=belle_sip_message_get_header_by_type(req,belle_sip_header_date_t); char* from; bool_t plain_text=FALSE; bool_t external_body=FALSE; from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t); if (content_type && ((plain_text=is_plain_text(content_type)) || (external_body=is_external_body(content_type)))) { SalMessage salmsg; char message_id[256]={0}; if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); op->pending_server_trans=server_transaction; belle_sip_object_ref(op->pending_server_trans); address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); snprintf(message_id,sizeof(message_id)-1,"%s%i" ,belle_sip_header_call_id_get_call_id(call_id) ,belle_sip_header_cseq_get_seq_number(cseq)); salmsg.from=from; salmsg.text=plain_text?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL; salmsg.url=NULL; if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) { size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")); salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/ ((char*)salmsg.url)[url_length-2]='\0'; /*remove trailing "*/ } salmsg.message_id=message_id; salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL); op->base.root->callbacks.text_received(op,&salmsg); belle_sip_object_unref(address); belle_sip_free(from); if (salmsg.url) ms_free((char*)salmsg.url); } else if (content_type && is_im_iscomposing(content_type)) { SalIsComposing saliscomposing; address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); saliscomposing.from=from; saliscomposing.text=belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); op->base.root->callbacks.is_composing_received(op,&saliscomposing); resp = belle_sip_response_create_from_request(req,200); belle_sip_server_transaction_send_response(server_transaction,resp); belle_sip_object_unref(address); belle_sip_free(from); } else { ms_error("Unsupported MESSAGE with content type [%s/%s]",belle_sip_header_content_type_get_type(content_type) ,belle_sip_header_content_type_get_subtype(content_type)); resp = belle_sip_response_create_from_request(req,415); add_message_accept((belle_sip_message_t*)resp); belle_sip_server_transaction_send_response(server_transaction,resp); return; } }