]> sjero.net Git - linphone/commitdiff
add support of external-body for SIP message
authorJehan Monnier <jehan.monnier@linphone.org>
Thu, 13 Sep 2012 15:42:54 +0000 (17:42 +0200)
committerJehan Monnier <jehan.monnier@linphone.org>
Thu, 13 Sep 2012 15:43:33 +0000 (17:43 +0200)
coreapi/callbacks.c
coreapi/chat.c
coreapi/linphonecore.h
coreapi/private.h
coreapi/sal.h
coreapi/sal_eXosip2.c
coreapi/sal_eXosip2_presence.c

index cd20cf6b9dfe634fd2919c7d32716a3165c6fc7f..14ca748e135968ce18570de3c61dbf95f08f0291 100644 (file)
@@ -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,
index cc36d730566c80c4b2b6835e2804f8c4c4aa43c8..941cce423c45c15a2f524fe737612f402345cd61 100644 (file)
@@ -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
index d4a0355b683db735e438b3569129644bb39a735a..009648be3053bf8db601a32c07d4d02c8d98711a 100644 (file)
@@ -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 <br> 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; /**<Notifies on change in the encryption of call streams */
index 3042342d2795cfc0ba8866e7e15f9478d44f28e9..f26c6f106f218c97e6748c6eb327483914e3bc43 100644 (file)
@@ -96,6 +96,8 @@ struct _LinphoneChatMessage {
        LinphoneChatMessageStateChangeCb cb;
        void* cb_ud;
        void* message_userdata;
+       char* external_body_url;
+       LinphoneAddress* from;
 };
        
 struct _LinphoneCall
@@ -259,7 +261,7 @@ void linphone_proxy_config_write_to_config_file(struct _LpConfig* config,Linphon
 
 int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char *username, char *result, size_t result_len);
 
-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);
 
 void linphone_core_play_tone(LinphoneCore *lc);
 
index e12cdaf0c5cbb09fa5915c04ff23afbead8c899f..9c3f6d61f2e46bf99631ec819b4c0d344eff24ca 100644 (file)
@@ -275,6 +275,7 @@ typedef void (*SalOnVfuRequest)(SalOp *op);
 typedef void (*SalOnDtmfReceived)(SalOp *op, char dtmf);
 typedef void (*SalOnRefer)(Sal *sal, SalOp *op, const char *referto);
 typedef void (*SalOnTextReceived)(Sal *sal, const char *from, const char *msg);
+typedef void (*SalOnMessageExternalBodyReceived)(Sal *sal, const char *from, const char *url);
 typedef void (*SalOnTextDeliveryUpdate)(SalOp *op, SalTextDeliveryStatus status);
 typedef void (*SalOnNotify)(SalOp *op, const char *from, const char *event);
 typedef void (*SalOnNotifyRefer)(SalOp *op, SalReferStatus state);
@@ -300,6 +301,7 @@ typedef struct SalCallbacks{
        SalOnDtmfReceived dtmf_received;
        SalOnRefer refer_received;
        SalOnTextReceived text_received;
+       SalOnMessageExternalBodyReceived message_external_body;
        SalOnTextDeliveryUpdate text_delivery_update;
        SalOnNotify notify;
        SalOnNotifyPresence notify_presence;
@@ -402,6 +404,7 @@ int sal_unregister(SalOp *h);
 
 /*Messaging */
 int sal_text_send(SalOp *op, const char *from, const char *to, const char *text);
+int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg);
 
 /*presence Subscribe/notify*/
 int sal_subscribe_presence(SalOp *op, const char *from, const char *to);
index 695d8568d4bddef4203fcb83e680bb5c313fc2ae..30b0f286dafb59c73ec2b28859793de9f9bebd3f 100644 (file)
@@ -341,6 +341,8 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
                ctx->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);
 }
 
index f79866a0a8d60b5890ab8aab213814b559a22e25..3559081db92f6192f9764c55430bfd155cba29cb 100644 (file)
@@ -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;