From a45d28a328be70f037995c48dd4742fbb1eb9519 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Mon, 10 Mar 2014 17:25:44 +0100 Subject: [PATCH] implement receiving of in-dialog chat message --- coreapi/bellesip_sal/sal_impl.h | 2 +- coreapi/bellesip_sal/sal_op_call.c | 39 +++++++++++------------ coreapi/bellesip_sal/sal_op_message.c | 45 +++++++++++++++++---------- coreapi/chat.c | 2 -- coreapi/linphonecall.c | 2 -- coreapi/private.h | 1 - tester/message_tester.c | 22 +++++++++++++ 7 files changed, 71 insertions(+), 42 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index 5a0faa82a..f74936b63 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -137,7 +137,7 @@ void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal void sal_op_presence_fill_cbs(SalOp*op); /*messaging*/ void sal_op_message_fill_cbs(SalOp*op); - +void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *event); void sal_op_subscribe_fill_cbs(SalOp*op); /*call transfer*/ diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index a51792706..bc97bd1a9 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -322,7 +322,7 @@ static void call_terminated(SalOp* op,belle_sip_server_transaction_t* server_tra static void unsupported_method(belle_sip_server_transaction_t* server_transaction,belle_sip_request_t* request) { belle_sip_response_t* resp; - resp=belle_sip_response_create_from_request(request,500); + resp=belle_sip_response_create_from_request(request,501); belle_sip_server_transaction_send_response(server_transaction,resp); return; } @@ -392,15 +392,16 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t 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); - if (strcmp("ACK",belle_sip_request_get_method(req))!=0){ /*ACK does'nt create srv transaction*/ + 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),op); sal_op_ref(op); } - if (strcmp("INVITE",belle_sip_request_get_method(req))==0) { + 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; @@ -414,7 +415,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t 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 (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) { @@ -429,15 +430,13 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t 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 (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 @@ -453,7 +452,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t 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) { + } 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 { @@ -464,7 +463,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t } case BELLE_SIP_DIALOG_CONFIRMED: /*great ACK received*/ - if (strcmp("ACK",belle_sip_request_get_method(req))==0) { + if (strcmp("ACK",method)==0) { if (op->sdp_offering){ SalReason reason; if (extract_sdp(BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){ @@ -485,13 +484,13 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t op->reinvite=FALSE; }*/ op->base.root->callbacks.call_ack(op); - } else if(strcmp("BYE",belle_sip_request_get_method(req))==0) { + } 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",belle_sip_request_get_method(req))==0) { + } else if(strcmp("INVITE",method)==0) { /*re-invite*/ if (op->base.remote_media){ sal_media_description_unref(op->base.remote_media); @@ -503,7 +502,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t } if (process_sdp_for_invite(op,req)==0) op->base.root->callbacks.call_updating(op); - } else if (strcmp("INFO",belle_sip_request_get_method(req))==0){ + } 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*/ @@ -528,19 +527,19 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t } 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) { + }else if (strcmp("REFER",method)==0) { sal_op_process_refer(op,event,server_transaction); - } else if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) { + } else if (strcmp("NOTIFY",method)==0) { sal_op_call_process_notify(op,event,server_transaction); - } else if (strcmp("OPTIONS",belle_sip_request_get_method(req))==0) { + } 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",belle_sip_request_get_method(req))==0) { + } 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{ + 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); } diff --git a/coreapi/bellesip_sal/sal_op_message.c b/coreapi/bellesip_sal/sal_op_message.c index c147b649b..bf7f7b82a 100644 --- a/coreapi/bellesip_sal/sal_op_message.c +++ b/coreapi/bellesip_sal/sal_op_message.c @@ -84,8 +84,11 @@ static bool_t is_im_iscomposing(belle_sip_header_content_type_t* content_type) { && strcmp("im-iscomposing+xml",belle_sip_header_content_type_get_subtype(content_type))==0; } -static void process_request_event(void *op_base, const belle_sip_request_event_t *event) { - SalOp* op = (SalOp*)op_base; +static void add_message_accept(belle_sip_message_t *msg){ + belle_sip_message_add_header(msg,belle_sip_header_create("Accept","text/plain, message/external-body, application/im-iscomposing+xml")); +} + +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; @@ -95,7 +98,6 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t 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); - int response_code=501; char* from; bool_t plain_text=FALSE; bool_t external_body=FALSE; @@ -126,7 +128,6 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t belle_sip_object_unref(address); belle_sip_free(from); if (salmsg.url) ms_free((char*)salmsg.url); - response_code=200; } 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)) @@ -137,14 +138,21 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t op->base.root->callbacks.is_composing_received(op,&saliscomposing); belle_sip_object_unref(address); belle_sip_free(from); - response_code=200; } 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)); - response_code=501; /*not implemented sound appropriate*/ + 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; } - resp = belle_sip_response_create_from_request(req,response_code); + resp = belle_sip_response_create_from_request(req,200); 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; + sal_process_incoming_message(op,event); sal_op_release(op); } @@ -154,16 +162,21 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co size_t content_length = msg?strlen(msg):0; time_t curtime=time(NULL); - 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; + 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))); + 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))); diff --git a/coreapi/chat.c b/coreapi/chat.c index 82e05fdaf..bb944e1cc 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -149,7 +149,6 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM call->state==LinphoneCallPausedByRemote){ ms_message("send SIP message through the existing call."); op = call->op; - call->pending_message=msg; identity=linphone_core_find_best_identity(cr->lc,linphone_call_get_remote_address(call)); } } @@ -224,7 +223,6 @@ LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAd } void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg){ - LinphoneChatRoom *cr=NULL; LinphoneAddress *addr; char *cleanfrom; diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index e6aebb7be..f73779377 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2845,8 +2845,6 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , } } return ret; - - } void linphone_call_set_contact_op(LinphoneCall* call) { diff --git a/coreapi/private.h b/coreapi/private.h index 7539e3bca..cd528994f 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -199,7 +199,6 @@ struct _LinphoneCall UpnpSession *upnp_session; #endif //BUILD_UPNP IceSession *ice_session; - LinphoneChatMessage* pending_message; int ping_time; unsigned int remote_session_id; unsigned int remote_session_ver; diff --git a/tester/message_tester.c b/tester/message_tester.c index c9c52cfe8..5cf1b54a8 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -94,6 +94,27 @@ static void text_message(void) { linphone_core_manager_destroy(pauline); } +static void text_message_within_dialog(void) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + + lp_config_set_int(pauline->lc->config,"sip","chat_use_call_dialogs",1); + + char* to = linphone_address_as_string(marie->identity); + LinphoneChatRoom* chat_room = linphone_core_create_chat_room(pauline->lc,to); + ms_free(to); + + CU_ASSERT_TRUE(call(marie,pauline)); + + linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); + + CU_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity)); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + static LinphoneAuthInfo* text_message_with_credential_from_auth_cb_auth_info; static void text_message_with_credential_from_auth_cb_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) { stats* counters; @@ -332,6 +353,7 @@ static void is_composing_notification(void) { test_t message_tests[] = { { "Text message", text_message }, + { "Text message within call's dialog", text_message_within_dialog}, { "Text message with credentials from auth info cb", text_message_with_credential_from_auth_cb}, { "Text message with privacy", text_message_with_privacy }, { "Text message compatibility mode", text_message_compatibility_mode },