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);
dtmf_received,
refer_received,
text_received,
+ message_external_body_received,
text_delivery_update,
notify,
notify_presence,
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 ||
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) {
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)){
/* 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);
}
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);
}
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
*/
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
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
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.
* @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 */
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 */
LinphoneChatMessageStateChangeCb cb;
void* cb_ud;
void* message_userdata;
+ char* external_body_url;
+ LinphoneAddress* from;
};
struct _LinphoneCall
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);
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);
SalOnDtmfReceived dtmf_received;
SalOnRefer refer_received;
SalOnTextReceived text_received;
+ SalOnMessageExternalBodyReceived message_external_body;
SalOnTextDeliveryUpdate text_delivery_update;
SalOnNotify notify;
SalOnNotifyPresence notify_presence;
/*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);
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){
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);
}
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)
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{
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;