Commit c10b5f65 authored by johan's avatar johan

File transfer implemented following RCS5.1 recommendation

- memory leaks to be fixed
parent 49e8c4f9
......@@ -55,6 +55,11 @@ static void process_response_event(void *op_base, const belle_sip_response_event
op->base.root->callbacks.text_delivery_update(op,status);
}
static bool_t is_rcs_filetransfer(belle_sip_header_content_type_t* content_type) {
return strcmp("application",belle_sip_header_content_type_get_type(content_type))==0
&& strcmp("vnd.gsma.rcs-ft-http+xml",belle_sip_header_content_type_get_subtype(content_type))==0;
}
static bool_t is_plain_text(belle_sip_header_content_type_t* content_type) {
return strcmp("text",belle_sip_header_content_type_get_type(content_type))==0
&& strcmp("plain",belle_sip_header_content_type_get_subtype(content_type))==0;
......@@ -69,7 +74,7 @@ static bool_t is_im_iscomposing(belle_sip_header_content_type_t* content_type) {
}
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"));
belle_sip_message_add_header(msg,belle_sip_header_create("Accept","text/plain, message/external-body, application/im-iscomposing+xml, application/vnd.gsma.rcs-ft-http+xml"));
}
void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *event){
......@@ -85,11 +90,13 @@ void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *eve
char* from;
bool_t plain_text=FALSE;
bool_t external_body=FALSE;
bool_t rcs_filetransfer=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)))) {
|| (external_body=is_external_body(content_type))
|| (rcs_filetransfer=is_rcs_filetransfer(content_type)))) {
SalMessage salmsg;
char message_id[256]={0};
......@@ -104,8 +111,12 @@ void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *eve
,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.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 "*/
......
This diff is collapsed.
......@@ -79,6 +79,8 @@ notify_LDADD=$(helloworld_LDADD)
filetransfer_SOURCES=filetransfer.c
LINPHONE_TUTOS+=$(filetransfer_SOURCES)
filetransfer_LDADD=$(helloworld_LDADD)
AM_CFLAGS=\
-I$(top_srcdir)/coreapi \
$(STRICT_OPTIONS) \
......
......@@ -52,7 +52,7 @@ static void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMess
const LinphoneAddress* from_address = linphone_chat_message_get_from(message);
const LinphoneAddress* to_address = linphone_chat_message_get_to(message);
char *address = linphone_chat_message_is_outgoing(message)?linphone_address_as_string(to_address):linphone_address_as_string(from_address);
printf(" File transfer [%i&] %s of type [%s/%s] %s [%s] \n", (int)(content->size/progress)*100
printf(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)progress
,(linphone_chat_message_is_outgoing(message)?"sent":"received")
, content->type
, content->subtype
......@@ -73,31 +73,32 @@ static void file_transfer_received(LinphoneCore *lc, LinphoneChatMessage *messag
, from);
if (!linphone_chat_message_get_user_data(message)) {
/*first chunk, creating file*/
file = open("receive_file.dump",O_WRONLY);
file = open("receive_file.dump",O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
linphone_chat_message_set_user_data(message,(void*)(long)(0x00000000FFFFFFFF&file)); /*store fd for next chunks*/
} else {
/*next chunk*/
file = (int)linphone_chat_message_get_user_data(message);
file = (int)((long)(linphone_chat_message_get_user_data(message))&0x00000000FFFFFFFF);
}
/*store content on a file*/
write(file,buff,size);
if (size==0) {
printf("File transfert completed");
printf("File transfert completed\n");
close(file);
} /*else wait for next chunk*/
running=FALSE;
} else { /* store content on a file*/
write(file,buff,size);
}
free(from);
}
char big_file [128000];
/*
* function call when is file transfer is initiated. file content should be feed into object LinphoneContent
* function called when the file transfer is initiated. file content should be feed into object LinphoneContent
* */
static void file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size){
const LinphoneAddress* to_address = linphone_chat_message_get_to(message);
char *to = linphone_address_as_string(to_address);
//const LinphoneAddress* to_address = linphone_chat_message_get_to(message);
//char *to = linphone_address_as_string(to_address);
int offset=-1;
/*content->size can be feed*/
......@@ -106,7 +107,7 @@ static void file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message,
offset=0;
} else {
/*subsequent chunk*/
offset = (int)linphone_chat_message_get_user_data(message);
offset = (int)((long)(linphone_chat_message_get_user_data(message))&0x00000000FFFFFFFF);
}
*size = MIN(*size,sizeof(big_file)-offset); /*updating content->size with minimun between remaining data and requested size*/
......@@ -119,11 +120,22 @@ static void file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message,
printf(" File transfer sending [%i] bytes of type [%s/%s] from [%s] \n" , (int)*size
, content->type
, content->subtype
, to);
, "pipo");
/*store offset for next chunk*/
linphone_chat_message_set_user_data(message,(void*)(offset+*size));
free(to);
//free(to);
}
/*
* Call back called when a message is received
*/
static void message_received(LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
const LinphoneContent *file_transfer_info = linphone_chat_message_get_file_transfer_information(msg);
printf ("Do you really want to download %s (size %ld)?[Y/n]\nOk, let's go\n", file_transfer_info->name, file_transfer_info->size);
linphone_chat_message_start_file_download(msg);
}
/*
......@@ -137,21 +149,21 @@ static void linphone_file_transfer_state_changed(LinphoneChatMessage* msg,Linpho
free(to);
}
LinphoneCore *lc;
int main(int argc, char *argv[]){
LinphoneCoreVTable vtable={0};
char* dest_friend=NULL;
const char* dest_friend=NULL;
int i;
const char* big_file_content="big file";
/*seting dummy file content to something*/
for (i=0;i<sizeof(big_file)/strlen(big_file_content);i++)
sprintf(big_file+i,"%s",big_file_content);
for (i=0;i<sizeof(big_file);i+=strlen(big_file_content))
memcpy(big_file+i, big_file_content, strlen(big_file_content));
big_file[0]=*"S";
big_file[sizeof(big_file)-1]=*"E";
/* takes sip uri identity from the command line arguments */
if (argc>1){
dest_friend=argv[1];
}
signal(SIGINT,stop);
//#define DEBUG
#ifdef DEBUG
......@@ -166,20 +178,24 @@ int main(int argc, char *argv[]){
vtable.file_transfer_received=file_transfer_received;
vtable.file_transfer_send=file_transfer_send;
vtable.file_transfer_progress_indication=file_transfer_progress_indication;
vtable.message_received=message_received;
/*
Instantiate a LinphoneCore object given the LinphoneCoreVTable
*/
lc=linphone_core_new(&vtable,NULL,NULL,NULL);
dest_friend = linphone_core_get_primary_contact(lc);
printf("Send message to me : %s\n", dest_friend);
/**
* Globally configure an http file transfer server.
*/
linphone_core_set_file_transfer_server(lc,"http://sharing.linphone.org/upload.php");
linphone_core_set_file_transfer_server(lc,"http://npasc.al/lft.php");
//linphone_core_set_file_transfer_server(lc,"https://www.linphone.org:444/upload.php");
/*Next step is to create a chat root*/
/*Next step is to create a chat room*/
LinphoneChatRoom* chat_room = linphone_core_create_chat_room(lc,dest_friend);
LinphoneContent content;
......@@ -187,13 +203,16 @@ int main(int argc, char *argv[]){
content.type="text";
content.subtype="plain";
content.size=sizeof(big_file); /*total size to be transfered*/
content.name = "bigfile.txt";
/*now create a chat message with custom content*/
LinphoneChatMessage* chat_message = linphone_chat_room_create_file_transfer_message(chat_room,&content);
if (chat_message == NULL) {
printf("returned message is null\n");
}
/*initiating file transfer*/
/**/
linphone_chat_room_send_message2(chat_room, chat_message,linphone_file_transfer_state_changed,NULL);
linphone_chat_room_send_message2(chat_room, chat_message, linphone_file_transfer_state_changed, NULL);
/* main loop for receiving incoming messages and doing background linphone core work: */
while(running){
......
......@@ -1392,6 +1392,8 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
lc->http_verify_policy = belle_tls_verify_policy_new();
belle_http_provider_set_tls_verify_policy(lc->http_provider,lc->http_verify_policy);
lc->file_transfer_server = NULL;
certificates_config_read(lc);
remote_provisioning_uri = linphone_core_get_provisioning_uri(lc);
......@@ -5891,6 +5893,8 @@ static void linphone_core_uninit(LinphoneCore *lc)
lc->last_recv_msg_ids=ms_list_free(lc->last_recv_msg_ids);
// Free struct variable
ms_free(lc->file_transfer_server);
if(lc->zrtp_secrets_cache != NULL) {
ms_free(lc->zrtp_secrets_cache);
}
......@@ -6536,3 +6540,11 @@ bool_t linphone_core_sdp_200_ack_enabled(const LinphoneCore *lc) {
return lc->sip_conf.sdp_200_ack!=0;
}
/**
* Globaly set an http file transfer server to be used for content type application/vnd.gsma.rcs-ft-http+xml. This value can also be set for a dedicated account using #linphone_proxy_config_set_file_transfer_server
* @param #LinphoneCore to be modified
* @param const char* url of the file server like https://file.linphone.org/upload.php
**/
void linphone_core_set_file_transfer_server(LinphoneCore *core, const char * server_url) {
core->file_transfer_server=ms_strdup(server_url);
}
......@@ -137,6 +137,7 @@ struct _LinphoneContent{
size_t size; /**<the size of the data buffer, excluding null character despite null character is always set for convenience.
When provided by callback #LinphoneCoreFileTransferSendCb or #LinphoneCoreFileTransferReceiveCb, it states the total number of bytes of the transfered file*/
char *encoding; /**<The encoding of the data buffer, for example "gzip"*/
char *name; /**< used by RCS File transfer messages to store the original filename of the file to be downloaded from server */
};
/**
......@@ -1124,6 +1125,8 @@ LINPHONE_PUBLIC void linphone_chat_message_set_to(LinphoneChatMessage* message,
LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_to(const LinphoneChatMessage* message);
LINPHONE_PUBLIC const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message);
LINPHONE_PUBLIC void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url);
LINPHONE_PUBLIC const LinphoneContent* linphone_chat_message_get_file_transfer_information(const LinphoneChatMessage* message);
LINPHONE_PUBLIC void linphone_chat_message_start_file_download(const LinphoneChatMessage*message);
LINPHONE_PUBLIC const char * linphone_chat_message_get_text(const LinphoneChatMessage* message);
LINPHONE_PUBLIC time_t linphone_chat_message_get_time(const LinphoneChatMessage* message);
LINPHONE_PUBLIC void* linphone_chat_message_get_user_data(const LinphoneChatMessage* message);
......
......@@ -151,6 +151,8 @@ struct _LinphoneChatMessage {
bool_t is_read;
unsigned int storage_id;
SalOp *op;
LinphoneContent *file_transfer_information;
char *content_type;
};
BELLE_SIP_DECLARE_VPTR(LinphoneChatMessage);
......@@ -700,6 +702,7 @@ struct _LinphoneCore
belle_tls_verify_policy_t *http_verify_policy;
MSList *tones;
LinphoneReason chat_deny_code;
char *file_transfer_server;
};
......
......@@ -233,6 +233,7 @@ typedef struct SalMessage{
const char *text;
const char *url;
const char *message_id;
const char *content_type;
time_t time;
}SalMessage;
......
mediastreamer2 @ fc3a434d
Subproject commit 77022250a04459648101c3b4152d83158bbe0e63
Subproject commit fc3a434df7845f20e0fc3415f25bbad4598fe3be
oRTP @ c93363ac
Subproject commit 519fabfed1b38c9cde977d4c7a8a7c2bb642e0cb
Subproject commit c93363ac023c2122bfdfb8b0d99b811dffbad827
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment