From 99d617c3aea8f5fe39dd621c6747d60353e5a763 Mon Sep 17 00:00:00 2001 From: Slava Monich Date: Mon, 14 Mar 2016 00:06:04 +0200 Subject: [PATCH] [mms-engine] Added transfer progress API. Contributes to JB#34534 --- mms-engine/Makefile | 32 +- mms-engine/mms-engine.pro | 4 + mms-engine/mms_engine.c | 5 +- mms-lib/Makefile | 1 + mms-lib/include/mms_dispatcher.h | 6 +- mms-lib/include/mms_lib_log.h | 3 +- mms-lib/include/mms_lib_types.h | 1 + mms-lib/include/mms_transfer_list.h | 98 ++++ mms-lib/mms-lib.pro | 4 +- mms-lib/src/mms_dispatcher.c | 20 +- mms-lib/src/mms_task.h | 20 +- mms-lib/src/mms_task_ack.c | 6 +- mms-lib/src/mms_task_decode.c | 14 +- mms-lib/src/mms_task_encode.c | 46 +- mms-lib/src/mms_task_http.c | 176 +++++-- mms-lib/src/mms_task_http.h | 5 +- mms-lib/src/mms_task_notification.c | 16 +- mms-lib/src/mms_task_notifyresp.c | 8 +- mms-lib/src/mms_task_read.c | 4 +- mms-lib/src/mms_task_retrieve.c | 13 +- mms-lib/src/mms_task_send.c | 12 +- mms-lib/src/mms_transfer_list.c | 130 ++++++ mms-lib/test/common/test_transfer_list.c | 105 +++++ mms-lib/test/common/test_transfer_list.h | 24 + mms-lib/test/test_delivery_ind/Makefile | 3 +- .../test_delivery_ind/test_delivery_ind.c | 6 +- mms-lib/test/test_read_ind/Makefile | 3 +- mms-lib/test/test_read_ind/test_read_ind.c | 6 +- mms-lib/test/test_read_report/Makefile | 2 +- .../test/test_read_report/test_read_report.c | 2 +- mms-lib/test/test_retrieve/Makefile | 2 +- mms-lib/test/test_retrieve/test_retrieve.c | 6 +- mms-lib/test/test_retrieve_cancel/Makefile | 2 +- .../test_retrieve_cancel.c | 5 +- mms-lib/test/test_retrieve_no_proxy/Makefile | 2 +- .../test_retrieve_no_proxy.c | 6 +- mms-lib/test/test_retrieve_order/Makefile | 2 +- .../test_retrieve_order/test_retrieve_order.c | 2 +- mms-lib/test/test_send/Makefile | 2 +- mms-lib/test/test_send/test_send.c | 10 +- mms-transfer-list-dbus/Makefile | 126 +++++ .../include/mms_transfer_list_dbus.h | 33 ++ .../mms-transfer-list-dbus.pro | 47 ++ .../org.nemomobile.MmsEngine.TransferList.xml | 71 +++ .../src/mms_transfer_dbus.c | 435 ++++++++++++++++++ .../src/mms_transfer_dbus.h | 74 +++ .../src/mms_transfer_list_dbus.c | 321 +++++++++++++ .../src/mms_transfer_list_dbus_log.h | 31 ++ mms.pro | 1 + 49 files changed, 1818 insertions(+), 135 deletions(-) create mode 100644 mms-lib/include/mms_transfer_list.h create mode 100644 mms-lib/src/mms_transfer_list.c create mode 100644 mms-lib/test/common/test_transfer_list.c create mode 100644 mms-lib/test/common/test_transfer_list.h create mode 100644 mms-transfer-list-dbus/Makefile create mode 100644 mms-transfer-list-dbus/include/mms_transfer_list_dbus.h create mode 100644 mms-transfer-list-dbus/mms-transfer-list-dbus.pro create mode 100644 mms-transfer-list-dbus/spec/org.nemomobile.MmsEngine.TransferList.xml create mode 100644 mms-transfer-list-dbus/src/mms_transfer_dbus.c create mode 100644 mms-transfer-list-dbus/src/mms_transfer_dbus.h create mode 100644 mms-transfer-list-dbus/src/mms_transfer_list_dbus.c create mode 100644 mms-transfer-list-dbus/src/mms_transfer_list_dbus_log.h diff --git a/mms-engine/Makefile b/mms-engine/Makefile index 99b7857..cfd095e 100644 --- a/mms-engine/Makefile +++ b/mms-engine/Makefile @@ -4,6 +4,7 @@ .PHONY: mms_lib_debug_lib mms_lib_release_lib .PHONY: mms_connman_debug_lib mms_connman_release_lib .PHONY: mms_handler_debug_lib mms_handler_release_lib +.PHONY: mms_transfers_debug_lib mms_transfers_release_lib .PHONY: mms_settings_debug_lib mms_settings_release_lib # @@ -84,6 +85,16 @@ MMS_HANDLER_BUILD_DIR = $(MMS_HANDLER_DIR)/build MMS_HANDLER_DEBUG_LIB = $(MMS_HANDLER_BUILD_DIR)/debug/$(MMS_HANDLER_LIB) MMS_HANDLER_RELEASE_LIB = $(MMS_HANDLER_BUILD_DIR)/release/$(MMS_HANDLER_LIB) +# +# mms-transfer-list-dbus +# + +MMS_TRANSFERS_LIB = libmms-transfer-list-dbus.a +MMS_TRANSFERS_DIR = ../mms-transfer-list-dbus +MMS_TRANSFERS_BUILD_DIR = $(MMS_TRANSFERS_DIR)/build +MMS_TRANSFERS_DEBUG_LIB = $(MMS_TRANSFERS_BUILD_DIR)/debug/$(MMS_TRANSFERS_LIB) +MMS_TRANSFERS_RELEASE_LIB = $(MMS_TRANSFERS_BUILD_DIR)/release/$(MMS_TRANSFERS_LIB) + # # mms-settings-dconf # @@ -108,8 +119,8 @@ WARN = -Wall BASE_FLAGS = -fPIC $(CFLAGS) FULL_CFLAGS = $(BASE_FLAGS) -I. -I$(GEN_DIR) -I$(MMS_LIB_DIR)/include \ -I$(MMS_CONNMAN_DIR)/include -I$(MMS_HANDLER_DIR)/include \ - -I$(MMS_SETTINGS_DIR)/include -MMD -MP \ - $(shell pkg-config --cflags $(PKGS)) + -I$(MMS_SETTINGS_DIR)/include -I$(MMS_TRANSFERS_DIR)/include \ + -MMD -MP $(shell pkg-config --cflags $(PKGS)) ifndef KEEP_SYMBOLS KEEP_SYMBOLS = 0 @@ -137,12 +148,14 @@ LIBS = $(shell pkg-config --libs $(LIB_PKGS)) -lmagic -ljpeg $(RESIZE_LIBS) DEBUG_LIBS = \ $(MMS_CONNMAN_DEBUG_LIB) \ $(MMS_HANDLER_DEBUG_LIB) \ + $(MMS_TRANSFERS_DEBUG_LIB) \ $(MMS_SETTINGS_DEBUG_LIB) \ $(MMS_LIB_DEBUG_LIB) \ $(LIBS) RELEASE_LIBS = \ $(MMS_CONNMAN_RELEASE_LIB) \ $(MMS_HANDLER_RELEASE_LIB) \ + $(MMS_TRANSFERS_RELEASE_LIB) \ $(MMS_SETTINGS_RELEASE_LIB) \ $(MMS_LIB_RELEASE_LIB) \ $(LIBS) @@ -168,21 +181,25 @@ DEBUG_DEPS = \ mms_lib_debug_lib \ mms_connman_debug_lib \ mms_handler_debug_lib \ + mms_transfers_debug_lib \ mms_settings_debug_lib RELEASE_DEPS = \ mms_lib_release_lib \ mms_connman_release_lib \ mms_handler_release_lib \ + mms_transfers_release_lib \ mms_settings_release_lib DEBUG_EXE_DEPS = \ $(MMS_LIB_DEBUG_LIB) \ $(MMS_CONNMAN_DEBUG_LIB) \ $(MMS_HANDLER_DEBUG_LIB) \ + $(MMS_TRANSFERS_DEBUG_LIB) \ $(MMS_SETTINGS_DEBUG_LIB) RELEASE_EXE_DEPS = \ $(MMS_LIB_RELEASE_LIB) \ $(MMS_CONNMAN_RELEASE_LIB) \ $(MMS_HANDLER_RELEASE_LIB) \ + $(MMS_TRANSFERS_RELEASE_LIB) \ $(MMS_SETTINGS_RELEASE_LIB) DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d) ifneq ($(MAKECMDGOALS),clean) @@ -214,6 +231,7 @@ cleaner: clean make -C $(MMS_LIB_DIR) $(SUBMAKE_OPTS) clean make -C $(MMS_CONNMAN_DIR) $(SUBMAKE_OPTS) clean make -C $(MMS_HANDLER_DIR) $(SUBMAKE_OPTS) clean + make -C $(MMS_TRANSFERS_DIR) $(SUBMAKE_OPTS) clean make -C $(MMS_SETTINGS_DIR) $(SUBMAKE_OPTS) clean $(GEN_DIR): @@ -243,6 +261,12 @@ mms_handler_debug_lib: mms_handler_release_lib: make -C $(MMS_HANDLER_DIR) $(SUBMAKE_OPTS) release +mms_transfers_debug_lib: + make -C $(MMS_TRANSFERS_DIR) $(SUBMAKE_OPTS) debug + +mms_transfers_release_lib: + make -C $(MMS_TRANSFERS_DIR) $(SUBMAKE_OPTS) release + mms_settings_debug_lib: make -C $(MMS_SETTINGS_DIR) $(SUBMAKE_OPTS) debug @@ -261,6 +285,10 @@ $(MMS_HANDLER_DEBUG_LIB): mms_handler_debug_lib $(MMS_HANDLER_RELEASE_LIB): mms_handler_release_lib +$(MMS_TRANSFERS_DEBUG_LIB): mms_transfers_debug_lib + +$(MMS_TRANSFERS_RELEASE_LIB): mms_transfers_release_lib + $(MMS_SETTINGS_DEBUG_LIB): mms_settings_debug_lib $(MMS_SETTINGS_RELEASE_LIB): mms_settings_release_lib diff --git a/mms-engine/mms-engine.pro b/mms-engine/mms-engine.pro index b58aa37..d05067a 100644 --- a/mms-engine/mms-engine.pro +++ b/mms-engine/mms-engine.pro @@ -23,12 +23,14 @@ DBUS_INTERFACE_DIR = $$_PRO_FILE_PWD_ MMS_LIB_DIR = $$_PRO_FILE_PWD_/../mms-lib MMS_HANDLER_DIR = $$_PRO_FILE_PWD_/../mms-handler-dbus MMS_SETTINGS_DIR = $$_PRO_FILE_PWD_/../mms-settings-dconf +MMS_TRANSFER_LIST_DIR = $$_PRO_FILE_PWD_/../mms-transfer-list-dbus MMS_CONNMAN_DIR = $$_PRO_FILE_PWD_/../$$MMS_CONNMAN INCLUDEPATH += $$MMS_LIB_DIR/include INCLUDEPATH += $$MMS_HANDLER_DIR/include INCLUDEPATH += $$MMS_SETTINGS_DIR/include INCLUDEPATH += $$MMS_CONNMAN_DIR/include +INCLUDEPATH += $$MMS_TRANSFER_LIST_DIR/include SOURCES += \ main.c \ @@ -47,12 +49,14 @@ CONFIG(debug, debug|release) { DESTDIR = $$_PRO_FILE_PWD_/build/debug LIBS += $$MMS_CONNMAN_DIR/build/debug/lib$${MMS_CONNMAN}.a LIBS += $$MMS_HANDLER_DIR/build/debug/libmms-handler-dbus.a + LIBS += $$MMS_TRANSFER_LIST_DIR/build/debug/libmms-transfer-list-dbus.a LIBS += $$MMS_LIB_DIR/build/debug/libmms-lib.a LIBS += $$MMS_SETTINGS_DIR/build/debug/libmms-settings-dconf.a } else { DESTDIR = $$_PRO_FILE_PWD_/build/release LIBS += $$MMS_CONNMAN_DIR/build/release/lib$${MMS_CONNMAN}.a LIBS += $$MMS_HANDLER_DIR/build/release/libmms-handler-dbus.a + LIBS += $$MMS_TRANSFER_LIST_DIR/build/release/libmms-transfer-list-dbus.a LIBS += $$MMS_LIB_DIR/build/release/libmms-lib.a LIBS += $$MMS_SETTINGS_DIR/build/release/libmms-settings-dconf.a } diff --git a/mms-engine/mms_engine.c b/mms-engine/mms_engine.c index d382d65..b768694 100644 --- a/mms-engine/mms_engine.c +++ b/mms-engine/mms_engine.c @@ -19,6 +19,7 @@ #include "mms_lib_util.h" #include "mms_handler_dbus.h" #include "mms_settings_dconf.h" +#include "mms_transfer_list_dbus.h" #include "mms_log.h" #include @@ -472,6 +473,7 @@ mms_engine_new( MMSEngine* mms = g_object_new(MMS_TYPE_ENGINE, NULL); MMSHandler* handler = mms_handler_dbus_new(); MMSSettings* settings = mms_settings_dconf_new(config); + MMSTransferList* txlist = mms_transfer_list_dbus_new(); if (flags & MMS_ENGINE_FLAG_OVERRIDE_USER_AGENT) { settings->flags |= MMS_SETTINGS_FLAG_OVERRIDE_USER_AGENT; @@ -494,8 +496,9 @@ mms_engine_new( settings->sim_defaults.data.max_pixels = override->max_pixels; } - mms->dispatcher = mms_dispatcher_new(settings, cm, handler); + mms->dispatcher = mms_dispatcher_new(settings, cm, handler, txlist); mms_handler_unref(handler); + mms_transfer_list_unref(txlist); mms_dispatcher_set_delegate(mms->dispatcher, &mms->dispatcher_delegate); diff --git a/mms-lib/Makefile b/mms-lib/Makefile index b2c4f3a..c24b820 100644 --- a/mms-lib/Makefile +++ b/mms-lib/Makefile @@ -49,6 +49,7 @@ SRC = \ mms_task_read.c \ mms_task_retrieve.c \ mms_task_send.c \ + mms_transfer_list.c \ mms_util.c ifeq ($(MMS_RESIZE),Qt) diff --git a/mms-lib/include/mms_dispatcher.h b/mms-lib/include/mms_dispatcher.h index 496ef0d..9cfa26f 100644 --- a/mms-lib/include/mms_dispatcher.h +++ b/mms-lib/include/mms_dispatcher.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. + * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -30,7 +31,8 @@ MMSDispatcher* mms_dispatcher_new( MMSSettings* settings, MMSConnMan* cm, - MMSHandler* handler); + MMSHandler* handler, + MMSTransferList* transfers); MMSDispatcher* mms_dispatcher_ref( diff --git a/mms-lib/include/mms_lib_log.h b/mms-lib/include/mms_lib_log.h index d9e5dcb..8099898 100644 --- a/mms-lib/include/mms_lib_log.h +++ b/mms-lib/include/mms_lib_log.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2015 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify @@ -21,6 +21,7 @@ #define MMS_LIB_LOG_MODULES(log) \ log(mms_dispatcher_log)\ log(mms_settings_log)\ + log(mms_transfer_list_log)\ log(mms_handler_log)\ log(mms_message_log)\ log(mms_attachment_log)\ diff --git a/mms-lib/include/mms_lib_types.h b/mms-lib/include/mms_lib_types.h index dbaa190..74484b7 100644 --- a/mms-lib/include/mms_lib_types.h +++ b/mms-lib/include/mms_lib_types.h @@ -60,6 +60,7 @@ typedef struct mms_handler MMSHandler; typedef struct mms_connman MMSConnMan; typedef struct mms_dispatcher MMSDispatcher; typedef struct mms_connection MMSConnection; +typedef struct mms_transfer_list MMSTransferList; typedef struct mms_message MMSPdu; typedef struct _mms_message MMSMessage; typedef struct _mms_attachment MMSAttachment; diff --git a/mms-lib/include/mms_transfer_list.h b/mms-lib/include/mms_transfer_list.h new file mode 100644 index 0000000..a7b5d73 --- /dev/null +++ b/mms-lib/include/mms_transfer_list.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2016 Jolla Ltd. + * Contact: Slava Monich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef JOLLA_MMS_TRANSFER_LIST_H +#define JOLLA_MMS_TRANSFER_LIST_H + +#include "mms_message.h" + +/* Instance */ +struct mms_transfer_list { + GObject object; +}; + +/* Class */ +typedef struct mms_transfer_list_class { + GObjectClass parent; + void (*fn_transfer_started)( + MMSTransferList* list, /* Instance */ + char* id, /* Message ID */ + char* type); /* Transfer type */ + void (*fn_transfer_finished)( + MMSTransferList* list, /* Instance */ + char* id, /* Message ID */ + char* type); /* Transfer type */ + void (*fn_send_progress)( + MMSTransferList* list, /* Instance */ + char* id, /* Message ID */ + char* type, /* Transfer type */ + guint bytes_sent, /* Bytes sent so far */ + guint bytes_total); /* Total bytes to send */ + void (*fn_receive_progress)( + MMSTransferList* list, /* Instance */ + char* id, /* Message ID */ + char* type, /* Transfer type */ + guint bytes_received, /* Bytes received so far */ + guint bytes_total); /* Total bytes to receive*/ +} MMSTransferListClass; + +GType mms_transfer_list_get_type(void); +#define MMS_TYPE_TRANSFER_LIST (mms_transfer_list_get_type()) + +MMSTransferList* +mms_transfer_list_ref( + MMSTransferList* list); + +void +mms_transfer_list_unref( + MMSTransferList* list); + +void +mms_transfer_list_transfer_started( + MMSTransferList* list, /* Instance */ + char* id, /* Message ID */ + char* type); /* Transfer type */ + +void +mms_transfer_list_transfer_finished( + MMSTransferList* list, /* Instance */ + char* id, /* Message ID */ + char* type); /* Transfer type */ + +void +mms_transfer_list_transfer_send_progress( + MMSTransferList* list, /* Instance */ + char* id, /* Message ID */ + char* type, /* Transfer type */ + guint bytes_sent, /* Bytes sent so far */ + guint bytes_total); /* Total bytes to send */ + +void +mms_transfer_list_transfer_receive_progress( + MMSTransferList* list, /* Instance */ + char* id, /* Message ID */ + char* type, /* Transfer type */ + guint bytes_received, /* Bytes received so far */ + guint bytes_total); /* Total bytes to receive*/ + +#endif /* JOLLA_MMS_TRANSFER_LIST_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/mms-lib.pro b/mms-lib/mms-lib.pro index 4b67e78..299165b 100644 --- a/mms-lib/mms-lib.pro +++ b/mms-lib/mms-lib.pro @@ -50,6 +50,7 @@ SOURCES += \ src/mms_task_read.c \ src/mms_task_retrieve.c \ src/mms_task_send.c \ + src/mms_transfer_list.c \ src/mms_util.c HEADERS += \ @@ -72,4 +73,5 @@ HEADERS += \ include/mms_lib_util.h \ include/mms_log.h \ include/mms_message.h \ - include/mms_settings.h + include/mms_settings.h \ + include/mms_transfer_list.h diff --git a/mms-lib/src/mms_dispatcher.c b/mms-lib/src/mms_dispatcher.c index e588aaf..fb73de5 100644 --- a/mms-lib/src/mms_dispatcher.c +++ b/mms-lib/src/mms_dispatcher.c @@ -18,6 +18,7 @@ #include "mms_settings.h" #include "mms_connection.h" #include "mms_connman.h" +#include "mms_transfer_list.h" #include "mms_file_util.h" #include "mms_codec.h" #include "mms_util.h" @@ -39,6 +40,7 @@ struct mms_dispatcher { MMSHandler* handler; MMSConnMan* cm; MMSConnection* connection; + MMSTransferList* transfers; MMSDispatcherDelegate* delegate; GQueue* tasks; guint next_run_id; @@ -570,7 +572,7 @@ mms_dispatcher_handle_push( { return mms_dispatcher_queue_and_unref_task(disp, mms_task_notification_new(disp->settings, disp->handler, - imsi, push, error)); + disp->transfers, imsi, push, error)); } /** @@ -593,8 +595,9 @@ mms_dispatcher_receive_message( const MMSConfig* config = disp->settings->config; ok = mms_dispatcher_queue_and_unref_task(disp, mms_task_retrieve_new(disp->settings, disp->handler, - id, imsi, pdu, automatic ? MMS_CONNECTION_TYPE_AUTO : - MMS_CONNECTION_TYPE_USER, error)); + disp->transfers, id, imsi, pdu, automatic ? + MMS_CONNECTION_TYPE_AUTO : MMS_CONNECTION_TYPE_USER, + error)); if (config->keep_temp_files) { char* dir = mms_message_dir(config, id); mms_write_bytes(dir, MMS_NOTIFICATION_IND_FILE, bytes, NULL); @@ -624,7 +627,7 @@ mms_dispatcher_send_read_report( GError** error) { return mms_dispatcher_queue_and_unref_task(disp, - mms_task_read_new(disp->settings, disp->handler, + mms_task_read_new(disp->settings, disp->handler, disp->transfers, id, imsi, message_id, to, status, error)); } @@ -652,8 +655,8 @@ mms_dispatcher_send_message( } if (imsi) { if (mms_dispatcher_queue_and_unref_task(disp, - mms_task_encode_new(disp->settings, disp->handler, id, imsi, - to, cc, bcc, subject, flags, parts, nparts, error))) { + mms_task_encode_new(disp->settings, disp->handler, disp->transfers, + id, imsi, to, cc, bcc, subject, flags, parts, nparts, error))) { return default_imsi ? default_imsi : g_strdup(imsi); } } else { @@ -754,7 +757,8 @@ MMSDispatcher* mms_dispatcher_new( MMSSettings* settings, MMSConnMan* cm, - MMSHandler* handler) + MMSHandler* handler, + MMSTransferList* transfers) { MMSDispatcher* disp = g_new0(MMSDispatcher, 1); disp->ref_count = 1; @@ -762,6 +766,7 @@ mms_dispatcher_new( disp->tasks = g_queue_new(); disp->handler = mms_handler_ref(handler); disp->cm = mms_connman_ref(cm); + disp->transfers = mms_transfer_list_ref(transfers); disp->task_delegate.fn_task_queue = mms_dispatcher_delegate_task_queue; disp->task_delegate.fn_task_state_changed = @@ -794,6 +799,7 @@ mms_dispatcher_finalize( mms_task_unref(task); } g_queue_free(disp->tasks); + mms_transfer_list_unref(disp->transfers); mms_settings_unref(disp->settings); mms_handler_unref(disp->handler); mms_connman_unref(disp->cm); diff --git a/mms-lib/src/mms_task.h b/mms-lib/src/mms_task.h index bca15cd..49aa1d9 100644 --- a/mms-lib/src/mms_task.h +++ b/mms-lib/src/mms_task.h @@ -37,6 +37,16 @@ typedef enum _MMS_TASK_STATE { MMS_TASK_STATE_COUNT /* Number of valid states */ } MMS_TASK_STATE; +/* + * Transfer types which double as task names. These are part of the D-Bus API, + * don't change them just because you don't like them + */ +#define MMS_TRANSFER_TYPE_ACK "Ack" +#define MMS_TRANSFER_TYPE_NOTIFY_RESP "NotifyResp" +#define MMS_TRANSFER_TYPE_READ_REPORT "ReadReport" +#define MMS_TRANSFER_TYPE_RETRIEVE "Retrieve" +#define MMS_TRANSFER_TYPE_SEND "Send" + /* Task priority */ typedef enum _MMS_TASK_PRIORITY { MMS_TASK_PRIORITY_NORMAL, /* Default priority */ @@ -176,6 +186,7 @@ MMSTask* mms_task_notification_new( MMSSettings* settings, MMSHandler* handler, + MMSTransferList* transfers, const char* imsi, GBytes* bytes, GError** error); @@ -184,6 +195,7 @@ MMSTask* mms_task_retrieve_new( MMSSettings* settings, MMSHandler* handler, + MMSTransferList* transfers, const char* id, const char* imsi, const MMSPdu* pdu, @@ -193,24 +205,28 @@ mms_task_retrieve_new( MMSTask* mms_task_decode_new( MMSTask* parent, + MMSTransferList* transfers, const char* transaction_id, const char* file); MMSTask* mms_task_notifyresp_new( MMSTask* parent, + MMSTransferList* transfers, const char* transaction_id, MMSNotifyStatus status); MMSTask* mms_task_ack_new( MMSTask* parent, + MMSTransferList* transfers, const char* transaction_id); MMSTask* mms_task_read_new( MMSSettings* settings, MMSHandler* handler, + MMSTransferList* transfers, const char* id, const char* imsi, const char* message_id, @@ -228,6 +244,7 @@ MMSTask* mms_task_encode_new( MMSSettings* settings, MMSHandler* handler, + MMSTransferList* transfers, const char* id, const char* imsi, const char* to, @@ -241,7 +258,8 @@ mms_task_encode_new( MMSTask* mms_task_send_new( - MMSTask* parent); + MMSTask* parent, + MMSTransferList* transfers); #endif /* JOLLA_MMS_TASK_H */ diff --git a/mms-lib/src/mms_task_ack.c b/mms-lib/src/mms_task_ack.c index 24e0cae..b9ed5d6 100644 --- a/mms-lib/src/mms_task_ack.c +++ b/mms-lib/src/mms_task_ack.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2013-2016 Jolla Ltd. + * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -49,14 +50,15 @@ mms_task_ack_encode( MMSTask* mms_task_ack_new( MMSTask* parent, + MMSTransferList* transfers, const char* tx_id) { MMSTask* task = NULL; const char* file = mms_task_ack_encode(task_config(parent), mms_task_sim_settings(parent), parent->id, tx_id); if (file) { - task = mms_task_http_alloc_with_parent(0, parent, "Ack", - NULL, NULL, file); + task = mms_task_http_alloc_with_parent(0, parent, transfers, + MMS_TRANSFER_TYPE_ACK, NULL, NULL, file); task->priority = MMS_TASK_PRIORITY_POST_PROCESS; } return task; diff --git a/mms-lib/src/mms_task_decode.c b/mms-lib/src/mms_task_decode.c index 5d92f85..be32256 100644 --- a/mms-lib/src/mms_task_decode.c +++ b/mms-lib/src/mms_task_decode.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2015 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify @@ -19,6 +19,7 @@ #include "mms_handler.h" #include "mms_message.h" #include "mms_file_util.h" +#include "mms_transfer_list.h" /* Logging */ #define MMS_LOG_MODULE_NAME mms_task_decode_log @@ -29,12 +30,13 @@ MMS_LOG_MODULE_DEFINE2("mms-task-decode", MMS_TASK_LOG); typedef MMSTaskClass MMSTaskDecodeClass; typedef struct mms_task_decode { MMSTask task; + MMSTransferList* transfers; GMappedFile* map; char* transaction_id; char* file; } MMSTaskDecode; -G_DEFINE_TYPE(MMSTaskDecode, mms_task_decode, MMS_TYPE_TASK); +G_DEFINE_TYPE(MMSTaskDecode, mms_task_decode, MMS_TYPE_TASK) #define MMS_TYPE_TASK_DECODE (mms_task_decode_get_type()) #define MMS_TASK_DECODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ MMS_TYPE_TASK_DECODE, MMSTaskDecode)) @@ -268,7 +270,8 @@ mms_task_decode_process_pdu( if (msg) { /* Successfully received and decoded MMS message */ mms_task_queue_and_unref(task->delegate, - mms_task_ack_new(task, dec->transaction_id)); + mms_task_ack_new(task, dec->transfers, + dec->transaction_id)); mms_task_queue_and_unref(task->delegate, mms_task_publish_new(task->settings, task->handler, msg)); @@ -293,7 +296,7 @@ mms_task_decode_process_pdu( /* Tell MMS server that we didn't understand this PDU */ mms_task_queue_and_unref(task->delegate, - mms_task_notifyresp_new(task, dec->transaction_id, + mms_task_notifyresp_new(task, dec->transfers, dec->transaction_id, MMS_MESSAGE_NOTIFY_STATUS_UNRECOGNISED)); mms_handler_message_receive_state_changed(task->handler, task->id, MMS_RECEIVE_STATE_DECODING_ERROR); @@ -319,6 +322,7 @@ mms_task_decode_finalize( if (!task_config(&dec->task)->keep_temp_files) { mms_remove_file_and_dir(dec->file); } + mms_transfer_list_unref(dec->transfers); g_mapped_file_unref(dec->map); g_free(dec->transaction_id); g_free(dec->file); @@ -345,6 +349,7 @@ mms_task_decode_init( MMSTask* mms_task_decode_new( MMSTask* parent, + MMSTransferList* transfers, const char* transaction_id, const char* file) { @@ -355,6 +360,7 @@ mms_task_decode_new( GError* error = NULL; dec->map = g_mapped_file_new(file, FALSE, &error); if (dec->map) { + dec->transfers = mms_transfer_list_ref(transfers); dec->transaction_id = g_strdup(transaction_id); dec->file = g_strdup(file); dec->task.priority = MMS_TASK_PRIORITY_POST_PROCESS; diff --git a/mms-lib/src/mms_task_encode.c b/mms-lib/src/mms_task_encode.c index 67e038f..0c66a63 100644 --- a/mms-lib/src/mms_task_encode.c +++ b/mms-lib/src/mms_task_encode.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2015 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify @@ -19,6 +19,7 @@ #include "mms_settings.h" #include "mms_handler.h" #include "mms_file_util.h" +#include "mms_transfer_list.h" #include "mms_util.h" #include "mms_codec.h" @@ -43,6 +44,7 @@ typedef struct mms_task_encode { MMSAttachment** parts; int nparts; MMSEncodeJob* active_job; + MMSTransferList* transfers; } MMSTaskEncode; G_DEFINE_TYPE(MMSTaskEncode, mms_task_encode, MMS_TYPE_TASK); @@ -322,7 +324,8 @@ mms_task_encode_job_done( MMS_VERBOSE_("Encoding completion state %d", job->state); enc->active_job = NULL; if (job->state == MMS_ENCODE_STATE_DONE) { - mms_task_queue_and_unref(task->delegate, mms_task_send_new(task)); + mms_task_queue_and_unref(task->delegate, + mms_task_send_new(task, enc->transfers)); } else { mms_handler_message_send_state_changed(task->handler, task->id, (job->state == MMS_ENCODE_STATE_TOO_BIG) ? @@ -376,24 +379,6 @@ mms_task_encode_cancel( MMS_TASK_CLASS(mms_task_encode_parent_class)->fn_cancel(task); } -static -void -mms_task_encode_finalize( - GObject* object) -{ - MMSTaskEncode* enc = MMS_TASK_ENCODE(object); - if (enc->parts) { - int i; - for (i=0; inparts; i++) mms_attachment_unref(enc->parts[i]); - g_free(enc->parts); - } - g_free(enc->to); - g_free(enc->cc); - g_free(enc->bcc); - g_free(enc->subject); - G_OBJECT_CLASS(mms_task_encode_parent_class)->finalize(object); -} - static char* mms_task_encode_generate_path( @@ -562,6 +547,25 @@ mms_task_encode_prepare_address_list( return NULL; } +static +void +mms_task_encode_finalize( + GObject* object) +{ + MMSTaskEncode* enc = MMS_TASK_ENCODE(object); + if (enc->parts) { + int i; + for (i=0; inparts; i++) mms_attachment_unref(enc->parts[i]); + g_free(enc->parts); + } + g_free(enc->to); + g_free(enc->cc); + g_free(enc->bcc); + g_free(enc->subject); + mms_transfer_list_unref(enc->transfers); + G_OBJECT_CLASS(mms_task_encode_parent_class)->finalize(object); +} + static void mms_task_encode_class_init( @@ -584,6 +588,7 @@ MMSTask* mms_task_encode_new( MMSSettings* settings, MMSHandler* handler, + MMSTransferList* transfers, const char* id, const char* imsi, const char* to, @@ -617,6 +622,7 @@ mms_task_encode_new( enc->bcc = mms_task_encode_prepare_address_list(bcc); enc->subject = g_strdup(subject); enc->flags = flags; + enc->transfers = mms_transfer_list_ref(transfers); MMS_ASSERT(!error || !*error); g_free(dir); diff --git a/mms-lib/src/mms_task_http.c b/mms-lib/src/mms_task_http.c index e7e6bd7..dcc98b8 100644 --- a/mms-lib/src/mms_task_http.c +++ b/mms-lib/src/mms_task_http.c @@ -17,6 +17,9 @@ #include "mms_connection.h" #include "mms_settings.h" #include "mms_file_util.h" +#include "mms_transfer_list.h" + +#include #ifndef _WIN32 # include @@ -44,6 +47,15 @@ typedef enum _mms_http_state { #define MMS_HTTP_MAX_CHUNK (4046) +/* Soup message signals */ +enum mms_http_soup_message_signals { + MMS_SOUP_MESSAGE_SIGNAL_WROTE_HEADERS, + MMS_SOUP_MESSAGE_SIGNAL_WROTE_CHUNK, + MMS_SOUP_MESSAGE_SIGNAL_GOT_HEADERS, + MMS_SOUP_MESSAGE_SIGNAL_GOT_CHUNK, + MMS_SOUP_MESSAGE_SIGNAL_COUNT +}; + /* Transfer context */ typedef struct mms_http_transfer { MMSConnection* connection; @@ -51,6 +63,11 @@ typedef struct mms_http_transfer { SoupMessage* message; int receive_fd; int send_fd; + guint bytes_sent; + guint bytes_received; + guint bytes_to_send; + guint bytes_to_receive; + gulong msg_signal_id[MMS_SOUP_MESSAGE_SIGNAL_COUNT]; } MMSHttpTransfer; /* Private state */ @@ -59,12 +76,8 @@ struct mms_task_http_priv { char* uri; char* send_path; char* receive_path; - const char* receive_file; - gulong wrote_headers_signal_id; - gulong wrote_chunk_signal_id; - gulong got_chunk_signal_id; - gsize bytes_sent; - guint bytes_received; + char* receive_file; + char* transfer_type; MMS_HTTP_STATE transaction_state; MMS_CONNECTION_TYPE connection_type; }; @@ -184,7 +197,7 @@ mms_http_transfer_new( { SoupURI* soup_uri = mms_http_uri_parse(uri); if (soup_uri) { - MMSHttpTransfer* tx = g_new(MMSHttpTransfer, 1); + MMSHttpTransfer* tx = g_new0(MMSHttpTransfer, 1); tx->session = mms_http_create_session(cfg, connection); tx->message = soup_message_new_from_uri(method, soup_uri); tx->connection = mms_connection_ref(connection); @@ -211,6 +224,8 @@ mms_http_transfer_free( MMSHttpTransfer* tx) { if (tx) { + gutil_disconnect_handlers(tx->message, tx->msg_signal_id, + G_N_ELEMENTS(tx->msg_signal_id)); soup_session_abort(tx->session); g_object_unref(tx->session); g_object_unref(tx->message); @@ -221,6 +236,36 @@ mms_http_transfer_free( } } +static +void +mms_task_http_send_progress( + MMSTaskHttp* http) +{ + MMSTaskHttpPriv* priv = http->priv; + MMSHttpTransfer* tx = priv->tx; + if (tx) { + MMS_ASSERT(tx->bytes_sent <= tx->bytes_to_send); + mms_transfer_list_transfer_send_progress(http->transfers, + http->task.id, priv->transfer_type, tx->bytes_sent, + tx->bytes_to_send); + } +} + +static +void +mms_task_http_receive_progress( + MMSTaskHttp* http) +{ + MMSTaskHttpPriv* priv = http->priv; + MMSHttpTransfer* tx = priv->tx; + if (tx) { + MMS_ASSERT(tx->bytes_received <= tx->bytes_to_receive); + mms_transfer_list_transfer_receive_progress(http->transfers, + http->task.id, priv->transfer_type, tx->bytes_received, + tx->bytes_to_receive); + } +} + static void mms_task_http_set_state( @@ -232,6 +277,20 @@ mms_task_http_set_state( if (priv->transaction_state != new_state && priv->transaction_state != MMS_HTTP_DONE) { MMSTaskHttpClass* klass = MMS_TASK_HTTP_GET_CLASS(http); + const gboolean is_active = (new_state == MMS_HTTP_ACTIVE); + + /* Notify interested parties about transfer state changes */ + if (is_active != (priv->transaction_state == MMS_HTTP_ACTIVE)) { + if (is_active) { + mms_transfer_list_transfer_started(http->transfers, + http->task.id, priv->transfer_type); + mms_task_http_send_progress(http); + } else { + mms_transfer_list_transfer_finished(http->transfers, + http->task.id, priv->transfer_type); + } + } + priv->transaction_state = new_state; switch (new_state) { case MMS_HTTP_ACTIVE: @@ -256,19 +315,6 @@ mms_task_http_finish_transfer( { MMSTaskHttpPriv* priv = http->priv; if (priv->tx) { - SoupMessage* msg = priv->tx->message; - if (priv->wrote_headers_signal_id) { - g_signal_handler_disconnect(msg, priv->wrote_headers_signal_id); - priv->wrote_headers_signal_id = 0; - } - if (priv->wrote_chunk_signal_id) { - g_signal_handler_disconnect(msg, priv->wrote_chunk_signal_id); - priv->wrote_chunk_signal_id = 0; - } - if (priv->got_chunk_signal_id) { - g_signal_handler_disconnect(msg, priv->got_chunk_signal_id); - priv->got_chunk_signal_id = 0; - } mms_http_transfer_free(priv->tx); priv->tx = NULL; } @@ -286,13 +332,14 @@ mms_task_http_finished( if (priv->tx && priv->tx->session == session) { MMS_HTTP_STATE next_http_state; MMSTask* task = &http->task; + MMSHttpTransfer* tx = priv->tx; SoupStatus http_status = msg->status_code; #if MMS_LOG_DEBUG - if (priv->bytes_received) { + if (tx->bytes_received) { MMS_DEBUG("HTTP status %u [%s] %u byte(s)", msg->status_code, soup_message_headers_get_content_type(msg->response_headers, - NULL), priv->bytes_received); + NULL), tx->bytes_received); } else { MMS_DEBUG("HTTP status %u (%s)", msg->status_code, soup_status_get_phrase(msg->status_code)); @@ -334,15 +381,18 @@ mms_task_http_write_next_chunk( MMSTaskHttpPriv* priv = http->priv; MMSHttpTransfer* tx = priv->tx; #if MMS_LOG_VERBOSE - if (priv->bytes_sent) MMS_VERBOSE("%d bytes sent", (int)priv->bytes_sent); + if (tx->bytes_sent) { + MMS_VERBOSE("%u bytes sent", tx->bytes_sent); + } #endif MMS_ASSERT(tx && tx->message == msg); if (tx && tx->message == msg) { void* chunk = g_malloc(MMS_HTTP_MAX_CHUNK); int nbytes = read(tx->send_fd, chunk, MMS_HTTP_MAX_CHUNK); if (nbytes > 0) { - priv->bytes_sent += nbytes; + tx->bytes_sent += nbytes; soup_message_body_append_take(msg->request_body, chunk, nbytes); + mms_task_http_send_progress(http); return; } g_free(chunk); @@ -350,6 +400,28 @@ mms_task_http_write_next_chunk( soup_message_body_complete(msg->request_body); } +static +void +mms_task_http_got_headers( + SoupMessage* msg, + MMSTaskHttp* http) +{ + MMSTaskHttpPriv* priv = http->priv; + MMSHttpTransfer* tx = priv->tx; + MMS_ASSERT(tx && tx->message == msg); + if (tx && tx->message == msg) { + MMS_ASSERT(!tx->bytes_received); + tx->bytes_to_receive = (guint)soup_message_headers_get_content_length( + msg->response_headers); +#if MMS_LOG_VERBOSE + if (tx->bytes_to_receive) { + MMS_VERBOSE("Receiving %u bytes", tx->bytes_to_receive); + } +#endif + mms_task_http_receive_progress(http); + } +} + static void mms_task_http_got_chunk( @@ -361,9 +433,11 @@ mms_task_http_got_chunk( MMSHttpTransfer* tx = priv->tx; MMS_ASSERT(tx && tx->message == msg); if (tx && tx->message == msg) { - priv->bytes_received += buf->length; - MMS_VERBOSE("%u bytes received", priv->bytes_received); - if (write(tx->receive_fd, buf->data, buf->length) != (int)buf->length) { + tx->bytes_received += buf->length; + MMS_VERBOSE("%u bytes received", tx->bytes_received); + if (write(tx->receive_fd, buf->data, buf->length) == (int)buf->length) { + mms_task_http_receive_progress(http); + } else { MMS_ERR("Write error: %s", strerror(errno)); mms_task_http_finish_transfer(http); mms_task_http_set_state(http, MMS_HTTP_PAUSED, 0); @@ -384,7 +458,6 @@ mms_task_http_start( MMSTaskHttpPriv* priv = http->priv; MMS_ASSERT(mms_connection_is_open(connection)); mms_task_http_finish_transfer(http); - priv->bytes_sent = 0; /* Open the files */ if (priv->send_path) { @@ -426,11 +499,13 @@ mms_task_http_start( connection, priv->send_path ? SOUP_METHOD_POST : SOUP_METHOD_GET, uri, receive_fd, send_fd); if (priv->tx) { - SoupMessage* msg = priv->tx->message; + MMSHttpTransfer* tx = priv->tx; + SoupMessage* msg = tx->message; soup_message_body_set_accumulate(msg->response_body, FALSE); /* If we have data to send */ if (priv->send_path) { + tx->bytes_to_send = bytes_to_send; soup_message_headers_set_content_type( msg->request_headers, MMS_CONTENT_TYPE, NULL); @@ -439,18 +514,21 @@ mms_task_http_start( bytes_to_send); /* Connect the signals */ - priv->wrote_headers_signal_id = + tx->msg_signal_id[MMS_SOUP_MESSAGE_SIGNAL_WROTE_HEADERS] = g_signal_connect(msg, "wrote_headers", G_CALLBACK(mms_task_http_write_next_chunk), http); - priv->wrote_chunk_signal_id = + tx->msg_signal_id[MMS_SOUP_MESSAGE_SIGNAL_WROTE_CHUNK] = g_signal_connect(msg, "wrote_chunk", G_CALLBACK(mms_task_http_write_next_chunk), http); } /* If we expect to receive data */ if (priv->receive_path) { - priv->got_chunk_signal_id = - g_signal_connect(msg, "got-chunk", + tx->msg_signal_id[MMS_SOUP_MESSAGE_SIGNAL_GOT_HEADERS] = + g_signal_connect(msg, "got_headers", + G_CALLBACK(mms_task_http_got_headers), http); + tx->msg_signal_id[MMS_SOUP_MESSAGE_SIGNAL_GOT_CHUNK] = + g_signal_connect(msg, "got_chunk", G_CALLBACK(mms_task_http_got_chunk), http); } @@ -478,7 +556,6 @@ mms_task_http_start( g_object_ref(msg); soup_session_queue_message(priv->tx->session, msg, mms_task_http_finished, http); - return TRUE; } } @@ -566,17 +643,18 @@ mms_task_http_finalize( GObject* object) { MMSTaskHttp* http = MMS_TASK_HTTP(object); - MMS_ASSERT(!http->priv->tx); - MMS_ASSERT(!http->priv->got_chunk_signal_id); - MMS_ASSERT(!http->priv->wrote_headers_signal_id); - MMS_ASSERT(!http->priv->wrote_chunk_signal_id); + MMSTaskHttpPriv* priv = http->priv; + MMS_ASSERT(!priv->tx); if (!task_config(&http->task)->keep_temp_files) { - mms_remove_file_and_dir(http->priv->send_path); - mms_remove_file_and_dir(http->priv->receive_path); + mms_remove_file_and_dir(priv->send_path); + mms_remove_file_and_dir(priv->receive_path); } - g_free(http->priv->uri); - g_free(http->priv->send_path); - g_free(http->priv->receive_path); + g_free(priv->uri); + g_free(priv->transfer_type); + g_free(priv->send_path); + g_free(priv->receive_path); + g_free(priv->receive_file); + mms_transfer_list_unref(http->transfers); G_OBJECT_CLASS(mms_task_http_parent_class)->finalize(object); } @@ -619,7 +697,8 @@ mms_task_http_alloc( GType type, /* Zero for MMS_TYPE_TASK_HTTP */ MMSSettings* settings, /* Settings */ MMSHandler* handler, /* MMS handler */ - const char* name, /* Task name */ + MMSTransferList* transfers, /* Transfer list */ + const char* name, /* Task name (and transfer type) */ const char* id, /* Database message id */ const char* imsi, /* IMSI associated with the message */ const char* uri, /* NULL to use MMSC URL */ @@ -630,8 +709,10 @@ mms_task_http_alloc( MMSTaskHttp* http = mms_task_alloc(type ? type : MMS_TYPE_TASK_HTTP, settings, handler, name, id, imsi); MMSTaskHttpPriv* priv = http->priv; + http->transfers = mms_transfer_list_ref(transfers); priv->uri = g_strdup(uri); - priv->receive_file = receive_file; /* Always static, don't strdup */ + priv->receive_file = g_strdup(receive_file); + priv->transfer_type = g_strdup(name); priv->connection_type = ct; if (send_file) { priv->send_path = mms_task_file(&http->task, send_file); @@ -644,14 +725,15 @@ void* mms_task_http_alloc_with_parent( GType type, /* Zero for MMS_TYPE_TASK_HTTP */ MMSTask* parent, /* Parent task */ + MMSTransferList* transfers, /* Transfer list */ const char* name, /* Task name */ const char* uri, /* NULL to use MMSC URL */ const char* receive_file, /* File to write data to (optional) */ const char* send_file) /* File to read data from (optional) */ { return mms_task_http_alloc(type, parent->settings, parent->handler, - name, parent->id, parent->imsi, uri, receive_file, send_file, - MMS_CONNECTION_TYPE_AUTO); + transfers, name, parent->id, parent->imsi, uri, receive_file, + send_file, MMS_CONNECTION_TYPE_AUTO); } /* diff --git a/mms-lib/src/mms_task_http.h b/mms-lib/src/mms_task_http.h index 12b6565..f3d06c1 100644 --- a/mms-lib/src/mms_task_http.h +++ b/mms-lib/src/mms_task_http.h @@ -36,6 +36,7 @@ typedef struct mms_task_http_priv MMSTaskHttpPriv; typedef struct mms_task_http { MMSTask task; /* Parent object */ MMSTaskHttpPriv* priv; /* Private data */ + MMSTransferList* transfers; /* Transfer list */ } MMSTaskHttp; typedef struct mms_task_http_class { @@ -57,18 +58,20 @@ mms_task_http_alloc( GType type, /* Zero for MMS_TYPE_TASK_HTTP */ MMSSettings* settings, /* Settings */ MMSHandler* handler, /* MMS handler */ + MMSTransferList* transfers, /* Transfer list */ const char* name, /* Task name */ const char* id, /* Database message id */ const char* imsi, /* IMSI associated with the message */ const char* uri, /* NULL to use MMSC URL */ const char* receive_file, /* File to write data to (optional) */ - const char* send_file, /* File to read data from (optional) */ + const char* send_file, /* File to read data from (optional) */ MMS_CONNECTION_TYPE ct); void* mms_task_http_alloc_with_parent( GType type, /* Zero for MMS_TYPE_TASK_HTTP */ MMSTask* parent, /* Parent task */ + MMSTransferList* transfers, /* Transfer list */ const char* name, /* Task name */ const char* uri, /* NULL to use MMSC URL */ const char* receive_file, /* File to write data to (optional) */ diff --git a/mms-lib/src/mms_task_notification.c b/mms-lib/src/mms_task_notification.c index 1dead84..78517ad 100644 --- a/mms-lib/src/mms_task_notification.c +++ b/mms-lib/src/mms_task_notification.c @@ -18,6 +18,7 @@ #include "mms_codec.h" #include "mms_handler.h" #include "mms_file_util.h" +#include "mms_transfer_list.h" /* Logging */ #define MMS_LOG_MODULE_NAME mms_task_notification_log @@ -32,9 +33,10 @@ typedef struct mms_task_notification { MMSPdu* pdu; GBytes* push; MMSHandlerMessageNotifyCall* notify; + MMSTransferList* transfers; } MMSTaskNotification; -G_DEFINE_TYPE(MMSTaskNotification, mms_task_notification, MMS_TYPE_TASK); +G_DEFINE_TYPE(MMSTaskNotification, mms_task_notification, MMS_TYPE_TASK) #define MMS_TYPE_TASK_NOTIFICATION (mms_task_notification_get_type()) #define MMS_TASK_NOTIFICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ MMS_TYPE_TASK_NOTIFICATION, MMSTaskNotification)) @@ -67,8 +69,8 @@ mms_task_notification_reject( { mms_task_make_id(&ind->task); mms_task_queue_and_unref(ind->task.delegate, - mms_task_notifyresp_new(&ind->task, ind->pdu->transaction_id, - MMS_MESSAGE_NOTIFY_STATUS_REJECTED)); + mms_task_notifyresp_new(&ind->task, ind->transfers, + ind->pdu->transaction_id, MMS_MESSAGE_NOTIFY_STATUS_REJECTED)); } /** @@ -120,8 +122,9 @@ mms_task_notification_done( /* Schedule the download task */ if (!mms_task_queue_and_unref(task->delegate, - mms_task_retrieve_new(task->settings, task->handler, - task->id, task->imsi, ind->pdu, FALSE, NULL))) { + mms_task_retrieve_new(task->settings, task->handler, + ind->transfers, task->id, task->imsi, ind->pdu, + FALSE, NULL))) { mms_handler_message_receive_state_changed(task->handler, id, MMS_RECEIVE_STATE_DOWNLOAD_ERROR); } @@ -341,6 +344,7 @@ mms_task_notification_finalize( MMS_ASSERT(!ind->notify); g_bytes_unref(ind->push); mms_message_free(ind->pdu); + mms_transfer_list_unref(ind->transfers); G_OBJECT_CLASS(mms_task_notification_parent_class)->finalize(object); } @@ -372,6 +376,7 @@ MMSTask* mms_task_notification_new( MMSSettings* settings, MMSHandler* handler, + MMSTransferList* transfers, const char* imsi, GBytes* bytes, GError** error) @@ -392,6 +397,7 @@ mms_task_notification_new( ind = mms_task_alloc(MMS_TYPE_TASK_NOTIFICATION, settings, handler, "Notification", NULL, imsi); + ind->transfers = mms_transfer_list_ref(transfers); ind->push = g_bytes_ref(bytes); ind->pdu = pdu; return &ind->task; diff --git a/mms-lib/src/mms_task_notifyresp.c b/mms-lib/src/mms_task_notifyresp.c index e5fe48a..bcd17f8 100644 --- a/mms-lib/src/mms_task_notifyresp.c +++ b/mms-lib/src/mms_task_notifyresp.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. + * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -49,14 +50,15 @@ mms_task_notifyresp_encode( MMSTask* mms_task_notifyresp_new( MMSTask* parent, + MMSTransferList* transfers, const char* tx_id, MMSNotifyStatus ns) { const char* file = mms_task_notifyresp_encode(task_config(parent), parent->id, tx_id, ns); if (file) { - return mms_task_http_alloc_with_parent(0, parent, "NotifyResp", - NULL, NULL, file); + return mms_task_http_alloc_with_parent(0, parent, transfers, + MMS_TRANSFER_TYPE_NOTIFY_RESP, NULL, NULL, file); } return NULL; } diff --git a/mms-lib/src/mms_task_read.c b/mms-lib/src/mms_task_read.c index c96c004..eb86724 100644 --- a/mms-lib/src/mms_task_read.c +++ b/mms-lib/src/mms_task_read.c @@ -116,6 +116,7 @@ MMSTask* mms_task_read_new( MMSSettings* settings, MMSHandler* handler, + MMSTransferList* transfers, const char* id, const char* imsi, const char* msg_id, @@ -127,7 +128,8 @@ mms_task_read_new( id, msg_id, to, rs, err); if (file) { return mms_task_http_alloc(MMS_TYPE_TASK_READ, settings, handler, - "Read", id, imsi, NULL, NULL, file, MMS_CONNECTION_TYPE_AUTO); + transfers, MMS_TRANSFER_TYPE_READ_REPORT, id, imsi, NULL, NULL, + file, MMS_CONNECTION_TYPE_AUTO); } return NULL; } diff --git a/mms-lib/src/mms_task_retrieve.c b/mms-lib/src/mms_task_retrieve.c index 6240ef7..1a2a5b3 100644 --- a/mms-lib/src/mms_task_retrieve.c +++ b/mms-lib/src/mms_task_retrieve.c @@ -67,9 +67,10 @@ mms_task_retrieve_done( MMS_RECEIVE_STATE state = (SOUP_STATUS_IS_SUCCESSFUL(status) && mms_task_queue_and_unref(task->delegate, - mms_task_decode_new(task, retrieve->transaction_id, path))) ? - MMS_RECEIVE_STATE_DECODING : - MMS_RECEIVE_STATE_DOWNLOAD_ERROR; + mms_task_decode_new(task, http->transfers, + retrieve->transaction_id, path))) ? + MMS_RECEIVE_STATE_DECODING : + MMS_RECEIVE_STATE_DOWNLOAD_ERROR; mms_handler_message_receive_state_changed(http->task.handler, http->task.id, state); } @@ -116,6 +117,7 @@ MMSTask* mms_task_retrieve_new( MMSSettings* settings, MMSHandler* handler, + MMSTransferList* transfers, const char* id, const char* imsi, const MMSPdu* pdu, @@ -128,8 +130,9 @@ mms_task_retrieve_new( MMS_ASSERT(pdu->transaction_id); if (pdu->ni.expiry > now) { MMSTaskRetrieve* retrieve = mms_task_http_alloc( - MMS_TYPE_TASK_RETRIEVE, settings, handler, "Retrieve", id, imsi, - pdu->ni.location, MMS_RETRIEVE_CONF_FILE, NULL, ct); + MMS_TYPE_TASK_RETRIEVE, settings, handler, transfers, + MMS_TRANSFER_TYPE_RETRIEVE, id, imsi, pdu->ni.location, + MMS_RETRIEVE_CONF_FILE, NULL, ct); if (retrieve->http.task.deadline > pdu->ni.expiry) { retrieve->http.task.deadline = pdu->ni.expiry; } diff --git a/mms-lib/src/mms_task_send.c b/mms-lib/src/mms_task_send.c index 42568ba..96dadbf 100644 --- a/mms-lib/src/mms_task_send.c +++ b/mms-lib/src/mms_task_send.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2015 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify @@ -29,7 +29,7 @@ MMS_LOG_MODULE_DEFINE2("mms-task-send", MMS_TASK_HTTP_LOG); typedef MMSTaskHttpClass MMSTaskSendClass; typedef MMSTaskHttp MMSTaskSend; -G_DEFINE_TYPE(MMSTaskSend, mms_task_send, MMS_TYPE_TASK_HTTP); +G_DEFINE_TYPE(MMSTaskSend, mms_task_send, MMS_TYPE_TASK_HTTP) #define MMS_TYPE_TASK_SEND (mms_task_send_get_type()) #define MMS_TASK_SEND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ MMS_TYPE_TASK_SEND, MMSTaskSend)) @@ -144,10 +144,12 @@ mms_task_send_init( /* Create MMS send task */ MMSTask* mms_task_send_new( - MMSTask* parent) + MMSTask* parent, + MMSTransferList* transfers) { - return mms_task_http_alloc_with_parent(MMS_TYPE_TASK_SEND, parent, "Send", - NULL, MMS_SEND_CONF_FILE, MMS_SEND_REQ_FILE); + return mms_task_http_alloc_with_parent(MMS_TYPE_TASK_SEND, parent, + transfers, MMS_TRANSFER_TYPE_SEND, NULL, MMS_SEND_CONF_FILE, + MMS_SEND_REQ_FILE); } /* diff --git a/mms-lib/src/mms_transfer_list.c b/mms-lib/src/mms_transfer_list.c new file mode 100644 index 0000000..0baf050 --- /dev/null +++ b/mms-lib/src/mms_transfer_list.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2013-2016 Jolla Ltd. + * Contact: Slava Monich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "mms_transfer_list.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_transfer_list_log +#include "mms_lib_log.h" + +G_DEFINE_TYPE(MMSTransferList, mms_transfer_list, G_TYPE_OBJECT) + +#define MMS_TRANSFER_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + MMS_TYPE_TRANSFER_LIST, MMSTransferList)) +#define MMS_TRANSFER_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ + MMS_TYPE_TRANSFER_LIST, MMSTransferListClass)) + +static +void +mms_transfer_list_class_init( + MMSTransferListClass* klass) +{ +} + +static +void +mms_transfer_list_init( + MMSTransferList* self) +{ +} + +MMSTransferList* +mms_transfer_list_ref( + MMSTransferList* self) +{ + if (self) { + MMS_ASSERT(MMS_TRANSFER_LIST(self)); + g_object_ref(self); + } + return self; +} + +void +mms_transfer_list_unref( + MMSTransferList* self) +{ + if (self) { + MMS_ASSERT(MMS_TRANSFER_LIST(self)); + g_object_unref(self); + } +} + +void +mms_transfer_list_transfer_started( + MMSTransferList* self, /* Instance */ + char* id, /* Database record ID */ + char* type) /* Transfer type */ +{ + if (self && id && type) { + MMSTransferListClass* klass = MMS_TRANSFER_LIST_GET_CLASS(self); + if (klass->fn_transfer_started) { + klass->fn_transfer_started(self, id, type); + } + } +} + +void +mms_transfer_list_transfer_finished( + MMSTransferList* self, /* Instance */ + char* id, /* Database record ID */ + char* type) /* Transfer type */ +{ + if (self && id) { + MMSTransferListClass* klass = MMS_TRANSFER_LIST_GET_CLASS(self); + if (klass->fn_transfer_finished) { + klass->fn_transfer_finished(self, id, type); + } + } +} + +void +mms_transfer_list_transfer_send_progress( + MMSTransferList* self, /* Instance */ + char* id, /* Message ID */ + char* type, /* Transfer type */ + guint sent, /* Bytes sent so far */ + guint total) /* Total bytes to send */ +{ + if (self && id) { + MMSTransferListClass* klass = MMS_TRANSFER_LIST_GET_CLASS(self); + if (klass->fn_send_progress) { + klass->fn_send_progress(self, id, type, sent, total); + } + } +} + +void +mms_transfer_list_transfer_receive_progress( + MMSTransferList* self, /* Instance */ + char* id, /* Message ID */ + char* type, /* Transfer type */ + guint received, /* Bytes received so far */ + guint total) /* Total bytes to receive*/ +{ + if (self && id) { + MMSTransferListClass* klass = MMS_TRANSFER_LIST_GET_CLASS(self); + if (klass->fn_receive_progress) { + klass->fn_receive_progress(self, id, type, received, total); + } + } +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/common/test_transfer_list.c b/mms-lib/test/common/test_transfer_list.c new file mode 100644 index 0000000..ce0d5eb --- /dev/null +++ b/mms-lib/test/common/test_transfer_list.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2016 Jolla Ltd. + * Contact: Slava Monich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "test_transfer_list.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_transfer_list_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-transfer-list-test"); + +/* Class definition */ +typedef MMSTransferListClass MMSTransferListTestClass; +typedef struct mms_transfer_list_test { + MMSTransferList super; +} MMSTransferListTest; + +G_DEFINE_TYPE(MMSTransferListTest, mms_transfer_list_test, \ + MMS_TYPE_TRANSFER_LIST) +#define MMS_TYPE_TRANSFER_LIST_TEST (mms_transfer_list_test_get_type()) +#define MMS_TRANSFER_LIST_TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + MMS_TYPE_TRANSFER_LIST_TEST, MMSTransferListTest)) + +MMSTransferList* +mms_transfer_list_test_new() +{ + return g_object_new(MMS_TYPE_TRANSFER_LIST_TEST, 0); +} + +static +void +mms_transfer_list_test_transfer_started( + MMSTransferList* self, /* Instance */ + char* id, /* Database record ID */ + char* type) /* Transfer type */ +{ +} + +static +void +mms_transfer_list_test_transfer_finished( + MMSTransferList* self, /* Instance */ + char* id, /* Database record ID */ + char* type) /* Transfer type */ +{ +} + +static +void +mms_transfer_list_test_send_progress( + MMSTransferList* self, /* Instance */ + char* id, /* Message ID */ + char* type, /* Transfer type */ + guint sent, /* Bytes sent so far */ + guint total) /* Total bytes to send */ +{ +} + +static +void +mms_transfer_list_test_receive_progress( + MMSTransferList* self, /* Instance */ + char* id, /* Message ID */ + char* type, /* Transfer type */ + guint received, /* Bytes received so far */ + guint total) /* Total bytes to receive*/ +{ +} + +static +void +mms_transfer_list_test_init( + MMSTransferListTest* self) +{ +} + +static +void +mms_transfer_list_test_class_init( + MMSTransferListTestClass* klass) +{ + klass->fn_transfer_started = mms_transfer_list_test_transfer_started; + klass->fn_transfer_finished = mms_transfer_list_test_transfer_finished; + klass->fn_send_progress = mms_transfer_list_test_send_progress; + klass->fn_receive_progress = mms_transfer_list_test_receive_progress; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/common/test_transfer_list.h b/mms-lib/test/common/test_transfer_list.h new file mode 100644 index 0000000..6ddfbd2 --- /dev/null +++ b/mms-lib/test/common/test_transfer_list.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2016 Jolla Ltd. + * Contact: Slava Monich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef TEST_TRANSFER_LIST_H +#define TEST_TRANSFER_LIST_H + +#include "mms_transfer_list.h" + +MMSTransferList* +mms_transfer_list_test_new(void); + +#endif /* TEST_TRANSFER_LIST_H */ diff --git a/mms-lib/test/test_delivery_ind/Makefile b/mms-lib/test/test_delivery_ind/Makefile index 6cf6ff7..55e1a47 100644 --- a/mms-lib/test/test_delivery_ind/Makefile +++ b/mms-lib/test/test_delivery_ind/Makefile @@ -2,6 +2,7 @@ EXE = test_delivery_ind SRC = $(EXE).c -COMMON_SRC = test_connection.c test_connman.c test_handler.c test_util.c +COMMON_SRC = test_connection.c test_connman.c test_handler.c \ + test_transfer_list.c test_util.c include ../common/Makefile diff --git a/mms-lib/test/test_delivery_ind/test_delivery_ind.c b/mms-lib/test/test_delivery_ind/test_delivery_ind.c index 760b496..c9dfab8 100644 --- a/mms-lib/test/test_delivery_ind/test_delivery_ind.c +++ b/mms-lib/test/test_delivery_ind/test_delivery_ind.c @@ -130,18 +130,18 @@ test_init( test->config = config; test->notification_ind = g_mapped_file_new(ni, FALSE, &error); if (test->notification_ind) { - MMSSettings* settings = mms_settings_default_new(config); + MMSSettings* set = mms_settings_default_new(config); test->desc = desc; test->cm = mms_connman_test_new(); test->handler = mms_handler_test_new(); - test->disp = mms_dispatcher_new(settings, test->cm, test->handler); + test->disp = mms_dispatcher_new(set, test->cm, test->handler, NULL); test->loop = g_main_loop_new(NULL, FALSE); test->timeout_id = g_timeout_add_seconds(10, test_timeout, test); test->delegate.fn_done = test_done; mms_dispatcher_set_delegate(test->disp, &test->delegate); test->id = g_strdup(mms_handler_test_send_new(test->handler, "IMSI")); mms_handler_message_sent(test->handler, test->id, desc->mmsid); - mms_settings_unref(settings); + mms_settings_unref(set); test->ret = RET_ERR; ok = TRUE; } else { diff --git a/mms-lib/test/test_read_ind/Makefile b/mms-lib/test/test_read_ind/Makefile index 12e3c09..afa559e 100644 --- a/mms-lib/test/test_read_ind/Makefile +++ b/mms-lib/test/test_read_ind/Makefile @@ -2,6 +2,7 @@ EXE = test_read_ind SRC = $(EXE).c -COMMON_SRC = test_connection.c test_connman.c test_handler.c test_util.c +COMMON_SRC = test_connection.c test_connman.c test_handler.c \ + test_transfer_list.c test_util.c include ../common/Makefile diff --git a/mms-lib/test/test_read_ind/test_read_ind.c b/mms-lib/test/test_read_ind/test_read_ind.c index 037a343..d899eb9 100644 --- a/mms-lib/test/test_read_ind/test_read_ind.c +++ b/mms-lib/test/test_read_ind/test_read_ind.c @@ -130,18 +130,18 @@ test_init( test->config = config; test->notification_ind = g_mapped_file_new(ni, FALSE, &error); if (test->notification_ind) { - MMSSettings* settings = mms_settings_default_new(config); + MMSSettings* set = mms_settings_default_new(config); test->desc = desc; test->cm = mms_connman_test_new(); test->handler = mms_handler_test_new(); - test->disp = mms_dispatcher_new(settings, test->cm, test->handler); + test->disp = mms_dispatcher_new(set, test->cm, test->handler, NULL); test->loop = g_main_loop_new(NULL, FALSE); test->timeout_id = g_timeout_add_seconds(10, test_timeout, test); test->delegate.fn_done = test_done; mms_dispatcher_set_delegate(test->disp, &test->delegate); test->id = g_strdup(mms_handler_test_send_new(test->handler, "IMSI")); mms_handler_message_sent(test->handler, test->id, desc->mmsid); - mms_settings_unref(settings); + mms_settings_unref(set); test->ret = RET_ERR; ok = TRUE; } else { diff --git a/mms-lib/test/test_read_report/Makefile b/mms-lib/test/test_read_report/Makefile index 2c81c9d..5e790a0 100644 --- a/mms-lib/test/test_read_report/Makefile +++ b/mms-lib/test/test_read_report/Makefile @@ -3,6 +3,6 @@ EXE = test_read_report SRC = $(EXE).c COMMON_SRC = test_connection.c test_connman.c test_handler.c test_http.c \ - test_util.c + test_transfer_list.c test_util.c include ../common/Makefile diff --git a/mms-lib/test/test_read_report/test_read_report.c b/mms-lib/test/test_read_report/test_read_report.c index f5228b7..6c7f3ef 100644 --- a/mms-lib/test/test_read_report/test_read_report.c +++ b/mms-lib/test/test_read_report/test_read_report.c @@ -148,7 +148,7 @@ test_init( test->desc = desc; test->cm = mms_connman_test_new(); test->handler = mms_handler_test_new(); - test->disp = mms_dispatcher_new(settings, test->cm, test->handler); + test->disp = mms_dispatcher_new(settings, test->cm, test->handler, NULL); test->loop = g_main_loop_new(NULL, FALSE); test->delegate.fn_done = test_done; mms_dispatcher_set_delegate(test->disp, &test->delegate); diff --git a/mms-lib/test/test_retrieve/Makefile b/mms-lib/test/test_retrieve/Makefile index f68d65c..aba1f70 100644 --- a/mms-lib/test/test_retrieve/Makefile +++ b/mms-lib/test/test_retrieve/Makefile @@ -3,6 +3,6 @@ EXE = test_retrieve SRC = $(EXE).c COMMON_SRC = test_connection.c test_connman.c test_handler.c test_http.c \ - test_util.c + test_transfer_list.c test_util.c include ../common/Makefile diff --git a/mms-lib/test/test_retrieve/test_retrieve.c b/mms-lib/test/test_retrieve/test_retrieve.c index b617ef2..0d06182 100644 --- a/mms-lib/test/test_retrieve/test_retrieve.c +++ b/mms-lib/test/test_retrieve/test_retrieve.c @@ -16,6 +16,7 @@ #include "test_connman.h" #include "test_handler.h" #include "test_http.h" +#include "test_transfer_list.h" #include "test_util.h" #include "mms_codec.h" @@ -605,11 +606,13 @@ test_init( if (rc) test->retrieve_conf = g_mapped_file_new(rc, FALSE, &error); if (test->retrieve_conf || !rc) { MMSSettings* settings = mms_settings_default_new(config); + MMSTransferList* transfers = mms_transfer_list_test_new(); g_mapped_file_ref(test->notification_ind); test->desc = desc; test->cm = mms_connman_test_new(); test->handler = mms_handler_test_new(); - test->disp = mms_dispatcher_new(settings, test->cm, test->handler); + test->disp = mms_dispatcher_new(settings, test->cm, test->handler, + transfers); test->loop = g_main_loop_new(NULL, FALSE); if (!debug) { test->timeout_id = g_timeout_add_seconds(TEST_TIMEOUT, @@ -633,6 +636,7 @@ test_init( test->msgreceived_id = mms_handler_test_add_msgreceived_fn(test->handler, test_msgreceived, test); + mms_transfer_list_unref(transfers); mms_settings_unref(settings); test->ret = RET_ERR; ok = TRUE; diff --git a/mms-lib/test/test_retrieve_cancel/Makefile b/mms-lib/test/test_retrieve_cancel/Makefile index 5bf7a8e..f314657 100644 --- a/mms-lib/test/test_retrieve_cancel/Makefile +++ b/mms-lib/test/test_retrieve_cancel/Makefile @@ -2,6 +2,6 @@ EXE = test_retrieve_cancel SRC = test_retrieve_cancel.c test_connman.c -COMMON_SRC = test_connection.c test_handler.c +COMMON_SRC = test_connection.c test_handler.c test_transfer_list.c include ../common/Makefile diff --git a/mms-lib/test/test_retrieve_cancel/test_retrieve_cancel.c b/mms-lib/test/test_retrieve_cancel/test_retrieve_cancel.c index f6821c7..0b24b64 100644 --- a/mms-lib/test/test_retrieve_cancel/test_retrieve_cancel.c +++ b/mms-lib/test/test_retrieve_cancel/test_retrieve_cancel.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2016 Jolla Ltd. + * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -85,7 +86,7 @@ test_init( test->desc = desc; test->cm = mms_connman_test_new(); test->handler = mms_handler_test_new(); - test->disp = mms_dispatcher_new(settings, test->cm, test->handler); + test->disp = mms_dispatcher_new(settings, test->cm, test->handler, NULL); test->pdu = g_bytes_new_static(desc->pdu, desc->pdusize); test->loop = g_main_loop_new(NULL, FALSE); test->delegate.fn_done = test_done; diff --git a/mms-lib/test/test_retrieve_no_proxy/Makefile b/mms-lib/test/test_retrieve_no_proxy/Makefile index 6ea9b62..261f89c 100644 --- a/mms-lib/test/test_retrieve_no_proxy/Makefile +++ b/mms-lib/test/test_retrieve_no_proxy/Makefile @@ -3,6 +3,6 @@ EXE = test_retrieve_no_proxy SRC = $(EXE).c COMMON_SRC = test_connection.c test_connman.c test_handler.c test_http.c \ - test_util.c + test_transfer_list.c test_util.c include ../common/Makefile diff --git a/mms-lib/test/test_retrieve_no_proxy/test_retrieve_no_proxy.c b/mms-lib/test/test_retrieve_no_proxy/test_retrieve_no_proxy.c index e03d6b7..af18e26 100644 --- a/mms-lib/test/test_retrieve_no_proxy/test_retrieve_no_proxy.c +++ b/mms-lib/test/test_retrieve_no_proxy/test_retrieve_no_proxy.c @@ -143,10 +143,10 @@ test_init( char* port_string; char* push_data; gsize push_len; - MMSSettings* settings = mms_settings_default_new(config); + MMSSettings* set = mms_settings_default_new(config); test->cm = mms_connman_test_new(); test->handler = mms_handler_test_new(); - test->disp = mms_dispatcher_new(settings, test->cm, test->handler); + test->disp = mms_dispatcher_new(set, test->cm, test->handler, NULL); test->loop = g_main_loop_new(NULL, FALSE); test->timeout_id = g_timeout_add_seconds(10, test_timeout, test); test->delegate.fn_done = test_done; @@ -166,7 +166,7 @@ test_init( g_free(push_data); g_free(port_string); - mms_settings_unref(settings); + mms_settings_unref(set); test->ret = RET_ERR; ok = TRUE; } else { diff --git a/mms-lib/test/test_retrieve_order/Makefile b/mms-lib/test/test_retrieve_order/Makefile index b731162..0e3e572 100644 --- a/mms-lib/test/test_retrieve_order/Makefile +++ b/mms-lib/test/test_retrieve_order/Makefile @@ -3,6 +3,6 @@ EXE = test_retrieve_order SRC = $(EXE).c COMMON_SRC = test_connection.c test_connman.c test_handler.c test_http.c \ - test_util.c + test_transfer_list.c test_util.c include ../common/Makefile diff --git a/mms-lib/test/test_retrieve_order/test_retrieve_order.c b/mms-lib/test/test_retrieve_order/test_retrieve_order.c index 90001c1..c5cfa01 100644 --- a/mms-lib/test/test_retrieve_order/test_retrieve_order.c +++ b/mms-lib/test/test_retrieve_order/test_retrieve_order.c @@ -250,7 +250,7 @@ test_init( test->desc = desc; test->cm = mms_connman_test_new(); test->handler = mms_handler_test_new(); - test->disp = mms_dispatcher_new(settings, test->cm, test->handler); + test->disp = mms_dispatcher_new(settings, test->cm, test->handler, NULL); test->loop = g_main_loop_new(NULL, FALSE); if (!debug) { test->timeout_id = g_timeout_add_seconds(TEST_TIMEOUT, diff --git a/mms-lib/test/test_send/Makefile b/mms-lib/test/test_send/Makefile index d9ab3a2..223063d 100644 --- a/mms-lib/test/test_send/Makefile +++ b/mms-lib/test/test_send/Makefile @@ -3,6 +3,6 @@ EXE = test_send SRC = $(EXE).c COMMON_SRC = test_connection.c test_connman.c test_handler.c test_http.c \ - test_util.c + test_transfer_list.c test_util.c include ../common/Makefile diff --git a/mms-lib/test/test_send/test_send.c b/mms-lib/test/test_send/test_send.c index eec5d62..367fe3c 100644 --- a/mms-lib/test/test_send/test_send.c +++ b/mms-lib/test/test_send/test_send.c @@ -369,7 +369,7 @@ test_init( if (!desc->resp_file || test->resp_file) { int i; guint port; - MMSSettings* settings = mms_settings_default_new(config); + MMSSettings* set = mms_settings_default_new(config); test->parts = g_new0(MMSAttachmentInfo, desc->nparts); test->files = g_new0(char*, desc->nparts); for (i=0; inparts; i++) { @@ -382,7 +382,7 @@ test_init( test->desc = desc; test->cm = mms_connman_test_new(); test->handler = mms_handler_test_new(); - test->disp = mms_dispatcher_new(settings, test->cm, test->handler); + test->disp = mms_dispatcher_new(set, test->cm, test->handler, NULL); test->loop = g_main_loop_new(NULL, FALSE); test->delegate.fn_done = test_done; mms_dispatcher_set_delegate(test->disp, &test->delegate); @@ -400,10 +400,10 @@ test_init( MMSSettingsSimData sim_settings; mms_settings_sim_data_default(&sim_settings); sim_settings.size_limit = desc->size_limit; - mms_settings_set_sim_defaults(settings, NULL); - mms_settings_set_sim_defaults(settings, &sim_settings); + mms_settings_set_sim_defaults(set, NULL); + mms_settings_set_sim_defaults(set, &sim_settings); } - mms_settings_unref(settings); + mms_settings_unref(set); test->ret = RET_ERR; ok = TRUE; } diff --git a/mms-transfer-list-dbus/Makefile b/mms-transfer-list-dbus/Makefile new file mode 100644 index 0000000..d4aade9 --- /dev/null +++ b/mms-transfer-list-dbus/Makefile @@ -0,0 +1,126 @@ +# -*- Mode: makefile-gmake -*- + +.PHONY: clean all debug release + +# Required packages +PKGS = libglibutil glib-2.0 gio-2.0 gio-unix-2.0 + +# +# Default target +# + +all: debug release + +# +# Sources +# + +SRC = mms_transfer_dbus.c mms_transfer_list_dbus.c +GEN_SRC = org.nemomobile.MmsEngine.TransferList.c + +# +# Directories +# + +SRC_DIR = src +INCLUDE_DIR = include +BUILD_DIR = build +GEN_DIR = $(BUILD_DIR) +SPEC_DIR = spec +MMS_LIB_INCLUDE = ../mms-lib/include +DEBUG_BUILD_DIR = $(BUILD_DIR)/debug +RELEASE_BUILD_DIR = $(BUILD_DIR)/release + +# +# Tools and flags +# + +CC = $(CROSS_COMPILE)gcc +LD = $(CC) +ARFLAGS = rc +DEBUG_FLAGS = -g +RELEASE_FLAGS = -O2 +WARNINGS = -Wall +BASE_FLAGS = -fPIC $(CFLAGS) +INCLUDES = -I$(SRC_DIR) -I$(INCLUDE_DIR) -I$(MMS_LIB_INCLUDE) -I$(GEN_DIR) -I. +FULL_CFLAGS = $(BASE_FLAGS) $(WARNINGS) $(INCLUDES) -fPIC -MMD \ + $(shell pkg-config --cflags $(PKGS)) + +ifndef KEEP_SYMBOLS +KEEP_SYMBOLS = 0 +endif + +ifneq ($(KEEP_SYMBOLS),0) +RELEASE_FLAGS += -g +endif + +DEBUG_CFLAGS = $(FULL_CFLAGS) $(DEBUG_FLAGS) -DDEBUG +RELEASE_CFLAGS = $(FULL_CFLAGS) $(RELEASE_FLAGS) -O2 + +# +# Files +# + +.PRECIOUS: $(GEN_SRC:%=$(GEN_DIR)/%) + +DEBUG_OBJS = \ + $(GEN_SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) \ + $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) +RELEASE_OBJS = \ + $(GEN_SRC:%.c=$(RELEASE_BUILD_DIR)/%.o) \ + $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o) + +# +# Dependencies +# + +DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d) +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(DEPS)),) +-include $(DEPS) +endif +endif + +# +# Rules +# +LIB = libmms-transfer-list-dbus.a +DEBUG_LIB = $(DEBUG_BUILD_DIR)/$(LIB) +RELEASE_LIB = $(RELEASE_BUILD_DIR)/$(LIB) + +debug: $(DEBUG_LIB) + +release: $(RELEASE_LIB) + +clean: + rm -fr $(BUILD_DIR) *~ $(SRC_DIR)/*~ $(INCLUDE_DIR)/*~ + +$(GEN_DIR): + mkdir -p $@ + +$(DEBUG_BUILD_DIR): + mkdir -p $@ + +$(RELEASE_BUILD_DIR): + mkdir -p $@ + +$(GEN_DIR)/%.c: $(SPEC_DIR)/%.xml + gdbus-codegen --generate-c-code $(@:%.c=%) $< + +$(DEBUG_BUILD_DIR)/%.o : $(SRC_DIR)/%.c + $(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ + +$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c + $(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ + +$(DEBUG_BUILD_DIR)/%.o : $(GEN_DIR)/%.c + $(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ + +$(RELEASE_BUILD_DIR)/%.o : $(GEN_DIR)/%.c + $(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ + +$(DEBUG_LIB): $(DEBUG_BUILD_DIR) $(DEBUG_OBJS) + $(AR) $(ARFLAGS) $@ $(DEBUG_OBJS) + +$(RELEASE_LIB): $(RELEASE_BUILD_DIR) $(RELEASE_OBJS) + $(AR) $(ARFLAGS) $@ $(RELEASE_OBJS) diff --git a/mms-transfer-list-dbus/include/mms_transfer_list_dbus.h b/mms-transfer-list-dbus/include/mms_transfer_list_dbus.h new file mode 100644 index 0000000..603de7a --- /dev/null +++ b/mms-transfer-list-dbus/include/mms_transfer_list_dbus.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2016 Jolla Ltd. + * Contact: Slava Monich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef JOLLA_MMS_TRANSFER_LIST_DBUS_H +#define JOLLA_MMS_TRANSFER_LIST_DBUS_H + +#include "mms_transfer_list.h" + +MMSTransferList* +mms_transfer_list_dbus_new(void); + +#endif /* JOLLA_MMS_TRANSFER_LIST_DBUS_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ + diff --git a/mms-transfer-list-dbus/mms-transfer-list-dbus.pro b/mms-transfer-list-dbus/mms-transfer-list-dbus.pro new file mode 100644 index 0000000..5fc5238 --- /dev/null +++ b/mms-transfer-list-dbus/mms-transfer-list-dbus.pro @@ -0,0 +1,47 @@ +TEMPLATE = lib +CONFIG += staticlib +CONFIG -= qt +CONFIG += link_pkgconfig +PKGCONFIG += libglibutil glib-2.0 gio-2.0 gio-unix-2.0 +DBUS_SPEC_DIR = $$_PRO_FILE_PWD_/spec +INCLUDEPATH += . include +INCLUDEPATH += ../mms-lib/include +QMAKE_CFLAGS += -Wno-unused-parameter +BUILD_DIR = $$_PRO_FILE_PWD_/build + +CONFIG(debug, debug|release) { + DEFINES += DEBUG + DESTDIR = $$BUILD_DIR/debug +} else { + DESTDIR = $$BUILD_DIR/release +} + +SOURCES += \ + src/mms_transfer_dbus.c \ + src/mms_transfer_list_dbus.c + +HEADERS += \ + src/mms_transfer_dbus.h \ + src/mms_transfer_list_dbus_log.h \ + include/mms_transfer_list_dbus.h + +SPEC = $$DBUS_SPEC_DIR/org.nemomobile.MmsEngine.TransferList.xml +OTHER_FILES += $$SPEC + +# org.nemomobile.MmsEngine.Transfer +STUB_GENERATE = gdbus-codegen --generate-c-code \ + org.nemomobile.MmsEngine.TransferList $$SPEC +STUB_H = org.nemomobile.MmsEngine.TransferList.h +stub_h.input = SPEC +stub_h.output = $$STUB_H +stub_h.commands = $$STUB_GENERATE +stub_h.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += stub_h + +STUB_C = org.nemomobile.MmsEngine.TransferList.c +stub_c.input = SPEC +stub_c.output = $$STUB_C +stub_c.commands = $$STUB_GENERATE +stub_c.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += stub_c +GENERATED_SOURCES += $$STUB_C diff --git a/mms-transfer-list-dbus/spec/org.nemomobile.MmsEngine.TransferList.xml b/mms-transfer-list-dbus/spec/org.nemomobile.MmsEngine.TransferList.xml new file mode 100644 index 0000000..03e663e --- /dev/null +++ b/mms-transfer-list-dbus/spec/org.nemomobile.MmsEngine.TransferList.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mms-transfer-list-dbus/src/mms_transfer_dbus.c b/mms-transfer-list-dbus/src/mms_transfer_dbus.c new file mode 100644 index 0000000..6a9f29e --- /dev/null +++ b/mms-transfer-list-dbus/src/mms_transfer_dbus.c @@ -0,0 +1,435 @@ +/* + * Copyright (C) 2016 Jolla Ltd. + * Contact: Slava Monich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "mms_transfer_dbus.h" +#include "mms_transfer_list_dbus_log.h" + +#include + +/* Generated code */ +#include "org.nemomobile.MmsEngine.TransferList.h" + +/* Class definition */ + +enum mms_transfer_dbus_method { + MMS_TRANSFER_DBUS_METHOD_GET_ALL, + MMS_TRANSFER_DBUS_METHOD_ENABLE_UPDATES, + MMS_TRANSFER_DBUS_METHOD_DISABLE_UPDATES, + MMS_TRANSFER_DBUS_METHOD_GET_INTERFACE_VERSION, + MMS_TRANSFER_DBUS_METHOD_GET_SEND_PROGRESS, + MMS_TRANSFER_DBUS_METHOD_GET_RECEIVE_PROGRESS, + MMS_TRANSFER_DBUS_METHOD_COUNT +}; + +typedef enum mms_transfer_flags { + MMS_TRANSFER_FLAG_SEND_UPDATES_ENABLED = 0x01, + MMS_TRANSFER_FLAG_RECEIVE_UPDATES_ENABLED = 0x02 +} MMS_TRANSFER_FLAGS; + +#define MMS_TRANSFER_FLAGS_UPDATES_ENABLED (\ + MMS_TRANSFER_FLAG_SEND_UPDATES_ENABLED |\ + MMS_TRANSFER_FLAG_RECEIVE_UPDATES_ENABLED) + +typedef GObjectClass MMSTransferDbusClass; +struct mms_transfer_dbus_priv { + char* id; + char* type; + char* path; + GDBusConnection* bus; + OrgNemomobileMmsEngineTransfer* proxy; + gulong proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_COUNT]; + GHashTable* clients; + guint last_update_cookie; + MMS_TRANSFER_FLAGS flags; + guint bytes_sent; + guint bytes_to_send; + guint bytes_received; + guint bytes_to_receive; +}; + +typedef struct mms_transfer_dbus_client { + gulong watch_id; + GHashTable* requests; +} MMSTransferDbusClient; + +G_DEFINE_TYPE(MMSTransferDbus, mms_transfer_dbus, G_TYPE_OBJECT) + +#define MMS_TRANSFER_DBUS_INTERFACE_VERSION (1) + +MMSTransferDbus* +mms_transfer_dbus_new( + GDBusConnection* bus, + const char* id, + const char* type) +{ + MMSTransferDbus* self = g_object_new(MMS_TYPE_TRANSFER_DBUS, NULL); + MMSTransferDbusPriv* priv = self->priv; + GError* error = NULL; + + self->key.id = priv->id = g_strdup(id); + self->key.type = priv->type = g_strdup(type); + self->path = priv->path = g_strconcat("/msg/", id, "/", type, NULL); + priv->bus = g_object_ref(bus); + if (!g_dbus_interface_skeleton_export( + G_DBUS_INTERFACE_SKELETON(priv->proxy), + priv->bus, priv->path, &error)) { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + } + return self; +} + +void +mms_transfer_dbus_send_progress( + MMSTransferDbus* self, + guint sent, + guint total) +{ + MMSTransferDbusPriv* priv = self->priv; + if (priv->bytes_sent != sent || + priv->bytes_to_send != total) { + priv->bytes_sent = sent; + priv->bytes_to_send = total; + if (priv->flags & MMS_TRANSFER_FLAG_SEND_UPDATES_ENABLED) { + org_nemomobile_mms_engine_transfer_emit_send_progress_changed( + priv->proxy, sent, total); + } + } +} + +void +mms_transfer_dbus_receive_progress( + MMSTransferDbus* self, + guint received, + guint total) +{ + MMSTransferDbusPriv* priv = self->priv; + if (priv->bytes_received != received || + priv->bytes_to_receive != total) { + priv->bytes_received = received; + priv->bytes_to_receive = total; + if (priv->flags & MMS_TRANSFER_FLAG_RECEIVE_UPDATES_ENABLED) { + org_nemomobile_mms_engine_transfer_emit_receive_progress_changed( + priv->proxy, received, total); + } + } +} + +void +mms_transfer_dbus_finished( + MMSTransferDbus* self) +{ + MMSTransferDbusPriv* priv = self->priv; + if (priv->flags & MMS_TRANSFER_FLAGS_UPDATES_ENABLED) { + org_nemomobile_mms_engine_transfer_emit_finished(priv->proxy); + } +} + +static +void +mms_transfer_dbus_client_destroy( + gpointer data) +{ + MMSTransferDbusClient* client = data; + g_bus_unwatch_name(client->watch_id); + g_hash_table_destroy(client->requests); +} + +static +MMS_TRANSFER_FLAGS +mms_transfer_dbus_client_flags( + MMSTransferDbusClient* client) +{ + MMS_TRANSFER_FLAGS flags = 0; + if (g_hash_table_size(client->requests)) { + gpointer value; + GHashTableIter it; + g_hash_table_iter_init(&it, client->requests); + while (g_hash_table_iter_next(&it, NULL, &value)) { + flags |= GPOINTER_TO_INT(value); + } + } + return flags; +} + +static +void +mms_transfer_dbus_update_flags( + MMSTransferDbus* self) +{ + MMSTransferDbusPriv* priv = self->priv; + MMS_TRANSFER_FLAGS flags = 0; + if (g_hash_table_size(priv->clients)) { + gpointer value; + GHashTableIter it; + g_hash_table_iter_init(&it, priv->clients); + while (g_hash_table_iter_next(&it, NULL, &value)) { + flags |= mms_transfer_dbus_client_flags(value); + } + } + if (priv->flags != flags) { + priv->flags = flags; + MMS_DEBUG("Update flags => %u", priv->flags); + } +} + +static +void +mms_transfer_dbus_client_vanished( + GDBusConnection* bus, + const gchar* name, + gpointer user_data) +{ + MMSTransferDbus* self = MMS_TRANSFER_DBUS(user_data); + MMSTransferDbusPriv* priv = self->priv; + GDEBUG("Name '%s' has disappeared", name); + g_hash_table_remove(priv->clients, name); + mms_transfer_dbus_update_flags(self); +} + +/* org.nemomobile.MmsEngine.Transfer.GetAll */ +static +gboolean +mms_transfer_dbus_handle_get_all( + OrgNemomobileMmsEngineTransfer* proxy, + GDBusMethodInvocation* call, + MMSTransferDbus* self) +{ + MMSTransferDbusPriv* priv = self->priv; + org_nemomobile_mms_engine_transfer_complete_get_all(proxy, call, + MMS_TRANSFER_DBUS_INTERFACE_VERSION, + priv->bytes_sent, + priv->bytes_to_send, + priv->bytes_received, + priv->bytes_to_receive); + return TRUE; +} + +/* org.nemomobile.MmsEngine.Transfer.EnableUpdates */ +static +gboolean +mms_transfer_dbus_handle_enable_updates( + OrgNemomobileMmsEngineTransfer* proxy, + GDBusMethodInvocation* call, + guint flags, + MMSTransferDbus* self) +{ + MMSTransferDbusPriv* priv = self->priv; + guint cookie = 0; + + if (flags) { + MMSTransferDbusClient* client = NULL; + const char* sender = g_dbus_method_invocation_get_sender(call); + cookie = ++(priv->last_update_cookie); + MMS_VERBOSE_("%s %u -> %u", sender, cookie, flags); + + /* Create client context if necessary */ + if (priv->clients) { + client = g_hash_table_lookup(priv->clients, sender); + } else { + priv->clients = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, mms_transfer_dbus_client_destroy); + } + if (!client) { + client = g_new0(MMSTransferDbusClient, 1); + client->requests = g_hash_table_new(g_direct_hash, g_direct_equal); + client->watch_id = g_bus_watch_name_on_connection(priv->bus, + sender, G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, + mms_transfer_dbus_client_vanished, self, NULL); + g_hash_table_insert(priv->clients, g_strdup(sender), client); + } + + g_hash_table_insert(client->requests, GINT_TO_POINTER(cookie), + GINT_TO_POINTER(flags)); + if ((priv->flags & flags) != flags) { + priv->flags |= flags; + MMS_DEBUG("Update flags => %u", priv->flags); + } + } else { + MMS_WARN("Client provided no update flags!"); + } + + org_nemomobile_mms_engine_transfer_complete_enable_updates(proxy, + call, cookie); + return TRUE; +} + +/* org.nemomobile.MmsEngine.Transfer.DisableUpdates */ +static +gboolean +mms_transfer_dbus_handle_disable_updates( + OrgNemomobileMmsEngineTransfer* proxy, + GDBusMethodInvocation* call, + guint cookie, + MMSTransferDbus* self) +{ + MMSTransferDbusPriv* priv = self->priv; + MMSTransferDbusClient* client = NULL; + const char* sender = g_dbus_method_invocation_get_sender(call); + + MMS_VERBOSE_("%s %u", sender, cookie); + org_nemomobile_mms_engine_transfer_complete_disable_updates(proxy, call); + + if (priv->clients) { + client = g_hash_table_lookup(priv->clients, sender); + } + if (client) { + g_hash_table_remove(client->requests, GINT_TO_POINTER(cookie)); + mms_transfer_dbus_update_flags(self); + } + + return TRUE; +} + +/* org.nemomobile.MmsEngine.Transfer.GetInterfaceVersion */ +static +gboolean +mms_transfer_dbus_handle_get_interface_version( + OrgNemomobileMmsEngineTransfer* proxy, + GDBusMethodInvocation* call, + MMSTransferDbus* self) +{ + org_nemomobile_mms_engine_transfer_complete_get_interface_version(proxy, + call, MMS_TRANSFER_DBUS_INTERFACE_VERSION); + return TRUE; +} + +/* org.nemomobile.MmsEngine.Transfer.GetSendProgress */ +static +gboolean +mms_transfer_dbus_handle_get_send_progress( + OrgNemomobileMmsEngineTransfer* proxy, + GDBusMethodInvocation* call, + MMSTransferDbus* self) +{ + MMSTransferDbusPriv* priv = self->priv; + org_nemomobile_mms_engine_transfer_complete_get_send_progress(proxy, + call, priv->bytes_sent, priv->bytes_to_send); + return TRUE; +} + +/* org.nemomobile.MmsEngine.Transfer.GetReceiveProgress */ +static +gboolean +mms_transfer_dbus_handle_get_receive_progress( + OrgNemomobileMmsEngineTransfer* proxy, + GDBusMethodInvocation* call, + MMSTransferDbus* self) +{ + MMSTransferDbusPriv* priv = self->priv; + org_nemomobile_mms_engine_transfer_complete_get_receive_progress(proxy, + call, priv->bytes_received, priv->bytes_to_receive); + return TRUE; +} + +/** + * First stage of deinitialization (release all references). + * May be called more than once in the lifetime of the object. + */ +static +void +mms_transfer_dbus_dispose( + GObject* object) +{ + MMSTransferDbus* self = MMS_TRANSFER_DBUS(object); + MMSTransferDbusPriv* priv = self->priv; + if (priv->clients) { + g_hash_table_destroy(priv->clients); + priv->clients = NULL; + } + if (priv->proxy) { + g_dbus_interface_skeleton_unexport( + G_DBUS_INTERFACE_SKELETON(priv->proxy)); + gutil_disconnect_handlers(priv->proxy, priv->proxy_signal_id, + G_N_ELEMENTS(priv->proxy_signal_id)); + g_object_unref(priv->proxy); + priv->proxy = NULL; + } + if (priv->bus) { + g_object_unref(priv->bus); + priv->bus = NULL; + } + G_OBJECT_CLASS(mms_transfer_dbus_parent_class)->dispose(object); +} + +/** + * Final stage of deinitialization + */ +static +void +mms_transfer_dbus_finalize( + GObject* object) +{ + MMSTransferDbus* self = MMS_TRANSFER_DBUS(object); + MMSTransferDbusPriv* priv = self->priv; + g_free(priv->id); + g_free(priv->type); + g_free(priv->path); + G_OBJECT_CLASS(mms_transfer_dbus_parent_class)->finalize(object); +} + +/** + * Per instance initializer + */ +static +void +mms_transfer_dbus_init( + MMSTransferDbus* self) +{ + MMSTransferDbusPriv* priv = G_TYPE_INSTANCE_GET_PRIVATE(self, + MMS_TYPE_TRANSFER_DBUS, MMSTransferDbusPriv); + self->priv = priv; + priv->proxy = org_nemomobile_mms_engine_transfer_skeleton_new(); + priv->proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_GET_ALL] = + g_signal_connect(priv->proxy, "handle-get-all", + G_CALLBACK(mms_transfer_dbus_handle_get_all), self); + priv->proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_ENABLE_UPDATES] = + g_signal_connect(priv->proxy, "handle-enable-updates", + G_CALLBACK(mms_transfer_dbus_handle_enable_updates), self); + priv->proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_DISABLE_UPDATES] = + g_signal_connect(priv->proxy, "handle-disable-updates", + G_CALLBACK(mms_transfer_dbus_handle_disable_updates), self); + priv->proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_GET_INTERFACE_VERSION] = + g_signal_connect(priv->proxy, "handle-get-interface-version", + G_CALLBACK(mms_transfer_dbus_handle_get_interface_version), self); + priv->proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_GET_SEND_PROGRESS] = + g_signal_connect(priv->proxy, "handle-get-send-progress", + G_CALLBACK(mms_transfer_dbus_handle_get_send_progress), self); + priv->proxy_signal_id[MMS_TRANSFER_DBUS_METHOD_GET_RECEIVE_PROGRESS] = + g_signal_connect(priv->proxy, "handle-get-receive-progress", + G_CALLBACK(mms_transfer_dbus_handle_get_receive_progress), self); +} + +/** + * Per class initializer + */ +static +void +mms_transfer_dbus_class_init( + MMSTransferDbusClass* klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + g_type_class_add_private(klass, sizeof(MMSTransferDbusPriv)); + object_class->dispose = mms_transfer_dbus_dispose; + object_class->finalize = mms_transfer_dbus_finalize; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-transfer-list-dbus/src/mms_transfer_dbus.h b/mms-transfer-list-dbus/src/mms_transfer_dbus.h new file mode 100644 index 0000000..5649c1a --- /dev/null +++ b/mms-transfer-list-dbus/src/mms_transfer_dbus.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 Jolla Ltd. + * Contact: Slava Monich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef JOLLA_MMS_TRANSFER_DBUS_H +#define JOLLA_MMS_TRANSFER_DBUS_H + +#include "mms_lib_types.h" + +#include + +typedef struct mms_transfer_key { + const char* id; + const char* type; +} MMSTransferKey; + +typedef struct mms_transfer_list_dbus MMSTransferListDbus; +typedef struct mms_transfer_dbus_priv MMSTransferDbusPriv; +typedef struct mms_transfer_dbus { + GObject object; + MMSTransferDbusPriv* priv; + MMSTransferListDbus* list; + MMSTransferKey key; + const char* path; +} MMSTransferDbus; + +GType mms_transfer_dbus_get_type(void); +#define MMS_TYPE_TRANSFER_DBUS (mms_transfer_dbus_get_type()) +#define MMS_TRANSFER_DBUS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + MMS_TYPE_TRANSFER_DBUS, MMSTransferDbus)) + +MMSTransferDbus* +mms_transfer_dbus_new( + GDBusConnection* bus, + const char* id, + const char* type); + +void +mms_transfer_dbus_send_progress( + MMSTransferDbus* transfer, /* Instance */ + guint sent, /* Bytes sent so far */ + guint total); /* Total bytes to send */ + +void +mms_transfer_dbus_receive_progress( + MMSTransferDbus* transfer, /* Instance */ + guint received, /* Bytes received so far */ + guint total); /* Total bytes to receive*/ + +void +mms_transfer_dbus_finished( + MMSTransferDbus* transfer); + +#endif /* JOLLA_MMS_TRANSFER_DBUS_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ + diff --git a/mms-transfer-list-dbus/src/mms_transfer_list_dbus.c b/mms-transfer-list-dbus/src/mms_transfer_list_dbus.c new file mode 100644 index 0000000..2ddf7e4 --- /dev/null +++ b/mms-transfer-list-dbus/src/mms_transfer_list_dbus.c @@ -0,0 +1,321 @@ +/* + * Copyright (C) 2016 Jolla Ltd. + * Contact: Slava Monich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "mms_transfer_list_dbus.h" +#include "mms_transfer_list_dbus_log.h" +#include "mms_transfer_dbus.h" + +#include + +/* Log module */ +MMS_LOG_MODULE_DEFINE("mms-transfer-list-dbus"); + +/* Generated code */ +#include "org.nemomobile.MmsEngine.TransferList.h" + +/* Class definition */ +typedef MMSTransferListClass MMSTransferListDbusClass; +struct mms_transfer_list_dbus { + MMSTransferList super; + GDBusConnection* bus; + OrgNemomobileMmsEngineTransferList* proxy; + gulong list_transfers_id; + GHashTable* transfers; +}; + +G_DEFINE_TYPE(MMSTransferListDbus, mms_transfer_list_dbus, \ + MMS_TYPE_TRANSFER_LIST) +#define MMS_TYPE_TRANSFER_LIST_DBUS (mms_transfer_list_dbus_get_type()) +#define MMS_TRANSFER_LIST_DBUS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + MMS_TYPE_TRANSFER_LIST_DBUS, MMSTransferListDbus)) + +#define MMS_TRANSFER_LIST_DBUS_PATH "/" +#define MMS_TRANSFER_LIST_DBUS_BUS G_BUS_TYPE_SYSTEM + +static +guint +mms_transfer_key_hash_cb( + gconstpointer data) +{ + if (data) { + /* There's shouldn't be more than one transfer per message at + * any time, it's enough to just hash the message id */ + const MMSTransferKey* key = data; + return g_str_hash(key->id); + } else { + return 0; + } +} + +static +gboolean +mms_transfer_key_equal_cb( + gconstpointer a, + gconstpointer b) +{ + if (a == b) { + return TRUE; + } else if (!a || !b) { + return FALSE; + } else { + const MMSTransferKey* key1 = a; + const MMSTransferKey* key2 = a; + return !g_strcmp0(key1->id, key2->id) && + !g_strcmp0(key1->type, key2->type); + } +} + +static +void +mms_transfer_destroy_cb( + gpointer data) +{ + MMSTransferDbus* transfer = MMS_TRANSFER_DBUS(data); + MMSTransferListDbus* list = MMS_TRANSFER_LIST_DBUS(transfer->list); + MMS_DEBUG("Transfer %s finished", transfer->path); + mms_transfer_dbus_finished(transfer); + org_nemomobile_mms_engine_transfer_list_emit_transfer_finished(list->proxy, + transfer->path); + transfer->list = NULL; + g_object_unref(transfer); +} + +static +void +mms_transfer_list_dbus_bus_cb( + GObject* object, + GAsyncResult* res, + gpointer user_data) +{ + MMSTransferListDbus* self = MMS_TRANSFER_LIST_DBUS(user_data); + self->bus = g_bus_get_finish(res, NULL); + if (self->bus) { + GError* error = NULL; + if (!g_dbus_interface_skeleton_export( + G_DBUS_INTERFACE_SKELETON(self->proxy), self->bus, + MMS_TRANSFER_LIST_DBUS_PATH, &error)) { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + } + } + g_object_unref(self); +} + +MMSTransferList* +mms_transfer_list_dbus_new() +{ + MMSTransferListDbus* self = g_object_new(MMS_TYPE_TRANSFER_LIST_DBUS, 0); + g_bus_get(MMS_TRANSFER_LIST_DBUS_BUS, NULL, mms_transfer_list_dbus_bus_cb, + g_object_ref(self)); + return &self->super; +} + +static +void +mms_transfer_list_dbus_transfer_started( + MMSTransferList* list, /* Instance */ + char* id, /* Database record ID */ + char* type) /* Transfer type */ +{ + MMSTransferListDbus* self = MMS_TRANSFER_LIST_DBUS(list); + MMSTransferDbus* transfer = mms_transfer_dbus_new(self->bus, id, type); + MMS_DEBUG("Transfer %s started", transfer->path); + transfer->list = self; + g_hash_table_replace(self->transfers, &transfer->key, transfer); + org_nemomobile_mms_engine_transfer_list_emit_transfer_started(self->proxy, + transfer->path); +} + +static +void +mms_transfer_list_dbus_transfer_finished( + MMSTransferList* list, /* Instance */ + char* id, /* Database record ID */ + char* type) /* Transfer type */ +{ + MMSTransferListDbus* self = MMS_TRANSFER_LIST_DBUS(list); + MMSTransferKey key; + key.id = id; + key.type = type; + if (!g_hash_table_remove(self->transfers, &key)) { + MMS_WARN("Transfer %s/%s not found", id, type); + } +} + +static +MMSTransferDbus* +mms_transfer_list_dbus_find( + MMSTransferListDbus* self, + char* id, + char* type) +{ + MMSTransferDbus* transfer; + MMSTransferKey key; + key.id = id; + key.type = type; + transfer = g_hash_table_lookup(self->transfers, &key); + if (transfer) { + return transfer; + } else { + MMS_WARN("Transfer %s/%s not found", id, type); + return NULL; + } +} + +static +void +mms_transfer_list_dbus_send_progress( + MMSTransferList* list, /* Instance */ + char* id, /* Message ID */ + char* type, /* Transfer type */ + guint sent, /* Bytes sent so far */ + guint total) /* Total bytes to send */ +{ + MMSTransferListDbus* self = MMS_TRANSFER_LIST_DBUS(list); + MMSTransferDbus* transfer = mms_transfer_list_dbus_find(self, id, type); + if (transfer) { + mms_transfer_dbus_send_progress(transfer, sent, total); + } +} + +static +void +mms_transfer_list_dbus_receive_progress( + MMSTransferList* list, /* Instance */ + char* id, /* Message ID */ + char* type, /* Transfer type */ + guint received, /* Bytes received so far */ + guint total) /* Total bytes to receive*/ +{ + MMSTransferListDbus* self = MMS_TRANSFER_LIST_DBUS(list); + MMSTransferDbus* transfer = mms_transfer_list_dbus_find(self, id, type); + if (transfer) { + mms_transfer_dbus_receive_progress(transfer, received, total); + } +} + +/* org.nemomobile.MmsEngine.TransferList.Get */ +static +gboolean +mms_transfer_list_dbus_handle_get( + OrgNemomobileMmsEngineTransferList* proxy, + GDBusMethodInvocation* call, + MMSTransferListDbus* self) +{ + const char* null = NULL; + const gchar *const *list = &null; + const gchar **paths = NULL; + guint n = g_hash_table_size(self->transfers); + if (n) { + guint i = 0; + gpointer value; + GHashTableIter it; + g_hash_table_iter_init(&it, self->transfers); + paths = g_new(const char*, n+1); + MMS_VERBOSE("%u transfer(s)", n); + while (i < n && g_hash_table_iter_next(&it, NULL, &value)) { + MMSTransferDbus* transfer = value; + MMS_VERBOSE(" %s", transfer->path); + paths[i++] = transfer->path; + } + paths[i++] = NULL; + list = paths; + } else { + MMS_VERBOSE("No transfers"); + list = &null; + } + org_nemomobile_mms_engine_transfer_list_complete_get(proxy, call, list); + g_free(paths); + return TRUE; +} + +/** + * First stage of deinitialization (release all references). + * May be called more than once in the lifetime of the object. + */ +static +void +mms_transfer_list_dbus_dispose( + GObject* object) +{ + MMSTransferListDbus* self = MMS_TRANSFER_LIST_DBUS(object); + g_hash_table_remove_all(self->transfers); + if (self->proxy) { + g_dbus_interface_skeleton_unexport( + G_DBUS_INTERFACE_SKELETON(self->proxy)); + g_signal_handler_disconnect(self->proxy, self->list_transfers_id); + g_object_unref(self->proxy); + self->list_transfers_id = 0; + self->proxy = NULL; + } + if (self->bus) { + g_object_unref(self->bus); + self->bus = NULL; + } + G_OBJECT_CLASS(mms_transfer_list_dbus_parent_class)->dispose(object); +} + +/** + * Final stage of deinitialization + */ +static +void +mms_transfer_list_dbus_finalize( + GObject* object) +{ + MMSTransferListDbus* self = MMS_TRANSFER_LIST_DBUS(object); + g_hash_table_destroy(self->transfers); + G_OBJECT_CLASS(mms_transfer_list_dbus_parent_class)->finalize(object); +} + +/** + * Per instance initializer + */ +static +void +mms_transfer_list_dbus_init( + MMSTransferListDbus* self) +{ + self->proxy = org_nemomobile_mms_engine_transfer_list_skeleton_new(); + self->list_transfers_id = g_signal_connect(self->proxy, "handle-get", + G_CALLBACK(mms_transfer_list_dbus_handle_get), self); + self->transfers = g_hash_table_new_full(mms_transfer_key_hash_cb, + mms_transfer_key_equal_cb, NULL, mms_transfer_destroy_cb); +} + +/** + * Per class initializer + */ +static +void +mms_transfer_list_dbus_class_init( + MMSTransferListDbusClass* klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + klass->fn_transfer_started = mms_transfer_list_dbus_transfer_started; + klass->fn_transfer_finished = mms_transfer_list_dbus_transfer_finished; + klass->fn_send_progress = mms_transfer_list_dbus_send_progress; + klass->fn_receive_progress = mms_transfer_list_dbus_receive_progress; + object_class->dispose = mms_transfer_list_dbus_dispose; + object_class->finalize = mms_transfer_list_dbus_finalize; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-transfer-list-dbus/src/mms_transfer_list_dbus_log.h b/mms-transfer-list-dbus/src/mms_transfer_list_dbus_log.h new file mode 100644 index 0000000..128ef29 --- /dev/null +++ b/mms-transfer-list-dbus/src/mms_transfer_list_dbus_log.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016 Jolla Ltd. + * Contact: Slava Monich + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef JOLLA_MMS_TRANSFER_LIST_DBUS_LOG_H +#define JOLLA_MMS_TRANSFER_LIST_DBUS_LOG_H + +#define MMS_LOG_MODULE_NAME mms_transfer_list_log +#include "mms_lib_log.h" + +#endif /* JOLLA_MMS_TRANSFER_LIST_DBUS_LOG_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ + diff --git a/mms.pro b/mms.pro index ee52a60..49ddf19 100644 --- a/mms.pro +++ b/mms.pro @@ -6,6 +6,7 @@ SUBDIRS += \ mms-connman-ofono \ mms-handler-dbus \ mms-settings-dconf \ + mms-transfer-list-dbus \ mms-engine \ mms-dump \ mms-send