From 8004607607c344a0f1dd09d1854848fca0e52d59 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Thu, 13 Sep 2012 17:42:54 +0200 Subject: [PATCH] add support of external-body for SIP message --- coreapi/callbacks.c | 8 +++- coreapi/chat.c | 76 ++++++++++++++++++++++++++++++---- coreapi/linphonecore.h | 61 +++++++++++++++++++++++++-- coreapi/private.h | 4 +- coreapi/sal.h | 3 ++ coreapi/sal_eXosip2.c | 33 ++++++++++++++- coreapi/sal_eXosip2_presence.c | 14 ++++--- 7 files changed, 177 insertions(+), 22 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index cd20cf6b..14ca748e 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -732,9 +732,12 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){ static void text_received(Sal *sal, const char *from, const char *msg){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal); - linphone_core_text_received(lc,from,msg); + linphone_core_message_received(lc,from,msg,NULL); +} +void message_external_body_received(Sal *sal, const char *from, const char *url) { + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal); + linphone_core_message_received(lc,from,NULL,url); } - static void notify(SalOp *op, const char *from, const char *msg){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer (op); @@ -840,6 +843,7 @@ SalCallbacks linphone_sal_callbacks={ dtmf_received, refer_received, text_received, + message_external_body_received, text_delivery_update, notify, notify_presence, diff --git a/coreapi/chat.c b/coreapi/chat.c index cc36d730..941cce42 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -55,6 +55,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM const char *identity=linphone_core_find_best_identity(cr->lc,cr->peer_url,&route); SalOp *op=NULL; LinphoneCall *call; + char* content_type; if((call = linphone_core_get_call_by_remote_address(cr->lc,cr->peer))!=NULL){ if (call->state==LinphoneCallConnected || call->state==LinphoneCallStreamsRunning || @@ -77,7 +78,15 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM cr->op=op; sal_op_set_user_pointer(op, msg); /*if out of call, directly store msg*/ } - sal_text_send(op,identity,cr->peer,msg->message); + if (msg->external_body_url) { + content_type=ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"",msg->external_body_url); + sal_message_send(op,identity,cr->peer,content_type,NULL); + ms_free(content_type); + } else { + sal_text_send(op, identity, cr->peer, msg->message); + } + + } void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg) { @@ -89,16 +98,20 @@ bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *f return FALSE; } -void linphone_chat_room_text_received(LinphoneChatRoom *cr, LinphoneCore *lc, const LinphoneAddress *from, const char *msg){ - if (lc->vtable.text_received!=NULL) lc->vtable.text_received(lc, cr, from, msg); +void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc, LinphoneChatMessage *msg){ + if (msg->message) + //legacy API + if (lc->vtable.text_received!=NULL) lc->vtable.text_received(lc, cr, msg->from, msg->message); + if (lc->vtable.message_received!=NULL) lc->vtable.message_received(lc, cr,msg); + } -void linphone_core_text_received(LinphoneCore *lc, const char *from, const char *msg){ +void linphone_core_message_received(LinphoneCore *lc, const char *from, const char *raw_msg,const char* external_url){ MSList *elem; LinphoneChatRoom *cr=NULL; LinphoneAddress *addr; char *cleanfrom; - + LinphoneChatMessage* msg; addr=linphone_address_new(from); linphone_address_clean(addr); for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){ @@ -113,9 +126,13 @@ void linphone_core_text_received(LinphoneCore *lc, const char *from, const char /* create a new chat room */ cr=linphone_core_create_chat_room(lc,cleanfrom); } - + msg = linphone_chat_room_create_message(cr, raw_msg); + linphone_chat_message_set_from(msg, cr->peer_url); + if (external_url) { + linphone_chat_message_set_external_body_url(msg, external_url); + } linphone_address_destroy(addr); - linphone_chat_room_text_received(cr,lc,cr->peer_url,msg); + linphone_chat_room_message_received(cr,lc,msg); ms_free(cleanfrom); } @@ -140,12 +157,14 @@ const LinphoneAddress* linphone_chat_room_get_peer_address(LinphoneChatRoom *cr) LinphoneChatMessage* linphone_chat_room_create_message(const LinphoneChatRoom *cr,const char* message) { LinphoneChatMessage* msg = ms_new0(LinphoneChatMessage,1); msg->chat_room=(LinphoneChatRoom*)cr; - msg->message=ms_strdup(message); + msg->message=message?ms_strdup(message):NULL; return msg; } void linphone_chat_message_destroy(LinphoneChatMessage* msg) { if (msg->message) ms_free(msg->message); + if (msg->external_body_url) ms_free(msg->external_body_url); + if (msg->from) linphone_address_destroy(msg->from); ms_free(msg); } @@ -186,3 +205,44 @@ void linphone_chat_message_set_user_data(LinphoneChatMessage* message,void* ud) void* linphone_chat_message_get_user_data(const LinphoneChatMessage* message) { return message->message_userdata; } + +const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message) { + return message->external_body_url; +} + +void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url) { + if (message->external_body_url) { + ms_free(message->external_body_url); + } + message->external_body_url=url?ms_strdup(url):NULL; +} +void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from) { + if(message->from) linphone_address_destroy(message->from); + message->from=linphone_address_clone(from); + +} +LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message) { + return message->from; +} +const char * linphone_chat_message_get_text(const LinphoneChatMessage* message) { + return message->message; +} +LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* msg) { + /*struct _LinphoneChatMessage { + char* message; + LinphoneChatRoom* chat_room; + LinphoneChatMessageStateChangeCb cb; + void* cb_ud; + void* message_userdata; + char* external_body_url; + LinphoneAddress* from; + };*/ + LinphoneChatMessage* new_message = linphone_chat_room_create_message(msg->chat_room,msg->message); + if (msg->external_body_url) new_message->external_body_url=ms_strdup(msg->external_body_url); + new_message->cb=msg->cb; + new_message->cb_ud=msg->cb_ud; + new_message->message_userdata=msg->message_userdata; + new_message->cb=msg->cb; + if (msg->from) new_message->from=linphone_address_clone(msg->from); + return new_message; +} \ No newline at end of file diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index d4a0355b..009648be 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -617,7 +617,6 @@ void linphone_chat_room_destroy(LinphoneChatRoom *cr); */ LinphoneChatMessage* linphone_chat_room_create_message(const LinphoneChatRoom *cr,const char* message); - /** * get peer address \link linphone_core_create_chat_room() associated to \endlink this #LinphoneChatRoom @@ -641,18 +640,61 @@ typedef enum _LinphoneChatMessageStates { LinphoneChatMessageStateNotDelivered /** message was not delivered*/ }LinphoneChatMessageState; + /** * to string function */ const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState state); + /** - * user pointer set function + * clone a chat message + *@param message #LinphoneChatMessage obj + *@return #LinphoneChatMessage */ -void linphone_chat_message_set_user_data(LinphoneChatMessage* message,void*); +LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* message); +/** + * set origine of the message + *@param message #LinphoneChatMessage obj + *@param from #LinphoneAddress origin of this message (copied) + */ +void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from); + +/** + * get origine of the message + *@param message #LinphoneChatMessage obj + *@return #LinphoneAddress + */ +LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message); + +/** + * Linphone message can carry external body as defined by rfc2017 + * @param message #LinphoneChatMessage + * @return return external body url null if not present. + */ +const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message); + +/** + * Linphone message can carry external body as defined by rfc2017 + * + * @param #LinphoneChatMessage + * @param url ex: access-type=URL; URL="http://www.foo.com/file" + */ +void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url); + +/** + * get text part of this message + *@return text or NULL if no text. + */ +const char * linphone_chat_message_get_text(const LinphoneChatMessage* message); /** * user pointer get function */ + void* linphone_chat_message_get_user_data(const LinphoneChatMessage* message); +/** + * user pointer set function + */ +void linphone_chat_message_set_user_data(LinphoneChatMessage* message,void*); /** * Call back used to notify message delivery status @@ -744,6 +786,7 @@ typedef void (*AuthInfoRequested)(struct _LinphoneCore *lc, const char *realm, c typedef void (*CallLogUpdated)(struct _LinphoneCore *lc, struct _LinphoneCallLog *newcl); /** * Callback prototype + * @deprecated use #MessageReceived instead. * * @param lc #LinphoneCore object * @param room #LinphoneChatRoom involved in this conversation. Can be be created by the framework in case \link #LinphoneAddress the from \endlink is not present in any chat room. @@ -751,6 +794,15 @@ typedef void (*CallLogUpdated)(struct _LinphoneCore *lc, struct _LinphoneCallLog * @param message incoming message * */ typedef void (*TextMessageReceived)(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message); +/** + * Chat message callback prototype + * + * @param lc #LinphoneCore object + * @param room #LinphoneChatRoom involved in this conversation. Can be be created by the framework in case \link #LinphoneAddress the from \endlink is not present in any chat room. + * @param LinphoneChatMessage incoming message + * */ +typedef void (*MessageReceived)(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message); + /** Callback prototype */ typedef void (*DtmfReceived)(struct _LinphoneCore* lc, LinphoneCall *call, int dtmf); /** Callback prototype */ @@ -774,7 +826,8 @@ typedef struct _LinphoneVTable{ NewSubscribtionRequestCb new_subscription_request; /**< Notify about pending subscription request */ AuthInfoRequested auth_info_requested; /**< Ask the application some authentication information */ CallLogUpdated call_log_updated; /**< Notifies that call log list has been updated */ - TextMessageReceived text_received; /**< A text message has been received */ + TextMessageReceived text_received; /** @deprecated, use #message_received instead
A text message has been received */ + MessageReceived message_received; /** a message is received, can be text or external body*/ DtmfReceived dtmf_received; /**< A dtmf has been received received */ ReferReceived refer_received; /**< An out of call refer was received */ CallEncryptionChangedCb call_encryption_changed; /**callbacks.text_received=(SalOnTextReceived)unimplemented_stub; if (ctx->callbacks.ping_reply==NULL) ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub; + if (ctx->callbacks.message_external_body==NULL) + ctx->callbacks.message_external_body=(SalOnMessageExternalBodyReceived)unimplemented_stub; } int sal_unlisten_ports(Sal *ctx){ @@ -1701,15 +1703,44 @@ static bool_t comes_from_local_if(osip_message_t *msg){ static void text_received(Sal *sal, eXosip_event_t *ev){ osip_body_t *body=NULL; char *from=NULL,*msg; + osip_content_type_t* content_type; + osip_uri_param_t* external_body_url; + char unquoted_external_body_url [256]; + int external_body_size=0; + content_type= osip_message_get_content_type(ev->request); + if (!content_type) { + ms_error("Could not get message because no content type"); + return; + } + osip_from_to_str(ev->request->from,&from); + if (content_type->type + && strcmp(content_type->type, "text")==0 + && content_type->subtype + && strcmp(content_type->subtype, "plain")==0 ) { osip_message_get_body(ev->request,0,&body); if (body==NULL){ ms_error("Could not get text message from SIP body"); return; } msg=body->body; - osip_from_to_str(ev->request->from,&from); sal->callbacks.text_received(sal,from,msg); + } if (content_type->type + && strcmp(content_type->type, "message")==0 + && content_type->subtype + && strcmp(content_type->subtype, "external-body")==0 ) { + + osip_content_type_param_get_byname(content_type, "URL", &external_body_url); + /*remove both first and last character*/ + strncpy(unquoted_external_body_url + ,&external_body_url->gvalue[1] + ,external_body_size=MIN(strlen(external_body_url->gvalue)-1,sizeof(unquoted_external_body_url))); + unquoted_external_body_url[external_body_size-1]='\0'; + sal->callbacks.message_external_body(sal,from,unquoted_external_body_url); + + } else { + ms_warning("Unsupported content type [%s/%s]",content_type->type,content_type->subtype); + } osip_free(from); } diff --git a/coreapi/sal_eXosip2_presence.c b/coreapi/sal_eXosip2_presence.c index f79866a0..3559081d 100644 --- a/coreapi/sal_eXosip2_presence.c +++ b/coreapi/sal_eXosip2_presence.c @@ -81,7 +81,7 @@ 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){ +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) @@ -97,8 +97,8 @@ int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg){ eXosip_message_build_request(&sip,"MESSAGE",sal_op_get_to(op), sal_op_get_from(op),sal_op_get_route(op)); if (sip!=NULL){ - osip_message_set_content_type(sip,"text/plain"); - osip_message_set_body(sip,msg,strlen(msg)); + 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{ @@ -118,14 +118,16 @@ int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg){ eXosip_unlock(); return -1; } - osip_message_set_content_type(sip,"text/plain"); - osip_message_set_body(sip,msg,strlen(msg)); + 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=NULL; -- 2.39.2