From a09d82187c883ddd88853cb5ce9fa8a85762a761 Mon Sep 17 00:00:00 2001 From: Slava Monich Date: Mon, 17 Feb 2014 14:58:57 +0200 Subject: [PATCH] Initial commit --- .gitignore | 24 + README | 13 + mms-dump/Makefile | 101 + mms-dump/mms-dump.c | 968 ++++++++ mms-dump/test/m-acknowledge.ind | Bin 0 -> 33 bytes mms-dump/test/m-delivery.ind | Bin 0 -> 80 bytes mms-dump/test/m-notification_1.0.ind | Bin 0 -> 164 bytes mms-dump/test/m-notification_1.1.ind | Bin 0 -> 155 bytes mms-dump/test/m-notification_1.2.ind | Bin 0 -> 124 bytes mms-dump/test/m-read-orig.ind | Bin 0 -> 118 bytes mms-dump/test/m-read-rec.ind | Bin 0 -> 78 bytes mms-dump/test/m-retrieve_1.0.conf | Bin 0 -> 14650 bytes mms-dump/test/m-retrieve_1.1.conf | Bin 0 -> 87560 bytes mms-dump/test/m-retrieve_1.2.conf | Bin 0 -> 137388 bytes mms-engine/Makefile | 217 ++ mms-engine/main.c | 261 +++ mms-engine/mms-engine.conf | 20 + mms-engine/mms-engine.pro | 54 + mms-engine/mms_engine.c | 521 +++++ mms-engine/mms_engine.h | 65 + mms-engine/org.nemomobile.MmsEngine.dbus.conf | 24 + mms-engine/org.nemomobile.MmsEngine.push.conf | 9 + mms-engine/org.nemomobile.MmsEngine.service | 5 + mms-engine/org.nemomobile.MmsEngine.xml | 211 ++ mms-handler-dbus/Makefile | 115 + mms-handler-dbus/include/mms_handler_dbus.h | 32 + mms-handler-dbus/mms-handler-dbus.pro | 39 + .../spec/org.nemomobile.MmsHandler.xml | 300 +++ mms-handler-dbus/src/mms_handler_dbus.c | 196 ++ .../test/mms_handler_dbus_client/Makefile | 155 ++ .../test_mms_handler_dbus_client.c | 109 + .../test/mms_handler_dbus_server/main.cpp | 35 + .../mms_handler_dbus_server/mmsadaptor.cpp | 74 + .../test/mms_handler_dbus_server/mmsadaptor.h | 96 + .../mms_handler_dbus_server/mmshandler.cpp | 108 + .../test/mms_handler_dbus_server/mmshandler.h | 42 + .../test/mms_handler_dbus_server/mmspart.cpp | 62 + .../test/mms_handler_dbus_server/mmspart.h | 50 + .../org.nemomobile.MmsHandler.conf | 14 + .../test_mms_handler_dbus_server.pro | 26 + mms-lib/Makefile | 107 + mms-lib/include/mms_connection.h | 105 + mms-lib/include/mms_connman.h | 56 + mms-lib/include/mms_dispatcher.h | 92 + mms-lib/include/mms_handler.h | 97 + mms-lib/include/mms_lib_log.h | 44 + mms-lib/include/mms_lib_types.h | 77 + mms-lib/include/mms_lib_util.h | 37 + mms-lib/include/mms_log.h | 286 +++ mms-lib/include/mms_message.h | 72 + mms-lib/mms-lib.pro | 53 + mms-lib/src/mms_codec.c | 1968 +++++++++++++++++ mms-lib/src/mms_codec.h | 200 ++ mms-lib/src/mms_connection.c | 117 + mms-lib/src/mms_connman.c | 83 + mms-lib/src/mms_dispatcher.c | 656 ++++++ mms-lib/src/mms_file_util.c | 124 ++ mms-lib/src/mms_file_util.h | 79 + mms-lib/src/mms_handler.c | 134 ++ mms-lib/src/mms_lib_util.c | 65 + mms-lib/src/mms_log.c | 368 +++ mms-lib/src/mms_message.c | 100 + mms-lib/src/mms_task.c | 298 +++ mms-lib/src/mms_task.h | 227 ++ mms-lib/src/mms_task_ack.c | 71 + mms-lib/src/mms_task_decode.c | 288 +++ mms-lib/src/mms_task_notification.c | 291 +++ mms-lib/src/mms_task_notifyresp.c | 76 + mms-lib/src/mms_task_publish.c | 98 + mms-lib/src/mms_task_read.c | 80 + mms-lib/src/mms_task_retrieve.c | 321 +++ mms-lib/src/mms_task_upload.c | 296 +++ mms-lib/src/mms_util.c | 247 +++ mms-lib/src/mms_util.h | 68 + mms-lib/test/Makefile | 8 + mms-lib/test/common/Makefile | 163 ++ mms-lib/test/common/test_connection.c | 111 + mms-lib/test/common/test_connection.h | 33 + mms-lib/test/common/test_connman.c | 111 + mms-lib/test/common/test_connman.h | 40 + mms-lib/test/common/test_handler.c | 260 +++ mms-lib/test/common/test_handler.h | 50 + mms-lib/test/common/test_http.c | 151 ++ mms-lib/test/common/test_http.h | 57 + mms-lib/test/coverage/run | 38 + mms-lib/test/mms_codec/Makefile | 6 + mms-lib/test/mms_codec/data/m-delivery.ind | Bin 0 -> 52 bytes .../mms_codec/data/m-notification_1.0.ind | Bin 0 -> 125 bytes .../mms_codec/data/m-notification_1.1.ind | Bin 0 -> 116 bytes .../mms_codec/data/m-notification_1.2.ind | Bin 0 -> 114 bytes mms-lib/test/mms_codec/data/m-notifyresp.ind | Bin 0 -> 42 bytes mms-lib/test/mms_codec/data/m-read-orig.ind | Bin 0 -> 79 bytes mms-lib/test/mms_codec/data/m-read-rec.ind | Bin 0 -> 78 bytes .../test/mms_codec/data/m-retrieve_1.0.conf | Bin 0 -> 14722 bytes .../test/mms_codec/data/m-retrieve_1.1.conf | Bin 0 -> 87560 bytes .../test/mms_codec/data/m-retrieve_1.2.conf | Bin 0 -> 137388 bytes mms-lib/test/mms_codec/test_mms_codec.c | 104 + mms-lib/test/read_report/Makefile | 7 + mms-lib/test/read_report/test_read_report.c | 179 ++ mms-lib/test/retrieve/Makefile | 7 + .../retrieve/data/DeliveryInd/m-delivery.ind | Bin 0 -> 52 bytes .../retrieve/data/Expired/m-notification.ind | Bin 0 -> 129 bytes .../test/retrieve/data/GarbagePush/garbage | 1 + .../retrieve/data/GarbageRetrieve/garbage | 1 + .../data/GarbageRetrieve/m-notification.ind | Bin 0 -> 125 bytes .../data/NotAllowed/m-notification.ind | Bin 0 -> 114 bytes .../retrieve/data/NotAllowed/not-allowed.html | 18 + .../retrieve/data/NotFound/m-notification.ind | Bin 0 -> 131 bytes .../retrieve/data/NotFound/not-found.html | 15 + .../retrieve/data/ReadOrigInd/m-read-orig.ind | Bin 0 -> 79 bytes .../data/SoonExpired/m-notification.ind | Bin 0 -> 129 bytes .../retrieve/data/Success/m-acknowledge.ind | Bin 0 -> 33 bytes .../retrieve/data/Success/m-notification.ind | Bin 0 -> 131 bytes .../retrieve/data/Success/m-retrieve.conf | Bin 0 -> 83241 bytes mms-lib/test/retrieve/data/Success/parts/0 | 23 + .../retrieve/data/Success/parts/131200181.jpg | Bin 0 -> 44022 bytes .../retrieve/data/Success/parts/140100041.jpg | Bin 0 -> 38063 bytes .../retrieve/data/Success/parts/text_0011.txt | 1 + .../retrieve/data/Success/parts/text_0021.txt | 1 + .../retrieve/data/UnsupportedPush/unsupported | Bin 0 -> 42 bytes mms-lib/test/retrieve/test_retrieve.c | 434 ++++ mms-lib/test/retrieve_cancel/Makefile | 7 + mms-lib/test/retrieve_cancel/test_connman.c | 93 + mms-lib/test/retrieve_cancel/test_connman.h | 43 + mms-lib/test/retrieve_cancel/test_handler.c | 113 + mms-lib/test/retrieve_cancel/test_handler.h | 43 + .../retrieve_cancel/test_retrieve_cancel.c | 283 +++ mms-ofono/Makefile | 127 ++ mms-ofono/include/mms_ofono_connman.h | 32 + mms-ofono/include/mms_ofono_log.h | 35 + mms-ofono/mms-ofono.pro | 130 ++ .../spec/org.ofono.ConnectionContext.xml | 17 + .../spec/org.ofono.ConnectionManager.xml | 37 + mms-ofono/spec/org.ofono.Manager.xml | 18 + mms-ofono/spec/org.ofono.MessageManager.xml | 42 + mms-ofono/spec/org.ofono.Modem.xml | 19 + .../spec/org.ofono.NetworkRegistration.xml | 22 + mms-ofono/spec/org.ofono.SimManager.xml | 45 + mms-ofono/src/mms_ofono_connection.c | 279 +++ mms-ofono/src/mms_ofono_connection.h | 58 + mms-ofono/src/mms_ofono_connman.c | 176 ++ mms-ofono/src/mms_ofono_context.c | 196 ++ mms-ofono/src/mms_ofono_context.h | 53 + mms-ofono/src/mms_ofono_manager.c | 191 ++ mms-ofono/src/mms_ofono_manager.h | 41 + mms-ofono/src/mms_ofono_modem.c | 392 ++++ mms-ofono/src/mms_ofono_modem.h | 56 + mms-ofono/src/mms_ofono_names.h | 47 + mms-ofono/src/mms_ofono_types.h | 34 + rpm/mms-engine.spec | 53 + 150 files changed, 15728 insertions(+) create mode 100644 .gitignore create mode 100644 README create mode 100644 mms-dump/Makefile create mode 100644 mms-dump/mms-dump.c create mode 100644 mms-dump/test/m-acknowledge.ind create mode 100644 mms-dump/test/m-delivery.ind create mode 100644 mms-dump/test/m-notification_1.0.ind create mode 100644 mms-dump/test/m-notification_1.1.ind create mode 100644 mms-dump/test/m-notification_1.2.ind create mode 100644 mms-dump/test/m-read-orig.ind create mode 100644 mms-dump/test/m-read-rec.ind create mode 100644 mms-dump/test/m-retrieve_1.0.conf create mode 100644 mms-dump/test/m-retrieve_1.1.conf create mode 100644 mms-dump/test/m-retrieve_1.2.conf create mode 100644 mms-engine/Makefile create mode 100644 mms-engine/main.c create mode 100644 mms-engine/mms-engine.conf create mode 100644 mms-engine/mms-engine.pro create mode 100644 mms-engine/mms_engine.c create mode 100644 mms-engine/mms_engine.h create mode 100644 mms-engine/org.nemomobile.MmsEngine.dbus.conf create mode 100644 mms-engine/org.nemomobile.MmsEngine.push.conf create mode 100644 mms-engine/org.nemomobile.MmsEngine.service create mode 100644 mms-engine/org.nemomobile.MmsEngine.xml create mode 100644 mms-handler-dbus/Makefile create mode 100644 mms-handler-dbus/include/mms_handler_dbus.h create mode 100644 mms-handler-dbus/mms-handler-dbus.pro create mode 100644 mms-handler-dbus/spec/org.nemomobile.MmsHandler.xml create mode 100644 mms-handler-dbus/src/mms_handler_dbus.c create mode 100644 mms-handler-dbus/test/mms_handler_dbus_client/Makefile create mode 100644 mms-handler-dbus/test/mms_handler_dbus_client/test_mms_handler_dbus_client.c create mode 100644 mms-handler-dbus/test/mms_handler_dbus_server/main.cpp create mode 100644 mms-handler-dbus/test/mms_handler_dbus_server/mmsadaptor.cpp create mode 100644 mms-handler-dbus/test/mms_handler_dbus_server/mmsadaptor.h create mode 100644 mms-handler-dbus/test/mms_handler_dbus_server/mmshandler.cpp create mode 100644 mms-handler-dbus/test/mms_handler_dbus_server/mmshandler.h create mode 100644 mms-handler-dbus/test/mms_handler_dbus_server/mmspart.cpp create mode 100644 mms-handler-dbus/test/mms_handler_dbus_server/mmspart.h create mode 100644 mms-handler-dbus/test/mms_handler_dbus_server/org.nemomobile.MmsHandler.conf create mode 100644 mms-handler-dbus/test/mms_handler_dbus_server/test_mms_handler_dbus_server.pro create mode 100644 mms-lib/Makefile create mode 100644 mms-lib/include/mms_connection.h create mode 100644 mms-lib/include/mms_connman.h create mode 100644 mms-lib/include/mms_dispatcher.h create mode 100644 mms-lib/include/mms_handler.h create mode 100644 mms-lib/include/mms_lib_log.h create mode 100644 mms-lib/include/mms_lib_types.h create mode 100644 mms-lib/include/mms_lib_util.h create mode 100644 mms-lib/include/mms_log.h create mode 100644 mms-lib/include/mms_message.h create mode 100644 mms-lib/mms-lib.pro create mode 100644 mms-lib/src/mms_codec.c create mode 100644 mms-lib/src/mms_codec.h create mode 100644 mms-lib/src/mms_connection.c create mode 100644 mms-lib/src/mms_connman.c create mode 100644 mms-lib/src/mms_dispatcher.c create mode 100644 mms-lib/src/mms_file_util.c create mode 100644 mms-lib/src/mms_file_util.h create mode 100644 mms-lib/src/mms_handler.c create mode 100644 mms-lib/src/mms_lib_util.c create mode 100644 mms-lib/src/mms_log.c create mode 100644 mms-lib/src/mms_message.c create mode 100644 mms-lib/src/mms_task.c create mode 100644 mms-lib/src/mms_task.h create mode 100644 mms-lib/src/mms_task_ack.c create mode 100644 mms-lib/src/mms_task_decode.c create mode 100644 mms-lib/src/mms_task_notification.c create mode 100644 mms-lib/src/mms_task_notifyresp.c create mode 100644 mms-lib/src/mms_task_publish.c create mode 100644 mms-lib/src/mms_task_read.c create mode 100644 mms-lib/src/mms_task_retrieve.c create mode 100644 mms-lib/src/mms_task_upload.c create mode 100644 mms-lib/src/mms_util.c create mode 100644 mms-lib/src/mms_util.h create mode 100644 mms-lib/test/Makefile create mode 100644 mms-lib/test/common/Makefile create mode 100644 mms-lib/test/common/test_connection.c create mode 100644 mms-lib/test/common/test_connection.h create mode 100644 mms-lib/test/common/test_connman.c create mode 100644 mms-lib/test/common/test_connman.h create mode 100644 mms-lib/test/common/test_handler.c create mode 100644 mms-lib/test/common/test_handler.h create mode 100644 mms-lib/test/common/test_http.c create mode 100644 mms-lib/test/common/test_http.h create mode 100755 mms-lib/test/coverage/run create mode 100644 mms-lib/test/mms_codec/Makefile create mode 100644 mms-lib/test/mms_codec/data/m-delivery.ind create mode 100644 mms-lib/test/mms_codec/data/m-notification_1.0.ind create mode 100644 mms-lib/test/mms_codec/data/m-notification_1.1.ind create mode 100644 mms-lib/test/mms_codec/data/m-notification_1.2.ind create mode 100644 mms-lib/test/mms_codec/data/m-notifyresp.ind create mode 100644 mms-lib/test/mms_codec/data/m-read-orig.ind create mode 100644 mms-lib/test/mms_codec/data/m-read-rec.ind create mode 100644 mms-lib/test/mms_codec/data/m-retrieve_1.0.conf create mode 100644 mms-lib/test/mms_codec/data/m-retrieve_1.1.conf create mode 100644 mms-lib/test/mms_codec/data/m-retrieve_1.2.conf create mode 100644 mms-lib/test/mms_codec/test_mms_codec.c create mode 100644 mms-lib/test/read_report/Makefile create mode 100644 mms-lib/test/read_report/test_read_report.c create mode 100644 mms-lib/test/retrieve/Makefile create mode 100644 mms-lib/test/retrieve/data/DeliveryInd/m-delivery.ind create mode 100644 mms-lib/test/retrieve/data/Expired/m-notification.ind create mode 100644 mms-lib/test/retrieve/data/GarbagePush/garbage create mode 100644 mms-lib/test/retrieve/data/GarbageRetrieve/garbage create mode 100644 mms-lib/test/retrieve/data/GarbageRetrieve/m-notification.ind create mode 100644 mms-lib/test/retrieve/data/NotAllowed/m-notification.ind create mode 100644 mms-lib/test/retrieve/data/NotAllowed/not-allowed.html create mode 100644 mms-lib/test/retrieve/data/NotFound/m-notification.ind create mode 100644 mms-lib/test/retrieve/data/NotFound/not-found.html create mode 100644 mms-lib/test/retrieve/data/ReadOrigInd/m-read-orig.ind create mode 100644 mms-lib/test/retrieve/data/SoonExpired/m-notification.ind create mode 100644 mms-lib/test/retrieve/data/Success/m-acknowledge.ind create mode 100644 mms-lib/test/retrieve/data/Success/m-notification.ind create mode 100644 mms-lib/test/retrieve/data/Success/m-retrieve.conf create mode 100644 mms-lib/test/retrieve/data/Success/parts/0 create mode 100644 mms-lib/test/retrieve/data/Success/parts/131200181.jpg create mode 100644 mms-lib/test/retrieve/data/Success/parts/140100041.jpg create mode 100644 mms-lib/test/retrieve/data/Success/parts/text_0011.txt create mode 100644 mms-lib/test/retrieve/data/Success/parts/text_0021.txt create mode 100644 mms-lib/test/retrieve/data/UnsupportedPush/unsupported create mode 100644 mms-lib/test/retrieve/test_retrieve.c create mode 100644 mms-lib/test/retrieve_cancel/Makefile create mode 100644 mms-lib/test/retrieve_cancel/test_connman.c create mode 100644 mms-lib/test/retrieve_cancel/test_connman.h create mode 100644 mms-lib/test/retrieve_cancel/test_handler.c create mode 100644 mms-lib/test/retrieve_cancel/test_handler.h create mode 100644 mms-lib/test/retrieve_cancel/test_retrieve_cancel.c create mode 100644 mms-ofono/Makefile create mode 100644 mms-ofono/include/mms_ofono_connman.h create mode 100644 mms-ofono/include/mms_ofono_log.h create mode 100644 mms-ofono/mms-ofono.pro create mode 100644 mms-ofono/spec/org.ofono.ConnectionContext.xml create mode 100644 mms-ofono/spec/org.ofono.ConnectionManager.xml create mode 100644 mms-ofono/spec/org.ofono.Manager.xml create mode 100644 mms-ofono/spec/org.ofono.MessageManager.xml create mode 100644 mms-ofono/spec/org.ofono.Modem.xml create mode 100644 mms-ofono/spec/org.ofono.NetworkRegistration.xml create mode 100644 mms-ofono/spec/org.ofono.SimManager.xml create mode 100644 mms-ofono/src/mms_ofono_connection.c create mode 100644 mms-ofono/src/mms_ofono_connection.h create mode 100644 mms-ofono/src/mms_ofono_connman.c create mode 100644 mms-ofono/src/mms_ofono_context.c create mode 100644 mms-ofono/src/mms_ofono_context.h create mode 100644 mms-ofono/src/mms_ofono_manager.c create mode 100644 mms-ofono/src/mms_ofono_manager.h create mode 100644 mms-ofono/src/mms_ofono_modem.c create mode 100644 mms-ofono/src/mms_ofono_modem.h create mode 100644 mms-ofono/src/mms_ofono_names.h create mode 100644 mms-ofono/src/mms_ofono_types.h create mode 100644 rpm/mms-engine.spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c6b2424 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +*~ +mms-engine/mms-engine.pro.user +mms-engine/build +mms-lib/mms-lib.pro.user +mms-lib/build +mms-lib/test/coverage/full.gcov +mms-lib/test/coverage/mms-lib.gcov +mms-lib/test/coverage/results +mms-lib/test/mms_codec/build +mms-lib/test/mms_lib_test.ncb +mms-lib/test/mms_lib_test.opt +mms-lib/test/read_report/build +mms-lib/test/retrieve/build +mms-lib/test/retrieve_cancel/build +mms-ofono/mms-ofono.pro.user +mms-ofono/build +mms-handler-dbus/mms-handler-dbus.pro.user +mms-handler-dbus/build +mms-handler-dbus/test/mms_handler_dbus_server/build +mms-handler-dbus/test/mms_handler_dbus_server/test_mms_handler_dbus_server.pro.user +mms-handler-dbus/test/mms_handler_dbus_client/build +mms-dump/build +mms-dump/mms_dump.ncb +mms-dump/mms_dump.opt diff --git a/README b/README new file mode 100644 index 0000000..3a96976 --- /dev/null +++ b/README @@ -0,0 +1,13 @@ +MMS engine. + +Copyright (C) 2013-2014 Jolla Ltd. +Copyright (C) 2010-2011 Intel Corporation. + +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. diff --git a/mms-dump/Makefile b/mms-dump/Makefile new file mode 100644 index 0000000..5e0551c --- /dev/null +++ b/mms-dump/Makefile @@ -0,0 +1,101 @@ +# -*- Mode: makefile -*- + +.PHONY: all debug release clean + +# Required packages +PKGS = glib-2.0 libwspcodec +LIB_PKGS = $(PKGS) + +# +# Default target +# + +all: debug release + +# +# Sources +# + +SRC = mms-dump.c + +# +# Directories +# + +SRC_DIR = . +BUILD_DIR = build +DEBUG_BUILD_DIR = $(BUILD_DIR)/debug +RELEASE_BUILD_DIR = $(BUILD_DIR)/release + +# +# Tools and flags +# + +CC = $(CROSS_COMPILE)gcc +LD = $(CC) +DEBUG_FLAGS = -g +RELEASE_FLAGS = -O2 +DEBUG_DEFS = -DDEBUG +RELEASE_DEFS = +WARNINGS = -Wall +CFLAGS = $(shell pkg-config --cflags $(PKGS)) -MMD +LIBS = $(shell pkg-config --libs $(LIB_PKGS)) + +DEBUG_CFLAGS = $(WARNINGS) $(DEBUG_FLAGS) $(DEBUG_DEFS) $(CFLAGS) +RELEASE_CFLAGS = $(WARNINGS) $(RELEASE_FLAGS) $(RELEASE_DEFS) $(CFLAGS) +DEBUG_LIBS = $(LIBS) +RELEASE_LIBS = $(LIBS) + +# +# Files +# + +DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) +RELEASE_OBJS = $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o) + +# +# Dependencies +# + +DEBUG_EXE_DEPS = $(DEBUG_BUILD_DIR) +RELEASE_EXE_DEPS = $(RELEASE_BUILD_DIR) +DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d) +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(DEPS)),) +-include $(DEPS) +endif +endif + +# +# Rules +# + +EXE = mms-dump +DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE) +RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE) + +debug: $(DEBUG_EXE) + +release: $(RELEASE_EXE) + +clean: + rm -fr $(BUILD_DIR) $(SRC_DIR)/*~ + +$(DEBUG_BUILD_DIR): + mkdir -p $@ + +$(RELEASE_BUILD_DIR): + mkdir -p $@ + +$(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_EXE): $(DEBUG_EXE_DEPS) $(DEBUG_OBJS) + $(LD) $(DEBUG_FLAGS) $(DEBUG_OBJS) $(DEBUG_LIBS) -o $@ + +$(RELEASE_EXE): $(RELEASE_EXE_DEPS) $(RELEASE_OBJS) + $(LD) $(RELEASE_FLAGS) $(RELEASE_OBJS) $(RELEASE_LIBS) -o $@ + strip $@ diff --git a/mms-dump/mms-dump.c b/mms-dump/mms-dump.c new file mode 100644 index 0000000..c2788cb --- /dev/null +++ b/mms-dump/mms-dump.c @@ -0,0 +1,968 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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 +#include +#include +#include + +static const char pname[] = "mms-dump"; + +enum app_ret_value { + RET_OK, + RET_ERR_CMDLINE, + RET_ERR_IO, + RET_ERR_DECODE +}; + +#define MMS_DUMP_FLAG_VERBOSE (0x01) + +#define WSP_QUOTE (127) + +struct mms_named_value { + const char* name; + unsigned int value; +}; + +typedef gboolean +(*mms_value_decoder)( + enum wsp_value_type type, + const guint8* val, + unsigned int len, + unsigned int flags); + +#define MMS_CONTENT_TYPE "application/vnd.wap.mms-message" + +#define MMS_WELL_KNOWN_HEADERS(h) \ + h(BCC, "Bcc", 0x01, etext )\ + h(CC, "Cc", 0x02, etext )\ + h(CONTENT_LOCATION, "X-Mms-Content-Location", 0x03, text )\ + h(CONTENT_TYPE, "Content-Type", 0x04, unknown )\ + h(DATE, "Date", 0x05, date )\ + h(DELIVERY_REPORT, "X-Mms-Delivery-Report", 0x06, bool )\ + h(DELIVERY_TIME, "X-Mms-Delivery-Time", 0x07, unknown )\ + h(EXPIRY, "X-Mms-Expiry", 0x08, expiry )\ + h(FROM, "From", 0x09, from )\ + h(MESSAGE_CLASS, "X-Mms-Message-Class", 0x0A, mclass )\ + h(MESSAGE_ID, "Message-ID", 0x0B, text )\ + h(MESSAGE_TYPE, "X-Mms-Message-Type", 0x0C, mtype )\ + h(MMS_VERSION, "X-Mms-MMS-Version", 0x0D, version )\ + h(MESSAGE_SIZE, "X-Mms-Message-Size", 0x0E, long )\ + h(PRIORITY, "X-Mms-Priority", 0x0F, prio )\ + h(READ_REPORT, "X-Mms-Read-Report", 0x10, bool )\ + h(REPORT_ALLOWED, "X-Mms-Report-Allowed", 0x11, bool )\ + h(RESPONSE_STATUS, "X-Mms-Response-Status", 0x12, short )\ + h(RESPONSE_TEXT, "X-Mms-Response-Text", 0x13, etext )\ + h(SENDER_VISIBILITY, "X-Mms-Sender-Visibility", 0x14, short )\ + h(STATUS, "X-Mms-Status", 0x15, status )\ + h(SUBJECT, "Subject", 0x16, etext )\ + h(TO, "To", 0x17, etext )\ + h(TRANSACTION_ID, "X-Mms-Transaction-Id", 0x18, text )\ + h(RETRIEVE_STATUS, "X-Mms-Retrieve-Status", 0x19, retrieve )\ + h(RETRIEVE_TEXT, "X-Mms-Retrieve-Text", 0x1A, etext )\ + h(READ_STATUS, "X-Mms-Read-Status", 0x1B, rstatus )\ + h(REPLY_CHARGING, "X-Mms-Reply-Charging", 0x1C, short )\ + h(REPLY_CHARGING_DEADLINE,"X-Mms-Reply-Charging-Deadline",0x1D, unknown )\ + h(REPLY_CHARGING_ID, "X-Mms-Reply-Charging-ID", 0x1E, text )\ + h(REPLY_CHARGING_SIZE, "X-Mms-Reply-Charging-Size", 0x1F, long )\ + h(PREVIOUSLY_SENT_BY, "X-Mms-Previously-Sent-By", 0x20, unknown )\ + h(PREVIOUSLY_SENT_DATE, "X-Mms-Previously-Sent-Date", 0x21, unknown ) + +#define WSP_WELL_KNOWN_HEADERS(h) \ + h(CONTENT_LOCATION, "Content-Location", 0x0E, text )\ + h(CONTENT_DISPOSITION, "Content-Disposition", 0x2E, contdisp )\ + h(CONTENT_ID, "Content-ID", 0x40, quote )\ + h(CONTENT_DISPOSITION2, "Content-Disposition", 0x45, contdisp ) + +#define MMS_HEADER_ID(id) MMS_HEADER_##id +#define MMS_PART_HEADER_ID(id) MMS_PART_HEADER_##id + +typedef enum mms_header { + MMS_HEADER_INVALID, +#define h(id,n,x,t) MMS_HEADER_ID(id) = x, + MMS_WELL_KNOWN_HEADERS(h) +#undef h + MMS_HEADER_END, +} MMS_HEADER; + +typedef enum mms_part_header { +#define h(id,n,x,t) MMS_PART_HEADER_ID(id) = x, + WSP_WELL_KNOWN_HEADERS(h) +#undef h +} MMS_PART_HEADER; + +static +const char* +mms_message_well_known_header_name( + int hdr) +{ + static char unknown[6]; + switch (hdr) { +#define h(id,n,x,t) case MMS_HEADER_ID(id): return n; + MMS_WELL_KNOWN_HEADERS(h) +#undef h + default: + snprintf(unknown, sizeof(unknown), "0x%02X", hdr); + unknown[sizeof(unknown)-1] = 0; + return unknown; + } +} + +static +const char* +mms_part_well_known_header_name( + int hdr) +{ + static char unknown[6]; + switch (hdr) { +#define h(id,n,x,t) case MMS_PART_HEADER_ID(id): return n; + WSP_WELL_KNOWN_HEADERS(h) +#undef h + default: + snprintf(unknown, sizeof(unknown), "0x%02X", hdr); + unknown[sizeof(unknown)-1] = 0; + return unknown; + } +} + +static +const struct mms_named_value* +mms_find_named_value( + const struct mms_named_value* values, + unsigned int num_values, + unsigned int value) +{ + unsigned int i; + for (i=0; i 1) { + unsigned int i; + printf("%02X", val[0]); + for (i=1; i *TEXT End-of-string */ + if (type == WSP_VALUE_TYPE_TEXT && len > 0 && val[0] == 0x22) { + printf("%s", val+1); + mms_value_verbose_dump(val, len, flags); + return TRUE; + } + return FALSE; +} + +static +gboolean +mms_value_decode_enum( + enum wsp_value_type type, + const guint8* val, + unsigned int len, + const struct mms_named_value* values, + unsigned int num_values, + unsigned int flags) +{ + if (type == WSP_VALUE_TYPE_SHORT && len == 1) { + const struct mms_named_value* nv; + nv = mms_find_named_value(values, num_values, val[0]); + if (nv) { + printf("%s", nv->name); + if (flags & MMS_DUMP_FLAG_VERBOSE) printf(" (%u)", nv->value); + return TRUE; + } + } + return mms_value_decode_unknown(type, val, len, flags); +} + +static +gboolean +mms_value_decode_version( + enum wsp_value_type type, + const guint8* val, + unsigned int len, + unsigned int flags) +{ + if (type == WSP_VALUE_TYPE_SHORT && len == 1) { + const unsigned int value = val[0]; + printf("%u.%u", (val[0] & 0x70) >> 4, val[0] & 0x0f); + if (flags & MMS_DUMP_FLAG_VERBOSE) printf(" (%u)", value); + return TRUE; + } + return mms_value_decode_unknown(type, val, len, flags); +} + +static +gboolean +mms_value_decode_long( + enum wsp_value_type type, + const guint8* val, + unsigned int len, + unsigned int flags) +{ + unsigned long long_val; + if (type == WSP_VALUE_TYPE_LONG && len <= sizeof(long_val)) { + unsigned int i; + for (long_val = 0, i=0; iname)) { + gsize bytes_in, bytes_out; + text = tmp = g_convert((char*)val+consumed, len-consumed, + dest_charset, cs->name, &bytes_in, &bytes_out, NULL); + } else { + if (val[consumed] == WSP_QUOTE) consumed++; + if (consumed <= len) text = (char*)val+consumed; + } + if (text) { + printf("%s", text); + mms_value_verbose_dump(val, len, flags); + g_free(tmp); + return TRUE; + } + } + } + } + return mms_value_decode_unknown(type, val, len, flags); +} + +static +gboolean +mms_value_decode_from( + enum wsp_value_type type, + const guint8* val, + unsigned int len, + unsigned int flags) +{ + /* + * Address-present-token Encoded-string-value | Insert-address-token + * Address-present-token = + * Insert-address-token = + */ + if (type == WSP_VALUE_TYPE_LONG && len > 0) { + if (val[0] == 0x81) { + printf(""); + if (flags & MMS_DUMP_FLAG_VERBOSE) printf(" (%u)", val[0]); + return TRUE; + } else if (val[0] == 0x80 && len > 1) { + enum wsp_value_type ftype; + const void* fval = NULL; + unsigned int flen = 0; + if (wsp_decode_field(val+1, len-1, &ftype, &fval, &flen, NULL) && + mms_value_decode_etext(ftype, fval, flen, 0)) { + mms_value_verbose_dump(val, len, flags); + return TRUE; + } + } + } + return mms_value_decode_unknown(type, val, len, flags); +} + +static +gboolean +mms_value_decode_expiry( + enum wsp_value_type type, + const guint8* val, + unsigned int len, + unsigned int flags) +{ + /* + * Absolute-token Date-value | Relative-token Delta-seconds-value + * Absolute-token = + * Relative-token = + */ + gboolean ok = FALSE; + enum wsp_value_type ftype; + const void* fval = NULL; + unsigned int flen = 0; + if (type == WSP_VALUE_TYPE_LONG && len > 1 && + wsp_decode_field(val+1, len-1, &ftype, &fval, &flen, NULL)) { + if (val[0] == 0x80 /* Absolute-token */) { + ok = mms_value_decode_date(ftype, fval, flen, 0); + } else if (val[0] == 0x81 /* Relative-token */) { + time_t t; + if (ftype == WSP_VALUE_TYPE_LONG && flen > 0 && flen <= sizeof(t)) { + unsigned int i; + for (t=0, i=0; i + * Length-quote = + * Length = Uintvar-integer + * + * Disposition = Form-data | Attachment | Inline | Token-text + * Form-data = + * Attachment = + * Inline = + */ + static const struct mms_named_value nv_d [] = { + { "Form-data", 128 }, + { "Attachment", 129 }, + { "Inline", 130 } + }; + + static const struct mms_named_value nv_p [] = { + { "Q", 0x00 }, + { "Charset", 0x01 }, + { "Level", 0x02 }, + { "Type", 0x03 }, + { "Name", 0x05 }, + { "Filename", 0x06 }, + { "Differences", 0x07 }, + { "Padding", 0x08 }, + { "Type", 0x09 }, + { "Start", 0x0A }, + { "Start-info", 0x0B }, + { "Comment", 0x0C }, + { "Domain", 0x0D }, + { "Max-Age", 0x0E }, + { "Path", 0x0F }, + { "Secure", 0x10 }, + { "SEC", 0x11 }, + { "MAC", 0x12 }, + { "Creation-date", 0x13 }, + { "Modification-date", 0x14 }, + { "Read-date", 0x15 }, + { "Size", 0x16 }, + { "Name", 0x17 }, + { "Filename", 0x18 }, + { "Start", 0x19 }, + { "Start-info", 0x1A }, + { "Comment", 0x1B }, + { "Domain", 0x1C }, + { "Path", 0x1D } + }; + + if ((type == WSP_VALUE_TYPE_LONG || + type == WSP_VALUE_TYPE_SHORT) && len > 0) { + const struct mms_named_value* nv; + nv = mms_find_named_value(nv_d, G_N_ELEMENTS(nv_d), val[0]); + if (nv) { + struct wsp_parameter_iter pi; + struct wsp_parameter p; + wsp_parameter_iter_init(&pi, val + 1, len - 1); + printf("%s", nv->name); + while (wsp_parameter_iter_next(&pi, &p)) { + nv = mms_find_named_value(nv_p, G_N_ELEMENTS(nv_p), p.type); + if (nv) { + printf("; %s=", nv->name); + } else { + printf(";0x%02x=", p.type); + } + switch (p.value) { + case WSP_PARAMETER_VALUE_TEXT: + printf("%s", p.text); + break; + case WSP_PARAMETER_VALUE_INT: + printf("%u", p.integer); + break; + case WSP_PARAMETER_VALUE_DATE: + mms_value_print_date(p.date); + break; + case WSP_PARAMETER_VALUE_Q: + printf("%g", p.q); + break;; + } + } + mms_value_verbose_dump(val, len, flags); + return TRUE; + } + } + return mms_value_decode_unknown(type, val, len, flags); +} + +#define mms_value_decode_short mms_value_decode_unknown +#define mms_value_decode_text mms_value_decode_unknown + +static +mms_value_decoder +mms_message_value_decoder_for_header( + const char* hdr) +{ +#define h(id,n,x,t) if (!strcmp(n,hdr)) return &mms_value_decode_##t; + MMS_WELL_KNOWN_HEADERS(h); +#undef h + return &mms_value_decode_unknown; +} + +static +mms_value_decoder +mms_part_value_decoder_for_header( + const char* hdr) +{ +#define h(id,n,x,t) if (!strcmp(n,hdr)) return &mms_value_decode_##t; + WSP_WELL_KNOWN_HEADERS(h); +#undef h + return &mms_value_decode_unknown; +} + +static +gboolean +mms_decode_headers( + struct wsp_header_iter* iter, + const char* prefix, + unsigned int flags, + const char* (*well_known_header_name)(int hdr), + mms_value_decoder (*value_decoder_for_header)(const char* hdr)) +{ + while (wsp_header_iter_next(iter)) { + const guint8* hdr = wsp_header_iter_get_hdr(iter); + const guint8* val = wsp_header_iter_get_val(iter); + unsigned int val_len = wsp_header_iter_get_val_len(iter); + mms_value_decoder dec; + const char* hdr_name; + + switch (wsp_header_iter_get_hdr_type(iter)) { + case WSP_HEADER_TYPE_WELL_KNOWN: + hdr_name = well_known_header_name(hdr[0] & 0x7f); + break; + case WSP_HEADER_TYPE_APPLICATION: + hdr_name = (const char*)hdr; + break; + default: + return FALSE; + } + printf("%s%s: ", prefix, hdr_name); + dec = value_decoder_for_header(hdr_name); + if (!dec(wsp_header_iter_get_val_type(iter), val, val_len, flags)) { + printf("ERROR!\n"); + return FALSE; + } + printf("\n"); + } + return TRUE; +} + +static +gboolean +mms_message_decode_headers( + struct wsp_header_iter* iter, + const char* prefix, + unsigned int flags) +{ + return mms_decode_headers(iter, prefix, flags, + mms_message_well_known_header_name, + mms_message_value_decoder_for_header); +} + +static +gboolean +mms_part_decode_headers( + struct wsp_header_iter* iter, + const char* prefix, + unsigned int flags) +{ + return mms_decode_headers(iter, prefix, flags, + mms_part_well_known_header_name, + mms_part_value_decoder_for_header); +} + +static +const char* +mms_decode_charset( + const unsigned char *pdu, + unsigned int len) +{ + struct wsp_parameter_iter iter; + struct wsp_parameter param; + wsp_parameter_iter_init(&iter, pdu, len); + while (wsp_parameter_iter_next(&iter, ¶m)) { + if (param.type == WSP_PARAMETER_TYPE_CHARSET) + return param.text; + } + return NULL; +} + +static +gboolean +mms_decode_attachments( + struct wsp_header_iter* iter, + unsigned int flags) +{ + struct wsp_multipart_iter mi; + if (wsp_multipart_iter_init(&mi, iter, NULL, NULL)) { + int i; + for (i=0; wsp_multipart_iter_next(&mi); i++) { + unsigned int n; + const void* type; + const unsigned char* ct = wsp_multipart_iter_get_content_type(&mi); + unsigned int ct_len = wsp_multipart_iter_get_content_type_len(&mi); + if (wsp_decode_content_type(ct, ct_len, &type, &n, NULL)) { + struct wsp_header_iter hi; + const char* cs = mms_decode_charset(ct + n, ct_len - n); + const unsigned char* body = wsp_multipart_iter_get_body(&mi); + unsigned int len = wsp_multipart_iter_get_body_len(&mi); + unsigned int off = body - wsp_header_iter_get_pdu(iter); + printf("Attachment #%d:\n", i+1); + if (flags & MMS_DUMP_FLAG_VERBOSE) { + printf("Offset: %u (0x%x)\n", off, off); + printf("Length: %u (0x%x)\n", len, len); + } else { + printf("Offset: %u\n", off); + printf("Length: %u\n", len); + } + if (cs) { + printf(" Content-Type: %s;charset=%s\n", (char*)type, cs); + } else { + printf(" Content-Type: %s\n", (char*)type); + } + wsp_header_iter_init(&hi, wsp_multipart_iter_get_hdr(&mi), + wsp_multipart_iter_get_hdr_len(&mi), 0); + if (mms_part_decode_headers(&hi, " ", flags) && + wsp_header_iter_at_end(&hi)) { + continue; + } + } + return FALSE; + } + return wsp_multipart_iter_close(&mi, iter); + } + return FALSE; +} + +static +int +mms_decode_data( + const guint8* data, + gsize len, + unsigned int flags) +{ + struct wsp_header_iter iter; + + /* Skip WSP Push notification header if we find one */ + if (len >= 3 && data[1] == 6 /* Push PDU */) { + unsigned int hdrlen = 0; + unsigned int off = 0; + const guint8* wsp_data = data+2; + gsize wsp_len = len - 2; + + /* Hdrlen */ + if (wsp_decode_uintvar(wsp_data, wsp_len, &hdrlen, &off) && + (off + hdrlen) <= wsp_len) { + const void* ct = NULL; + wsp_data += off; + wsp_len -= off; + if (wsp_decode_content_type(wsp_data, hdrlen, &ct, &off, NULL) && + strcmp(ct, MMS_CONTENT_TYPE) == 0) { + printf("WSP header:\n %s\n", (char*)ct); + data = wsp_data + hdrlen; + len = wsp_len - hdrlen; + } + } + } + + printf("MMS headers:\n"); + wsp_header_iter_init(&iter, data, len, WSP_HEADER_ITER_FLAG_REJECT_CP | + WSP_HEADER_ITER_FLAG_DETECT_MMS_MULTIPART); + if (mms_message_decode_headers(&iter, " ", flags) && + (wsp_header_iter_at_end(&iter) || + (wsp_header_iter_is_multipart(&iter) && + mms_decode_attachments(&iter, flags) && + wsp_header_iter_at_end(&iter)))) { + return RET_OK; + } else { + printf("Decoding FAILED\n"); + } + return RET_ERR_DECODE; +} + +static +int +mms_decode_file( + const char* fname, + unsigned int flags) +{ + int ret = RET_ERR_IO; + GError* error = NULL; + GMappedFile* map = g_mapped_file_new(fname, FALSE, &error); + if (map) { + const void* data = g_mapped_file_get_contents(map); + const gsize size = g_mapped_file_get_length(map); + ret = mms_decode_data(data, size, flags); + g_mapped_file_unref(map); + } else { + printf("%s: %s\n", pname, error->message); + g_error_free(error); + } + return ret; +} + +int main(int argc, char* argv[]) +{ + int ret = RET_ERR_CMDLINE; + gboolean ok, verbose = FALSE; + GError* error = NULL; + GOptionEntry entries[] = { + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, + "Enable verbose output", NULL }, + { NULL } + }; + GOptionContext* options = g_option_context_new("FILES"); + g_option_context_add_main_entries(options, entries, NULL); + ok = g_option_context_parse(options, &argc, &argv, &error); + if (ok) { + if (argc > 1) { + int i, flags = 0; + if (verbose) flags |= MMS_DUMP_FLAG_VERBOSE; + for (i=1; i 2) printf("\n%s\n\n", fname); + ret = mms_decode_file(fname, flags); + if (ret != RET_OK) break; + } + } else { + char* help = g_option_context_get_help(options, TRUE, NULL); + printf("%s", help); + g_free(help); + } + } else { + printf("%s: %s\n", pname, error->message); + g_error_free(error); + } + g_option_context_free(options); + return ret; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-dump/test/m-acknowledge.ind b/mms-dump/test/m-acknowledge.ind new file mode 100644 index 0000000000000000000000000000000000000000..2b944dbdbafecf1ff14a784d56b95266f2c13ed9 GIT binary patch literal 33 ocmeBao#EtR7VhP0~82#k(;PzZe*gDoS)0kJ8@zI0Js28OWmw;Gcydo$@5EM?pe^+* k-A*1xCeBV?UXCUP;f4%T8>btaT9_J`SQuMcnwu~H0Fg8r^Z)<= literal 0 HcmV?d00001 diff --git a/mms-dump/test/m-notification_1.0.ind b/mms-dump/test/m-notification_1.0.ind new file mode 100644 index 0000000000000000000000000000000000000000..19c60ee610fde7fa62346bd41b76864448943e31 GIT binary patch literal 164 zcmZo>Q%Ni+$jMAjEXmBz(=W?Q(JN0Z(96v&*3C^VE>28OW!TcbzNM#WMy{bjj%BWS zsey5Ba*0t^QnI0u15lY>Qfg{WW?rgZQ7J?3gieVDZF5TlQzKI&V-rgw{gB82SK9y| sUq6PfhCZgm;~lJx%*1L+bVzGq*0N++Pk^lez literal 0 HcmV?d00001 diff --git a/mms-dump/test/m-notification_1.1.ind b/mms-dump/test/m-notification_1.1.ind new file mode 100644 index 0000000000000000000000000000000000000000..043e00e8453107f19e1dc79d95e35745c8315235 GIT binary patch literal 155 zcmZQ%Q%Ni+$jMAjEXmBz(=W?Q(JN0Z(96v&*3C^VE>28OWmw;GcydqE3?~mmXSVT6nzYB vjUB9w%*UcCa=wGk>XX&L}A28OWmw;Gcydoi@5EM?pe^;& zJ0%;mjZG~~4NNSIEiKJW^g|*8Tx|n3`)R~xAnj0Be Lnpq;Lo815aV&5fH literal 0 HcmV?d00001 diff --git a/mms-dump/test/m-read-rec.ind b/mms-dump/test/m-read-rec.ind new file mode 100644 index 0000000000000000000000000000000000000000..7b39a4707b7e7bcfa274e8817b567868a2f59e03 GIT binary patch literal 78 zcmeBa@15A~>SE&N>gr~oYi@37s%viOYOL#IX>P3RVq#%xW@74MXl&ukFkRc&)WX!j h#KPFp(%eKpBr?F&Ho(W%kD-&Xv6Ut0^oPH*8vsDl7M%b9 literal 0 HcmV?d00001 diff --git a/mms-dump/test/m-retrieve_1.0.conf b/mms-dump/test/m-retrieve_1.0.conf new file mode 100644 index 0000000000000000000000000000000000000000..2488f7c48e4a0fe04dd8faec7ac5cff09b017643 GIT binary patch literal 14650 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 T5qaqkFGwR(?zD$ez-QlC^%us9-wgiAR6L_klX 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%0A6<$mf&{K3bB` zPrhTHJunAm2a2I_YjbUMvB7dARye@r zd;V2VPSU24iw2K5+BrD>RlllDclJewND7YR`qfPVnnHI1F!;?D8ql)(CC{JCktl3( zSf1ZXd-!tYVg20EF=O3`J3&vY}joB zgGi)#-G+^Mbuo=vB?{bvc>M8NFX5Z0B-reQk4!Pg@~s^O@p%6Lckd3h(@!Y-YJ#ht zIs7RB$6I)2{TQ)Gi#OdRvOgcfqPXzY!(Il-IN6G?NM85CL5BB8HvsS9jO7&#iZ)3 za#BcJIpb@nIn7hnG;KyUGR+zxVm?)F1$L=$2BDIGei*9$E0J0-cKUx>3OSn%7XEvG zmKJ3_esDh?ywuO4YJxV*A1E2%_kfe+pLwc|vJda9OB8gi+-UCO69p|PB8_Mdw3U|W(i&P8Qe>GLbQ z`3$FN2M3e`GDn^(#V`&S)hX74P%SYDsRNd8n@M=;jcajD-6?d(A3HCh;?c?yW# zn|A;&{{UXPyY!RGJDxLwGCvB#v=Y73d2=d&{{VLckL5@RWQE{U=i17okC!X!^`g=V z0B4674bhkb_*MN*;!vSwZTQ9l@%|NiM_)5bazrWz_oQt1phufa^V_PH;PhUZr`TJ! zn#vanI%H=Rsix`CUdBX;xQ;u4TY7$yY?@L&VElzuKP^$AixbZq5xW6K21g&2GgrE~ zn%)$V)sa+TRDW9OnjOHYwaz-0;<@d0amYfOM?suWfX)&=L#SZEagohMadc#j0~RB+sLQag-#)H1-t^2euAC~CpD)LrT3?_7q?3Fexkdy?74J5Y)Hw#QNJQ(HjNXQnz} zia=K(&~4Alo(FolV4;{PoJG@?&#gUdx2tD%M?e&slFl?$b$CmW{@Db66al3)=q
EDV4Vo7f|Ts!X0Mh-@E&02!;S+An<-Bc?5 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%0A2IXq&#hfeV7X*&JV>KI_LGR8n5 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 OnZ^b^>7>~ +#include + +#include "mms_engine.h" +#include "mms_ofono_log.h" +#include "mms_lib_log.h" +#include "mms_lib_util.h" +#include "mms_dispatcher.h" + +/* Options configurable from the command line */ +typedef struct mms_app_options { + GBusType bus_type; + gboolean keep_running; + MMSConfig config; +} MMSAppOptions; + +/* All known log modules */ +static MMSLogModule* mms_app_log_modules[] = { + &mms_log_default, +#define MMS_LIB_LOG_MODULE(m) &(m), + MMS_LIB_LOG_MODULES(MMS_LIB_LOG_MODULE) + MMS_OFONO_LOG_MODULES(MMS_LIB_LOG_MODULE) +#undef MMS_LIB_LOG_MODULE +}; + +/* Signal handler */ +static +gboolean +mms_app_signal( + gpointer arg) +{ + GMainLoop* loop = arg; + MMS_INFO("Caught signal, shutting down..."); + if (loop) { + g_idle_add((GSourceFunc)g_main_loop_quit, loop); + } else { + exit(0); + } + return FALSE; +} + +/* D-Bus event handlers */ +static +void +mms_app_bus_acquired( + GDBusConnection* bus, + const gchar* name, + gpointer arg) +{ + MMSEngine* engine = arg; + GError* error = NULL; + MMS_DEBUG("Bus acquired, starting..."); + if (!mms_engine_register(engine, bus, &error)) { + MMS_ERR("Could not start: %s", MMS_ERRMSG(error)); + g_error_free(error); + mms_engine_stop(engine); + } +} + +static +void +mms_app_name_acquired( + GDBusConnection* bus, + const gchar* name, + gpointer arg) +{ + MMS_DEBUG("Acquired service name '%s'", name); +} + +static +void +mms_app_name_lost( + GDBusConnection* bus, + const gchar* name, + gpointer arg) +{ + MMSEngine* engine = arg; + MMS_ERR("'%s' service already running or access denied", name); + mms_engine_stop(engine); +} + +/* Option parsing callbacks */ +static +gboolean +mms_app_option_loglevel( + const gchar* name, + const gchar* value, + gpointer data, + GError** error) +{ + return mms_log_parse_option(value, mms_app_log_modules, + G_N_ELEMENTS(mms_app_log_modules), error); +} + +static +gboolean +mms_app_option_logtype( + const gchar* name, + const gchar* value, + gpointer data, + GError** error) +{ + if (mms_log_set_type(value, MMS_APP_LOG_PREFIX)) { + return TRUE; + } else { + if (error) { + *error = g_error_new(G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Invalid log type \'%s\'", value); + } + return FALSE; + } +} + +static +gboolean +mms_app_option_verbose( + const gchar* name, + const gchar* value, + gpointer data, + GError** error) +{ + mms_log_default.level = MMS_LOGLEVEL_VERBOSE; + return TRUE; +} + +/* Parses command line and sets up application options */ +static +gboolean +mms_app_parse_options( + MMSAppOptions* opt, + int argc, + char* argv[]) +{ + gboolean ok; + GError* error = NULL; + gboolean session_bus = FALSE; + char* root_dir_help = g_strdup_printf( + "Root directory for MMS files [%s]", + opt->config.root_dir); + char* retry_secs_help = g_strdup_printf( + "Retry period in seconds [%d]", + opt->config.retry_secs); + char* idle_secs_help = g_strdup_printf( + "Inactivity timeout in seconds [%d]", + opt->config.idle_secs); + char* description = mms_log_description(mms_app_log_modules, + G_N_ELEMENTS(mms_app_log_modules)); + + GOptionContext* options; + GOptionEntry entries[] = { + { "session", 0, 0, G_OPTION_ARG_NONE, &session_bus, + "Use session bus (default is system)", NULL }, + { "root-dir", 'd', 0, G_OPTION_ARG_FILENAME, + (void*)&opt->config.root_dir, root_dir_help, "DIR" }, + { "retry-secs", 'r', 0, G_OPTION_ARG_INT, + &opt->config.retry_secs, retry_secs_help, "SEC" }, + { "idle-secs", 'i', 0, G_OPTION_ARG_INT, + &opt->config.idle_secs, idle_secs_help, "SEC" }, + { "keep-running", 'k', 0, G_OPTION_ARG_NONE, &opt->keep_running, + "Keep running after everything is done", NULL }, + { "keep-temp-files", 't', 0, G_OPTION_ARG_NONE, + &opt->config.keep_temp_files, + "Don't delete temporary files", NULL }, + { "attic", 'a', 0, G_OPTION_ARG_NONE, + &opt->config.attic_enabled, + "Store unrecognized push messages in the attic", NULL }, + { "verbose", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, + mms_app_option_verbose, "Be verbose (equivalent to -l=verbose)", + NULL }, + { "log-output", 'o', 0, G_OPTION_ARG_CALLBACK, mms_app_option_logtype, + "Log output [stdout]", "" }, + { "log-level", 'l', 0, G_OPTION_ARG_CALLBACK, mms_app_option_loglevel, + "Set log level (repeatable)", "[MODULE:]LEVEL" }, + { NULL } + }; + + options = g_option_context_new("- part of Jolla MMS system"); + g_option_context_add_main_entries(options, entries, NULL); + g_option_context_set_description(options, description); + ok = g_option_context_parse(options, &argc, &argv, &error); + g_option_context_free(options); + g_free(root_dir_help); + g_free(retry_secs_help); + g_free(idle_secs_help); + g_free(description); + + if (ok) { + MMS_INFO("Starting"); + if (session_bus) { + MMS_DEBUG("Attaching to session bus"); + opt->bus_type = G_BUS_TYPE_SESSION; + } else { + MMS_DEBUG("Attaching to system bus"); + opt->bus_type = G_BUS_TYPE_SYSTEM; + } + return TRUE; + } else { + fprintf(stderr, "%s\n", MMS_ERRMSG(error)); + g_error_free(error); + return FALSE; + } +} + +int main(int argc, char* argv[]) +{ + int result = 1; + MMSAppOptions opt = {0}; + mms_lib_init(); + mms_log_default.name = MMS_APP_LOG_PREFIX; + mms_lib_default_config(&opt.config); + if (mms_app_parse_options(&opt, argc, argv)) { + MMSEngine* engine; + unsigned int engine_flags = 0; + if (opt.keep_running) engine_flags |= MMS_ENGINE_FLAG_KEEP_RUNNING; + + /* Create engine instance. This may fail */ + engine = mms_engine_new(&opt.config, engine_flags, + mms_app_log_modules, G_N_ELEMENTS(mms_app_log_modules)); + if (engine) { + guint name_id; + + /* Setup main loop */ + GMainLoop* loop = g_main_loop_new(NULL, FALSE); + g_unix_signal_add(SIGTERM, mms_app_signal, loop); + g_unix_signal_add(SIGINT, mms_app_signal, loop); + + /* Acquire name, don't allow replacement */ + name_id = g_bus_own_name(opt.bus_type, MMS_ENGINE_SERVICE, + G_BUS_NAME_OWNER_FLAGS_REPLACE, mms_app_bus_acquired, + mms_app_name_acquired, mms_app_name_lost, engine, NULL); + + /* Run the main loop */ + mms_engine_run(engine, loop); + + /* Cleanup and exit */ + g_bus_unown_name(name_id); + g_main_loop_unref(loop); + mms_engine_unref(engine); + } + MMS_INFO("Exiting"); + result = 0; + } + if (mms_log_func == mms_log_syslog) { + closelog(); + } + return result; +} diff --git a/mms-engine/mms-engine.conf b/mms-engine/mms-engine.conf new file mode 100644 index 0000000..17cfb30 --- /dev/null +++ b/mms-engine/mms-engine.conf @@ -0,0 +1,20 @@ + + + + + + diff --git a/mms-engine/mms-engine.pro b/mms-engine/mms-engine.pro new file mode 100644 index 0000000..2553824 --- /dev/null +++ b/mms-engine/mms-engine.pro @@ -0,0 +1,54 @@ +TEMPLATE = app +CONFIG -= qt +CONFIG += link_pkgconfig +PKGCONFIG += libsoup-2.4 gio-unix-2.0 gio-2.0 glib-2.0 dbus-1 libwspcodec +DBUS_INTERFACE_DIR = $$_PRO_FILE_PWD_ +MMS_LIB_DIR = $$_PRO_FILE_PWD_/../mms-lib +MMS_OFONO_DIR = $$_PRO_FILE_PWD_/../mms-ofono +MMS_HANDLER_DIR = $$_PRO_FILE_PWD_/../mms-handler-dbus +INCLUDEPATH += $$MMS_OFONO_DIR/include +INCLUDEPATH += $$MMS_LIB_DIR/include +INCLUDEPATH += $$MMS_HANDLER_DIR/include +QMAKE_CFLAGS += -Wno-unused + +SOURCES += \ + main.c \ + mms_engine.c +HEADERS += \ + mms_engine.h +OTHER_FILES += \ + org.nemomobile.MmsEngine.push.conf \ + org.nemomobile.MmsEngine.dbus.conf \ + org.nemomobile.MmsEngine.service \ + org.nemomobile.MmsEngine.xml + +CONFIG(debug, debug|release) { + DEFINES += DEBUG + DESTDIR = $$_PRO_FILE_PWD_/build/debug + LIBS += $$MMS_OFONO_DIR/build/debug/libmms-ofono.a + LIBS += $$MMS_HANDLER_DIR/build/debug/libmms-handler-dbus.a + LIBS += $$MMS_LIB_DIR/build/debug/libmms-lib.a +} else { + DESTDIR = $$_PRO_FILE_PWD_/build/release + LIBS += $$MMS_OFONO_DIR/build/release/libmms-ofono.a + LIBS += $$MMS_HANDLER_DIR/build/release/libmms-handler-dbus.a + LIBS += $$MMS_LIB_DIR/build/release/libmms-lib.a +} + +MMS_ENGINE_DBUS_XML = $$DBUS_INTERFACE_DIR/org.nemomobile.MmsEngine.xml +MMS_ENGINE_DBUS_H = org.nemomobile.MmsEngine.h +org_nemomobile_mmsengine_h.input = MMS_ENGINE_DBUS_XML +org_nemomobile_mmsengine_h.output = $$MMS_ENGINE_DBUS_H +org_nemomobile_mmsengine_h.commands = gdbus-codegen --generate-c-code \ + org.nemomobile.MmsEngine $$MMS_ENGINE_DBUS_XML +org_nemomobile_mmsengine_h.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_nemomobile_mmsengine_h + +MMS_ENGINE_DBUS_C = org.nemomobile.MmsEngine.c +org_nemomobile_mmsengine_c.input = MMS_ENGINE_DBUS_XML +org_nemomobile_mmsengine_c.output = $$MMS_ENGINE_DBUS_C +org_nemomobile_mmsengine_c.commands = gdbus-codegen --generate-c-code \ + org.nemomobile.MmsEngine $$MMS_ENGINE_DBUS_XML +org_nemomobile_mmsengine_c.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_nemomobile_mmsengine_c +GENERATED_SOURCES += $$MMS_ENGINE_DBUS_C diff --git a/mms-engine/mms_engine.c b/mms-engine/mms_engine.c new file mode 100644 index 0000000..907d2d0 --- /dev/null +++ b/mms-engine/mms_engine.c @@ -0,0 +1,521 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_engine.h" +#include "mms_dispatcher.h" +#include "mms_lib_util.h" +#include "mms_ofono_connman.h" +#include "mms_handler_dbus.h" +#include "mms_log.h" + +/* Generated code */ +#include "org.nemomobile.MmsEngine.h" + +#ifdef DEBUG +# define ENABLE_TEST +#endif + +struct mms_engine { + GObject parent; + const MMSConfig* config; + MMSDispatcher* dispatcher; + MMSDispatcherDelegate dispatcher_delegate; + MMSLogModule** log_modules; + int log_count; + GDBusConnection* engine_bus; + OrgNemomobileMmsEngine* service; + GMainLoop* loop; + gboolean stopped; + gboolean keep_running; + guint start_timeout_id; + gulong push_signal_id; + gulong push_notify_signal_id; + gulong receive_signal_id; + gulong read_report_signal_id; + gulong cancel_signal_id; + gulong set_log_level_signal_id; + gulong set_log_type_signal_id; +#ifdef ENABLE_TEST + gulong test_signal_id; +#endif +}; + +typedef GObjectClass MMSEngineClass; +G_DEFINE_TYPE(MMSEngine, mms_engine, G_TYPE_OBJECT); +#define MMS_ENGINE_TYPE (mms_engine_get_type()) +#define MMS_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_ENGINE_TYPE, MMSEngine)) + +inline static MMSEngine* +mms_engine_from_dispatcher_delegate(MMSDispatcherDelegate* delegate) + { return MMS_CAST(delegate,MMSEngine,dispatcher_delegate); } + +static +gboolean +mms_engine_stop_callback( + gpointer data) +{ + MMSEngine* engine = data; + mms_engine_stop(engine); + mms_engine_unref(engine); + return FALSE; +} + +static +void +mms_engine_stop_schedule( + MMSEngine* engine) +{ + g_idle_add(mms_engine_stop_callback, mms_engine_ref(engine)); +} + +static +gboolean +mms_engine_start_timeout_callback( + gpointer data) +{ + MMSEngine* engine = data; + MMS_ASSERT(engine->start_timeout_id); + MMS_INFO("Shutting down due to inactivity..."); + engine->start_timeout_id = 0; + mms_engine_stop_schedule(engine); + return FALSE; +} + +static +void +mms_engine_start_timeout_cancel( + MMSEngine* engine) +{ + if (engine->start_timeout_id) { + g_source_remove(engine->start_timeout_id); + engine->start_timeout_id = 0; + } +} + +static +void +mms_engine_start_timeout_schedule( + MMSEngine* engine) +{ + mms_engine_start_timeout_cancel(engine); + engine->start_timeout_id = g_timeout_add_seconds(engine->config->idle_secs, + mms_engine_start_timeout_callback, engine); +} + +#ifdef ENABLE_TEST +/* org.nemomobile.MmsEngine.test */ +static +gboolean +mms_engine_handle_test( + OrgNemomobileMmsEngine* service, + GDBusMethodInvocation* call, + MMSEngine* engine) +{ + MMS_DEBUG("Test"); + org_nemomobile_mms_engine_complete_test(service, call); + return TRUE; +} +#endif /* ENABLE_TEST */ + +/* org.nemomobile.MmsEngine.receiveMessage */ +static +gboolean +mms_engine_handle_receive_message( + OrgNemomobileMmsEngine* service, + GDBusMethodInvocation* call, + int database_id, + const char* imsi, + gboolean automatic, + GVariant* data, + MMSEngine* engine) +{ + gsize len = 0; + const guint8* bytes = g_variant_get_fixed_array(data, &len, 1); + MMS_DEBUG("Processing push %u bytes from %s", (guint)len, imsi); + if (imsi && bytes && len) { + char* id = g_strdup_printf("%d", database_id); + GBytes* push = g_bytes_new(bytes, len); + if (mms_dispatcher_receive_message(engine->dispatcher, id, imsi, + automatic, push)) { + if (mms_dispatcher_start(engine->dispatcher)) { + mms_engine_start_timeout_cancel(engine); + } + org_nemomobile_mms_engine_complete_receive_message(service, call); + } else { + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "Unable to receive message"); + } + g_bytes_unref(push); + g_free(id); + } else { + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "Invalid parameters"); + } + return TRUE; +} + +/* org.nemomobile.MmsEngine.sendReadReport */ +static +gboolean +mms_engine_handle_send_read_report( + OrgNemomobileMmsEngine* service, + GDBusMethodInvocation* call, + const char* id, + const char* imsi, + const char* message_id, + const char* to, + int read_status, /* 0: Read 1: Deleted without reading */ + MMSEngine* engine) +{ + MMS_DEBUG_("%s %s %s %s %d", id, imsi, message_id, to, read_status); + if (mms_dispatcher_send_read_report(engine->dispatcher, id, imsi, + message_id, to, (read_status == 1) ? MMS_READ_STATUS_DELETED : + MMS_READ_STATUS_READ)) { + if (mms_dispatcher_start(engine->dispatcher)) { + mms_engine_start_timeout_cancel(engine); + } + org_nemomobile_mms_engine_complete_send_read_report(service, call); + } else { + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "Error submitting read report"); + } + return TRUE; +} + +/* org.nemomobile.MmsEngine.cancel */ +static +gboolean +mms_engine_handle_cancel( + OrgNemomobileMmsEngine* service, + GDBusMethodInvocation* call, + const char* id, + MMSEngine* engine) +{ + MMS_DEBUG_("%s", id); + mms_dispatcher_cancel(engine->dispatcher, id); + org_nemomobile_mms_engine_complete_cancel(service, call); + return TRUE; +} + +/* org.nemomobile.MmsEngine.pushNotify */ +static +gboolean +mms_engine_handle_push_notify( + OrgNemomobileMmsEngine* proxy, + GDBusMethodInvocation* call, + const char* imsi, + const char* type, + GVariant* data, + MMSEngine* engine) +{ + gsize len = 0; + const guint8* bytes = g_variant_get_fixed_array(data, &len, 1); + MMS_DEBUG("Received %u bytes from %s", (guint)len, imsi); + if (!type || g_ascii_strcasecmp(type, MMS_CONTENT_TYPE)) { + MMS_ERR("Unsupported content type %s", type); + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "Unsupported content type"); + } else if (!imsi || !imsi[0]) { + MMS_ERR_("IMSI is missing"); + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "IMSI is missing"); + } else if (!bytes || !len) { + MMS_ERR_("No data provided"); + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "No data provided"); + } else { + GBytes* msg = g_bytes_new(bytes, len); + if (mms_dispatcher_handle_push(engine->dispatcher, imsi, msg)) { + if (mms_dispatcher_start(engine->dispatcher)) { + mms_engine_start_timeout_cancel(engine); + } + org_nemomobile_mms_engine_complete_push(proxy, call); + } else { + g_dbus_method_invocation_return_error(call, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, "Unable to handle push message"); + } + g_bytes_unref(msg); + } + return TRUE; +} + +/* org.nemomobile.MmsEngine.push */ +static +gboolean +mms_engine_handle_push( + OrgNemomobileMmsEngine* proxy, + GDBusMethodInvocation* call, + const char* imsi, + const char* from, + guint32 remote_time, + guint32 local_time, + int dst_port, + int src_port, + const char* type, + GVariant* data, + MMSEngine* eng) +{ + return mms_engine_handle_push_notify(proxy, call, imsi, type, data, eng); +} + +/* org.nemomobile.MmsEngine.setLogLevel */ +static +gboolean +mms_engine_handle_set_log_level( + OrgNemomobileMmsEngine* service, + GDBusMethodInvocation* call, + const char* module, + gint level, + MMSEngine* engine) +{ + MMS_DEBUG_("%s:%d", module, level); + if (module && module[0]) { + int i; + for (i=0; ilog_count; i++) { + MMSLogModule* log = engine->log_modules[i]; + if (log->name && log->name[0] && !strcmp(log->name, module)) { + log->level = level; + break; + } + } + } else { + mms_log_default.level = level; + } + org_nemomobile_mms_engine_complete_set_log_level(service, call); + return TRUE; +} + +/* org.nemomobile.MmsEngine.setLogType */ +static +gboolean +mms_engine_handle_set_log_type( + OrgNemomobileMmsEngine* service, + GDBusMethodInvocation* call, + const char* type, + MMSEngine* engine) +{ + MMS_DEBUG_("%s", type); + mms_log_set_type(type, MMS_APP_LOG_PREFIX); + org_nemomobile_mms_engine_complete_set_log_type(service, call); + return TRUE; +} + +MMSEngine* +mms_engine_new( + const MMSConfig* config, + unsigned int flags, + MMSLogModule* log_modules[], + int log_count) +{ + MMSConnMan* cm = mms_connman_ofono_new(); + if (cm) { + MMSEngine* mms = g_object_new(MMS_ENGINE_TYPE, NULL); + MMSHandler* handler = mms_handler_dbus_new(); + mms->dispatcher = mms_dispatcher_new(config, cm, handler); + mms_connman_unref(cm); + mms_handler_unref(handler); + mms_dispatcher_set_delegate(mms->dispatcher, + &mms->dispatcher_delegate); + + if (flags & MMS_ENGINE_FLAG_KEEP_RUNNING) { + mms->keep_running = TRUE; + } + + mms->config = config; + mms->log_modules = log_modules; + mms->log_count = log_count; + mms->service = org_nemomobile_mms_engine_skeleton_new(); + mms->push_signal_id = + g_signal_connect(mms->service, "handle-push", + G_CALLBACK(mms_engine_handle_push), mms); + mms->push_notify_signal_id = + g_signal_connect(mms->service, "handle-push-notify", + G_CALLBACK(mms_engine_handle_push_notify), mms); + mms->cancel_signal_id = + g_signal_connect(mms->service, "handle-cancel", + G_CALLBACK(mms_engine_handle_cancel), mms); + mms->receive_signal_id = + g_signal_connect(mms->service, "handle-receive-message", + G_CALLBACK(mms_engine_handle_receive_message), mms); + mms->read_report_signal_id = + g_signal_connect(mms->service, "handle-send-read-report", + G_CALLBACK(mms_engine_handle_send_read_report), mms); + mms->set_log_level_signal_id = + g_signal_connect(mms->service, "handle-set-log-level", + G_CALLBACK(mms_engine_handle_set_log_level), mms); + mms->set_log_type_signal_id = + g_signal_connect(mms->service, "handle-set-log-type", + G_CALLBACK(mms_engine_handle_set_log_type), mms); + +#ifdef ENABLE_TEST + mms->test_signal_id = + g_signal_connect(mms->service, "handle-test", + G_CALLBACK(mms_engine_handle_test), mms); +#endif + + return mms; + } + + return NULL; +} + +MMSEngine* +mms_engine_ref( + MMSEngine* engine) +{ + return g_object_ref(MMS_ENGINE(engine)); +} + +void +mms_engine_unref( + MMSEngine* engine) +{ + if (engine) g_object_unref(MMS_ENGINE(engine)); +} + +void +mms_engine_run( + MMSEngine* engine, + GMainLoop* loop) +{ + MMS_ASSERT(!engine->loop); + engine->loop = loop; + engine->stopped = FALSE; + if (!mms_dispatcher_start(engine->dispatcher) && !engine->keep_running) { + mms_engine_start_timeout_schedule(engine); + } + g_main_loop_run(loop); + mms_engine_start_timeout_cancel(engine); + engine->loop = NULL; +} + +void +mms_engine_stop( + MMSEngine* engine) +{ + engine->stopped = TRUE; + if (engine->loop) g_main_loop_quit(engine->loop); +} + +void +mms_engine_unregister( + MMSEngine* engine) +{ + if (engine->engine_bus) { + g_dbus_interface_skeleton_unexport( + G_DBUS_INTERFACE_SKELETON(engine->service)); + g_object_unref(engine->engine_bus); + engine->engine_bus = NULL; + } +} + +gboolean +mms_engine_register( + MMSEngine* engine, + GDBusConnection* bus, + GError** error) +{ + mms_engine_unregister(engine); + if (g_dbus_interface_skeleton_export( + G_DBUS_INTERFACE_SKELETON(engine->service), bus, + MMS_ENGINE_PATH, error)) { + g_object_ref(engine->engine_bus = bus); + return TRUE; + } else { + return FALSE; + } +} + +static +void +mms_engine_delegate_dispatcher_done( + MMSDispatcherDelegate* delegate, + MMSDispatcher* dispatcher) +{ + MMSEngine* engine = mms_engine_from_dispatcher_delegate(delegate); + MMS_DEBUG("All done"); + if (!engine->keep_running) mms_engine_stop_schedule(engine); +} + +/** + * Per object initializer + * + * Only sets up internal state (all values set to zero) + */ +static +void +mms_engine_init( + MMSEngine* engine) +{ + engine->dispatcher_delegate.fn_done = mms_engine_delegate_dispatcher_done; +} + +/** + * First stage of deinitialization (release all references). + * May be called more than once in the lifetime of the object. + */ +static +void +mms_engine_dispose( + GObject* object) +{ + MMSEngine* e = MMS_ENGINE(object); + MMS_VERBOSE_("%p", e); + MMS_ASSERT(!e->loop); + mms_engine_unregister(e); + mms_engine_start_timeout_cancel(e); + if (e->service) { +#ifdef ENABLE_TEST + g_signal_handler_disconnect(e->service, e->test_signal_id); +#endif + g_signal_handler_disconnect(e->service, e->push_signal_id); + g_signal_handler_disconnect(e->service, e->push_notify_signal_id); + g_signal_handler_disconnect(e->service, e->receive_signal_id); + g_signal_handler_disconnect(e->service, e->read_report_signal_id); + g_signal_handler_disconnect(e->service, e->cancel_signal_id); + g_signal_handler_disconnect(e->service, e->set_log_level_signal_id); + g_signal_handler_disconnect(e->service, e->set_log_type_signal_id); + g_object_unref(e->service); + e->service = NULL; + } + if (e->dispatcher) { + mms_dispatcher_set_delegate(e->dispatcher, NULL); + mms_dispatcher_unref(e->dispatcher); + e->dispatcher = NULL; + } + G_OBJECT_CLASS(mms_engine_parent_class)->dispose(object); +} + +/** + * Per class initializer + */ +static +void +mms_engine_class_init( + MMSEngineClass* klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + MMS_ASSERT(object_class); + object_class->dispose = mms_engine_dispose; + MMS_VERBOSE_("done"); +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-engine/mms_engine.h b/mms-engine/mms_engine.h new file mode 100644 index 0000000..1c62e0b --- /dev/null +++ b/mms-engine/mms_engine.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_ENGINE_H +#define JOLLA_MMS_ENGINE_H + +#include +#include +#include "mms_lib_types.h" + +#define MMS_APP_LOG_PREFIX "mms-engine" + +#define MMS_ENGINE_SERVICE "org.nemomobile.MmsEngine" +#define MMS_ENGINE_PATH "/" + +#define MMS_ENGINE_FLAG_KEEP_RUNNING (0x01) + +typedef struct mms_engine MMSEngine; + +MMSEngine* +mms_engine_new( + const MMSConfig* config, + unsigned int flags, + MMSLogModule* log_modules[], + int log_count); + +MMSEngine* +mms_engine_ref( + MMSEngine* engine); + +void +mms_engine_unref( + MMSEngine* engine); + +void +mms_engine_run( + MMSEngine* engine, + GMainLoop* loop); + +void +mms_engine_stop( + MMSEngine* engine); + +gboolean +mms_engine_register( + MMSEngine* engine, + GDBusConnection* bus, + GError** error); + +void +mms_engine_unregister( + MMSEngine* engine); + +#endif /* JOLLA_MMS_ENGINE_H */ diff --git a/mms-engine/org.nemomobile.MmsEngine.dbus.conf b/mms-engine/org.nemomobile.MmsEngine.dbus.conf new file mode 100644 index 0000000..cf906e3 --- /dev/null +++ b/mms-engine/org.nemomobile.MmsEngine.dbus.conf @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/mms-engine/org.nemomobile.MmsEngine.push.conf b/mms-engine/org.nemomobile.MmsEngine.push.conf new file mode 100644 index 0000000..baf1667 --- /dev/null +++ b/mms-engine/org.nemomobile.MmsEngine.push.conf @@ -0,0 +1,9 @@ +# This file goes to /etc/ofono/push_forwarder.d or /etc/push-agent +# directory depending of who starts MMS engine, push-forwarder oFono +# plugin or push-agent service. +[MMS Engine] +ContentType = application/vnd.wap.mms-message +Interface = org.nemomobile.MmsEngine +Service = org.nemomobile.MmsEngine +Method = push +Path = / diff --git a/mms-engine/org.nemomobile.MmsEngine.service b/mms-engine/org.nemomobile.MmsEngine.service new file mode 100644 index 0000000..a4d9667 --- /dev/null +++ b/mms-engine/org.nemomobile.MmsEngine.service @@ -0,0 +1,5 @@ +# Goes to /usr/share/dbus-1/system-services +[D-BUS Service] +Name=org.nemomobile.MmsEngine +Exec=/usr/sbin/mms-engine -o syslog +User=nemo diff --git a/mms-engine/org.nemomobile.MmsEngine.xml b/mms-engine/org.nemomobile.MmsEngine.xml new file mode 100644 index 0000000..2abd8e3 --- /dev/null +++ b/mms-engine/org.nemomobile.MmsEngine.xml @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mms-handler-dbus/Makefile b/mms-handler-dbus/Makefile new file mode 100644 index 0000000..82981e6 --- /dev/null +++ b/mms-handler-dbus/Makefile @@ -0,0 +1,115 @@ +# -*- Mode: makefile -*- + +.PHONY: clean all debug release + +# Required packages +PKGS = glib-2.0 gio-2.0 gio-unix-2.0 + +# +# Default target +# + +all: debug release + +# +# Sources +# + +SRC = mms_handler_dbus.c +GEN_SRC = org.nemomobile.MmsHandler.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) +WARN = -Wall +ARFLAGS = rc +INCLUDES = -I$(SRC_DIR) -I$(INCLUDE_DIR) -I$(MMS_LIB_INCLUDE) -I$(GEN_DIR) -I. +CFLAGS = $(WARNINGS) $(INCLUDES) $(shell pkg-config --cflags $(PKGS)) -MMD +DEBUG_FLAGS = -g +RELEASE_FLAGS = -O2 +DEBUG_CFLAGS = $(DEBUG_FLAGS) $(DEBUG_DEFS) $(CFLAGS) +RELEASE_CFLAGS = $(RELEASE_FLAGS) $(RELEASE_DEFS) $(CFLAGS) + +# +# 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-handler-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 $(WARN) $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ + +$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c + $(CC) -c $(WARN) $(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-handler-dbus/include/mms_handler_dbus.h b/mms-handler-dbus/include/mms_handler_dbus.h new file mode 100644 index 0000000..772134b --- /dev/null +++ b/mms-handler-dbus/include/mms_handler_dbus.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_HANDLER_DBUS_H +#define JOLLA_MMS_HANDLER_DBUS_H + +#include "mms_handler.h" + +MMSHandler* +mms_handler_dbus_new(void); + +#endif /* JOLLA_MMS_HANDLER_DBUS_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ + diff --git a/mms-handler-dbus/mms-handler-dbus.pro b/mms-handler-dbus/mms-handler-dbus.pro new file mode 100644 index 0000000..7796b77 --- /dev/null +++ b/mms-handler-dbus/mms-handler-dbus.pro @@ -0,0 +1,39 @@ +TEMPLATE = lib +CONFIG += staticlib +CONFIG -= qt +CONFIG += link_pkgconfig +PKGCONFIG += 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 + +CONFIG(debug, debug|release) { + DEFINES += DEBUG + DESTDIR = $$_PRO_FILE_PWD_/build/debug +} else { + DESTDIR = $$_PRO_FILE_PWD_/build/release +} + +SOURCES += src/mms_handler_dbus.c +HEADERS += include/mms_handler_dbus.h +OTHER_FILES += spec/org.nemomobile.MmsHandler.xml + +# org.nemomobile.MmsHandler +COMMHISTORYIF_XML = $$DBUS_SPEC_DIR/org.nemomobile.MmsHandler.xml +COMMHISTORYIF_GENERATE = gdbus-codegen --generate-c-code \ + org.nemomobile.MmsHandler $$COMMHISTORYIF_XML +COMMHISTORYIF_H = org.nemomobile.MmsHandler.h +org_nemomobile_MmsHandler_h.input = COMMHISTORYIF_XML +org_nemomobile_MmsHandler_h.output = $$COMMHISTORYIF_H +org_nemomobile_MmsHandler_h.commands = $$COMMHISTORYIF_GENERATE +org_nemomobile_MmsHandler_h.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_nemomobile_MmsHandler_h + +COMMHISTORYIF_C = org.nemomobile.MmsHandler.c +org_nemomobile_MmsHandler_c.input = COMMHISTORYIF_XML +org_nemomobile_MmsHandler_c.output = $$COMMHISTORYIF_C +org_nemomobile_MmsHandler_c.commands = $$COMMHISTORYIF_GENERATE +org_nemomobile_MmsHandler_c.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_nemomobile_MmsHandler_c +GENERATED_SOURCES += $$COMMHISTORYIF_C diff --git a/mms-handler-dbus/spec/org.nemomobile.MmsHandler.xml b/mms-handler-dbus/spec/org.nemomobile.MmsHandler.xml new file mode 100644 index 0000000..8687eff --- /dev/null +++ b/mms-handler-dbus/spec/org.nemomobile.MmsHandler.xml @@ -0,0 +1,300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mms-handler-dbus/src/mms_handler_dbus.c b/mms-handler-dbus/src/mms_handler_dbus.c new file mode 100644 index 0000000..0d574ee --- /dev/null +++ b/mms-handler-dbus/src/mms_handler_dbus.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_handler_dbus.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_handler_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-handler-dbus"); + +/* Generated code */ +#include "org.nemomobile.MmsHandler.h" + +/* Class definition */ +typedef MMSHandlerClass MMSHandlerDbusClass; +typedef struct mms_handler_dbus { + MMSHandler handler; + OrgNemomobileMmsHandler* proxy; +} MMSHandlerDbus; + +G_DEFINE_TYPE(MMSHandlerDbus, mms_handler_dbus, MMS_TYPE_HANDLER); +#define MMS_TYPE_HANDLER_DBUS (mms_handler_dbus_get_type()) +#define MMS_HANDLER_DBUS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_TYPE_HANDLER_DBUS, MMSHandlerDbus)) + +MMSHandler* +mms_handler_dbus_new() +{ + MMSHandlerDbus* db = g_object_new(MMS_TYPE_HANDLER_DBUS, NULL); + return &db->handler; +} + +/** + * Creates D-Bus connection to MMS handler. Caller owns the returned + * reference. + */ +static +OrgNemomobileMmsHandler* +mms_handler_dbus_connect( + MMSHandler* handler) +{ + MMSHandlerDbus* dbus = MMS_HANDLER_DBUS(handler); + if (!dbus->proxy) { + GError* error = NULL; + dbus->proxy = org_nemomobile_mms_handler_proxy_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, + "org.nemomobile.MmsHandler", "/", NULL, &error); + if (!dbus->proxy) { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + } + } + return dbus->proxy; +} + +static +char* +mms_handler_dbus_message_notify( + MMSHandler* handler, + const char* imsi, + const char* from, + const char* subject, + time_t expiry, + GBytes* push) +{ + char* id = NULL; + OrgNemomobileMmsHandler* proxy = mms_handler_dbus_connect(handler); + if (proxy) { + gsize len = 0; + const void* data = g_bytes_get_data(push, &len); + GError* error = NULL; + GVariant* bytes = g_variant_ref_sink(g_variant_new_from_data( + G_VARIANT_TYPE_BYTESTRING, data, len, TRUE, NULL, NULL)); + if (!org_nemomobile_mms_handler_call_message_notification_sync( + proxy, imsi, from, subject, expiry, bytes, &id, NULL, &error)) { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + } + g_variant_unref(bytes); + } + return id; +} + +static +gboolean +mms_handler_dbus_message_received( + MMSHandler* handler, + MMSMessage* msg) +{ + gboolean ok = FALSE; + OrgNemomobileMmsHandler* proxy = mms_handler_dbus_connect(handler); + MMS_ASSERT(msg->id && msg->id[0]); + if (msg->id && msg->id[0] && proxy) { + const char* subject = msg->subject ? msg->subject : ""; + GError* error = NULL; + GSList* list = msg->parts; + GVariant* parts; + GVariantBuilder b; + + g_variant_builder_init(&b, G_VARIANT_TYPE("a(sss)")); + while (list) { + const MMSMessagePart* part = list->data; + g_variant_builder_add(&b, "(sss)", part->file, + part->content_type, part->content_id); + list = list->next; + } + + parts = g_variant_ref_sink(g_variant_builder_end(&b)); + ok = org_nemomobile_mms_handler_call_message_received_sync( + proxy, msg->id, msg->message_id, msg->from, (const char**)msg->to, + (const char**)msg->cc, subject, msg->date, msg->priority, + msg->cls, msg->read_report_req, parts, NULL, &error); + if (!ok) { + MMS_ERR("Failed to nofity commhistoryd: %s", MMS_ERRMSG(error)); + g_error_free(error); + } + + g_variant_unref(parts); + } + return ok; +} + +/* Updates message state in the database */ +static +gboolean +mms_handler_dbus_message_receive_state_changed( + MMSHandler* handler, + const char* id, + MMS_RECEIVE_STATE state) +{ + gboolean ok = FALSE; + OrgNemomobileMmsHandler* proxy = mms_handler_dbus_connect(handler); + MMS_ASSERT(id && id[0]); + if (id && id[0] && proxy) { + GError* error = NULL; + if (org_nemomobile_mms_handler_call_message_receive_state_changed_sync( + proxy, id, state, NULL, &error)) { + ok = TRUE; + } else { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + } + } + return ok; +} + +static +void +mms_handler_dbus_dispose( + GObject* object) +{ + MMSHandlerDbus* dbus = MMS_HANDLER_DBUS(object); + if (dbus->proxy) { + g_object_unref(dbus->proxy); + dbus->proxy = NULL; + } + G_OBJECT_CLASS(mms_handler_dbus_parent_class)->dispose(object); +} + +static +void +mms_handler_dbus_class_init( + MMSHandlerDbusClass* klass) +{ + klass->fn_message_notify = mms_handler_dbus_message_notify; + klass->fn_message_received = mms_handler_dbus_message_received; + klass->fn_message_receive_state_changed = + mms_handler_dbus_message_receive_state_changed; + G_OBJECT_CLASS(klass)->dispose = mms_handler_dbus_dispose; +} + +static +void +mms_handler_dbus_init( + MMSHandlerDbus* dbus) +{ +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-handler-dbus/test/mms_handler_dbus_client/Makefile b/mms-handler-dbus/test/mms_handler_dbus_client/Makefile new file mode 100644 index 0000000..f9abeef --- /dev/null +++ b/mms-handler-dbus/test/mms_handler_dbus_client/Makefile @@ -0,0 +1,155 @@ +# -*- Mode: makefile -*- + +.PHONY: all debug release clean +.PHONY: mms_lib_debug_lib mms_lib_release_lib + +# Required packages +LIB_PKGS = libsoup-2.4 glib-2.0 gio-2.0 gio-unix-2.0 +PKGS = $(LIB_PKGS) + +# +# Default target +# + +all: debug release + +# +# Sources +# + +SRC = test_mms_handler_dbus_client.c +SRC1 = mms_handler_dbus.c +GEN_SRC = org.nemomobile.MmsHandler.c + +# +# Directories +# + +SRC_DIR = . +SRC1_DIR = ../../src +BUILD_DIR = build +GEN_DIR = $(BUILD_DIR) +SPEC_DIR = ../../spec +DEBUG_BUILD_DIR = $(BUILD_DIR)/debug +RELEASE_BUILD_DIR = $(BUILD_DIR)/release + +# +# mms-lib +# + +MMS_LIB_LIB = libmms.a +MMS_LIB_DIR = ../../../mms-lib +MMS_LIB_BUILD_DIR = $(MMS_LIB_DIR)/build +MMS_LIB_DEBUG_LIB = $(MMS_LIB_BUILD_DIR)/debug/$(MMS_LIB_LIB) +MMS_LIB_RELEASE_LIB = $(MMS_LIB_BUILD_DIR)/release/$(MMS_LIB_LIB) + +# +# Tools and flags +# + +CC = $(CROSS_COMPILE)gcc +LD = $(CC) +DEBUG_FLAGS = -g +RELEASE_FLAGS = -O2 +DEBUG_DEFS = -DDEBUG +RELEASE_DEFS = +WARNINGS = -Wall +LIBS = $(shell pkg-config --libs $(LIB_PKGS)) +CFLAGS = $(shell pkg-config --cflags $(PKGS)) -I. -I../../include \ + -I$(MMS_LIB_DIR)/include -I$(SRC1_DIR) -I$(GEN_DIR) -MMD + +DEBUG_CFLAGS = $(WARNINGS) $(DEBUG_FLAGS) $(DEBUG_DEFS) $(CFLAGS) +RELEASE_CFLAGS = $(WARNINGS) $(RELEASE_FLAGS) $(RELEASE_DEFS) $(CFLAGS) +DEBUG_LIBS = $(MMS_LIB_DEBUG_LIB) $(LIBS) +RELEASE_LIBS = $(MMS_LIB_RELEASE_LIB) $(LIBS) + +# +# Files +# + +.PRECIOUS: $(GEN_SRC:%=$(GEN_DIR)/%) + +DEBUG_OBJS = \ + $(GEN_SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) \ + $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) \ + $(SRC1:%.c=$(DEBUG_BUILD_DIR)/%.o) +RELEASE_OBJS = \ + $(GEN_SRC:%.c=$(RELEASE_BUILD_DIR)/%.o) \ + $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o) \ + $(SRC1:%.c=$(RELEASE_BUILD_DIR)/%.o) + +# +# Dependencies +# + +DEBUG_EXE_DEPS = $(MMS_LIB_DEBUG_LIB) $(DEBUG_BUILD_DIR) +RELEASE_EXE_DEPS = $(MMS_LIB_RELEASE_LIB) $(RELEASE_BUILD_DIR) +DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d) +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(DEPS)),) +-include $(DEPS) +endif +endif + +# +# Rules +# + +EXE = test_mms_handler_dbus_client +DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE) +RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE) + +debug: $(DEBUG_EXE) + +release: $(RELEASE_EXE) + +clean: + make -C $(MMS_LIB_DIR) clean + rm -fr $(BUILD_DIR) $(SRC_DIR)/*~ + +mms_lib_debug_lib: + make -C $(MMS_LIB_DIR) debug + +mms_lib_release_lib: + make -C $(MMS_LIB_DIR) release + +$(MMS_LIB_DEBUG_LIB): mms_lib_debug_lib + +$(MMS_LIB_RELEASE_LIB): mms_lib_release_lib + +$(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 : $(SRC1_DIR)/%.c + $(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ + +$(RELEASE_BUILD_DIR)/%.o : $(SRC1_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_EXE): $(DEBUG_EXE_DEPS) $(DEBUG_OBJS) + $(LD) $(DEBUG_FLAGS) $(DEBUG_OBJS) $(DEBUG_LIBS) -o $@ + +$(RELEASE_EXE): $(RELEASE_EXE_DEPS) $(RELEASE_OBJS) + $(LD) $(RELEASE_FLAGS) $(RELEASE_OBJS) $(RELEASE_LIBS) -o $@ + strip $@ diff --git a/mms-handler-dbus/test/mms_handler_dbus_client/test_mms_handler_dbus_client.c b/mms-handler-dbus/test/mms_handler_dbus_client/test_mms_handler_dbus_client.c new file mode 100644 index 0000000..a743aca --- /dev/null +++ b/mms-handler-dbus/test/mms_handler_dbus_client/test_mms_handler_dbus_client.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_handler_dbus.h" + +#define RET_ERR (1) +#define RET_OK (0) + +static int run_test(MMSHandler* handler) +{ + const static guint8 data [] = {0,1,2,3,4,5}; + static const char IMSI[] = "IMSI"; + static const char Sender[] = "Sender"; + static const char Subject[] = "Subject"; + + int ret = RET_ERR; + GBytes* pdu = g_bytes_new(data, sizeof(data)); + time_t date = time(NULL); + time_t expiry = date + 10; + char* id = mms_handler_message_notify(handler, IMSI, Sender, Subject, + expiry, pdu); + g_bytes_unref(pdu); + if (id && id[0]) { + printf("Record id: %s\n", id); + if (mms_handler_message_receive_state_changed(handler, id, + MMS_RECEIVE_STATE_RECEIVING) && + mms_handler_message_receive_state_changed(handler, id, + MMS_RECEIVE_STATE_DECODING)) { + + gboolean ok; + MMSMessage* msg = mms_message_new(); + MMSMessagePart* p1 = g_new0(MMSMessagePart, 1); + MMSMessagePart* p2 = g_new0(MMSMessagePart, 1); + MMSMessagePart* p3 = g_new0(MMSMessagePart, 1); + msg->id = g_strdup(id); + msg->message_id = g_strdup("MessageID"); + msg->from = g_strdup(Sender); + msg->to = g_strsplit("To1,To2", ",", 0); + msg->cc = g_strsplit("Cc1,Cc2,Cc3", ",", 0); + msg->subject = g_strdup(Subject); + msg->date = date; + msg->cls = g_strdup("Personal"); + msg->flags |= MMS_MESSAGE_FLAG_KEEP_FILES; + + p1->content_type = g_strdup("application/smil;charset=utf-8"); + p1->content_id = g_strdup("<0>"); + p1->file = g_strdup("0"); + msg->parts = g_slist_append(msg->parts, p1); + + p2->content_type = g_strdup("text/plain;charset=utf-8"); + p2->content_id = g_strdup(""); + p2->file = g_strdup("text_0011.txt"); + msg->parts = g_slist_append(msg->parts, p2); + + p3->content_type = g_strdup("image/jpeg"); + p3->content_id = g_strdup("<131200181.jpg>"); + p3->file = g_strdup("131200181.jpg"); + msg->parts = g_slist_append(msg->parts, p3); + + ok = mms_handler_message_received(handler, msg); + mms_message_unref(msg); + + if (ok) { + printf("OK\n"); + ret = RET_OK; + } + } + } else { + printf("ERROR: no record id\n"); + } + g_free(id); + return ret; +} + +int main(int argc, char* argv[]) +{ + int ret; + MMSHandler* handler; + +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + /* g_type_init has been deprecated since version 2.36 + * the type system is initialised automagically since then */ + g_type_init(); +#pragma GCC diagnostic pop + + handler = mms_handler_dbus_new(); + ret = run_test(handler); + mms_handler_unref(handler); + return ret; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-handler-dbus/test/mms_handler_dbus_server/main.cpp b/mms-handler-dbus/test/mms_handler_dbus_server/main.cpp new file mode 100644 index 0000000..d3a720e --- /dev/null +++ b/mms-handler-dbus/test/mms_handler_dbus_server/main.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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 "mmshandler.h" +#include "mmsadaptor.h" + +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + const char* rootDir = "/tmp/mms"; + if (argc > 1) rootDir = argv[1]; + qDebug() << "Using" << rootDir << "as storage for MMS files"; + MmsHandler* service = new MmsHandler(&app, rootDir); + if (service->isRegistered()) { + new MmsAdaptor(service); + qDebug() << "MmsHandler created"; + return app.exec(); + } else { + qCritical() << "MmsHandler registration failed (already running or DBus not found), exiting"; + return 1; + } +} diff --git a/mms-handler-dbus/test/mms_handler_dbus_server/mmsadaptor.cpp b/mms-handler-dbus/test/mms_handler_dbus_server/mmsadaptor.cpp new file mode 100644 index 0000000..bee1453 --- /dev/null +++ b/mms-handler-dbus/test/mms_handler_dbus_server/mmsadaptor.cpp @@ -0,0 +1,74 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -c MmsAdaptor -a mmsadaptor ../../spec/org.nemomobile.MmsHandler.xml + * + * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#include "mmsadaptor.h" +#include "mmshandler.h" +#include +#include +#include +#include +#include +#include +#include + +/* + * Implementation of adaptor class MmsAdaptor + */ + +MmsAdaptor::MmsAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + // constructor + setAutoRelaySignals(true); +} + +MmsAdaptor::~MmsAdaptor() +{ + // destructor +} + +void MmsAdaptor::deliveryReport(const QString &imsi, const QString &mmsId, const QString &recipient, int status) +{ + // handle method call org.nemomobile.MmsHandler.deliveryReport + QMetaObject::invokeMethod(parent(), "deliveryReport", Q_ARG(QString, imsi), Q_ARG(QString, mmsId), Q_ARG(QString, recipient), Q_ARG(int, status)); +} + +QString MmsAdaptor::messageNotification(const QString &imsi, const QString &from, const QString &subject, uint expiry, const QByteArray &data) +{ + // handle method call org.nemomobile.MmsHandler.messageNotification + QString recId; + QMetaObject::invokeMethod(parent(), "messageNotification", Q_RETURN_ARG(QString, recId), Q_ARG(QString, imsi), Q_ARG(QString, from), Q_ARG(QString, subject), Q_ARG(uint, expiry), Q_ARG(QByteArray, data)); + return recId; +} + +void MmsAdaptor::messageReceiveStateChanged(const QString &recId, int state) +{ + // handle method call org.nemomobile.MmsHandler.messageReceiveStateChanged + QMetaObject::invokeMethod(parent(), "messageReceiveStateChanged", Q_ARG(QString, recId), Q_ARG(int, state)); +} + +void MmsAdaptor::messageReceived(const QString &recId, const QString &mmsId, const QString &from, const QStringList &to, const QStringList &cc, const QString &subject, uint date, int priority, const QString &cls, bool readReport, MmsPartList parts) +{ + // handle method call org.nemomobile.MmsHandler.messageReceived + static_cast(parent())->messageReceived(recId, mmsId, from, to, cc, subject, date, priority, cls, readReport, parts); +} + +void MmsAdaptor::messageSendStateChanged(const QString &recId, int state) +{ + // handle method call org.nemomobile.MmsHandler.messageSendStateChanged + QMetaObject::invokeMethod(parent(), "messageSendStateChanged", Q_ARG(QString, recId), Q_ARG(int, state)); +} + +void MmsAdaptor::readReport(const QString &imsi, const QString &mmsId, const QString &recipient, int status) +{ + // handle method call org.nemomobile.MmsHandler.readReport + QMetaObject::invokeMethod(parent(), "readReport", Q_ARG(QString, imsi), Q_ARG(QString, mmsId), Q_ARG(QString, recipient), Q_ARG(int, status)); +} + diff --git a/mms-handler-dbus/test/mms_handler_dbus_server/mmsadaptor.h b/mms-handler-dbus/test/mms_handler_dbus_server/mmsadaptor.h new file mode 100644 index 0000000..16aeae9 --- /dev/null +++ b/mms-handler-dbus/test/mms_handler_dbus_server/mmsadaptor.h @@ -0,0 +1,96 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -c MmsAdaptor -a mmsadaptor ../../spec/org.nemomobile.MmsHandler.xml + * + * qdbusxml2cpp is Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#ifndef MMSADAPTOR_H_1390561457 +#define MMSADAPTOR_H_1390561457 + +#include "mmspart.h" + +#include +#include +QT_BEGIN_NAMESPACE +class QByteArray; +template class QList; +template class QMap; +class QString; +class QStringList; +class QVariant; +QT_END_NAMESPACE + +/* + * Adaptor class for interface org.nemomobile.MmsHandler + */ +class MmsAdaptor: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.nemomobile.MmsHandler") + Q_CLASSINFO("D-Bus Introspection", "" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" + "") +public: + MmsAdaptor(QObject *parent); + virtual ~MmsAdaptor(); + +public: // PROPERTIES +public Q_SLOTS: // METHODS + void deliveryReport(const QString &imsi, const QString &mmsId, const QString &recipient, int status); + QString messageNotification(const QString &imsi, const QString &from, const QString &subject, uint expiry, const QByteArray &data); + void messageReceiveStateChanged(const QString &recId, int state); + void messageReceived(const QString &recId, const QString &mmsId, const QString &from, const QStringList &to, const QStringList &cc, const QString &subject, uint date, int priority, const QString &cls, bool readReport, MmsPartList parts); + void messageSendStateChanged(const QString &recId, int state); + void readReport(const QString &imsi, const QString &mmsId, const QString &recipient, int status); +Q_SIGNALS: // SIGNALS +}; + +#endif diff --git a/mms-handler-dbus/test/mms_handler_dbus_server/mmshandler.cpp b/mms-handler-dbus/test/mms_handler_dbus_server/mmshandler.cpp new file mode 100644 index 0000000..8044d83 --- /dev/null +++ b/mms-handler-dbus/test/mms_handler_dbus_server/mmshandler.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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 "mmshandler.h" + +MmsHandler::MmsHandler(QObject* parent, QString rootDir) : + QObject(parent), + m_isRegistered(false), + m_rootDir(rootDir) +{ + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + QDBusConnection dbus = QDBusConnection::systemBus(); + if (dbus.isConnected()) { + if (dbus.registerObject("/", this)) { + if (dbus.registerService("org.nemomobile.MmsHandler")) { + m_isRegistered = true; + } else { + qWarning() << "Unable to register service!" << dbus.lastError(); + } + } else { + qWarning() << "Object registration failed!" << dbus.lastError(); + } + } else { + qCritical() << "ERROR: No DBus session bus found!"; + } +} + +QString MmsHandler::messageNotification(QString imsi, QString from, + QString subject, uint expiry, QByteArray data) +{ + qDebug() << "messageNotification" << imsi << from << subject << expiry + << data.size() << "bytes"; + for (int i=1; i<=1000; i++) { + QString id = QString::number(i); + QDir dir(m_rootDir + "/" + id); + if (!dir.exists() && dir.mkpath(dir.path())) { + QString path(dir.filePath("pdu")); + QFile file(path); + if (file.open(QIODevice::WriteOnly)) { + file.write(data); + file.close(); + qDebug() << "Record id" << id; + return id; + } else { + qWarning() << "messageNotification failed to create" << path; + } + } + } + qWarning() << "messageNotification failed to generate message id"; + return QString(); +} + +void MmsHandler::messageReceiveStateChanged(QString recId, int state) +{ + qDebug() << "messageReceiveStateChanged" << recId << state; +} + +void MmsHandler::messageReceived(QString recId, QString mmsId, QString from, + QStringList to, QStringList cc, QString subj, uint date, int priority, + QString cls, bool readReport, MmsPartList parts) +{ + QDir dir(m_rootDir + "/" + recId); + if (dir.exists()) { + qDebug() << "messageReceived" << recId << mmsId << from + << subj << date << priority << cls << readReport; + foreach (QString addr, to) { + qDebug() << " To:" << addr; + } + foreach (QString addr, cc) { + qDebug() << " Cc:" << addr; + } + + qDebug() << parts.size() << "parts"; + QDir partDir(dir.filePath("parts")); + if (partDir.mkpath(partDir.path())) { + foreach (MmsPart part, parts) { + QFileInfo partInfo(part.fileName()); + if (partInfo.isFile()) { + QFile partFile(partInfo.canonicalFilePath()); + qDebug() << " " << part.contentId() << part.contentType() + << partInfo.canonicalFilePath(); + QString destName(partDir.filePath(partInfo.fileName())); + if (!partFile.copy(destName)) { + qWarning() << "Failed to copy" << partFile.fileName() + << "->" << destName; + } + } else { + qDebug() << " " << part.contentId() << part.contentType() + << part.fileName() << "(no such file)"; + } + } + } + } else { + qWarning() << "Invalid record id" << recId; + } +} diff --git a/mms-handler-dbus/test/mms_handler_dbus_server/mmshandler.h b/mms-handler-dbus/test/mms_handler_dbus_server/mmshandler.h new file mode 100644 index 0000000..1c711cb --- /dev/null +++ b/mms-handler-dbus/test/mms_handler_dbus_server/mmshandler.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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 MMSHANDLER_H +#define MMSHANDLER_H + +#include "mmspart.h" +#include + +class MmsHandler : public QObject +{ + Q_OBJECT +public: + MmsHandler(QObject* parent, QString rootDir); + + bool isRegistered() const { return m_isRegistered; } + +public Q_SLOTS: + QString messageNotification(QString imsi, QString from, QString subject, + uint expiry, QByteArray data); + void messageReceiveStateChanged(QString recId, int state); + void messageReceived(QString recId, QString mmsId, QString from, + QStringList to, QStringList cc, QString subj, uint date, int priority, + QString cls, bool readReport, MmsPartList parts); + +private: + bool m_isRegistered; + QString m_rootDir; +}; + +#endif // MMSHANDLER_H diff --git a/mms-handler-dbus/test/mms_handler_dbus_server/mmspart.cpp b/mms-handler-dbus/test/mms_handler_dbus_server/mmspart.cpp new file mode 100644 index 0000000..a60a635 --- /dev/null +++ b/mms-handler-dbus/test/mms_handler_dbus_server/mmspart.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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 "mmspart.h" + +MmsPart::MmsPart(QObject* parent) : + QObject(parent) +{ +} + +MmsPart::MmsPart(const MmsPart& other) : + QObject(other.parent()), + m_fileName(other.m_fileName), + m_contentType(other.m_contentType), + m_contentId(other.m_contentId) +{ +} + +MmsPart& MmsPart::operator=(const MmsPart& other) +{ + m_fileName = other.m_fileName; + m_contentType = other.m_contentType; + m_contentId = other.m_contentId; + return *this; +} + +void MmsPart::marshall(QDBusArgument& arg) const +{ + arg.beginStructure(); + arg << m_fileName << m_contentType << m_contentId; + arg.endStructure(); +} + +void MmsPart::demarshall(const QDBusArgument& arg) +{ + arg.beginStructure(); + arg >> m_fileName >> m_contentType >> m_contentId; + arg.endStructure(); +} + +QDBusArgument& operator<<(QDBusArgument& arg, const MmsPart& part) +{ + part.marshall(arg); + return arg; +} + +const QDBusArgument& operator>>(const QDBusArgument& arg, MmsPart& part) +{ + part.demarshall(arg); + return arg; +} diff --git a/mms-handler-dbus/test/mms_handler_dbus_server/mmspart.h b/mms-handler-dbus/test/mms_handler_dbus_server/mmspart.h new file mode 100644 index 0000000..8e39976 --- /dev/null +++ b/mms-handler-dbus/test/mms_handler_dbus_server/mmspart.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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 MMSPART_H +#define MMSPART_H + +#include +#include + +class MmsPart : public QObject +{ + Q_OBJECT +public: + explicit MmsPart(QObject* parent = 0); + MmsPart(const MmsPart& other); + MmsPart& operator=(const MmsPart& other); + + inline QString fileName() const { return m_fileName; } + inline QString contentType() const { return m_contentType; } + inline QString contentId() const { return m_contentId; } + + void marshall(QDBusArgument& arg) const; + void demarshall(const QDBusArgument& arg); + +private: + QString m_fileName; + QString m_contentType; + QString m_contentId; +}; + +QDBusArgument& operator<<(QDBusArgument& arg, const MmsPart& part); +const QDBusArgument& operator>>(const QDBusArgument& arg, MmsPart& part); + +typedef QList MmsPartList; + +Q_DECLARE_METATYPE(MmsPart); +Q_DECLARE_METATYPE(MmsPartList); + +#endif // MMSPART_H diff --git a/mms-handler-dbus/test/mms_handler_dbus_server/org.nemomobile.MmsHandler.conf b/mms-handler-dbus/test/mms_handler_dbus_server/org.nemomobile.MmsHandler.conf new file mode 100644 index 0000000..6bd450e --- /dev/null +++ b/mms-handler-dbus/test/mms_handler_dbus_server/org.nemomobile.MmsHandler.conf @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/mms-handler-dbus/test/mms_handler_dbus_server/test_mms_handler_dbus_server.pro b/mms-handler-dbus/test/mms_handler_dbus_server/test_mms_handler_dbus_server.pro new file mode 100644 index 0000000..2342e03 --- /dev/null +++ b/mms-handler-dbus/test/mms_handler_dbus_server/test_mms_handler_dbus_server.pro @@ -0,0 +1,26 @@ +TARGET = test_mms_handler_dbus_server +CONFIG += console +CONFIG -= app_bundle + +QT += core +QT -= gui +QT += dbus + +QMAKE_CXXFLAGS *= -Werror -Wall -fno-exceptions -Wno-psabi -Wno-unused-parameter + +TEMPLATE = app + +SOURCES += \ + main.cpp \ + mmsadaptor.cpp \ + mmshandler.cpp \ + mmspart.cpp + +HEADERS += \ + mmsadaptor.h \ + mmshandler.h \ + mmspart.h + +OTHER_FILES += \ + org.nemomobile.MmsHandler.conf \ + ../../spec/org.nemomobile.MmsHandler.xml diff --git a/mms-lib/Makefile b/mms-lib/Makefile new file mode 100644 index 0000000..cbf15e0 --- /dev/null +++ b/mms-lib/Makefile @@ -0,0 +1,107 @@ +# -*- Mode: makefile -*- + +.PHONY: clean all debug release + +# Required packages +PKGS = glib-2.0 libsoup-2.4 libwspcodec + +# +# Default target +# + +all: debug release + +# +# Sources +# + +SRC = mms_codec.c mms_connection.c mms_connman.c mms_dispatcher.c \ + mms_handler.c mms_lib_util.c mms_file_util.c mms_log.c \ + mms_message.c mms_task.c mms_task_ack.c mms_task_decode.c \ + mms_task_notification.c mms_task_notifyresp.c mms_task_publish.c \ + mms_task_read.c mms_task_retrieve.c mms_task_upload.c mms_util.c + +# +# Directories +# + +SRC_DIR = src +INCLUDE_DIR = include +BUILD_DIR = build +DEBUG_BUILD_DIR = $(BUILD_DIR)/debug +RELEASE_BUILD_DIR = $(BUILD_DIR)/release + +# +# Code coverage +# + +ifndef GCOV +GCOV = 0 +endif + +ifneq ($(GCOV),0) +CFLAGS += --coverage +endif + +# +# Tools and flags +# + +CC = $(CROSS_COMPILE)gcc +LD = $(CC) +WARNINGS = -Wall +INCLUDES = -I$(SRC_DIR) -I$(INCLUDE_DIR) +CFLAGS += $(WARNINGS) $(INCLUDES) $(shell pkg-config --cflags $(PKGS)) -MMD +DEBUG_CFLAGS = -g -DDEBUG $(CFLAGS) +RELEASE_CFLAGS = -O2 $(CFLAGS) +ARFLAGS = rc + +# +# Files +# + +DEBUG_OBJS = $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) +RELEASE_OBJS = $(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.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)/*~ + +$(DEBUG_BUILD_DIR): + mkdir -p $@ + +$(RELEASE_BUILD_DIR): + mkdir -p $@ + +$(DEBUG_LIB): $(DEBUG_BUILD_DIR) $(DEBUG_OBJS) + $(AR) $(ARFLAGS) $@ $(DEBUG_OBJS) + +$(RELEASE_LIB): $(RELEASE_BUILD_DIR) $(RELEASE_OBJS) + $(AR) $(ARFLAGS) $@ $(RELEASE_OBJS) + +$(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 $@ diff --git a/mms-lib/include/mms_connection.h b/mms-lib/include/mms_connection.h new file mode 100644 index 0000000..1c30c52 --- /dev/null +++ b/mms-lib/include/mms_connection.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_CONNECTION_H +#define JOLLA_MMS_CONNECTION_H + +#include "mms_lib_types.h" + +/* Connection errors */ +#define G_MMS_CONNECTION_ERROR mms_connection_error_quark() +GQuark mms_connection__error_quark(void); + +typedef enum _MMS_CONNECTION_ERROR { + MMS_CONNECTION_ERROR_NOT_FOUND, /* Requested SIM not found */ + MMS_CONNECTION_ERROR_NOT_ALLOWED, /* Data transfer disabled */ + MMS_CONNECTION_ERROR_FAILED, /* Connection failed */ + MMS_CONNECTION_ERROR_INTERRUPTED /* Interrupted by something */ +} MMS_CONNECTION_ERROR; + +/* Connection state. There are only two state change sequences allowed: + * OPENING -> FAILED and OPENING -> OPEN -> CLOSE. Once connection fails + * to open or gets closed, it will remain on FAILED or CLOSED state forever. + * The client should drop its reference to the closed or failed connection + * and open a new one when it needs it. */ +typedef enum _MMS_CONNECTION_STATE { + MMS_CONNECTION_STATE_INVALID, /* Invalid state */ + MMS_CONNECTION_STATE_OPENING, /* Connection is being opened */ + MMS_CONNECTION_STATE_FAILED, /* Connection failed to open */ + MMS_CONNECTION_STATE_OPEN, /* Connection is active */ + MMS_CONNECTION_STATE_CLOSED /* Connection has been closed */ +} MMS_CONNECTION_STATE; + +/* Delegate (one per connection) */ +typedef struct mms_connection_delegate MMSConnectionDelegate; +struct mms_connection_delegate { + void (*fn_connection_state_changed)( + MMSConnectionDelegate* delegate, + MMSConnection* connection); +}; + +/* Connection data. The delegate field may be changed by the client at + * any time. */ +struct mms_connection { + GObject parent; + char* imsi; + char* mmsc; + char* mmsproxy; + char* netif; + gboolean user_connection; + MMS_CONNECTION_STATE state; + MMSConnectionDelegate* delegate; +}; + +/* Connection class for implementation */ +typedef struct mms_connection_class { + GObjectClass parent; + void (*fn_close)(MMSConnection* connection); +} MMSConnectionClass; + +GType mms_connection_get_type(void); +#define MMS_TYPE_CONNECTION (mms_connection_get_type()) + +MMSConnection* +mms_connection_ref( + MMSConnection* connection); + +void +mms_connection_unref( + MMSConnection* connection); + +const char* +mms_connection_state_name( + MMSConnection* connection); + +MMS_CONNECTION_STATE +mms_connection_state( + MMSConnection* connection); + +void +mms_connection_close( + MMSConnection* connection); + +#define mms_connection_is_open(connection) \ + (mms_connection_state(connection) == MMS_CONNECTION_STATE_OPEN) + +#endif /* JOLLA_MMS_CONNECTION_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/include/mms_connman.h b/mms-lib/include/mms_connman.h new file mode 100644 index 0000000..235a426 --- /dev/null +++ b/mms-lib/include/mms_connman.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_CONNMAN_H +#define JOLLA_MMS_CONNMAN_H + +#include "mms_lib_types.h" + +typedef struct mms_connman_class { + GObjectClass parent; + MMSConnection* (*fn_open_connection)(MMSConnMan* cm, const char* imsi, + gboolean user_request); +} MMSConnManClass; + +GType mms_connman_get_type(void); +#define MMS_TYPE_CONNMAN (mms_connman_get_type()) + +/* Reference counting */ +MMSConnMan* +mms_connman_ref( + MMSConnMan* cm); + +void +mms_connman_unref( + MMSConnMan* cm); + +/** + * Creates a new connection or returns the reference to an aready active one. + * The caller must release the reference. + */ +MMSConnection* +mms_connman_open_connection( + MMSConnMan* cm, + const char* imsi, + gboolean user_request); + +#endif /* JOLLA_MMS_CONNMAN_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/include/mms_dispatcher.h b/mms-lib/include/mms_dispatcher.h new file mode 100644 index 0000000..7cb041c --- /dev/null +++ b/mms-lib/include/mms_dispatcher.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_DISPATCHER_H +#define JOLLA_MMS_DISPATCHER_H + +#include "mms_lib_types.h" + +/* Delegate (one per dispatcher) */ +typedef struct mms_dispatcher_delegate MMSDispatcherDelegate; +struct mms_dispatcher_delegate { + /* Dispatcher deactivated because it has nothing to do */ + void (*fn_done)( + MMSDispatcherDelegate* delegate, + MMSDispatcher* dispatcher); +}; + +MMSDispatcher* +mms_dispatcher_new( + const MMSConfig* config, + MMSConnMan* cm, + MMSHandler* handler); + +MMSDispatcher* +mms_dispatcher_ref( + MMSDispatcher* dispatcher); + +void +mms_dispatcher_unref( + MMSDispatcher* dispatcher); + +void +mms_dispatcher_set_delegate( + MMSDispatcher* dispatcher, + MMSDispatcherDelegate* delegate); + +gboolean +mms_dispatcher_is_active( + MMSDispatcher* dispatcher); + +gboolean +mms_dispatcher_start( + MMSDispatcher* dispatcher); + +gboolean +mms_dispatcher_handle_push( + MMSDispatcher* dispatcher, + const char* imsi, + GBytes* push); + +gboolean +mms_dispatcher_receive_message( + MMSDispatcher* dispatcher, + const char* id, + const char* imsi, + gboolean automatic, + GBytes* push); + +gboolean +mms_dispatcher_send_read_report( + MMSDispatcher* dispatcher, + const char* id, + const char* imsi, + const char* message_id, + const char* to, + MMSReadStatus status); + +void +mms_dispatcher_cancel( + MMSDispatcher* dispatcher, + const char* id); + +#endif /* JOLLA_MMS_DISPATCHER_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/include/mms_handler.h b/mms-lib/include/mms_handler.h new file mode 100644 index 0000000..14452a1 --- /dev/null +++ b/mms-lib/include/mms_handler.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_HANDLER_H +#define JOLLA_MMS_HANDLER_H + +#include "mms_message.h" + +/* Receive state */ +typedef enum _mmm_receive_state { + MMS_RECEIVE_STATE_INVALID = -1, + MMS_RECEIVE_STATE_RECEIVING, + MMS_RECEIVE_STATE_DEFERRED, + MMS_RECEIVE_STATE_NOSPACE, + MMS_RECEIVE_STATE_DECODING, + MMS_RECEIVE_STATE_DOWNLOAD_ERROR, + MMS_RECEIVE_STATE_DECODING_ERROR +} MMS_RECEIVE_STATE; + +/* Class */ +typedef struct mms_handler_class { + GObjectClass parent; + + /* New incoming message notification. Returns the handler message id + * to start download immediately, NULL or empty string to postpone it. */ + char* (*fn_message_notify)( + MMSHandler* handler, /* Handler instance */ + const char* imsi, /* Subscriber identity */ + const char* from, /* Sender's phone number */ + const char* subject, /* Subject (optional) */ + time_t expiry, /* Message expiry time */ + GBytes* push); /* Raw push message */ + + /* Sets the receive state */ + gboolean (*fn_message_receive_state_changed)( + MMSHandler* handler, /* Handler instance */ + const char* id, /* Handler record id */ + MMS_RECEIVE_STATE state); /* Receive state */ + + /* Message has been successfully received */ + gboolean (*fn_message_received)( + MMSHandler* handler, /* Handler instance */ + MMSMessage* msg); /* Decoded message */ + +} MMSHandlerClass; + +GType mms_handler_get_type(void); +#define MMS_TYPE_HANDLER (mms_handler_get_type()) + +MMSHandler* +mms_handler_ref( + MMSHandler* handler); + +void +mms_handler_unref( + MMSHandler* handler); + +char* +mms_handler_message_notify( + MMSHandler* handler, /* Handler instance */ + const char* imsi, /* Subscriber identity */ + const char* from, /* Sender's phone number */ + const char* subject, /* Subject (optional) */ + time_t expiry, /* Message expiry time */ + GBytes* push); /* Raw push message */ + +gboolean +mms_handler_message_receive_state_changed( + MMSHandler* handler, /* Handler instance */ + const char* id, /* Handler record id */ + MMS_RECEIVE_STATE state); /* Receive state */ + +gboolean +mms_handler_message_received( + MMSHandler* handler, /* Handler instance */ + MMSMessage* msg); /* Decoded message */ + +#endif /* JOLLA_MMS_HANDLER_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/include/mms_lib_log.h b/mms-lib/include/mms_lib_log.h new file mode 100644 index 0000000..65c5042 --- /dev/null +++ b/mms-lib/include/mms_lib_log.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_LIB_LOG_H +#define JOLLA_MMS_LIB_LOG_H + +#include "mms_log.h" + +#define MMS_LIB_LOG_MODULES(log) \ + log(mms_dispatcher_log)\ + log(mms_handler_log)\ + log(mms_message_log)\ + log(mms_util_log)\ + log(mms_task_log)\ + log(mms_task_decode_log)\ + log(mms_task_notification_log)\ + log(mms_task_retrieve_log)\ + log(mms_task_upload_log)\ + log(mms_task_publish_log)\ + log(mms_connman_log)\ + log(mms_connection_log) + +MMS_LIB_LOG_MODULES(MMS_LOG_MODULE_DECL) + +#endif /* JOLLA_MMS_LIB_LOG_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/include/mms_lib_types.h b/mms-lib/include/mms_lib_types.h new file mode 100644 index 0000000..76fd40d --- /dev/null +++ b/mms-lib/include/mms_lib_types.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_LIB_TYPES_H +#define JOLLA_MMS_LIB_TYPES_H + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +# include +#else +# include +# include +#endif + +#include +#include + +/* Static configuration, chosen at startup and never changing since then */ +typedef struct mms_config { + const char* root_dir; /* Root directory for storing MMS files */ + const char* user_agent; /* User agent string */ + int retry_secs; /* Retry timeout in seconds */ + int idle_secs; /* Idle timeout */ + gboolean keep_temp_files; /* Keep temporary files around */ + gboolean attic_enabled; /* Keep unrecognized push message in attic */ + gboolean send_dr; /* Allow sending delivery reports */ +} MMSConfig; + +/* Types */ +typedef GObject MMSHandler; +typedef GObject MMSConnMan; +typedef struct mms_log_module MMSLogModule; +typedef struct mms_dispatcher MMSDispatcher; +typedef struct mms_connection MMSConnection; +typedef struct mms_message MMSPdu; +typedef struct _mms_message MMSMessage; + +/* MMS content type */ +#define MMS_CONTENT_TYPE "application/vnd.wap.mms-message" + +/* MMS read status */ +typedef enum mms_read_status { + MMS_READ_STATUS_READ, /* Message has been read */ + MMS_READ_STATUS_DELETED /* Message has been deleted without reading */ +} MMSReadStatus; + +/* Convenience macros */ +#define MMS_CAST(address,type,field) ((type *)( \ + (char*)(address) - \ + (char*)(&((type *)0)->field))) + +#endif /* JOLLA_MMS_LIB_TYPES_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/include/mms_lib_util.h b/mms-lib/include/mms_lib_util.h new file mode 100644 index 0000000..ca78a2c --- /dev/null +++ b/mms-lib/include/mms_lib_util.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_LIB_UTIL_H +#define JOLLA_MMS_LIB_UTIL_H + +#include "mms_lib_types.h" + +/* One-time initialization */ +void +mms_lib_init(void); + +/* Reset configuration to default */ +void +mms_lib_default_config( + MMSConfig* config); + +#endif /* JOLLA_MMS_LIB_UTIL_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/include/mms_log.h b/mms-lib/include/mms_log.h new file mode 100644 index 0000000..fcb112d --- /dev/null +++ b/mms-lib/include/mms_log.h @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_LOG_H +#define JOLLA_MMS_LOG_H + +#include "mms_lib_types.h" +#include + +/* Log levels */ +#define MMS_LOGLEVEL_GLOBAL (-1) +#define MMS_LOGLEVEL_NONE (0) +#define MMS_LOGLEVEL_ERR (1) +#define MMS_LOGLEVEL_WARN (2) +#define MMS_LOGLEVEL_INFO (3) +#define MMS_LOGLEVEL_DEBUG (4) +#define MMS_LOGLEVEL_VERBOSE (5) + +/* Allow these to be redefined */ +#ifndef MMS_LOGLEVEL_MAX +# ifdef DEBUG +# define MMS_LOGLEVEL_MAX MMS_LOGLEVEL_VERBOSE +# else +# define MMS_LOGLEVEL_MAX MMS_LOGLEVEL_DEBUG +# endif +#endif /* MMS_LOGLEVEL_MAX */ + +#ifndef MMS_LOGLEVEL_DEFAULT +# ifdef DEBUG +# define MMS_LOGLEVEL_DEFAULT MMS_LOGLEVEL_DEBUG +# else +# define MMS_LOGLEVEL_DEFAULT MMS_LOGLEVEL_INFO +# endif +#endif /* MMS_LOGLEVEL_DEFAULT */ + +/* Do we need a separate log level for ASSERTs? */ +#ifndef MMS_LOGLEVEL_ASSERT +# ifdef DEBUG +# define MMS_LOGLEVEL_ASSERT MMS_LOGLEVEL_ERR +# else + /* No asserts in release build */ +# define MMS_LOGLEVEL_ASSERT (MMS_LOGLEVEL_MAX+1) +# endif +#endif + +/* Log module */ +struct mms_log_module { + const char* name; + const int max_level; + int level; +}; + +/* Command line parsing helper. Option format is [module]:level + * where level can be either a number or log level name ("none", err etc.) */ +gboolean +mms_log_parse_option( + const char* opt, /* String to parse */ + MMSLogModule** modules, /* Known modules */ + int count, /* Number of known modules */ + GError** error); /* Optional error message */ + +/* Set log type by name ("syslog", "stdout" or "glib"). This is also + * primarily for parsing command line options */ +gboolean +mms_log_set_type( + const char* type, + const char* default_name); + +const char* +mms_log_get_type( + void); + +/* Generates the string containg description of log levels and list of + * log modules. The caller must deallocate the string with g_free */ +char* +mms_log_description( + MMSLogModule** modules, /* Known modules */ + int count); /* Number of known modules */ + +/* Logging function */ +void +mms_log( + const MMSLogModule* module, /* Calling module (NULL for default) */ + int level, /* Message log level */ + const char* format, /* Message format */ + ...) G_GNUC_PRINTF(3,4); /* Followed by arguments */ + +void +mms_logv( + const MMSLogModule* module, + int level, + const char* format, + va_list va); + +#ifdef unix +# define MMS_LOG_SYSLOG +#endif + +/* Available log handlers */ +#define MMS_DEFINE_LOG_FN(fn) void fn(const char* name, int level, \ + const char* format, va_list va) +MMS_DEFINE_LOG_FN(mms_log_stdout); +MMS_DEFINE_LOG_FN(mms_log_glib); +#ifdef MMS_LOG_SYSLOG +MMS_DEFINE_LOG_FN(mms_log_syslog); +#endif + +/* Log configuration */ +#define MMS_LOG_MODULE_DECL(m) extern MMSLogModule m; +MMS_LOG_MODULE_DECL(mms_log_default) +typedef MMS_DEFINE_LOG_FN((*MMSLogFunc)); +extern MMSLogFunc mms_log_func; +extern gboolean mms_log_stdout_timestamp; + +/* Log module (optional) */ +#define MMS_LOG_MODULE_DEFINE_(mod,name) \ + MMSLogModule mod = {name, \ + MMS_LOGLEVEL_MAX, MMS_LOGLEVEL_GLOBAL} +#ifdef MMS_LOG_MODULE_NAME +extern MMSLogModule MMS_LOG_MODULE_NAME; +# define MMS_LOG_MODULE_CURRENT (&MMS_LOG_MODULE_NAME) +# define MMS_LOG_MODULE_DEFINE(name) \ + MMS_LOG_MODULE_DEFINE_(MMS_LOG_MODULE_NAME,name) +#else +# define MMS_LOG_MODULE_CURRENT NULL +#endif + +/* Logging macros */ + +#define MMS_LOG_NOTHING ((void)0) +#define MMS_ERRMSG(err) (((err) && (err)->message) ? (err)->message : \ + "Unknown error") + +#if !defined(MMS_LOG_VARARGS) && defined(__GNUC__) +# define MMS_LOG_VARARGS +#endif + +#ifndef MMS_LOG_VARARGS +# define MMS_LOG_VA_NONE(x) static inline void MMS_##x(const char* f, ...) {} +# define MMS_LOG_VA(x) static inline void MMS_##x(const char* f, ...) { \ + if (f && f[0]) { \ + va_list va; va_start(va,f); \ + mms_logv(MMS_LOG_MODULE_CURRENT, MMS_LOGLEVEL_##x, f, va); \ + va_end(va); \ + } \ +} +#endif /* MMS_LOG_VARARGS */ + +#define MMS_LOG_ENABLED (MMS_LOGLEVEL_MAX >= MMS_LOGLEVEL_NONE) +#define MMS_LOG_ERR (MMS_LOGLEVEL_MAX >= MMS_LOGLEVEL_ERR) +#define MMS_LOG_WARN (MMS_LOGLEVEL_MAX >= MMS_LOGLEVEL_WARN) +#define MMS_LOG_INFO (MMS_LOGLEVEL_MAX >= MMS_LOGLEVEL_INFO) +#define MMS_LOG_DEBUG (MMS_LOGLEVEL_MAX >= MMS_LOGLEVEL_DEBUG) +#define MMS_LOG_VERBOSE (MMS_LOGLEVEL_MAX >= MMS_LOGLEVEL_VERBOSE) +#define MMS_LOG_ASSERT (MMS_LOGLEVEL_MAX >= MMS_LOGLEVEL_ASSERT) + +#if MMS_LOG_ASSERT +void +mms_log_assert( + const MMSLogModule* module, /* Calling module (NULL for default) */ + const char* expr, /* Assert expression */ + const char* file, /* File name */ + int line); /* Line number */ +# define MMS_ASSERT(expr) ((expr) ? MMS_LOG_NOTHING : \ + mms_log_assert(MMS_LOG_MODULE_CURRENT, #expr, __FILE__, __LINE__)) +# define MMS_VERIFY(expr) MMS_ASSERT(expr) +#else +# define MMS_ASSERT(expr) +# define MMS_VERIFY(expr) (expr) +#endif + +#ifdef MMS_LOG_VARARGS +# if MMS_LOG_ERR +# define MMS_ERR(f,args...) mms_log(MMS_LOG_MODULE_CURRENT, \ + MMS_LOGLEVEL_ERR, f, ##args) +# define MMS_ERR_(f,args...) mms_log(MMS_LOG_MODULE_CURRENT, \ + MMS_LOGLEVEL_ERR, "%s() " f, __FUNCTION__, ##args) +# else +# define MMS_ERR(f,args...) MMS_LOG_NOTHING +# define MMS_ERR_(f,args...) MMS_LOG_NOTHING +# endif /* MMS_LOG_ERR */ +#else +# define MMS_ERR_ MMS_ERR +# if MMS_LOG_ERR + MMS_LOG_VA(ERR) +# else + MMS_LOG_VA_NONE(ERR) +# endif /* MMS_LOG_ERR */ +#endif /* MMS_LOG_VARARGS */ + +#ifdef MMS_LOG_VARARGS +# if MMS_LOG_WARN +# define MMS_WARN(f,args...) mms_log(MMS_LOG_MODULE_CURRENT, \ + MMS_LOGLEVEL_WARN, f, ##args) +# define MMS_WARN_(f,args...) mms_log(MMS_LOG_MODULE_CURRENT, \ + MMS_LOGLEVEL_WARN, "%s() " f, __FUNCTION__, ##args) +# else +# define MMS_WARN(f,args...) MMS_LOG_NOTHING +# define MMS_WARN_(f,args...) MMS_LOG_NOTHING +# endif /* MMS_LOGL_WARN */ +#else +# define MMS_WARN_ MMS_WARN +# if MMS_LOG_WARN + MMS_LOG_VA(WARN) +# else + MMS_LOG_VA_NONE(WARN) +# endif /* MMS_LOGL_WARN */ +# endif /* MMS_LOG_VARARGS */ + +#ifdef MMS_LOG_VARARGS +# if MMS_LOG_INFO +# define MMS_INFO(f,args...) mms_log(MMS_LOG_MODULE_CURRENT, \ + MMS_LOGLEVEL_INFO, f, ##args) +# define MMS_INFO_(f,args...) mms_log(MMS_LOG_MODULE_CURRENT, \ + MMS_LOGLEVEL_INFO, "%s() " f, __FUNCTION__, ##args) +# else +# define MMS_INFO(f,args...) MMS_LOG_NOTHING +# define MMS_INFO_(f,args...) MMS_LOG_NOTHING +# endif /* MMS_LOG_INFO */ +#else +# define MMS_INFO_ MMS_INFO +# if MMS_LOG_INFO + MMS_LOG_VA(INFO) +# else + MMS_LOG_VA_NONE(INFO) +# endif /* MMS_LOG_INFO */ +#endif /* MMS_LOG_VARARGS */ + +#ifdef MMS_LOG_VARARGS +# if MMS_LOG_DEBUG +# define MMS_DEBUG(f,args...) mms_log(MMS_LOG_MODULE_CURRENT, \ + MMS_LOGLEVEL_DEBUG, f, ##args) +# define MMS_DEBUG_(f,args...) mms_log(MMS_LOG_MODULE_CURRENT, \ + MMS_LOGLEVEL_DEBUG, "%s() " f, __FUNCTION__, ##args) +# else +# define MMS_DEBUG(f,args...) MMS_LOG_NOTHING +# define MMS_DEBUG_(f,args...) MMS_LOG_NOTHING +# endif /* MMS_LOG_DEBUG */ +#else +# define MMS_DEBUG_ MMS_DEBUG +# if MMS_LOG_DEBUG + MMS_LOG_VA(DEBUG) +# else + MMS_LOG_VA_NONE(DEBUG) +# endif /* MMS_LOG_DEBUG */ +#endif /* MMS_LOG_VARARGS */ + +#ifdef MMS_LOG_VARARGS +# if MMS_LOG_VERBOSE +# define MMS_VERBOSE(f,args...) mms_log(MMS_LOG_MODULE_CURRENT, \ + MMS_LOGLEVEL_VERBOSE, f, ##args) +# define MMS_VERBOSE_(f,args...) mms_log(MMS_LOG_MODULE_CURRENT, \ + MMS_LOGLEVEL_VERBOSE, "%s() " f, __FUNCTION__, ##args) +# else +# define MMS_VERBOSE(f,args...) MMS_LOG_NOTHING +# define MMS_VERBOSE_(f,args...) MMS_LOG_NOTHING +# endif /* MMS_LOG_VERBOSE */ +#else +# define MMS_VERBOSE_ MMS_VERBOSE +# if MMS_LOG_VERBOSE + MMS_LOG_VA(VERBOSE) +# else + MMS_LOG_VA_NONE(VERBOSE) +# endif /* MMS_LOG_VERBOSE */ +#endif /* MMS_LOG_VARARGS */ + +#endif /* JOLLA_MMS_LOG_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/include/mms_message.h b/mms-lib/include/mms_message.h new file mode 100644 index 0000000..56670d7 --- /dev/null +++ b/mms-lib/include/mms_message.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_MESSAGE_H +#define JOLLA_MMS_MESSAGE_H + +#include "mms_lib_types.h" + +typedef enum mms_message_prority { + MMS_PRIORITY_LOW, + MMS_PRIORITY_NORMAL, + MMS_PRIORITY_HIGH +} MMS_PRIORITY; + +struct _mms_message { + gint ref_count; /* Reference count */ + char* id; /* Database record ID */ + char* message_id; /* Message-ID */ + char* from; /* Sender */ + char** to; /* To: list */ + char** cc; /* Cc: list */ + char* subject; /* Subject */ + time_t date; /* Original send date */ + MMS_PRIORITY priority; /* Message priority */ + char* cls; /* Message class */ + gboolean read_report_req; /* Request for read report */ + char* parts_dir; /* Where parts are stored */ + GSList* parts; /* Message parts */ + int flags; /* Message flags: */ + +#define MMS_MESSAGE_FLAG_KEEP_FILES (0x01) /* Don't delete files */ + +}; + +typedef struct _mms_message_part { + char* content_type; /* Content-Type */ + char* content_id; /* Content-ID */ + char* file; /* File name */ +} MMSMessagePart; + +MMSMessage* +mms_message_new( + void); + +MMSMessage* +mms_message_ref( + MMSMessage* msg); + +void +mms_message_unref( + MMSMessage* msg); + +#endif /* JOLLA_MMS_MESSAGE_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 new file mode 100644 index 0000000..737bf7b --- /dev/null +++ b/mms-lib/mms-lib.pro @@ -0,0 +1,53 @@ +TEMPLATE = lib +CONFIG += staticlib +CONFIG -= qt +CONFIG += link_pkgconfig +PKGCONFIG += glib-2.0 libsoup-2.4 libwspcodec +INCLUDEPATH += include +QMAKE_CFLAGS += -Wno-unused + +CONFIG(debug, debug|release) { + DEFINES += DEBUG + DESTDIR = $$_PRO_FILE_PWD_/build/debug +} else { + DESTDIR = $$_PRO_FILE_PWD_/build/release +} + +SOURCES += \ + src/mms_codec.c \ + src/mms_connection.c \ + src/mms_connman.c \ + src/mms_dispatcher.c \ + src/mms_file_util.c \ + src/mms_handler.c \ + src/mms_message.c \ + src/mms_lib_util.c \ + src/mms_log.c \ + src/mms_task.c \ + src/mms_task_ack.c \ + src/mms_task_decode.c \ + src/mms_task_notification.c \ + src/mms_task_notifyresp.c \ + src/mms_task_publish.c \ + src/mms_task_read.c \ + src/mms_task_retrieve.c \ + src/mms_task_upload.c \ + src/mms_util.c + +HEADERS += \ + src/mms_codec.h \ + src/mms_file_util.h \ + src/mms_task.h \ + src/mms_util.h \ + +HEADERS += \ + include/mms_connection.h \ + include/mms_connman.h \ + include/mms_database.h \ + include/mms_dispatcher.h \ + include/mms_handler.h \ + include/mms_lib_log.h \ + include/mms_lib_types.h \ + include/mms_lib_util.h \ + include/mms_log.h \ + include/mms_message.h diff --git a/mms-lib/src/mms_codec.c b/mms-lib/src/mms_codec.c new file mode 100644 index 0000000..9ac0692 --- /dev/null +++ b/mms-lib/src/mms_codec.c @@ -0,0 +1,1968 @@ +/* + * + * Multimedia Messaging Service + * + * Copyright (C) 2010-2011 Intel Corporation. All rights reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#ifdef _WIN32 +# define ssize_t int +# define write _write +# include +# define uninitialized_var(x) x +#else +# include +# define uninitialized_var(x) x = x +#endif + +#include + +#include "wsputil.h" +#include "mms_codec.h" + +#define MAX_ENC_VALUE_BYTES 6 + +#ifdef TEMP_FAILURE_RETRY +#define TFR TEMP_FAILURE_RETRY +#else +#define TFR +#endif + +enum mms_message_value_bool { + MMS_MESSAGE_VALUE_BOOL_YES = 128, + MMS_MESSAGE_VALUE_BOOL_NO = 129, +}; + +enum header_flag { + HEADER_FLAG_MANDATORY = 1, + HEADER_FLAG_ALLOW_MULTI = 2, + HEADER_FLAG_PRESET_POS = 4, + HEADER_FLAG_MARKED = 8, +}; + +enum mms_header { + MMS_HEADER_BCC = 0x01, + MMS_HEADER_CC = 0x02, + MMS_HEADER_CONTENT_LOCATION = 0x03, + MMS_HEADER_CONTENT_TYPE = 0x04, + MMS_HEADER_DATE = 0x05, + MMS_HEADER_DELIVERY_REPORT = 0x06, + MMS_HEADER_DELIVERY_TIME = 0x07, + MMS_HEADER_EXPIRY = 0x08, + MMS_HEADER_FROM = 0x09, + MMS_HEADER_MESSAGE_CLASS = 0x0a, + MMS_HEADER_MESSAGE_ID = 0x0b, + MMS_HEADER_MESSAGE_TYPE = 0x0c, + MMS_HEADER_MMS_VERSION = 0x0d, + MMS_HEADER_MESSAGE_SIZE = 0x0e, + MMS_HEADER_PRIORITY = 0x0f, + MMS_HEADER_READ_REPORT = 0x10, + MMS_HEADER_REPORT_ALLOWED = 0x11, + MMS_HEADER_RESPONSE_STATUS = 0x12, + MMS_HEADER_RESPONSE_TEXT = 0x13, + MMS_HEADER_SENDER_VISIBILITY = 0x14, + MMS_HEADER_STATUS = 0x15, + MMS_HEADER_SUBJECT = 0x16, + MMS_HEADER_TO = 0x17, + MMS_HEADER_TRANSACTION_ID = 0x18, + MMS_HEADER_RETRIEVE_STATUS = 0x19, + MMS_HEADER_RETRIEVE_TEXT = 0x1a, + MMS_HEADER_READ_STATUS = 0x1b, + __MMS_HEADER_MAX = 0x1c, + MMS_HEADER_INVALID = 0x80, +}; + +enum mms_part_header { + MMS_PART_HEADER_CONTENT_LOCATION = 0x0e, + MMS_PART_HEADER_CONTENT_ID = 0x40, +}; + +/* + * Reference: IANA http://www.iana.org/assignments/character-sets + */ +static const struct { + unsigned int mib_enum; + const char *charset; +} charset_assignments[] = { + { 3, "US-ASCII" }, + { 4, "ISO_8859-1" }, + { 5, "ISO_8859-2" }, + { 6, "ISO_8859-3" }, + { 7, "ISO_8859-4" }, + { 8, "ISO_8859-5" }, + { 9, "ISO_8859-6" }, + { 10, "ISO_8859-7" }, + { 11, "ISO_8859-8" }, + { 12, "ISO_8859-9" }, + { 13, "ISO-8859-10" }, + { 17, "Shift_JIS" }, + { 18, "EUC-JP" }, + { 36, "KS_C_5601-1987" }, + { 37, "ISO-2022-KR" }, + { 38, "EUC-KR" }, + { 39, "ISO-2022-JP" }, + { 40, "ISO-2022-JP-2" }, + { 81, "ISO_8859-6-E" }, + { 82, "ISO_8859-6-I" }, + { 84, "ISO_8859-8-E" }, + { 85, "ISO_8859-8-I" }, + { 106, "UTF-8" }, + { 109, "ISO-8859-13" }, + { 110, "ISO-8859-14" }, + { 111, "ISO-8859-15" }, + { 112, "ISO-8859-16" }, + { 113, "GBK" }, + { 114, "GB18030" }, + { 1000, "ISO-10646-UCS-2" }, + { 1001, "ISO-10646-UCS-4" }, + { 1004, "ISO-10646-J-1" }, + { 1012, "UTF-7" }, + { 1013, "UTF-16BE" }, + { 1014, "UTF-16LE" }, + { 1015, "UTF-16" }, + { 1017, "UTF-32" }, + { 1018, "UTF-32BE" }, + { 1019, "UTF-32LE" }, + { 2025, "GB2312" }, + { 2026, "Big5" }, + { 2027, "macintosh" }, + { 2084, "KOI8-R" }, + { 2109, "windows-874" }, + { 2250, "windows-1250" }, + { 2251, "windows-1251" }, + { 2252, "windows-1252" }, + { 2253, "windows-1253" }, + { 2254, "windows-1254" }, + { 2255, "windows-1255" }, + { 2256, "windows-1256" }, + { 2257, "windows-1257" }, + { 2258, "windows-1258" } +}; + +#define FB_SIZE 256 + +struct file_buffer { + unsigned char buf[FB_SIZE]; + unsigned int size; + unsigned int fsize; + int fd; +}; + +typedef gboolean (*header_handler)(struct wsp_header_iter *, void *); +typedef gboolean (*header_encoder)(struct file_buffer *, enum mms_header, + void *); + +char *mms_content_type_get_param_value(const char *content_type, + const char *param_name) +{ + struct wsp_text_header_iter iter; + + if (wsp_text_header_iter_init(&iter, content_type) == FALSE) + return NULL; + + while (wsp_text_header_iter_param_next(&iter) == TRUE) { + const char *key = wsp_text_header_iter_get_key(&iter); + + if (g_str_equal(key, param_name) == TRUE) + return g_strdup(wsp_text_header_iter_get_value(&iter)); + } + + return NULL; +} + +static const char *charset_index2string(unsigned int index) +{ + int low = 0; + int high = G_N_ELEMENTS(charset_assignments) - 1; + + while (low <= high) { + const int mid = (low + high)/2; + const unsigned int val = charset_assignments[mid].mib_enum; + if (val < index) { + low = mid + 1; + } else if (val > index) { + high = mid - 1; + } else { + return charset_assignments[mid].charset; + } + } + + return NULL; +} + +static gboolean extract_short(struct wsp_header_iter *iter, void *user) +{ + unsigned char *out = user; + const unsigned char *p; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_SHORT) + return FALSE; + + p = wsp_header_iter_get_val(iter); + *out = p[0]; + + return TRUE; +} + +static const char *decode_text(struct wsp_header_iter *iter) +{ + const unsigned char *p; + unsigned int l; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_TEXT) + return NULL; + + p = wsp_header_iter_get_val(iter); + l = wsp_header_iter_get_val_len(iter); + + return wsp_decode_text(p, l, NULL); +} + +static gboolean extract_text(struct wsp_header_iter *iter, void *user) +{ + char **out = user; + const char *text; + + text = decode_text(iter); + if (text == NULL) + return FALSE; + + *out = g_strdup(text); + + return TRUE; +} + +static gboolean extract_text_array_element(struct wsp_header_iter *iter, + void *user) +{ + char **out = user; + const char *element; + char *tmp; + + element = decode_text(iter); + if (element == NULL) + return FALSE; + + if (*out == NULL) { + *out = g_strdup(element); + return TRUE; + } + + tmp = g_strjoin(",", *out, element, NULL); + if (tmp == NULL) + return FALSE; + + g_free(*out); + + *out = tmp; + + return TRUE; +} + +static char *decode_encoded_string_with_mib_enum(const unsigned char *p, + unsigned int l) +{ + unsigned int mib_enum; + unsigned int consumed; + const char *text; + const char *from_codeset; + const char *to_codeset = "UTF-8"; + gsize bytes_read; + gsize bytes_written; + + if (wsp_decode_integer(p, l, &mib_enum, &consumed) == FALSE) + return NULL; + + if (mib_enum == 106) { + /* header is UTF-8 already */ + text = wsp_decode_text(p + consumed, l - consumed, NULL); + + return g_strdup(text); + } + + /* convert to UTF-8 */ + from_codeset = charset_index2string(mib_enum); + if (from_codeset == NULL) + return NULL; + + return g_convert((const char *) p + consumed, l - consumed, + to_codeset, from_codeset, + &bytes_read, &bytes_written, NULL); +} + +static gboolean extract_encoded_text(struct wsp_header_iter *iter, void *user) +{ + char **out = user; + const unsigned char *p; + unsigned int l; + const char *text; + char *uninitialized_var(dec_text); + + p = wsp_header_iter_get_val(iter); + l = wsp_header_iter_get_val_len(iter); + + switch (wsp_header_iter_get_val_type(iter)) { + case WSP_VALUE_TYPE_TEXT: + /* Text-string */ + text = wsp_decode_text(p, l, NULL); + dec_text = g_strdup(text); + break; + case WSP_VALUE_TYPE_LONG: + /* (Value-len) Char-set Text-string */ + dec_text = decode_encoded_string_with_mib_enum(p, l); + break; + case WSP_VALUE_TYPE_SHORT: + dec_text = NULL; + break; + } + + if (dec_text == NULL) + return FALSE; + + *out = dec_text; + + return TRUE; +} + +static gboolean extract_date(struct wsp_header_iter *iter, void *user) +{ + time_t *out = user; + const unsigned char *p; + unsigned int l; + unsigned int i; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_LONG) + return FALSE; + + p = wsp_header_iter_get_val(iter); + l = wsp_header_iter_get_val_len(iter); + + if (l > 4) + return FALSE; + + for (i = 0, *out = 0; i < l; i++) + *out = *out << 8 | p[i]; + + /* It is possible to overflow time_t on 32 bit systems */ + *out = *out & 0x7fffffff; + + return TRUE; +} + +static gboolean extract_absolute_relative_date(struct wsp_header_iter *iter, + void *user) +{ + time_t *out = user; + const unsigned char *p; + unsigned int l; + unsigned int i; + unsigned int seconds; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_LONG) + return FALSE; + + p = wsp_header_iter_get_val(iter); + l = wsp_header_iter_get_val_len(iter); + + if (l < 2 || l > 5) + return FALSE; + + if (p[0] != 128 && p[0] != 129) + return FALSE; + + for (i = 2, seconds = 0; i < l; i++) + seconds = seconds << 8 | p[i]; + + if (p[0] == 129) { + *out = time(NULL); + *out += seconds; + } else + *out = seconds; + + /* It is possible to overflow time_t on 32 bit systems */ + *out = *out & 0x7fffffff; + + return TRUE; +} + +static gboolean extract_boolean(struct wsp_header_iter *iter, void *user) +{ + gboolean *out = user; + const unsigned char *p; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_SHORT) + return FALSE; + + p = wsp_header_iter_get_val(iter); + + if (p[0] == MMS_MESSAGE_VALUE_BOOL_YES) { + *out = TRUE; + return TRUE; + } else if (p[0] == MMS_MESSAGE_VALUE_BOOL_NO) { + *out = FALSE; + return TRUE; + } else { + return TRUE; + } +} + +static gboolean extract_from(struct wsp_header_iter *iter, void *user) +{ + char **out = user; + const unsigned char *p; + unsigned int l; + const char *text; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_LONG) + return FALSE; + + p = wsp_header_iter_get_val(iter); + l = wsp_header_iter_get_val_len(iter); + + if (p[0] != 128 && p[0] != 129) + return FALSE; + + if (p[0] == 129) { + *out = NULL; + return TRUE; + } + + text = wsp_decode_text(p + 1, l - 1, NULL); + if (text == NULL) + return FALSE; + + *out = g_strdup(text); + + return TRUE; +} + +static gboolean extract_message_class(struct wsp_header_iter *iter, void *user) +{ + char **out = user; + const unsigned char *p; + unsigned int l; + const char *text; + + if (wsp_header_iter_get_val_type(iter) == WSP_VALUE_TYPE_LONG) + return FALSE; + + p = wsp_header_iter_get_val(iter); + + if (wsp_header_iter_get_val_type(iter) == WSP_VALUE_TYPE_SHORT) { + switch (p[0]) { + case 128: + *out = g_strdup(MMS_MESSAGE_CLASS_PERSONAL); + return TRUE; + case 129: + *out = g_strdup(MMS_MESSAGE_CLASS_ADVERTISEMENT); + return TRUE; + case 130: + *out = g_strdup(MMS_MESSAGE_CLASS_INFORMATIONAL); + return TRUE; + case 131: + *out = g_strdup(MMS_MESSAGE_CLASS_AUTO); + return TRUE; + default: + return FALSE; + } + } + + l = wsp_header_iter_get_val_len(iter); + + text = wsp_decode_token_text(p, l, NULL); + if (text == NULL) + return FALSE; + + *out = g_strdup(text); + + return TRUE; +} + +static gboolean extract_sender_visibility(struct wsp_header_iter *iter, + void *user) +{ + enum mms_message_sender_visibility *out = user; + const unsigned char *p; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_SHORT) + return FALSE; + + p = wsp_header_iter_get_val(iter); + + if (p[0] != 128 && p[0] != 129) + return FALSE; + + *out = p[0]; + + return TRUE; +} + +static gboolean extract_priority(struct wsp_header_iter *iter, void *user) +{ + enum mms_message_priority *out = user; + const unsigned char *p; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_SHORT) + return FALSE; + + p = wsp_header_iter_get_val(iter); + + switch (p[0]) { + case MMS_MESSAGE_PRIORITY_LOW: + case MMS_MESSAGE_PRIORITY_NORMAL: + case MMS_MESSAGE_PRIORITY_HIGH: + *out = p[0]; + return TRUE; + } + + return FALSE; +} + +static gboolean extract_rsp_status(struct wsp_header_iter *iter, void *user) +{ + unsigned char *out = user; + const unsigned char *p; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_SHORT) + return FALSE; + + p = wsp_header_iter_get_val(iter); + + switch (p[0]) { + case MMS_MESSAGE_RSP_STATUS_OK: + case MMS_MESSAGE_RSP_STATUS_ERR_UNSUPPORTED_MESSAGE: + case MMS_MESSAGE_RSP_STATUS_ERR_TRANS_FAILURE: + case MMS_MESSAGE_RSP_STATUS_ERR_TRANS_NETWORK_PROBLEM: + case MMS_MESSAGE_RSP_STATUS_ERR_PERM_FAILURE: + case MMS_MESSAGE_RSP_STATUS_ERR_PERM_SERVICE_DENIED: + case MMS_MESSAGE_RSP_STATUS_ERR_PERM_MESSAGE_FORMAT_CORRUPT: + case MMS_MESSAGE_RSP_STATUS_ERR_PERM_SENDING_ADDRESS_UNRESOLVED: + case MMS_MESSAGE_RSP_STATUS_ERR_PERM_CONTENT_NOT_ACCEPTED: + case MMS_MESSAGE_RSP_STATUS_ERR_PERM_LACK_OF_PREPAID: + *out = p[0]; + return TRUE; + } + + return FALSE; +} + +static gboolean extract_status(struct wsp_header_iter *iter, void *user) +{ + enum mms_message_delivery_status *out = user; + const unsigned char *p; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_SHORT) + return FALSE; + + p = wsp_header_iter_get_val(iter); + + switch (p[0]) { + case MMS_MESSAGE_DELIVERY_STATUS_EXPIRED: + case MMS_MESSAGE_DELIVERY_STATUS_RETRIEVED: + case MMS_MESSAGE_DELIVERY_STATUS_REJECTED: + case MMS_MESSAGE_DELIVERY_STATUS_DEFERRED: + case MMS_MESSAGE_DELIVERY_STATUS_UNRECOGNISED: + case MMS_MESSAGE_DELIVERY_STATUS_INDETERMINATE: + case MMS_MESSAGE_DELIVERY_STATUS_FORWARDED: + case MMS_MESSAGE_DELIVERY_STATUS_UNREACHABLE: + *out = p[0]; + return TRUE; + } + + return FALSE; +} + +static gboolean extract_retrieve_status(struct wsp_header_iter *iter, void *user) +{ + unsigned char *out = user; + const unsigned char *p; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_SHORT) + return FALSE; + + p = wsp_header_iter_get_val(iter); + + switch (p[0]) { + case MMS_MESSAGE_RETRIEVE_STATUS_OK: + case MMS_MESSAGE_RETRIEVE_STATUS_ERR_TRANS_FAILURE: + case MMS_MESSAGE_RETRIEVE_STATUS_ERR_TRANS_MESSAGE_NOT_FOUND: + case MMS_MESSAGE_RETRIEVE_STATUS_ERR_TRANS_NETWORK_PROBLEM: + case MMS_MESSAGE_RETRIEVE_STATUS_ERR_PERM_FAILURE: + case MMS_MESSAGE_RETRIEVE_STATUS_ERR_PERM_SERVICE_DENIED: + case MMS_MESSAGE_RETRIEVE_STATUS_ERR_PERM_MESSAGE_NOT_FOUND: + case MMS_MESSAGE_RETRIEVE_STATUS_ERR_PERM_CONTENT_UNSUPPORTED: + *out = p[0]; + return TRUE; + } + + return FALSE; +} + +static gboolean extract_read_status(struct wsp_header_iter *iter, void *user) +{ + enum mms_message_read_status *out = user; + const unsigned char *p; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_SHORT) + return FALSE; + + p = wsp_header_iter_get_val(iter); + + switch (p[0]) { + case MMS_MESSAGE_READ_STATUS_READ: + case MMS_MESSAGE_READ_STATUS_DELETED: + *out = p[0]; + return TRUE; + } + + return FALSE; +} + +static gboolean extract_unsigned(struct wsp_header_iter *iter, void *user) +{ + unsigned long *out = user; + const unsigned char *p; + unsigned int l; + unsigned int i; + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_LONG) + return FALSE; + + p = wsp_header_iter_get_val(iter); + l = wsp_header_iter_get_val_len(iter); + + if (l > sizeof(unsigned long)) + return FALSE; + + for (i = 0, *out = 0; i < l; i++) + *out = *out << 8 | p[i]; + + return TRUE; +} + +static header_handler handler_for_type(enum mms_header header) +{ + switch (header) { + case MMS_HEADER_BCC: + return &extract_text_array_element; + case MMS_HEADER_CC: + return &extract_text_array_element; + case MMS_HEADER_CONTENT_LOCATION: + return &extract_text; + case MMS_HEADER_CONTENT_TYPE: + return &extract_text; + case MMS_HEADER_DATE: + return &extract_date; + case MMS_HEADER_DELIVERY_REPORT: + return &extract_boolean; + case MMS_HEADER_DELIVERY_TIME: + return &extract_absolute_relative_date; + case MMS_HEADER_EXPIRY: + return &extract_absolute_relative_date; + case MMS_HEADER_FROM: + return &extract_from; + case MMS_HEADER_MESSAGE_CLASS: + return &extract_message_class; + case MMS_HEADER_MESSAGE_ID: + return &extract_text; + case MMS_HEADER_MESSAGE_TYPE: + return &extract_short; + case MMS_HEADER_MMS_VERSION: + return &extract_short; + case MMS_HEADER_MESSAGE_SIZE: + return &extract_unsigned; + case MMS_HEADER_PRIORITY: + return &extract_priority; + case MMS_HEADER_READ_REPORT: + return &extract_boolean; + case MMS_HEADER_REPORT_ALLOWED: + return &extract_boolean; + case MMS_HEADER_RESPONSE_STATUS: + return &extract_rsp_status; + case MMS_HEADER_RESPONSE_TEXT: + return &extract_encoded_text; + case MMS_HEADER_SENDER_VISIBILITY: + return &extract_sender_visibility; + case MMS_HEADER_STATUS: + return &extract_status; + case MMS_HEADER_SUBJECT: + return &extract_encoded_text; + case MMS_HEADER_TO: + return &extract_text_array_element; + case MMS_HEADER_TRANSACTION_ID: + return &extract_text; + case MMS_HEADER_RETRIEVE_STATUS: + return &extract_retrieve_status; + case MMS_HEADER_RETRIEVE_TEXT: + return &extract_encoded_text; + case MMS_HEADER_READ_STATUS: + return &extract_read_status; + case MMS_HEADER_INVALID: + case __MMS_HEADER_MAX: + return NULL; + } + + return NULL; +} + +struct header_handler_entry { + int flags; + void *data; + int pos; +}; + +static gboolean mms_parse_headers(struct wsp_header_iter *iter, + enum mms_header orig_header, ...) +{ + struct header_handler_entry entries[__MMS_HEADER_MAX + 1]; + va_list args; + const unsigned char *p; + int i; + enum mms_header header; + + memset(&entries, 0, sizeof(entries)); + + va_start(args, orig_header); + header = orig_header; + + while (header != MMS_HEADER_INVALID) { + entries[header].flags = va_arg(args, int); + entries[header].data = va_arg(args, void *); + + header = va_arg(args, enum mms_header); + } + + va_end(args); + + for (i = 1; wsp_header_iter_next(iter); i++) { + unsigned char h; + header_handler handler; + + /* Skip application headers */ + if (wsp_header_iter_get_hdr_type(iter) != + WSP_HEADER_TYPE_WELL_KNOWN) + continue; + + p = wsp_header_iter_get_hdr(iter); + h = p[0] & 0x7f; + + handler = handler_for_type(h); + if (handler == NULL) + return FALSE; + + /* Unsupported header, skip */ + if (entries[h].data == NULL) + continue; + + /* Skip multiply present headers unless explicitly requested */ + if ((entries[h].flags & HEADER_FLAG_MARKED) && + !(entries[h].flags & HEADER_FLAG_ALLOW_MULTI)) + continue; + + /* Parse the header */ + if (handler(iter, entries[h].data) == FALSE) + return FALSE; + + entries[h].pos = i; + entries[h].flags |= HEADER_FLAG_MARKED; + } + + for (i = 0; i < __MMS_HEADER_MAX + 1; i++) { + if ((entries[i].flags & HEADER_FLAG_MANDATORY) && + !(entries[i].flags & HEADER_FLAG_MARKED)) + return FALSE; + } + + /* + * Here we check for header positions. This function assumes that + * headers marked with PRESET_POS are in the beginning of the message + * and follow the same order as given in the va_arg list. The headers + * marked this way have to be contiguous. + */ + for (i = 0; i < __MMS_HEADER_MAX + 1; i++) { + int check_flags = HEADER_FLAG_PRESET_POS | HEADER_FLAG_MARKED; + int expected_pos = 1; + + if ((entries[i].flags & check_flags) != check_flags) + continue; + + va_start(args, orig_header); + header = orig_header; + + while (header != MMS_HEADER_INVALID && (int)header != i) { + va_arg(args, int); + va_arg(args, void *); + + if (entries[header].flags & HEADER_FLAG_MARKED) + expected_pos += 1; + + header = va_arg(args, enum mms_header); + } + + va_end(args); + + if (entries[i].pos != expected_pos) + return FALSE; + } + + return TRUE; +} + +static gboolean decode_notification_ind(struct wsp_header_iter *iter, + struct mms_message *out) +{ + return mms_parse_headers(iter, MMS_HEADER_TRANSACTION_ID, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->transaction_id, + MMS_HEADER_MMS_VERSION, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->version, + MMS_HEADER_FROM, + 0, &out->ni.from, + MMS_HEADER_SUBJECT, + 0, &out->ni.subject, + MMS_HEADER_MESSAGE_CLASS, + HEADER_FLAG_MANDATORY, &out->ni.cls, + MMS_HEADER_MESSAGE_SIZE, + HEADER_FLAG_MANDATORY, &out->ni.size, + MMS_HEADER_EXPIRY, + HEADER_FLAG_MANDATORY, &out->ni.expiry, + MMS_HEADER_CONTENT_LOCATION, + HEADER_FLAG_MANDATORY, &out->ni.location, + MMS_HEADER_INVALID); +} + +static gboolean decode_notify_resp_ind(struct wsp_header_iter *iter, + struct mms_message *out) +{ + return mms_parse_headers(iter, MMS_HEADER_TRANSACTION_ID, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->transaction_id, + MMS_HEADER_MMS_VERSION, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->version, + MMS_HEADER_STATUS, + HEADER_FLAG_MANDATORY, &out->nri.notify_status, + MMS_HEADER_INVALID); +} + +static gboolean decode_acknowledge_ind(struct wsp_header_iter *iter, + struct mms_message *out) +{ + return mms_parse_headers(iter, MMS_HEADER_TRANSACTION_ID, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->transaction_id, + MMS_HEADER_MMS_VERSION, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->version, + MMS_HEADER_REPORT_ALLOWED, + 0, &out->ai.report, + MMS_HEADER_INVALID); +} + +static gboolean decode_delivery_ind(struct wsp_header_iter *iter, + struct mms_message *out) +{ + return mms_parse_headers(iter, MMS_HEADER_MMS_VERSION, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->version, + MMS_HEADER_MESSAGE_ID, + HEADER_FLAG_MANDATORY, &out->di.msgid, + MMS_HEADER_TO, + HEADER_FLAG_MANDATORY, &out->di.to, + MMS_HEADER_DATE, + HEADER_FLAG_MANDATORY, &out->di.date, + MMS_HEADER_STATUS, + HEADER_FLAG_MANDATORY, &out->di.dr_status, + MMS_HEADER_INVALID); +} + +static gboolean decode_read_ind(struct wsp_header_iter *iter, + struct mms_message *out) +{ + return mms_parse_headers(iter, MMS_HEADER_MMS_VERSION, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->version, + MMS_HEADER_MESSAGE_ID, + HEADER_FLAG_MANDATORY, &out->ri.msgid, + MMS_HEADER_TO, + HEADER_FLAG_MANDATORY, &out->ri.to, + MMS_HEADER_FROM, + HEADER_FLAG_MANDATORY, &out->ri.from, + MMS_HEADER_DATE, + HEADER_FLAG_MANDATORY, &out->ri.date, + MMS_HEADER_READ_STATUS, + HEADER_FLAG_MANDATORY, &out->ri.rr_status, + MMS_HEADER_INVALID); +} + +static const char *decode_attachment_charset(const unsigned char *pdu, + unsigned int len) +{ + struct wsp_parameter_iter iter; + struct wsp_parameter param; + + wsp_parameter_iter_init(&iter, pdu, len); + + while (wsp_parameter_iter_next(&iter, ¶m)) { + if (param.type == WSP_PARAMETER_TYPE_CHARSET) + return param.text; + } + + return NULL; +} + +static gboolean extract_content_id(struct wsp_header_iter *iter, void *user) +{ + char **out = user; + const unsigned char *p; + unsigned int l; + const char *text; + + p = wsp_header_iter_get_val(iter); + l = wsp_header_iter_get_val_len(iter); + + if (wsp_header_iter_get_val_type(iter) != WSP_VALUE_TYPE_TEXT) + return FALSE; + + text = wsp_decode_quoted_string(p, l, NULL); + + if (text == NULL) + return FALSE; + + *out = g_strdup(text); + + return TRUE; +} + +static gboolean attachment_parse_headers(struct wsp_header_iter *iter, + struct mms_attachment *part) +{ + while (wsp_header_iter_next(iter)) { + const unsigned char *hdr = wsp_header_iter_get_hdr(iter); + unsigned char h; + + /* Skip application headers */ + if (wsp_header_iter_get_hdr_type(iter) != + WSP_HEADER_TYPE_WELL_KNOWN) + continue; + + h = hdr[0] & 0x7f; + + switch (h) { + case MMS_PART_HEADER_CONTENT_ID: + if (extract_content_id(iter, &part->content_id) + == FALSE) + return FALSE; + break; + case MMS_PART_HEADER_CONTENT_LOCATION: + break; + } + } + + return TRUE; +} + +static void free_attachment(gpointer data, gpointer user_data) +{ + struct mms_attachment *attach = data; + + g_free(attach->content_type); + g_free(attach->content_id); + + g_free(attach); +} + +static gboolean mms_parse_attachments(struct wsp_header_iter *iter, + struct mms_message *out) +{ + struct wsp_multipart_iter mi; + const void *ct; + unsigned int ct_len; + unsigned int consumed; + + if (wsp_multipart_iter_init(&mi, iter, &ct, &ct_len) == FALSE) + return FALSE; + + while (wsp_multipart_iter_next(&mi) == TRUE) { + struct mms_attachment *part; + struct wsp_header_iter hi; + const void *mimetype; + const char *charset; + + ct = wsp_multipart_iter_get_content_type(&mi); + ct_len = wsp_multipart_iter_get_content_type_len(&mi); + + if (wsp_decode_content_type(ct, ct_len, &mimetype, + &consumed, NULL) == FALSE) + return FALSE; + + charset = decode_attachment_charset( + (const unsigned char *)ct + consumed, + ct_len - consumed); + + wsp_header_iter_init(&hi, wsp_multipart_iter_get_hdr(&mi), + wsp_multipart_iter_get_hdr_len(&mi), + 0); + + part = g_try_new0(struct mms_attachment, 1); + if (part == NULL) + return FALSE; + + if (attachment_parse_headers(&hi, part) == FALSE) { + free_attachment(part, NULL); + return FALSE; + } + + if (wsp_header_iter_at_end(&hi) == FALSE) { + free_attachment(part, NULL); + return FALSE; + } + + if (charset == NULL) + part->content_type = g_strdup(mimetype); + else + part->content_type = g_strconcat(mimetype, ";charset=", + charset, NULL); + + part->length = wsp_multipart_iter_get_body_len(&mi); + part->offset = (const unsigned char *) + wsp_multipart_iter_get_body(&mi) - + wsp_header_iter_get_pdu(iter); + + out->attachments = g_slist_prepend(out->attachments, part); + } + + if (wsp_multipart_iter_close(&mi, iter) == FALSE) + return FALSE; + + out->attachments = g_slist_reverse(out->attachments); + + return TRUE; +} + +static gboolean decode_retrieve_conf(struct wsp_header_iter *iter, + struct mms_message *out) +{ + if (mms_parse_headers(iter, MMS_HEADER_TRANSACTION_ID, + HEADER_FLAG_PRESET_POS, &out->transaction_id, + MMS_HEADER_MMS_VERSION, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->version, + MMS_HEADER_FROM, + 0, &out->rc.from, + MMS_HEADER_TO, + HEADER_FLAG_ALLOW_MULTI, &out->rc.to, + MMS_HEADER_CC, + HEADER_FLAG_ALLOW_MULTI, &out->rc.cc, + MMS_HEADER_SUBJECT, + 0, &out->rc.subject, + MMS_HEADER_MESSAGE_CLASS, + 0, &out->rc.cls, + MMS_HEADER_PRIORITY, + 0, &out->rc.priority, + MMS_HEADER_MESSAGE_ID, + 0, &out->rc.msgid, + MMS_HEADER_DATE, + HEADER_FLAG_MANDATORY, &out->rc.date, + MMS_HEADER_INVALID) == FALSE) + return FALSE; + + if (wsp_header_iter_at_end(iter) == TRUE) + return TRUE; + + if (wsp_header_iter_is_multipart(iter) == FALSE) + return FALSE; + + if (mms_parse_attachments(iter, out) == FALSE) + return FALSE; + + if (wsp_header_iter_at_end(iter) == FALSE) + return FALSE; + + return TRUE; +} + +static gboolean decode_send_conf(struct wsp_header_iter *iter, + struct mms_message *out) +{ + return mms_parse_headers(iter, MMS_HEADER_TRANSACTION_ID, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->transaction_id, + MMS_HEADER_MMS_VERSION, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->version, + MMS_HEADER_RESPONSE_STATUS, + HEADER_FLAG_MANDATORY, &out->sc.rsp_status, + MMS_HEADER_MESSAGE_ID, + 0, &out->sc.msgid, + MMS_HEADER_INVALID); +} + +static gboolean decode_send_req(struct wsp_header_iter *iter, + struct mms_message *out) +{ + if (mms_parse_headers(iter, MMS_HEADER_TRANSACTION_ID, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->transaction_id, + MMS_HEADER_MMS_VERSION, + HEADER_FLAG_MANDATORY | HEADER_FLAG_PRESET_POS, + &out->version, + MMS_HEADER_TO, + HEADER_FLAG_ALLOW_MULTI, &out->sr.to, + MMS_HEADER_INVALID) == FALSE) + return FALSE; + + if (wsp_header_iter_at_end(iter) == TRUE) + return TRUE; + + if (wsp_header_iter_is_multipart(iter) == FALSE) + return FALSE; + + if (mms_parse_attachments(iter, out) == FALSE) + return FALSE; + + if (wsp_header_iter_at_end(iter) == FALSE) + return FALSE; + + return TRUE; +} + +#define CHECK_WELL_KNOWN_HDR(hdr) \ + if (wsp_header_iter_next(&iter) == FALSE) \ + return FALSE; \ + \ + if (wsp_header_iter_get_hdr_type(&iter) != \ + WSP_HEADER_TYPE_WELL_KNOWN) \ + return FALSE; \ + \ + p = wsp_header_iter_get_hdr(&iter); \ + \ + if ((p[0] & 0x7f) != hdr) \ + return FALSE \ + +gboolean mms_message_decode(const unsigned char *pdu, + unsigned int len, struct mms_message *out) +{ + unsigned int flags = 0; + struct wsp_header_iter iter; + const unsigned char *p; + unsigned char octet; + + memset(out, 0, sizeof(*out)); + + flags |= WSP_HEADER_ITER_FLAG_REJECT_CP; + flags |= WSP_HEADER_ITER_FLAG_DETECT_MMS_MULTIPART; + wsp_header_iter_init(&iter, pdu, len, flags); + + CHECK_WELL_KNOWN_HDR(MMS_HEADER_MESSAGE_TYPE); + + if (extract_short(&iter, &octet) == FALSE) + return FALSE; + + out->type = octet; + + switch (out->type) { + case MMS_MESSAGE_TYPE_SEND_REQ: + return decode_send_req(&iter, out); + case MMS_MESSAGE_TYPE_SEND_CONF: + return decode_send_conf(&iter, out); + case MMS_MESSAGE_TYPE_NOTIFICATION_IND: + return decode_notification_ind(&iter, out); + case MMS_MESSAGE_TYPE_NOTIFYRESP_IND: + return decode_notify_resp_ind(&iter, out); + case MMS_MESSAGE_TYPE_RETRIEVE_CONF: + return decode_retrieve_conf(&iter, out); + case MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND: + return decode_acknowledge_ind(&iter, out); + case MMS_MESSAGE_TYPE_DELIVERY_IND: + return decode_delivery_ind(&iter, out); + case MMS_MESSAGE_TYPE_READ_REC_IND: + case MMS_MESSAGE_TYPE_READ_ORIG_IND: + return decode_read_ind(&iter, out); + } + + return FALSE; +} + +void mms_message_free(struct mms_message *msg) +{ + switch (msg->type) { + case MMS_MESSAGE_TYPE_SEND_REQ: + g_free(msg->sr.to); + g_free(msg->sr.content_type); + break; + case MMS_MESSAGE_TYPE_SEND_CONF: + g_free(msg->sc.msgid); + break; + case MMS_MESSAGE_TYPE_NOTIFICATION_IND: + g_free(msg->ni.from); + g_free(msg->ni.subject); + g_free(msg->ni.cls); + g_free(msg->ni.location); + break; + case MMS_MESSAGE_TYPE_NOTIFYRESP_IND: + break; + case MMS_MESSAGE_TYPE_RETRIEVE_CONF: + g_free(msg->rc.from); + g_free(msg->rc.to); + g_free(msg->rc.cc); + g_free(msg->rc.subject); + g_free(msg->rc.cls); + g_free(msg->rc.msgid); + break; + case MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND: + break; + case MMS_MESSAGE_TYPE_DELIVERY_IND: + g_free(msg->di.msgid); + g_free(msg->di.to); + break; + case MMS_MESSAGE_TYPE_READ_REC_IND: + case MMS_MESSAGE_TYPE_READ_ORIG_IND: + g_free(msg->ri.msgid); + g_free(msg->ri.to); + g_free(msg->ri.from); + break; + } + + g_free(msg->transaction_id); + + if (msg->attachments != NULL) { + g_slist_foreach(msg->attachments, free_attachment, NULL); + g_slist_free(msg->attachments); + } + + g_free(msg); +} + +static void fb_init(struct file_buffer *fb, int fd) +{ + fb->size = 0; + fb->fsize = 0; + fb->fd = fd; +} + +static gboolean fb_flush(struct file_buffer *fb) +{ + unsigned int size; + ssize_t len; + + if (fb->size == 0) + return TRUE; + + len = write(fb->fd, fb->buf, fb->size); + if (len < 0) + return FALSE; + + size = len; + + if (size != fb->size) + return FALSE; + + fb->fsize += size; + + fb->size = 0; + + return TRUE; +} + +static unsigned int fb_get_file_size(struct file_buffer *fb) +{ + return fb->fsize + fb->size; +} + +static void *fb_request(struct file_buffer *fb, unsigned int count) +{ + if (fb->size + count < FB_SIZE) { + void *ptr = fb->buf + fb->size; + fb->size += count; + return ptr; + } + + if (fb_flush(fb) == FALSE) + return NULL; + + if (count > FB_SIZE) + return NULL; + + fb->size = count; + + return fb->buf; +} + +static void *fb_request_field(struct file_buffer *fb, unsigned char token, + unsigned int len) +{ + unsigned char *ptr; + + ptr = fb_request(fb, len + 1); + if (ptr == NULL) + return NULL; + + ptr[0] = token | 0x80; + + return ptr + 1; +} + +static gboolean fb_copy(struct file_buffer *fb, const void *buf, unsigned int c) +{ + unsigned int written; + ssize_t len; + + if (fb_flush(fb) == FALSE) + return FALSE; + + len = TFR(write(fb->fd, buf, c)); + if (len < 0) + return FALSE; + + written = len; + + if (written != c) + return FALSE; + + fb->fsize += written; + + return TRUE; +} + +static gboolean fb_put_value_length(struct file_buffer *fb, unsigned int val) +{ + unsigned int count; + + if (fb->size + MAX_ENC_VALUE_BYTES > FB_SIZE) { + if (fb_flush(fb) == FALSE) + return FALSE; + } + + if (wsp_encode_value_length(val, fb->buf + fb->size, FB_SIZE - fb->size, + &count) == FALSE) + return FALSE; + + fb->size += count; + + return TRUE; +} + +static gboolean fb_put_uintvar(struct file_buffer *fb, unsigned int val) +{ + unsigned int count; + + if (fb->size + MAX_ENC_VALUE_BYTES > FB_SIZE) { + if (fb_flush(fb) == FALSE) + return FALSE; + } + + if (wsp_encode_uintvar(val, fb->buf + fb->size, FB_SIZE - fb->size, + &count) == FALSE) + return FALSE; + + fb->size += count; + + return TRUE; +} + +static gboolean encode_short(struct file_buffer *fb, + enum mms_header header, void *user) +{ + char *ptr; + unsigned int *wk = user; + + ptr = fb_request_field(fb, header, 1); + if (ptr == NULL) + return FALSE; + + *ptr = *wk | 0x80; + + return TRUE; +} + +static gboolean encode_boolean(struct file_buffer *fb, + enum mms_header header, void *user) +{ + char *ptr; + gboolean *value = user; + + ptr = fb_request_field(fb, header, 1); + if (ptr == NULL) + return FALSE; + + *ptr = *value ? MMS_MESSAGE_VALUE_BOOL_YES : MMS_MESSAGE_VALUE_BOOL_NO; + + return TRUE; +} + +static gboolean encode_from(struct file_buffer *fb, + enum mms_header header, void *user) +{ + char *ptr; + char **text = user; + + if (strlen(*text) > 0) + return FALSE; + + /* From: header token + value length + Insert-address-token */ + ptr = fb_request_field(fb, header, 2); + if (ptr == NULL) + return FALSE; + + ptr[0] = 1; + ptr[1] = '\x81'; + + return TRUE; +} + +static gboolean encode_date(struct file_buffer *fb, + enum mms_header header, void *user) +{ + time_t date = *((time_t *)user); + guint8 octets[sizeof(date)]; + guint8 *ptr; + int i, len; + + /* + * Date: Long-integer + * In seconds from 1970-01-01, 00:00:00 GMT. + * + * Long-integer = Short-length Multi-octet-integer + * Short-length = + * Multi-octet-integer = 1*30 OCTET + * + * The content octets shall be an unsigned integer value with the + * most significant octet encoded first (big-endian representation). + * The minimum number of octets must be used to encode the value. + */ + for (i=sizeof(date)-1; i>=0; i--, date >>= 8) { + /* Most significant byte first */ + octets[i] = (guint8)date; + } + /* Skip most significant zeros */ + for (i=0; i<(int)(sizeof(date)-1) && !octets[i]; i++); + len = sizeof(date) - i; + + ptr = fb_request_field(fb, header, len+1); + if (ptr == NULL) + return FALSE; + + ptr[0] = (guint8)len; + memcpy(ptr+1, octets+i, len); + return TRUE; +} + +static gboolean encode_text(struct file_buffer *fb, + enum mms_header header, void *user) +{ + char *ptr; + char **text = user; + unsigned int len; + + len = strlen(*text) + 1; + + ptr = fb_request_field(fb, header, len); + if (ptr == NULL) + return FALSE; + + strcpy(ptr, *text); + + return TRUE; +} + +static gboolean encode_quoted_string(struct file_buffer *fb, + enum mms_header header, void *user) +{ + char *ptr; + char **text = user; + unsigned int len; + + len = strlen(*text) + 1; + + ptr = fb_request_field(fb, header, len + 3); + if (ptr == NULL) + return FALSE; + + ptr[0] = '"'; + ptr[1] = '<'; + strcpy(ptr + 2, *text); + ptr[len + 1] = '>'; + ptr[len + 2] = '\0'; + + return TRUE; +} + +static gboolean encode_text_array_element(struct file_buffer *fb, + enum mms_header header, void *user) +{ + char **text = user; + char **tos; + int i; + + tos = g_strsplit(*text, ",", 0); + + for (i = 0; tos[i] != NULL; i++) { + if (encode_text(fb, header, &tos[i]) == FALSE) { + g_strfreev(tos); + return FALSE; + } + } + + g_strfreev(tos); + + return TRUE; +} + +static gboolean encode_content_type(struct file_buffer *fb, + enum mms_header header, void *user) +{ + char *ptr; + char **hdr = user; + unsigned int len; + unsigned int ct; + unsigned int ct_len; + unsigned int type_len; + unsigned int start_len; + const char *ct_str; + const char *uninitialized_var(type); + const char *uninitialized_var(start); + struct wsp_text_header_iter iter; + + if (wsp_text_header_iter_init(&iter, *hdr) == FALSE) + return FALSE; + + if (g_ascii_strcasecmp("Content-Type", + wsp_text_header_iter_get_key(&iter)) != 0) + return FALSE; + + ct_str = wsp_text_header_iter_get_value(&iter); + + if (wsp_get_well_known_content_type(ct_str, &ct) == TRUE) + ct_len = 1; + else + ct_len = strlen(ct_str) + 1; + + len = ct_len; + + type_len = 0; + start_len = 0; + + while (wsp_text_header_iter_param_next(&iter) == TRUE) { + if (g_ascii_strcasecmp("type", + wsp_text_header_iter_get_key(&iter)) == 0) { + type = wsp_text_header_iter_get_value(&iter); + type_len = strlen(type) + 1; + len += 1 + type_len; + } else if (g_ascii_strcasecmp("start", + wsp_text_header_iter_get_key(&iter)) == 0) { + start = wsp_text_header_iter_get_value(&iter); + start_len = strlen(start) + 1; + len += 1 + start_len; + } + } + + if (len == 1) + return encode_short(fb, header, &ct); + + ptr = fb_request(fb, 1); + if (ptr == NULL) + return FALSE; + + *ptr = header | 0x80; + + /* Encode content type value length */ + if (fb_put_value_length(fb, len) == FALSE) + return FALSE; + + /* Encode content type including parameters */ + ptr = fb_request(fb, ct_len); + if (ptr == NULL) + return FALSE; + + if (ct_len == 1) + *ptr = ct | 0x80; + else + strcpy(ptr, ct_str); + + if (type_len > 0) { + ptr = fb_request_field(fb, WSP_PARAMETER_TYPE_CONTENT_TYPE, + type_len); + if (ptr == NULL) + return FALSE; + + strcpy(ptr, type); + } + + if (start_len > 0) { + ptr = fb_request_field(fb, WSP_PARAMETER_TYPE_START_DEFUNCT, + start_len); + if (ptr == NULL) + return FALSE; + + strcpy(ptr, start); + } + + return TRUE; +} + +static header_encoder encoder_for_type(enum mms_header header) +{ + switch (header) { + case MMS_HEADER_BCC: + return &encode_text_array_element; + case MMS_HEADER_CC: + return &encode_text_array_element; + case MMS_HEADER_CONTENT_LOCATION: + return NULL; + case MMS_HEADER_CONTENT_TYPE: + return &encode_content_type; + case MMS_HEADER_DATE: + return &encode_date; + case MMS_HEADER_DELIVERY_REPORT: + return &encode_boolean; + case MMS_HEADER_DELIVERY_TIME: + return NULL; + case MMS_HEADER_EXPIRY: + return NULL; + case MMS_HEADER_FROM: + return &encode_from; + case MMS_HEADER_MESSAGE_CLASS: + return NULL; + case MMS_HEADER_MESSAGE_ID: + return &encode_text; + case MMS_HEADER_MESSAGE_TYPE: + return &encode_short; + case MMS_HEADER_MMS_VERSION: + return &encode_short; + case MMS_HEADER_MESSAGE_SIZE: + return NULL; + case MMS_HEADER_PRIORITY: + return NULL; + case MMS_HEADER_READ_REPORT: + return &encode_boolean; + case MMS_HEADER_REPORT_ALLOWED: + return &encode_boolean; + case MMS_HEADER_RESPONSE_STATUS: + return NULL; + case MMS_HEADER_RESPONSE_TEXT: + return NULL; + case MMS_HEADER_SENDER_VISIBILITY: + return NULL; + case MMS_HEADER_STATUS: + return &encode_short; + case MMS_HEADER_SUBJECT: + return NULL; + case MMS_HEADER_TO: + return &encode_text_array_element; + case MMS_HEADER_TRANSACTION_ID: + return &encode_text; + case MMS_HEADER_RETRIEVE_STATUS: + return &encode_short; + case MMS_HEADER_RETRIEVE_TEXT: + return NULL; + case MMS_HEADER_READ_STATUS: + return &encode_short; + case MMS_HEADER_INVALID: + case __MMS_HEADER_MAX: + return NULL; + } + + return NULL; +} + +static gboolean mms_encode_send_req_part_header(struct mms_attachment *part, + struct file_buffer *fb) +{ + char *ptr; + unsigned int len; + unsigned int ct; + unsigned int ct_len; + unsigned int cs_len; + const char *ct_str; + const char *uninitialized_var(cs_str); + unsigned int ctp_len; + unsigned int cid_len; + unsigned char ctp_val[MAX_ENC_VALUE_BYTES]; + unsigned char cs_val[MAX_ENC_VALUE_BYTES]; + unsigned int cs; + struct wsp_text_header_iter iter; + + /* + * Compute Headers length: content-type [+ params] [+ content-id] + * ex. : "Content-Type:text/plain; charset=us-ascii" + */ + if (wsp_text_header_iter_init(&iter, part->content_type) == FALSE) + return FALSE; + + if (g_ascii_strcasecmp("Content-Type", + wsp_text_header_iter_get_key(&iter)) != 0) + return FALSE; + + ct_str = wsp_text_header_iter_get_value(&iter); + + if (wsp_get_well_known_content_type(ct_str, &ct) == TRUE) + ct_len = 1; + else + ct_len = strlen(ct_str) + 1; + + len = ct_len; + + cs_len = 0; + + while (wsp_text_header_iter_param_next(&iter) == TRUE) { + const char *key = wsp_text_header_iter_get_key(&iter); + + if (g_ascii_strcasecmp("charset", key) == 0) { + cs_str = wsp_text_header_iter_get_value(&iter); + if (cs_str == NULL) + return FALSE; + + len += 1; + + if (wsp_get_well_known_charset(cs_str, &cs) == FALSE) + return FALSE; + + if (wsp_encode_integer(cs, cs_val, MAX_ENC_VALUE_BYTES, + &cs_len) == FALSE) + return FALSE; + + len += cs_len; + } + } + + if (wsp_encode_value_length(len, ctp_val, MAX_ENC_VALUE_BYTES, + &ctp_len) == FALSE) + return FALSE; + + len += ctp_len; + + /* Compute content-id header length : token + (Quoted String) */ + if (part->content_id != NULL) { + cid_len = 1 + strlen(part->content_id) + 3 + 1; + len += cid_len; + } else + cid_len = 0; + + /* Encode total headers length */ + if (fb_put_uintvar(fb, len) == FALSE) + return FALSE; + + /* Encode data length */ + if (fb_put_uintvar(fb, part->length) == FALSE) + return FALSE; + + /* Encode content-type */ + ptr = fb_request(fb, ctp_len); + if (ptr == NULL) + return FALSE; + + memcpy(ptr, &ctp_val, ctp_len); + + ptr = fb_request(fb, ct_len); + if (ptr == NULL) + return FALSE; + + if (ct_len == 1) + ptr[0] = ct | 0x80; + else + strcpy(ptr, ct_str); + + /* Encode "charset" param */ + if (cs_len > 0) { + ptr = fb_request_field(fb, WSP_PARAMETER_TYPE_CHARSET, cs_len); + if (ptr == NULL) + return FALSE; + + memcpy(ptr, &cs_val, cs_len); + } + + /* Encode content-id */ + if (part->content_id != NULL) { + if (encode_quoted_string(fb, MMS_PART_HEADER_CONTENT_ID, + &part->content_id) == FALSE) + return FALSE; + } + + return TRUE; +} + +static gboolean mms_encode_send_req_part(struct mms_attachment *part, + struct file_buffer *fb) +{ + if (mms_encode_send_req_part_header(part, fb) == FALSE) + return FALSE; + + part->offset = fb_get_file_size(fb); + + return fb_copy(fb, part->data, part->length); +} + +static gboolean mms_encode_headers(struct file_buffer *fb, + enum mms_header orig_header, ...) +{ + va_list args; + void *data; + enum mms_header header; + header_encoder encoder; + + va_start(args, orig_header); + header = orig_header; + + while (header != MMS_HEADER_INVALID) { + data = va_arg(args, void *); + + encoder = encoder_for_type(header); + if (encoder == NULL) + return FALSE; + + if (data && encoder(fb, header, data) == FALSE) + return FALSE; + + header = va_arg(args, enum mms_header); + } + + va_end(args); + + return TRUE; +} + +static gboolean mms_encode_notify_resp_ind(struct mms_message *msg, + struct file_buffer *fb) +{ + if (mms_encode_headers(fb, MMS_HEADER_MESSAGE_TYPE, &msg->type, + MMS_HEADER_TRANSACTION_ID, &msg->transaction_id, + MMS_HEADER_MMS_VERSION, &msg->version, + MMS_HEADER_STATUS, &msg->nri.notify_status, + MMS_HEADER_INVALID) == FALSE) + return FALSE; + + return fb_flush(fb); +} + + +static gboolean mms_encode_acknowledge_ind(struct mms_message *msg, + struct file_buffer *fb) +{ + if (mms_encode_headers(fb, MMS_HEADER_MESSAGE_TYPE, &msg->type, + MMS_HEADER_TRANSACTION_ID, &msg->transaction_id, + MMS_HEADER_MMS_VERSION, &msg->version, + MMS_HEADER_REPORT_ALLOWED, &msg->ai.report, + MMS_HEADER_INVALID) == FALSE) + return FALSE; + + return fb_flush(fb); +} + +static gboolean mms_encode_read_rec_ind(struct mms_message *msg, + struct file_buffer *fb) +{ + const char *empty_from = ""; + if (mms_encode_headers(fb, MMS_HEADER_MESSAGE_TYPE, &msg->type, + MMS_HEADER_MMS_VERSION, &msg->version, + MMS_HEADER_MESSAGE_ID, &msg->ri.msgid, + MMS_HEADER_TO, &msg->ri.to, + MMS_HEADER_FROM, &empty_from, + MMS_HEADER_DATE, &msg->ri.date, + MMS_HEADER_READ_STATUS, &msg->ri.rr_status, + MMS_HEADER_INVALID) == FALSE) + return FALSE; + + return fb_flush(fb); +} + +static gboolean mms_encode_send_req(struct mms_message *msg, + struct file_buffer *fb) +{ + const char *empty_from = ""; + GSList *item; + + if (mms_encode_headers(fb, MMS_HEADER_MESSAGE_TYPE, &msg->type, + MMS_HEADER_TRANSACTION_ID, &msg->transaction_id, + MMS_HEADER_MMS_VERSION, &msg->version, + MMS_HEADER_FROM, &empty_from, + MMS_HEADER_TO, &msg->sr.to, + MMS_HEADER_DELIVERY_REPORT, &msg->sr.dr, + MMS_HEADER_CONTENT_TYPE, &msg->sr.content_type, + MMS_HEADER_INVALID) == FALSE) + return FALSE; + + if (msg->attachments == NULL) + goto done; + + if (fb_put_uintvar(fb, g_slist_length(msg->attachments)) == FALSE) + return FALSE; + + for (item = msg->attachments; item != NULL; item = g_slist_next(item)) { + if (mms_encode_send_req_part(item->data, fb) == FALSE) + return FALSE; + } + +done: + return fb_flush(fb); +} + +gboolean mms_message_encode(struct mms_message *msg, int fd) +{ + struct file_buffer fb; + + fb_init(&fb, fd); + + switch (msg->type) { + case MMS_MESSAGE_TYPE_SEND_REQ: + return mms_encode_send_req(msg, &fb); + case MMS_MESSAGE_TYPE_SEND_CONF: + case MMS_MESSAGE_TYPE_NOTIFICATION_IND: + return FALSE; + case MMS_MESSAGE_TYPE_NOTIFYRESP_IND: + return mms_encode_notify_resp_ind(msg, &fb); + case MMS_MESSAGE_TYPE_RETRIEVE_CONF: + return FALSE; + case MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND: + return mms_encode_acknowledge_ind(msg, &fb); + case MMS_MESSAGE_TYPE_DELIVERY_IND: + return FALSE; + case MMS_MESSAGE_TYPE_READ_REC_IND: + return mms_encode_read_rec_ind(msg, &fb); + case MMS_MESSAGE_TYPE_READ_ORIG_IND: + return FALSE; + } + + return FALSE; +} + +const char *mms_message_status_get_string(enum mms_message_status status) +{ + switch (status) { + case MMS_MESSAGE_STATUS_DOWNLOADED: + return "downloaded"; + case MMS_MESSAGE_STATUS_RECEIVED: + return "received"; + case MMS_MESSAGE_STATUS_READ: + return "read"; + case MMS_MESSAGE_STATUS_SENT: + return "sent"; + case MMS_MESSAGE_STATUS_DRAFT: + return "draft"; + } + + return NULL; +} diff --git a/mms-lib/src/mms_codec.h b/mms-lib/src/mms_codec.h new file mode 100644 index 0000000..377f436 --- /dev/null +++ b/mms-lib/src/mms_codec.h @@ -0,0 +1,200 @@ +/* + * + * Multimedia Messaging Service + * + * Copyright (C) 2010-2011 Intel Corporation. All rights reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +enum mms_message_type { + MMS_MESSAGE_TYPE_SEND_REQ = 128, + MMS_MESSAGE_TYPE_SEND_CONF = 129, + MMS_MESSAGE_TYPE_NOTIFICATION_IND = 130, + MMS_MESSAGE_TYPE_NOTIFYRESP_IND = 131, + MMS_MESSAGE_TYPE_RETRIEVE_CONF = 132, + MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND = 133, + MMS_MESSAGE_TYPE_DELIVERY_IND = 134, + MMS_MESSAGE_TYPE_READ_REC_IND = 135, + MMS_MESSAGE_TYPE_READ_ORIG_IND = 136, +}; + +enum mms_message_status { + MMS_MESSAGE_STATUS_DOWNLOADED, + MMS_MESSAGE_STATUS_RECEIVED, + MMS_MESSAGE_STATUS_READ, + MMS_MESSAGE_STATUS_SENT, + MMS_MESSAGE_STATUS_DRAFT +}; + +enum mms_message_rsp_status { + MMS_MESSAGE_RSP_STATUS_OK = 128, + MMS_MESSAGE_RSP_STATUS_ERR_UNSUPPORTED_MESSAGE = 136, + MMS_MESSAGE_RSP_STATUS_ERR_TRANS_FAILURE = 192, + MMS_MESSAGE_RSP_STATUS_ERR_TRANS_NETWORK_PROBLEM = 195, + MMS_MESSAGE_RSP_STATUS_ERR_PERM_FAILURE = 224, + MMS_MESSAGE_RSP_STATUS_ERR_PERM_SERVICE_DENIED = 225, + MMS_MESSAGE_RSP_STATUS_ERR_PERM_MESSAGE_FORMAT_CORRUPT = 226, + MMS_MESSAGE_RSP_STATUS_ERR_PERM_SENDING_ADDRESS_UNRESOLVED = 227, + MMS_MESSAGE_RSP_STATUS_ERR_PERM_CONTENT_NOT_ACCEPTED = 229, + MMS_MESSAGE_RSP_STATUS_ERR_PERM_LACK_OF_PREPAID = 235, +}; + +enum mms_message_notify_status { + MMS_MESSAGE_NOTIFY_STATUS_RETRIEVED = 129, + MMS_MESSAGE_NOTIFY_STATUS_REJECTED = 130, + MMS_MESSAGE_NOTIFY_STATUS_DEFERRED = 131, + MMS_MESSAGE_NOTIFY_STATUS_UNRECOGNISED = 132, +}; + +enum mms_message_delivery_status { + MMS_MESSAGE_DELIVERY_STATUS_EXPIRED = 128, + MMS_MESSAGE_DELIVERY_STATUS_RETRIEVED = 129, + MMS_MESSAGE_DELIVERY_STATUS_REJECTED = 130, + MMS_MESSAGE_DELIVERY_STATUS_DEFERRED = 131, + MMS_MESSAGE_DELIVERY_STATUS_UNRECOGNISED = 132, + MMS_MESSAGE_DELIVERY_STATUS_INDETERMINATE = 133, + MMS_MESSAGE_DELIVERY_STATUS_FORWARDED = 134, + MMS_MESSAGE_DELIVERY_STATUS_UNREACHABLE = 135, +}; + +enum mms_message_retrieve_status { + MMS_MESSAGE_RETRIEVE_STATUS_OK = 128, + MMS_MESSAGE_RETRIEVE_STATUS_ERR_TRANS_FAILURE = 192, + MMS_MESSAGE_RETRIEVE_STATUS_ERR_TRANS_MESSAGE_NOT_FOUND = 193, + MMS_MESSAGE_RETRIEVE_STATUS_ERR_TRANS_NETWORK_PROBLEM = 194, + MMS_MESSAGE_RETRIEVE_STATUS_ERR_PERM_FAILURE = 224, + MMS_MESSAGE_RETRIEVE_STATUS_ERR_PERM_SERVICE_DENIED = 225, + MMS_MESSAGE_RETRIEVE_STATUS_ERR_PERM_MESSAGE_NOT_FOUND = 226, + MMS_MESSAGE_RETRIEVE_STATUS_ERR_PERM_CONTENT_UNSUPPORTED = 227, +}; + +enum mms_message_read_status { + MMS_MESSAGE_READ_STATUS_READ = 128, + MMS_MESSAGE_READ_STATUS_DELETED = 129, +}; + +enum mms_message_sender_visibility { + MMS_MESSAGE_SENDER_VISIBILITY_HIDE = 128, + MMS_MESSAGE_SENDER_VISIBILITY_SHOW = 129, +}; + +enum mms_message_priority { + MMS_MESSAGE_PRIORITY_LOW = 128, + MMS_MESSAGE_PRIORITY_NORMAL = 129, + MMS_MESSAGE_PRIORITY_HIGH = 130 +}; + +enum mms_message_version { + MMS_MESSAGE_VERSION_1_0 = 0x90, + MMS_MESSAGE_VERSION_1_1 = 0x91, + MMS_MESSAGE_VERSION_1_2 = 0x92, + MMS_MESSAGE_VERSION_1_3 = 0x93, +}; + +#define MMS_MESSAGE_CLASS_PERSONAL "Personal" +#define MMS_MESSAGE_CLASS_ADVERTISEMENT "Advertisement" +#define MMS_MESSAGE_CLASS_INFORMATIONAL "Informational" +#define MMS_MESSAGE_CLASS_AUTO "Auto" + +struct mms_notification_ind { + char *from; + char *subject; + char *cls; + unsigned int size; + time_t expiry; + char *location; +}; + +struct mms_retrieve_conf { + enum mms_message_status status; + char *from; + char *to; + char *cc; + char *subject; + char *cls; + enum mms_message_priority priority; + char *msgid; + time_t date; +}; + +struct mms_send_req { + enum mms_message_status status; + char *to; + time_t date; + char *content_type; + gboolean dr; +}; + +struct mms_send_conf { + enum mms_message_rsp_status rsp_status; + char *msgid; +}; + +struct mms_notification_resp_ind { + enum mms_message_notify_status notify_status; +}; + +struct mms_acknowledge_ind { + gboolean report; +}; + +struct mms_delivery_ind { + enum mms_message_delivery_status dr_status; + char *msgid; + char *to; + time_t date; +}; + +struct mms_read_ind { + enum mms_message_read_status rr_status; + char *msgid; + char *to; + char *from; + time_t date; +}; + +struct mms_attachment { + unsigned char *data; + size_t offset; + size_t length; + char *content_type; + char *content_id; +}; + +struct mms_message { + enum mms_message_type type; + char *transaction_id; + unsigned char version; + GSList *attachments; + union { + struct mms_notification_ind ni; + struct mms_retrieve_conf rc; + struct mms_send_req sr; + struct mms_send_conf sc; + struct mms_notification_resp_ind nri; + struct mms_delivery_ind di; + struct mms_read_ind ri; + struct mms_acknowledge_ind ai; + }; +}; + +char *mms_content_type_get_param_value(const char *content_type, + const char *param_name); +gboolean mms_message_decode(const unsigned char *pdu, + unsigned int len, struct mms_message *out); +gboolean mms_message_encode(struct mms_message *msg, int fd); +void mms_message_free(struct mms_message *msg); +const char *mms_message_status_get_string(enum mms_message_status status); diff --git a/mms-lib/src/mms_connection.c b/mms-lib/src/mms_connection.c new file mode 100644 index 0000000..53d254e --- /dev/null +++ b/mms-lib/src/mms_connection.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_connection.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_connection_log +#include "mms_lib_log.h" + +G_DEFINE_TYPE(MMSConnection, mms_connection, G_TYPE_OBJECT); +#define MMS_CONNECTION_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), MMS_TYPE_CONNECTION, MMSConnectionClass)) +#define MMS_CONNECTION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), MMS_TYPE_CONNECTION, MMSConnection)) + +GQuark +mms_connection_error_quark() +{ + return g_quark_from_static_string("mms-connection-error-quark"); +} + +MMSConnection* +mms_connection_ref( + MMSConnection* conn) +{ + if (conn) g_object_ref(MMS_CONNECTION(conn)); + return conn; +} + +void +mms_connection_unref( + MMSConnection* conn) +{ + if (conn) g_object_unref(MMS_CONNECTION(conn)); +} + +const char* +mms_connection_state_name( + MMSConnection* conn) +{ + static const char* names[] = {"????","OPENING","FAILED","OPEN","CLOSED"}; + return names[mms_connection_state(conn)]; +} + +MMS_CONNECTION_STATE +mms_connection_state( + MMSConnection* conn) +{ + return conn ? conn->state : MMS_CONNECTION_STATE_INVALID; +} + +void +mms_connection_close( + MMSConnection* conn) +{ + if (conn) MMS_CONNECTION_GET_CLASS(conn)->fn_close(conn); +} + +/** + * Final stage of deinitialization + */ +static +void +mms_connection_finalize( + GObject* object) +{ + MMSConnection* conn = MMS_CONNECTION(object); + MMS_VERBOSE_("%p", conn); + MMS_ASSERT(!conn->delegate); + g_free(conn->imsi); + g_free(conn->mmsc); + g_free(conn->mmsproxy); + g_free(conn->netif); + G_OBJECT_CLASS(mms_connection_parent_class)->finalize(object); +} + +/** + * Per class initializer + */ +static +void +mms_connection_class_init( + MMSConnectionClass* klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + object_class->finalize = mms_connection_finalize; +} + +/** + * Per instance initializer + */ +static +void +mms_connection_init( + MMSConnection* conn) +{ + MMS_VERBOSE_("%p", conn); +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_connman.c b/mms-lib/src/mms_connman.c new file mode 100644 index 0000000..c2fc2f5 --- /dev/null +++ b/mms-lib/src/mms_connman.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_connman.h" + +G_DEFINE_TYPE(MMSConnMan, mms_connman, G_TYPE_OBJECT); +#define MMS_CONNMAN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_TYPE_CONNMAN, MMSConnMan)) +#define MMS_CONNMAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ + MMS_TYPE_CONNMAN, MMSConnManClass)) + +MMSConnMan* +mms_connman_ref( + MMSConnMan* cm) +{ + if (cm) g_object_ref(MMS_CONNMAN(cm)); + return cm; +} + +void +mms_connman_unref( + MMSConnMan* cm) +{ + if (cm) g_object_unref(MMS_CONNMAN(cm)); +} + +/** + * Per class initializer + */ +static +void +mms_connman_class_init( + MMSConnManClass* klass) +{ +} + +/** + * Per instance initializer + */ +static +void +mms_connman_init( + MMSConnMan* cm) +{ +} + +/** + * Creates a new connection or returns the reference to an aready active one. + * The caller must release the reference. + */ +MMSConnection* +mms_connman_open_connection( + MMSConnMan* cm, + const char* imsi, + gboolean user_request) +{ + if (cm) { + MMSConnManClass* klass = MMS_CONNMAN_GET_CLASS(cm); + if (klass->fn_open_connection) { + return klass->fn_open_connection(cm, imsi, user_request); + } + } + return NULL; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_dispatcher.c b/mms-lib/src/mms_dispatcher.c new file mode 100644 index 0000000..68b5ec4 --- /dev/null +++ b/mms-lib/src/mms_dispatcher.c @@ -0,0 +1,656 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_dispatcher.h" +#include "mms_handler.h" +#include "mms_connection.h" +#include "mms_connman.h" +#include "mms_file_util.h" +#include "mms_codec.h" +#include "mms_util.h" +#include "mms_task.h" + +#include + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_dispatcher_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-dispatcher"); + +struct mms_dispatcher { + gint ref_count; + const MMSConfig* config; + MMSTask* active_task; + MMSTaskDelegate task_delegate; + MMSHandler* handler; + MMSConnMan* cm; + MMSConnection* connection; + MMSConnectionDelegate connection_delegate; + MMSDispatcherDelegate* delegate; + GQueue* tasks; + guint next_run_id; + guint network_idle_id; +}; + +typedef void (*MMSDispatcherIdleCallbackProc)(MMSDispatcher* disp); +typedef struct mms_dispatcher_idle_callback { + MMSDispatcher* dispatcher; + MMSDispatcherIdleCallbackProc proc; +} MMSDispatcherIdleCallback; + +inline static MMSDispatcher* +mms_dispatcher_from_task_delegate(MMSTaskDelegate* delegate) + { return MMS_CAST(delegate,MMSDispatcher,task_delegate); } +inline static MMSDispatcher* +mms_dispatcher_from_connection_delegate(MMSConnectionDelegate* delegate) + { return MMS_CAST(delegate,MMSDispatcher,connection_delegate); } + +static +void +mms_dispatcher_run( + MMSDispatcher* disp); + +/** + * Close the network connection + */ +static +void +mms_dispatcher_close_connection( + MMSDispatcher* disp) +{ + if (disp->connection) { + disp->connection->delegate = NULL; + mms_connection_close(disp->connection); + mms_connection_unref(disp->connection); + disp->connection = NULL; + + if (!mms_dispatcher_is_active(disp)) { + /* Report to delegate that we are done */ + if (disp->delegate && disp->delegate->fn_done) { + disp->delegate->fn_done(disp->delegate, disp); + } + } + } + if (disp->network_idle_id) { + g_source_remove(disp->network_idle_id); + disp->network_idle_id = 0; + } +} + +/** + * Run loop callbacks + */ +static +void +mms_dispatcher_callback_free( + gpointer data) +{ + MMSDispatcherIdleCallback* call = data; + mms_dispatcher_unref(call->dispatcher); + g_free(call); +} + +static +gboolean +mms_dispatcher_idle_callback_cb( + gpointer data) +{ + MMSDispatcherIdleCallback* call = data; + call->proc(call->dispatcher); + return FALSE; +} + +static +guint +mms_dispatcher_callback_schedule( + MMSDispatcher* disp, + MMSDispatcherIdleCallbackProc proc) +{ + MMSDispatcherIdleCallback* call = g_new0(MMSDispatcherIdleCallback,1); + call->dispatcher = mms_dispatcher_ref(disp); + call->proc = proc; + return g_idle_add_full(G_PRIORITY_HIGH, mms_dispatcher_idle_callback_cb, + call, mms_dispatcher_callback_free); +} + +static +guint +mms_dispatcher_timeout_callback_schedule( + MMSDispatcher* disp, + guint interval, + MMSDispatcherIdleCallbackProc proc) +{ + MMSDispatcherIdleCallback* call = g_new0(MMSDispatcherIdleCallback,1); + call->dispatcher = mms_dispatcher_ref(disp); + call->proc = proc; + return g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, interval, + mms_dispatcher_idle_callback_cb, call, mms_dispatcher_callback_free); +} + +/** + * Network idle timeout + */ + +static +void +mms_dispatcher_network_idle_run( + MMSDispatcher* disp) +{ + MMS_ASSERT(disp->network_idle_id); + disp->network_idle_id = 0; + mms_dispatcher_close_connection(disp); +} + +static +void +mms_dispatcher_network_idle_check( + MMSDispatcher* disp) +{ + if (disp->connection && !disp->network_idle_id) { + /* Schedule idle inactivity timeout callback */ + MMS_VERBOSE("Network connection is inactive"); + disp->network_idle_id = mms_dispatcher_timeout_callback_schedule(disp, + disp->config->idle_secs, mms_dispatcher_network_idle_run); + } +} + +static +void +mms_dispatcher_network_idle_cancel( + MMSDispatcher* disp) +{ + if (disp->network_idle_id) { + MMS_VERBOSE("Cancel network inactivity timeout"); + g_source_remove(disp->network_idle_id); + disp->network_idle_id = 0; + } +} + +/** + * Dispatcher run on a fresh stack + */ +static +void +mms_dispatcher_next_run( + MMSDispatcher* disp) +{ + MMS_ASSERT(disp->next_run_id); + MMS_ASSERT(!disp->active_task); + disp->next_run_id = 0; + if (!disp->active_task) { + mms_dispatcher_run(disp); + } +} + +static +void +mms_dispatcher_next_run_schedule( + MMSDispatcher* disp) +{ + if (disp->next_run_id) g_source_remove(disp->next_run_id); + disp->next_run_id = mms_dispatcher_callback_schedule(disp, + mms_dispatcher_next_run); +} + +/** + * Set the delegate that receives dispatcher notifications. + * One delegate per dispatcher. + */ +void +mms_dispatcher_set_delegate( + MMSDispatcher* disp, + MMSDispatcherDelegate* delegate) +{ + MMS_ASSERT(!disp->delegate || !delegate); + disp->delegate = delegate; +} + +/** + * Checks if dispatcher has something to do. + */ +gboolean +mms_dispatcher_is_active( + MMSDispatcher* disp) +{ + return disp && (disp->connection || disp->active_task || + !g_queue_is_empty(disp->tasks)); +} + +/** + * Picks the next task for processing. Reference is passed to the caller. + * Caller must eventually dereference the task or place it back to the queue. + */ +static +MMSTask* +mms_dispatcher_pick_next_task( + MMSDispatcher* disp) +{ + GList* entry; + gboolean connection_in_use = FALSE; + + /* Check the current connection */ + if (disp->connection) { + + /* Don't interfere with the task transmiting the data */ + for (entry = disp->tasks->head; entry; entry = entry->next) { + MMSTask* task = entry->data; + if (task->state == MMS_TASK_STATE_TRANSMITTING) { + MMS_ASSERT(!strcmp(task->imsi, disp->connection->imsi)); + return NULL; + } + } + + /* Look for another task that has use for the existing connection + * before we close it */ + for (entry = disp->tasks->head; entry; entry = entry->next) { + MMSTask* task = entry->data; + if (task->state == MMS_TASK_STATE_NEED_CONNECTION || + task->state == MMS_TASK_STATE_NEED_USER_CONNECTION) { + if (!strcmp(task->imsi, disp->connection->imsi)) { + if (mms_connection_state(disp->connection) == + MMS_CONNECTION_STATE_OPEN) { + /* Found a task that can use this connection */ + g_queue_delete_link(disp->tasks, entry); + mms_dispatcher_network_idle_cancel(disp); + return task; + } + connection_in_use = TRUE; + } + } + } + } + + if (connection_in_use) { + /* Connection is needed but isn't open yet, make sure that network + * inactivity timer is off while connection is being established */ + mms_dispatcher_network_idle_cancel(disp); + } else { + /* Then look for a task that needs any sort of network connection */ + for (entry = disp->tasks->head; entry; entry = entry->next) { + MMSTask* task = entry->data; + if ((task->state == MMS_TASK_STATE_NEED_CONNECTION || + task->state == MMS_TASK_STATE_NEED_USER_CONNECTION)) { + mms_dispatcher_close_connection(disp); + disp->connection = mms_connman_open_connection( + disp->cm, task->imsi, FALSE); + if (disp->connection) { + disp->connection->delegate = &disp->connection_delegate; + g_queue_delete_link(disp->tasks, entry); + return task; + } else { + mms_task_network_unavailable(task); + } + } + } + } + + /* Finally look for a runnable task that doesn't need network */ + for (entry = disp->tasks->head; entry; entry = entry->next) { + MMSTask* task = entry->data; + if (task->state == MMS_TASK_STATE_READY || + task->state == MMS_TASK_STATE_DONE) { + g_queue_delete_link(disp->tasks, entry); + return task; + } + } + + /* Nothing found, we are done for now */ + return NULL; +} + +/** + * Task dispatch loop. + */ +static +void +mms_dispatcher_run( + MMSDispatcher* disp) +{ + MMSTask* task; + MMS_ASSERT(!disp->active_task); + while ((task = mms_dispatcher_pick_next_task(disp)) != NULL) { + MMS_DEBUG("%s %s", task->name, mms_task_state_name(task->state)); + disp->active_task = task; + switch (task->state) { + case MMS_TASK_STATE_READY: + mms_task_run(task); + break; + + case MMS_TASK_STATE_NEED_CONNECTION: + case MMS_TASK_STATE_NEED_USER_CONNECTION: + MMS_ASSERT(disp->connection); + if (mms_connection_is_open(disp->connection)) { + /* Connection is already active, send/receive the data */ + mms_task_transmit(task, disp->connection); + } + break; + + default: + break; + } + + if (task->state == MMS_TASK_STATE_DONE) { + task->delegate = NULL; + mms_task_unref(task); + } else { + g_queue_push_tail(disp->tasks, task); + } + disp->active_task = NULL; + } + + if (disp->connection) { + /* Check if network connection is being used */ + GList* entry; + gboolean connection_in_use = FALSE; + for (entry = disp->tasks->head; entry; entry = entry->next) { + MMSTask* task = entry->data; + if (task->state == MMS_TASK_STATE_NEED_CONNECTION || + task->state == MMS_TASK_STATE_NEED_USER_CONNECTION || + task->state == MMS_TASK_STATE_TRANSMITTING) { + connection_in_use = TRUE; + break; + } + } + if (connection_in_use) { + /* It's in use, disable idle inactivity callback */ + mms_dispatcher_network_idle_cancel(disp); + } else { + /* Make sure that network inactivity timer is ticking */ + mms_dispatcher_network_idle_check(disp); + } + } + + if (!mms_dispatcher_is_active(disp)) { + /* Report to delegate that we are done */ + if (disp->delegate && disp->delegate->fn_done) { + disp->delegate->fn_done(disp->delegate, disp); + } + } +} + +/** + * Starts task processing. + */ +gboolean +mms_dispatcher_start( + MMSDispatcher* disp) +{ + int err = g_mkdir_with_parents(disp->config->root_dir, MMS_DIR_PERM); + if (!err || errno == EEXIST) { + if (!g_queue_is_empty(disp->tasks)) { + mms_dispatcher_next_run_schedule(disp); + return TRUE; + } + } else { + MMS_ERR("Failed to create %s: %s", disp->config->root_dir, + strerror(errno)); + } + return FALSE; +} + +static +void +mms_dispatcher_queue_task( + MMSDispatcher* disp, + MMSTask* task) +{ + task->delegate = &disp->task_delegate; + g_queue_push_tail(disp->tasks, mms_task_ref(task)); +} + +/** + * Creates a WAP push receive task and adds it to the queue. + */ +gboolean +mms_dispatcher_handle_push( + MMSDispatcher* disp, + const char* imsi, + GBytes* push) +{ + MMSTask* task = mms_task_notification_new(disp->config, disp->handler, + imsi, push); + if (task) { + mms_dispatcher_queue_task(disp, task); + mms_task_unref(task); + return TRUE; + } else { + return FALSE; + } +} + +/** + * Creates download task and adds it to the queue. + */ +gboolean +mms_dispatcher_receive_message( + MMSDispatcher* disp, + const char* id, + const char* imsi, + gboolean automatic, + GBytes* bytes) +{ + gboolean ok = FALSE; + MMSPdu* pdu = mms_decode_bytes(bytes); + if (pdu) { + MMS_ASSERT(pdu->type == MMS_MESSAGE_TYPE_NOTIFICATION_IND); + if (pdu->type == MMS_MESSAGE_TYPE_NOTIFICATION_IND) { + MMSTask* task = mms_task_retrieve_new(disp->config, + disp->handler, id, imsi, pdu); + if (task) { + mms_dispatcher_queue_task(disp, task); + mms_task_unref(task); + ok = TRUE; + } + } + mms_message_free(pdu); + } else { + MMS_ERR("Unable to parse MMS push data"); + } + return ok; +} + +/** + * Sends read report + */ +gboolean +mms_dispatcher_send_read_report( + MMSDispatcher* disp, + const char* id, + const char* imsi, + const char* message_id, + const char* to, + MMSReadStatus status) +{ + gboolean ok = FALSE; + MMSTask* task = mms_task_read_new(disp->config, disp->handler, id, imsi, + message_id, to, status); + if (task) { + mms_dispatcher_queue_task(disp, task); + mms_task_unref(task); + ok = TRUE; + } + return ok; +} + +/** + * Cancels al the activity associated with the specified message + */ +void +mms_dispatcher_cancel( + MMSDispatcher* disp, + const char* id) +{ + GList* entry; + for (entry = disp->tasks->head; entry; entry = entry->next) { + MMSTask* task = entry->data; + if (!id || !strcmp(task->id, id)) { + mms_task_cancel(task); + } + } + if (disp->active_task && (!id || !strcmp(disp->active_task->id, id))) { + mms_task_cancel(disp->active_task); + } +} + +/** + * Connection delegate callbacks + */ +static +void +mms_dispatcher_delegate_connection_state_changed( + MMSConnectionDelegate* delegate, + MMSConnection* conn) +{ + MMSDispatcher* disp = mms_dispatcher_from_connection_delegate(delegate); + MMS_CONNECTION_STATE state = mms_connection_state(conn); + MMS_VERBOSE_("%s %s", conn->imsi, mms_connection_state_name(conn)); + MMS_ASSERT(conn == disp->connection); + if (state == MMS_CONNECTION_STATE_FAILED || + state == MMS_CONNECTION_STATE_CLOSED) { + GList* entry; + mms_dispatcher_close_connection(disp); + for (entry = disp->tasks->head; entry; entry = entry->next) { + MMSTask* task = entry->data; + switch (task->state) { + case MMS_TASK_STATE_NEED_CONNECTION: + case MMS_TASK_STATE_NEED_USER_CONNECTION: + case MMS_TASK_STATE_TRANSMITTING: + if (!strcmp(conn->imsi, task->imsi)) { + mms_task_network_unavailable(task); + } + default: + break; + } + } + } + if (!disp->active_task) { + mms_dispatcher_next_run_schedule(disp); + } +} + +/** + * Task delegate callbacks + */ +static +void +mms_dispatcher_delegate_task_queue( + MMSTaskDelegate* delegate, + MMSTask* task) +{ + MMSDispatcher* disp = mms_dispatcher_from_task_delegate(delegate); + mms_dispatcher_queue_task(disp, task); + if (!disp->active_task) { + mms_dispatcher_next_run_schedule(disp); + } +} + +static +void +mms_dispatcher_delegate_task_state_changed( + MMSTaskDelegate* delegate, + MMSTask* task) +{ + MMSDispatcher* disp = mms_dispatcher_from_task_delegate(delegate); + if (!disp->active_task) { + mms_dispatcher_next_run_schedule(disp); + } +} + +/** + * Creates the dispatcher object. Caller must clal mms_dispatcher_unref + * when it no longer needs it. + */ +MMSDispatcher* +mms_dispatcher_new( + const MMSConfig* config, + MMSConnMan* cm, + MMSHandler* handler) +{ + MMSDispatcher* disp = g_new0(MMSDispatcher, 1); + disp->ref_count = 1; + disp->config = config; + disp->tasks = g_queue_new(); + disp->handler = mms_handler_ref(handler); + disp->cm = mms_connman_ref(cm); + disp->task_delegate.fn_task_queue = + mms_dispatcher_delegate_task_queue; + disp->task_delegate.fn_task_state_changed = + mms_dispatcher_delegate_task_state_changed; + disp->connection_delegate.fn_connection_state_changed = + mms_dispatcher_delegate_connection_state_changed; + return disp; +} + +/** + * Deinitializer + */ +static +void +mms_dispatcher_finalize( + MMSDispatcher* disp) +{ + MMSTask* task; + char* msg_dir = g_strconcat(disp->config->root_dir, + "/" MMS_MESSAGE_DIR "/", NULL); + + MMS_VERBOSE_(""); + mms_dispatcher_close_connection(disp); + while ((task = g_queue_pop_head(disp->tasks)) != NULL) { + task->delegate = NULL; + mms_task_cancel(task); + mms_task_unref(task); + } + g_queue_free(disp->tasks); + mms_handler_unref(disp->handler); + mms_connman_unref(disp->cm); + + /* Try to remove the message directory */ + remove(msg_dir); + g_free(msg_dir); +} + +/** + * Reference counting. NULL argument is safely ignored. + */ +MMSDispatcher* +mms_dispatcher_ref( + MMSDispatcher* disp) +{ + if (disp) { + MMS_ASSERT(disp->ref_count > 0); + g_atomic_int_inc(&disp->ref_count); + } + return disp; +} + +void +mms_dispatcher_unref( + MMSDispatcher* disp) +{ + if (disp) { + MMS_ASSERT(disp->ref_count > 0); + if (g_atomic_int_dec_and_test(&disp->ref_count)) { + mms_dispatcher_finalize(disp); + g_free(disp); + } + } +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_file_util.c b/mms-lib/src/mms_file_util.c new file mode 100644 index 0000000..3af33bc --- /dev/null +++ b/mms-lib/src/mms_file_util.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_file_util.h" +#include "mms_log.h" +#include + +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +/** + * Removes both the file and the directory containing it, if it's empty. + */ +void +mms_remove_file_and_dir( + const char* file) +{ + char* dir = g_path_get_dirname(file); + remove(file); + remove(dir); + g_free(dir); +} + +/** + * Creates a file in the specified directory. Creates the directory if + * it doesn't exist. If file already exists, truncates it. Returns file + * discriptor positioned at the beginning of the new file or -1 if an I/O + * error occurs. + */ +int +mms_create_file( + const char* dir, + const char* file, + char** path) +{ + int fd = -1; + int err = g_mkdir_with_parents(dir, MMS_DIR_PERM); + if (!err || errno == EEXIST) { + char* fname = g_strconcat(dir, "/", file, NULL); + fd = open(fname, O_CREAT|O_RDWR|O_TRUNC|O_BINARY, MMS_FILE_PERM); + if (fd < 0) { + MMS_ERR("Failed to create %s: %s", fname, strerror(errno)); + } else if (path) { + *path = fname; + fname = NULL; + } + g_free(fname); + } else { + MMS_ERR("Failed to create directory %s: %s", dir, strerror(errno)); + } + return fd; +} + +/** + * Writes data to a file, creating the directory hierarhy if necessary. + */ +gboolean +mms_write_file( + const char* dir, + const char* file, + const void* data, + gsize size, + char** path) +{ + gboolean saved = FALSE; + int err = g_mkdir_with_parents(dir, MMS_DIR_PERM); + if (!err || errno == EEXIST) { + GError* error = NULL; + char* fname = g_strconcat(dir, "/", file, NULL); + unlink(fname); + if (g_file_set_contents(fname, data, size, &error)) { + MMS_VERBOSE("Created %s", fname); + chmod(fname, MMS_FILE_PERM); + saved = TRUE; + if (path) { + *path = fname; + fname = NULL; + } + } else { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + } + g_free(fname); + } else { + MMS_ERR("Failed to create directory %s: %s", dir, strerror(errno)); + } + return saved; +} + +/** + * Same as mms_write_file, only works with GBytes + */ +gboolean +mms_write_bytes( + const char* dir, + const char* file, + GBytes* bytes, + char** path) +{ + gsize len = 0; + const guint8* data = g_bytes_get_data(bytes, &len); + return mms_write_file(dir, file, data, len, path); +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ + diff --git a/mms-lib/src/mms_file_util.h b/mms-lib/src/mms_file_util.h new file mode 100644 index 0000000..15c0b5a --- /dev/null +++ b/mms-lib/src/mms_file_util.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_FILE_UTIL_H +#define JOLLA_MMS_FILE_UTIL_H + +#include "mms_lib_types.h" + +/* Permissions for MMS files and directories */ +#define MMS_DIR_PERM (0755) +#define MMS_FILE_PERM (0644) + +/* Directories and files */ +#define MMS_ATTIC_DIR "attic" +#define MMS_MESSAGE_DIR "msg" +#define MMS_PARTS_DIR "parts" + +#define MMS_NOTIFICATION_IND_FILE "m-notification.ind" +#define MMS_NOTIFYRESP_IND_FILE "m-notifyresp.ind" +#define MMS_RETRIEVE_CONF_FILE "m-retrieve.conf" +#define MMS_ACKNOWLEDGE_IND_FILE "m-acknowledge.ind" +#define MMS_DELIVERY_IND_FILE "m-delivery.ind" +#define MMS_READ_REC_IND_FILE "m-read-rec.ind" +#define MMS_READ_ORIG_IND_FILE "m-read-orig.ind" +#define MMS_UNRECOGNIZED_PUSH_FILE "push.pdu" + +void +mms_remove_file_and_dir( + const char* file); + +int +mms_create_file( + const char* dir, + const char* fname, + char** path); + +gboolean +mms_write_file( + const char* dir, + const char* file, + const void* data, + gsize size, + char** path); + +gboolean +mms_write_bytes( + const char* dir, + const char* file, + GBytes* bytes, + char** path); + +#define mms_message_dir(config,id) \ + (g_strconcat((config)->root_dir, "/" MMS_MESSAGE_DIR "/" , id, NULL)) +#define mms_task_dir(task) \ + mms_message_dir((task)->config,(task)->id) +#define mms_task_file(task,file) \ + (g_strconcat((task)->config->root_dir, "/" MMS_MESSAGE_DIR "/" , \ + (task)->id, "/", file, NULL)) + +#endif /* JOLLA_MMS_FILE_UTIL_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_handler.c b/mms-lib/src/mms_handler.c new file mode 100644 index 0000000..526acdb --- /dev/null +++ b/mms-lib/src/mms_handler.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_handler.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_handler_log +#include "mms_lib_log.h" + +G_DEFINE_TYPE(MMSHandler, mms_handler, G_TYPE_OBJECT); + +#define MMS_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), MMS_TYPE_HANDLER, MMSHandler)) +#define MMS_HANDLER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), MMS_TYPE_HANDLER, MMSHandlerClass)) +#define MMS_HANDLER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), MMS_TYPE_HANDLER, MMSHandlerClass)) + +static +void +mms_handler_finalize( + GObject* object) +{ + MMS_VERBOSE_("%p", object); + G_OBJECT_CLASS(mms_handler_parent_class)->finalize(object); +} + +static +void +mms_handler_class_init( + MMSHandlerClass* klass) +{ + G_OBJECT_CLASS(klass)->finalize = mms_handler_finalize; +} + +static +void +mms_handler_init( + MMSHandler* h) +{ + MMS_VERBOSE_("%p", h); +} + +MMSHandler* +mms_handler_ref( + MMSHandler* h) +{ + if (h) { + MMS_ASSERT(MMS_HANDLER(h)); + g_object_ref(h); + } + return h; +} + +void +mms_handler_unref( + MMSHandler* h) +{ + if (h) { + MMS_ASSERT(MMS_HANDLER(h)); + g_object_unref(h); + } +} + +char* +mms_handler_message_notify( + MMSHandler* h, + const char* imsi, + const char* from, + const char* subj, + time_t exp, + GBytes* push) +{ + if (h) { + MMSHandlerClass* klass = MMS_HANDLER_GET_CLASS(h); + if (klass->fn_message_notify) { + if (!from) from = ""; + if (!subj) subj = ""; + return klass->fn_message_notify(h, imsi, from, subj, exp, push); + } + MMS_ERR("mms_handler_message_notify not implemented"); + } + return NULL; +} + +gboolean +mms_handler_message_receive_state_changed( + MMSHandler* h, + const char* id, + MMS_RECEIVE_STATE state) +{ + if (h) { + MMSHandlerClass* klass = MMS_HANDLER_GET_CLASS(h); + if (klass->fn_message_receive_state_changed) { + return klass->fn_message_receive_state_changed(h, id, state); + } + MMS_ERR("mms_handler_message_receive_state_changed not implemented"); + } + return FALSE; +} + +gboolean +mms_handler_message_received( + MMSHandler* h, + MMSMessage* msg) +{ + if (h) { + MMSHandlerClass* klass = MMS_HANDLER_GET_CLASS(h); + if (klass->fn_message_received) { + return klass->fn_message_received(h, msg); + } + MMS_ERR("mms_handler_message_received not implemented"); + } + return FALSE; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_lib_util.c b/mms-lib/src/mms_lib_util.c new file mode 100644 index 0000000..2854eb0 --- /dev/null +++ b/mms-lib/src/mms_lib_util.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_lib_util.h" +#include "mms_file_util.h" +#include "mms_message.h" +#include "mms_task.h" +#include "mms_log.h" + +#define MMS_DEFAULT_ROOT_DIR "/var/mms" +#define MMS_DEFAULT_USER_AGENT "Jolla MMS" +#define MMS_DEFAULT_RETRY_SECS (15) +#define MMS_DEFAULT_IDLE_SECS (20) + +/** + * One-time initialization + */ +void +mms_lib_init(void) +{ +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + /* g_type_init has been deprecated since version 2.36 + * the type system is initialised automagically since then */ + g_type_init(); +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif +} + +/** + * Reset configuration to default + */ +void +mms_lib_default_config( + MMSConfig* config) +{ + config->root_dir = MMS_DEFAULT_ROOT_DIR; + config->user_agent = MMS_DEFAULT_USER_AGENT; + config->retry_secs = MMS_DEFAULT_RETRY_SECS; + config->idle_secs = MMS_DEFAULT_IDLE_SECS; + config->keep_temp_files = FALSE; + config->attic_enabled = FALSE; + config->send_dr = TRUE; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_log.c b/mms-lib/src/mms_log.c new file mode 100644 index 0000000..425b7f4 --- /dev/null +++ b/mms-lib/src/mms_log.c @@ -0,0 +1,368 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_log.h" +#include +#include + +#ifdef _WIN32 +# ifdef DEBUG +# include +# endif +# define vsnprintf _vsnprintf +# define snprintf _snprintf +# define strcasecmp _stricmp +# define strncasecmp _strnicmp +#endif + +/* Allows timestamps in stdout log */ +gboolean mms_log_stdout_timestamp = TRUE; + +/* Log configuration */ +MMSLogFunc mms_log_func = mms_log_stdout; +MMSLogModule mms_log_default = { + NULL, /* name */ + MMS_LOGLEVEL_MAX, /* max_level */ + MMS_LOGLEVEL_DEFAULT /* level */ +}; + +/* Log level descriptions */ +static const struct _mms_log_level { + const char* name; + const char* description; +} mms_log_levels [] = { + { "none", "Disable log output" }, + { "error", "Errors only"}, + { "warning", "From warning level to errors" }, + { "info", "From information level to errors" }, + { "debug", "From debug messages to errors" }, + { "verbose", "From verbose trace messages to errors" } +}; + +static const char MMS_LOG_TYPE_STDOUT[] = "stdout"; +static const char MMS_LOG_TYPE_GLIB[] = "glib"; +static const char MMS_LOG_TYPE_CUSTOM[] = "custom"; +#ifdef MMS_LOG_SYSLOG +static const char MMS_LOG_TYPE_SYSLOG[] = "syslog"; +#endif + +G_STATIC_ASSERT(G_N_ELEMENTS(mms_log_levels) > MMS_LOGLEVEL_MAX); +G_STATIC_ASSERT(G_N_ELEMENTS(mms_log_levels) > MMS_LOGLEVEL_DEFAULT); + +/* Forwards output to stdout */ +void +mms_log_stdout( + const char* name, + int level, + const char* format, + va_list va) +{ + char t[32]; + char buf[512]; + const char* prefix = ""; + if (mms_log_stdout_timestamp) { + time_t now; + time(&now); + strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S ", localtime(&now)); + } else { + t[0] = 0; + } + switch (level) { + case MMS_LOGLEVEL_WARN: prefix = "WARNING: "; break; + case MMS_LOGLEVEL_ERR: prefix = "ERROR: "; break; + default: break; + } + vsnprintf(buf, sizeof(buf), format, va); + buf[sizeof(buf)-1] = 0; +#if defined(DEBUG) && defined(_WIN32) + { + char s[1023]; + if (name) { + snprintf(s, sizeof(s), "%s[%s] %s%s\n", t, name, prefix, buf); + } else { + snprintf(s, sizeof(s), "%s%s%s\n", t, prefix, buf); + } + OutputDebugString(s); + } +#endif + if (name) { + printf("%s[%s] %s%s\n", t, name, prefix, buf); + } else { + printf("%s%s%s\n", t, prefix, buf); + } +} + +/* Formards output to syslog */ +#ifdef MMS_LOG_SYSLOG +#include +void +mms_log_syslog( + const char* name, + int level, + const char* format, + va_list va) +{ + int priority; + const char* prefix = NULL; + switch (level) { + default: + case MMS_LOGLEVEL_VERBOSE: + priority = LOG_DEBUG; + break; + case MMS_LOGLEVEL_DEBUG: + priority = LOG_INFO; + break; + case MMS_LOGLEVEL_INFO: + priority = LOG_NOTICE; + break; + case MMS_LOGLEVEL_WARN: + priority = LOG_WARNING; + prefix = "WARNING! "; + break; + case MMS_LOGLEVEL_ERR: + priority = LOG_ERR; + prefix = "ERROR! "; + break; + } + if (name || prefix) { + char buf[512]; + vsnprintf(buf, sizeof(buf), format, va); + if (!prefix) prefix = ""; + if (name) { + syslog(priority, "[%s] %s%s", name, prefix, buf); + } else { + syslog(priority, "%s%s", prefix, buf); + } + } else { + vsyslog(priority, format, va); + } +} +#endif /* MMS_LOG_SYSLOG */ + +/* Forwards output to g_logv */ +void +mms_log_glib( + const char* name, + int level, + const char* format, + va_list va) +{ + GLogLevelFlags flags; + switch (level) { + default: + case MMS_LOGLEVEL_VERBOSE: flags = G_LOG_LEVEL_DEBUG; break; + case MMS_LOGLEVEL_DEBUG: flags = G_LOG_LEVEL_INFO; break; + case MMS_LOGLEVEL_INFO: flags = G_LOG_LEVEL_MESSAGE; break; + case MMS_LOGLEVEL_WARN: flags = G_LOG_LEVEL_WARNING; break; + case MMS_LOGLEVEL_ERR: flags = G_LOG_LEVEL_CRITICAL; break; + } + g_logv(name, flags, format, va); +} + +/* Logging function */ +void +mms_logv( + const MMSLogModule* module, + int level, + const char* format, + va_list va) +{ + if (level != MMS_LOGLEVEL_NONE) { + MMSLogFunc log = mms_log_func; + if (log) { + int max_level; + if (module) { + max_level = (module->level < 0) ? + mms_log_default.level : + module->level; + } else { + module = &mms_log_default; + max_level = mms_log_default.level; + } + if (level <= max_level) { + log(module->name, level, format, va); + } + } + } +} + +void +mms_log( + const MMSLogModule* module, + int level, + const char* format, + ...) +{ + va_list va; + va_start(va, format); + mms_logv(module, level, format, va); + va_end(va); +} + +void +mms_log_assert( + const MMSLogModule* module, + const char* expr, + const char* file, + int line) +{ + mms_log(module, MMS_LOGLEVEL_ASSERT, "Assert %s failed at %s:%d\r", + expr, file, line); +} + +/* mms_log_parse_option helper */ +static +int +mms_log_parse_level( + const char* str, + GError** error) +{ + if (str && str[0]) { + guint i; + const size_t len = strlen(str); + if (len == 1) { + const char* valid_numbers = "012345"; + const char* number = strchr(valid_numbers, str[0]); + if (number) { + return number - valid_numbers; + } + } + + for (i=0; i= 0) { + int i; + const size_t namelen = sep - opt; + for (i=0; iname, opt, namelen)) { + MMS_ASSERT(modules[i]->max_level >= modlevel); + modules[i]->level = modlevel; + return TRUE; + } + } + if (error) { + *error = g_error_new(G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Unknown log module '%.*s'", (int)namelen, opt); + } + } + } else { + const int deflevel = mms_log_parse_level(opt, error); + if (deflevel >= 0) { + mms_log_default.level = deflevel; + return TRUE; + } + } + return FALSE; +} + +/* Generates the string containg description of log levels and list of + * log modules. The caller must deallocate the string with g_free */ +char* +mms_log_description( + MMSLogModule** modules, /* Known modules */ + int count) /* Number of known modules */ +{ + int i; + GString* desc = g_string_sized_new(128); + g_string_append(desc, "Log Levels:\n"); + for (i=0; i<=MMS_LOGLEVEL_MAX; i++) { + g_string_append_printf(desc, " %d, ", i); + g_string_append_printf(desc, "%-8s ", mms_log_levels[i].name); + g_string_append(desc, mms_log_levels[i].description); + if (i == MMS_LOGLEVEL_DEFAULT) g_string_append(desc, " (default)"); + g_string_append(desc, "\n"); + } + if (modules) { + g_string_append(desc, "\nLog Modules:\n"); + for (i=0; iname); + } + } + return g_string_free(desc, FALSE); +} + +gboolean +mms_log_set_type( + const char* type, + const char* default_name) +{ +#ifdef MMS_LOG_SYSLOG + if (!strcasecmp(type, MMS_LOG_TYPE_SYSLOG)) { + if (mms_log_func != mms_log_syslog) { + openlog(NULL, LOG_PID | LOG_CONS, LOG_USER); + } + mms_log_default.name = NULL; + mms_log_func = mms_log_syslog; + return TRUE; + } + if (mms_log_func == mms_log_syslog) { + closelog(); + } +#endif /* MMS_LOG_SYSLOG */ + mms_log_default.name = default_name; + if (!strcasecmp(type, MMS_LOG_TYPE_STDOUT)) { + mms_log_func = mms_log_stdout; + return TRUE; + } else if (!strcasecmp(type, MMS_LOG_TYPE_GLIB)) { + mms_log_func = mms_log_glib; + return TRUE; + } + return FALSE; +} + +const char* +mms_log_get_type() +{ + return (mms_log_func == mms_log_stdout) ? MMS_LOG_TYPE_STDOUT : +#ifdef MMS_LOG_SYSLOG + (mms_log_func == mms_log_syslog) ? MMS_LOG_TYPE_SYSLOG : +#endif /* MMS_LOG_SYSLOG */ + (mms_log_func == mms_log_glib) ? MMS_LOG_TYPE_STDOUT : + MMS_LOG_TYPE_CUSTOM; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_message.c b/mms-lib/src/mms_message.c new file mode 100644 index 0000000..88d58b8 --- /dev/null +++ b/mms-lib/src/mms_message.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_message.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_message_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-message"); + +static +void +mms_message_part_free( + gpointer data, + gpointer user_data) +{ + MMSMessagePart* part = data; + MMSMessage* msg = user_data; + g_free(part->content_type); + g_free(part->content_id); + if (part->file) { + if (!(msg->flags & MMS_MESSAGE_FLAG_KEEP_FILES)) remove(part->file); + g_free(part->file); + } + g_free(part); +} + +static +void +mms_message_finalize( + MMSMessage* msg) +{ + MMS_VERBOSE_("%p", msg); + g_free(msg->id); + g_free(msg->message_id); + g_free(msg->from); + g_strfreev(msg->to); + g_strfreev(msg->cc); + g_free(msg->subject); + g_free(msg->cls); + g_slist_foreach(msg->parts, mms_message_part_free, msg); + g_slist_free(msg->parts); + if (msg->parts_dir) { + if (!(msg->flags & MMS_MESSAGE_FLAG_KEEP_FILES)) remove(msg->parts_dir); + g_free(msg->parts_dir); + } +} + +MMSMessage* +mms_message_new() +{ + MMSMessage* msg = g_new0(MMSMessage, 1); + MMS_VERBOSE_("%p", msg); + msg->ref_count = 1; + msg->priority = MMS_PRIORITY_NORMAL; + return msg; +} + +MMSMessage* +mms_message_ref( + MMSMessage* msg) +{ + if (msg) { + MMS_ASSERT(msg->ref_count > 0); + g_atomic_int_inc(&msg->ref_count); + } + return msg; +} + +void +mms_message_unref( + MMSMessage* msg) +{ + if (msg) { + MMS_ASSERT(msg->ref_count > 0); + if (g_atomic_int_dec_and_test(&msg->ref_count)) { + mms_message_finalize(msg); + g_free(msg); + } + } +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_task.c b/mms-lib/src/mms_task.c new file mode 100644 index 0000000..c113ee3 --- /dev/null +++ b/mms-lib/src/mms_task.c @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_task.h" +#include "mms_handler.h" +#include "mms_file_util.h" + +#ifdef _WIN32 +# define snprintf _snprintf +#endif + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_task_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-task"); + +#define MMS_TASK_DEFAULT_LIFETIME (600) + +G_DEFINE_TYPE(MMSTask, mms_task, G_TYPE_OBJECT); + +#define MMS_TASK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), MMS_TYPE_TASK, MMSTask)) +#define MMS_TASK_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), MMS_TYPE_TASK, MMSTaskClass)) + +static +void +mms_task_wakeup_free( + gpointer data) +{ + mms_task_unref(data); +} + +static +gboolean +mms_task_wakeup_callback( + gpointer data) +{ + MMSTask* task = data; + task->wakeup_id = 0; + MMS_ASSERT(task->state == MMS_TASK_STATE_SLEEP); + mms_task_set_state(task, MMS_TASK_STATE_READY); + return FALSE; +} + +gboolean +mms_task_schedule_wakeup( + MMSTask* task, + unsigned int secs) +{ + const time_t now = time(NULL); + if (!secs) secs = task->config->retry_secs; + + /* Cancel the previous sleep */ + if (task->wakeup_id) { + MMS_ASSERT(task->state == MMS_TASK_STATE_SLEEP); + g_source_remove(task->wakeup_id); + task->wakeup_id = 0; + } + + if (now < task->deadline) { + /* Don't sleep past deadline */ + const unsigned int max_secs = task->deadline - now; + if (secs > max_secs) secs = max_secs; + /* Schedule wakeup */ + task->wakeup_time = now + secs; + task->wakeup_id = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, + secs, mms_task_wakeup_callback, mms_task_ref(task), + mms_task_wakeup_free); + MMS_ASSERT(task->wakeup_id); + MMS_VERBOSE("%s sleeping for %u sec", task->name, secs); + } + + return (task->wakeup_id > 0); +} + +gboolean +mms_task_sleep( + MMSTask* task, + unsigned int secs) +{ + gboolean ok = mms_task_schedule_wakeup(task, secs); + mms_task_set_state(task, ok ? MMS_TASK_STATE_SLEEP : MMS_TASK_STATE_DONE); + return ok; +} + +static +void +mms_task_cancel_cb( + MMSTask* task) +{ + if (task->wakeup_id) { + MMS_ASSERT(task->state == MMS_TASK_STATE_SLEEP); + g_source_remove(task->wakeup_id); + task->wakeup_id = 0; + } + task->flags |= MMS_TASK_FLAG_CANCELLED; + mms_task_set_state(task, MMS_TASK_STATE_DONE); +} + +static +void +mms_task_finalize( + GObject* object) +{ + MMSTask* task = MMS_TASK(object); + MMS_VERBOSE_("%p", task); + MMS_ASSERT(!task->delegate); + MMS_ASSERT(!task->wakeup_id); + g_free(task->name); + g_free(task->id); + g_free(task->imsi); + mms_handler_unref(task->handler); + G_OBJECT_CLASS(mms_task_parent_class)->finalize(object); +} + +static +void +mms_task_class_init( + MMSTaskClass* klass) +{ + klass->fn_cancel = mms_task_cancel_cb; + G_OBJECT_CLASS(klass)->finalize = mms_task_finalize; +} + +static +void +mms_task_init( + MMSTask* task) +{ + MMS_VERBOSE_("%p", task); +} + +void* +mms_task_alloc( + GType type, + const MMSConfig* config, + MMSHandler* handler, + const char* name, + const char* id, + const char* imsi) +{ + MMSTask* task = g_object_new(type, NULL); + const time_t now = time(NULL); + time_t max_lifetime = MMS_TASK_GET_CLASS(task)->max_lifetime; + if (!max_lifetime) max_lifetime = MMS_TASK_DEFAULT_LIFETIME; + task->config = config; + task->handler = mms_handler_ref(handler); + if (name) { + task->name = id ? + g_strdup_printf("%s[%.08s]", name, id) : + g_strdup(name); + } + task->id = g_strdup(id); + task->imsi = g_strdup(imsi); + task->deadline = now + max_lifetime; + return task; +} + +MMSTask* +mms_task_ref( + MMSTask* task) +{ + if (task) g_object_ref(MMS_TASK(task)); + return task; +} + +void +mms_task_unref( + MMSTask* task) +{ + if (task) g_object_unref(MMS_TASK(task)); +} + +void +mms_task_run( + MMSTask* task) +{ + MMS_ASSERT(task->state == MMS_TASK_STATE_READY); + MMS_TASK_GET_CLASS(task)->fn_run(task); + time(&task->last_run_time); + MMS_ASSERT(task->state != MMS_TASK_STATE_READY); +} + +void +mms_task_transmit( + MMSTask* task, + MMSConnection* connection) +{ + MMS_ASSERT(task->state == MMS_TASK_STATE_NEED_CONNECTION || + task->state == MMS_TASK_STATE_NEED_USER_CONNECTION); + MMS_TASK_GET_CLASS(task)->fn_transmit(task, connection); + time(&task->last_run_time); + MMS_ASSERT(task->state != MMS_TASK_STATE_NEED_CONNECTION && + task->state != MMS_TASK_STATE_NEED_USER_CONNECTION); +} + +void +mms_task_network_unavailable( + MMSTask* task) +{ + if (task->state != MMS_TASK_STATE_DONE) { + MMS_ASSERT(task->state == MMS_TASK_STATE_NEED_CONNECTION || + task->state == MMS_TASK_STATE_NEED_USER_CONNECTION || + task->state == MMS_TASK_STATE_TRANSMITTING); + MMS_TASK_GET_CLASS(task)->fn_network_unavailable(task); + MMS_ASSERT(task->state != MMS_TASK_STATE_NEED_CONNECTION && + task->state != MMS_TASK_STATE_NEED_USER_CONNECTION && + task->state != MMS_TASK_STATE_TRANSMITTING); + time(&task->last_run_time); + } +} + +void +mms_task_cancel( + MMSTask* task) +{ + MMS_DEBUG_("%s", task->name); + MMS_TASK_GET_CLASS(task)->fn_cancel(task); +} + +void +mms_task_set_state( + MMSTask* task, + MMS_TASK_STATE state) +{ + if (task->state != state) { + MMS_DEBUG("%s %s -> %s", task->name, + mms_task_state_name(task->state), + mms_task_state_name(state)); + if (state == MMS_TASK_STATE_SLEEP && !task->wakeup_id) { + if (!mms_task_schedule_wakeup(task, task->config->retry_secs)) { + MMS_DEBUG("%s SLEEP -> DONE (no time left)", task->name); + state = MMS_TASK_STATE_DONE; + } + } + task->state = state; + if (task->delegate && task->delegate->fn_task_state_changed) { + task->delegate->fn_task_state_changed(task->delegate, task); + } + } +} + +/* Utilities */ + +static const char* mms_task_names[] = {"READY", "NEED_CONNECTION", + "NEED_USER_CONNECTION", "TRANSMITTING", "WORKING", "SLEEP", "DONE" +}; +G_STATIC_ASSERT(G_N_ELEMENTS(mms_task_names) == MMS_TASK_STATE_COUNT); + +const char* +mms_task_state_name( + MMS_TASK_STATE state) +{ + if (state >= 0 && state < G_N_ELEMENTS(mms_task_names)) { + return mms_task_names[state]; + } else { + /* This shouldn't happen */ + static char unknown[32]; + snprintf(unknown, sizeof(unknown), "%d ????", state); + return unknown; + } +} + +gboolean +mms_task_queue_and_unref( + MMSTaskDelegate* delegate, + MMSTask* task) +{ + gboolean ok = FALSE; + if (task) { + if (delegate && delegate->fn_task_queue) { + delegate->fn_task_queue(delegate, task); + ok = TRUE; + } + mms_task_unref(task); + } + return ok; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_task.h b/mms-lib/src/mms_task.h new file mode 100644 index 0000000..b28b463 --- /dev/null +++ b/mms-lib/src/mms_task.h @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_TASK_H +#define JOLLA_MMS_TASK_H + +#include "mms_lib_types.h" + +/* Claim MMS 1.1 support */ +#define MMS_VERSION MMS_MESSAGE_VERSION_1_1 + +/* mmsutil.h */ +typedef enum mms_message_notify_status MMSNotifyStatus; + +/* Task state */ +typedef enum _MMS_TASK_STATE { + MMS_TASK_STATE_READY, /* Ready to run */ + MMS_TASK_STATE_NEED_CONNECTION, /* Network connection us needed */ + MMS_TASK_STATE_NEED_USER_CONNECTION, /* Connection requested by user */ + MMS_TASK_STATE_TRANSMITTING, /* Sending or receiving the data */ + MMS_TASK_STATE_WORKING, /* Active but not using network */ + MMS_TASK_STATE_SLEEP, /* Will change state later */ + MMS_TASK_STATE_DONE, /* Nothing left to do */ + MMS_TASK_STATE_COUNT /* Number of valid states */ +} MMS_TASK_STATE; + +/* Delegate (one per task) */ +typedef struct mms_task MMSTask; +typedef struct mms_task_delegate MMSTaskDelegate; +struct mms_task_delegate { + /* Submits new task to the queue */ + void (*fn_task_queue)( + MMSTaskDelegate* delegate, + MMSTask* task); + /* Task has changed its state */ + void (*fn_task_state_changed)( + MMSTaskDelegate* delegate, + MMSTask* task); +}; + +/* Task object */ +struct mms_task { + GObject parent; /* Parent object */ + char* name; /* Task name for debug purposes */ + char* id; /* Database record ID */ + char* imsi; /* Associated subscriber identity */ + const MMSConfig* config; /* Immutable configuration */ + MMSHandler* handler; /* Message database interface */ + MMSTaskDelegate* delegate; /* Observer */ + MMS_TASK_STATE state; /* Task state */ + time_t last_run_time; /* Last run time */ + time_t deadline; /* Task deadline */ + time_t wakeup_time; /* Wake up time (if sleeping) */ + guint wakeup_id; /* ID of the wakeup source */ + int flags; /* Flags: */ + +#define MMS_TASK_FLAG_CANCELLED (0x01) /* Task has been cancelled */ + +}; + +typedef struct mms_task_class { + GObjectClass parent; + time_t max_lifetime; /* Maximum lifetime, in seconds */ + /* Invoked in IDLE/RETRY state to get the task going */ + void (*fn_run)(MMSTask* task); + /* Invoked in NEED_[USER_]CONNECTION state */ + void (*fn_transmit)(MMSTask* task, MMSConnection* conn); + /* Invoked in NEED_[USER_]CONNECTION or TRANSMITTING state */ + void (*fn_network_unavailable)(MMSTask* task); + /* May be invoked in any state */ + void (*fn_cancel)(MMSTask* task); +} MMSTaskClass; + +GType mms_task_get_type(void); +#define MMS_TYPE_TASK (mms_task_get_type()) +#define MMS_TASK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ + MMS_TYPE_TASK, MMSTaskClass)) + +void* +mms_task_alloc( + GType type, + const MMSConfig* config, + MMSHandler* handler, + const char* name, + const char* id, + const char* imsi); + +MMSTask* +mms_task_ref( + MMSTask* task); + +void +mms_task_unref( + MMSTask* task); + +void +mms_task_run( + MMSTask* task); + +void +mms_task_transmit( + MMSTask* task, + MMSConnection* connection); + +void +mms_task_network_unavailable( + MMSTask* task); + +void +mms_task_cancel( + MMSTask* task); + +void +mms_task_set_state( + MMSTask* task, + MMS_TASK_STATE state); + +gboolean +mms_task_sleep( + MMSTask* task, + unsigned int secs); + +#define mms_task_retry(task) \ + mms_task_sleep(task, 0) + +/* Utilities */ +const char* +mms_task_state_name( + MMS_TASK_STATE state); + +gboolean +mms_task_queue_and_unref( + MMSTaskDelegate* delegate, + MMSTask* task); + +/* Create particular types of tasks */ +MMSTask* +mms_task_notification_new( + const MMSConfig* config, + MMSHandler* handler, + const char* imsi, + GBytes* bytes); + +MMSTask* +mms_task_retrieve_new( + const MMSConfig* config, + MMSHandler* handler, + const char* id, + const char* imsi, + const MMSPdu* pdu); + +MMSTask* +mms_task_decode_new( + const MMSConfig* config, + MMSHandler* handler, + const char* id, + const char* imsi, + const char* transaction_id, + const char* file); + +MMSTask* +mms_task_upload_new( + const MMSConfig* config, + MMSHandler* handler, + const char* name, + const char* id, + const char* imsi, + const char* file); + +MMSTask* +mms_task_notifyresp_new( + const MMSConfig* config, + MMSHandler* handler, + const char* id, + const char* imsi, + const char* transaction_id, + MMSNotifyStatus status); + +MMSTask* +mms_task_ack_new( + const MMSConfig* config, + MMSHandler* handler, + const char* id, + const char* imsi, + const char* transaction_id); + +MMSTask* +mms_task_read_new( + const MMSConfig* config, + MMSHandler* handler, + const char* id, + const char* imsi, + const char* message_id, + const char* to, + MMSReadStatus status); + +MMSTask* +mms_task_publish_new( + const MMSConfig* config, + MMSHandler* handler, + MMSMessage* msg); + +MMSTask* +mms_task_delete_new( + const MMSConfig* config, + const char* uuid); + +#endif /* JOLLA_MMS_TASK_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_task_ack.c b/mms-lib/src/mms_task_ack.c new file mode 100644 index 0000000..dd1c77a --- /dev/null +++ b/mms-lib/src/mms_task_ack.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_task.h" +#include "mms_log.h" +#include "mms_codec.h" +#include "mms_file_util.h" + +static +char* +mms_task_ack_create_pdu_file( + const MMSConfig* config, + const char* id, + const char* transaction_id) +{ + char* path = NULL; + char* dir = mms_message_dir(config, id); + int fd = mms_create_file(dir, MMS_ACKNOWLEDGE_IND_FILE, &path); + if (fd >= 0) { + MMSPdu* pdu = g_new0(MMSPdu, 1); + pdu->type = MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND; + pdu->version = MMS_VERSION; + pdu->transaction_id = g_strdup(transaction_id); + pdu->ai.report = config->send_dr; + if (!mms_message_encode(pdu, fd)) { + g_free(path); + path = NULL; + } + mms_message_free(pdu); + close(fd); + } + g_free(dir); + return path; +} + +/* Create MMS delivery acknowledgement task */ +MMSTask* +mms_task_ack_new( + const MMSConfig* cfg, + MMSHandler* h, + const char* id, + const char* imsi, + const char* transaction_id) +{ + char* path = mms_task_ack_create_pdu_file(cfg, id, transaction_id); + if (path) { + MMSTask* task = mms_task_upload_new(cfg, h, "Ack", id, imsi, path); + g_free(path); + return task; + } + return NULL; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_task_decode.c b/mms-lib/src/mms_task_decode.c new file mode 100644 index 0000000..132e145 --- /dev/null +++ b/mms-lib/src/mms_task_decode.c @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_task.h" +#include "mms_util.h" +#include "mms_codec.h" +#include "mms_handler.h" +#include "mms_message.h" +#include "mms_file_util.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_task_decode_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-task-decode"); + +/* Class definition */ +typedef MMSTaskClass MMSTaskDecodeClass; +typedef struct mms_task_decode { + MMSTask task; + GMappedFile* map; + char* transaction_id; + char* file; +} MMSTaskDecode; + +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)) + +static +gboolean +mms_task_decode_array_contains_string( + const GPtrArray* array, + const char* str) +{ + guint i; + for (i=0; ilen; i++) { + if (!strcmp(array->pdata[i], str)) { + return TRUE; + } + } + return FALSE; +} + +static +char* +mms_task_decode_add_file_name( + GPtrArray* names, + const char* proposed) +{ + const char* src; + char* file = g_new(char, strlen(proposed)+1); + char* dest = file; + for (src = proposed; *src; src++) { + switch (*src) { + case '<': case '>': case '[': case ']': + break; + case '/': case '\\': + *dest++ = '_'; + break; + default: + *dest++ = *src; + break; + } + } + *dest = 0; + while (mms_task_decode_array_contains_string(names, file)) { + char* _file = g_strconcat("_", file, NULL); + g_free(file); + file = _file; + } + g_ptr_array_add(names, file); + return file; +} + +static +MMSMessage* +mms_task_decode_process_retrieve_conf( + MMSTask* task, + const MMSPdu* pdu, + const guint8* pdu_data, + gsize pdu_size) +{ + GSList* entry; + int i, nparts = g_slist_length(pdu->attachments); + GPtrArray* part_files = g_ptr_array_new_full(nparts, g_free); + char* dir = mms_task_dir(task); + const struct mms_retrieve_conf* rc = &pdu->rc; + MMSMessage* msg = mms_message_new(); + +#if MMS_LOG_DEBUG + char date[128]; + strftime(date, sizeof(date), "%Y-%m-%dT%H:%M:%S%z", localtime(&rc->date)); + date[sizeof(date)-1] = '\0'; +#endif /* MMS_LOG_DEBUG */ + + MMS_ASSERT(pdu->type == MMS_MESSAGE_TYPE_RETRIEVE_CONF); + MMS_INFO("Processing M-Retrieve.conf"); + MMS_INFO(" From: %s", rc->from); + +#if MMS_LOG_DEBUG + MMS_DEBUG(" To: %s", rc->to); + if (rc->cc) MMS_DEBUG(" Cc: %s", rc->cc); + MMS_DEBUG(" Message-ID: %s", rc->msgid); + MMS_DEBUG(" Transaction-ID: %s", pdu->transaction_id); + if (rc->subject) MMS_DEBUG(" Subject: %s", rc->subject); + MMS_DEBUG(" Date: %s", date); + MMS_DEBUG(" %u parts", nparts); +#endif /* MMS_LOG_DEBUG */ + + if (task->config->keep_temp_files) { + msg->flags |= MMS_MESSAGE_FLAG_KEEP_FILES; + } + + msg->id = g_strdup(task->id); + msg->message_id = g_strdup(rc->msgid); + msg->from = mms_strip_address_type(g_strdup(rc->from)); + msg->to = mms_split_address_list(rc->to); + msg->cc = mms_split_address_list(rc->cc); + msg->subject = g_strdup(rc->subject); + msg->cls = g_strdup(rc->cls ? rc->cls : MMS_MESSAGE_CLASS_PERSONAL); + msg->date = rc->date ? rc->date : time(NULL); + + switch (rc->priority) { + case MMS_MESSAGE_PRIORITY_LOW: + msg->priority = MMS_PRIORITY_LOW; + break; + case MMS_MESSAGE_PRIORITY_NORMAL: + msg->priority = MMS_PRIORITY_NORMAL; + break; + case MMS_MESSAGE_PRIORITY_HIGH: + msg->priority = MMS_PRIORITY_HIGH; + break; + } + + msg->parts_dir = g_strconcat(dir, "/" , MMS_PARTS_DIR, NULL); + for (i=0, entry = pdu->attachments; entry; entry = entry->next, i++) { + struct mms_attachment* attach = entry->data; + const char* id = attach->content_id; + char* path = NULL; + char* file; + if (id && id[0]) { + file = mms_task_decode_add_file_name(part_files, id); + } else { + char* name = g_strdup_printf("part_%d",i); + file = mms_task_decode_add_file_name(part_files, name); + g_free(name); + } + MMS_DEBUG("Part: %s %s", id, attach->content_type); + MMS_ASSERT(attach->offset < pdu_size); + if (mms_write_file(msg->parts_dir, file, pdu_data + attach->offset, + attach->length, &path)) { + MMSMessagePart* part = g_new0(MMSMessagePart, 1); + part->content_type = g_strdup(attach->content_type); + part->content_id = g_strdup(id); + part->file = path; + msg->parts = g_slist_append(msg->parts, part); + } + } + + g_ptr_array_free(part_files, TRUE); + g_free(dir); + return msg; +} + +static +MMSMessage* +mms_task_decode_process_pdu( + MMSTask* task, + const guint8* data, + gsize len) +{ + MMSMessage* msg = NULL; + MMSPdu* pdu = g_new0(MMSPdu, 1); + if (mms_message_decode(data, len, pdu)) { + if (pdu->type == MMS_MESSAGE_TYPE_RETRIEVE_CONF) { + msg = mms_task_decode_process_retrieve_conf(task, pdu, data, len); + } else { + MMS_ERR("Unexpected MMS PDU type %u", (guint)pdu->type); + } + } else { + MMS_ERR("Failed to decode MMS PDU"); + } + mms_message_free(pdu); + return msg; +} + +static +void +mms_task_decode_run( + MMSTask* task) +{ + MMSTaskDecode* dec = MMS_TASK_DECODE(task); + const void* data = g_mapped_file_get_contents(dec->map); + const gsize size = g_mapped_file_get_length(dec->map); + MMSMessage* msg = mms_task_decode_process_pdu(task, data, size); + if (msg) { + mms_task_queue_and_unref(task->delegate, + mms_task_ack_new(task->config, task->handler, task->id, task->imsi, + dec->transaction_id)); + mms_task_queue_and_unref(task->delegate, + mms_task_publish_new(task->config, task->handler, msg)); + mms_message_unref(msg); + } else { + mms_handler_message_receive_state_changed(task->handler, task->id, + MMS_RECEIVE_STATE_DECODING_ERROR); + mms_task_queue_and_unref(task->delegate, + mms_task_notifyresp_new(task->config, task->handler, task->id, + task->imsi, dec->transaction_id, + MMS_MESSAGE_NOTIFY_STATUS_UNRECOGNISED)); + } + mms_task_set_state(task, MMS_TASK_STATE_DONE); +} + +static +void +mms_task_decode_finalize( + GObject* object) +{ + MMSTaskDecode* dec = MMS_TASK_DECODE(object); + if (!dec->task.config->keep_temp_files) { + mms_remove_file_and_dir(dec->file); + } + g_mapped_file_unref(dec->map); + g_free(dec->transaction_id); + g_free(dec->file); + G_OBJECT_CLASS(mms_task_decode_parent_class)->finalize(object); +} + +static +void +mms_task_decode_class_init( + MMSTaskDecodeClass* klass) +{ + klass->fn_run = mms_task_decode_run; + G_OBJECT_CLASS(klass)->finalize = mms_task_decode_finalize; +} + +static +void +mms_task_decode_init( + MMSTaskDecode* decode) +{ +} + +/* Create MMS decode task */ +MMSTask* +mms_task_decode_new( + const MMSConfig* config, + MMSHandler* handler, + const char* id, + const char* imsi, + const char* transaction_id, + const char* file) +{ + MMSTaskDecode* dec = mms_task_alloc(MMS_TYPE_TASK_DECODE, + config, handler, "Decode", id, imsi); + GError* error = NULL; + dec->map = g_mapped_file_new(file, FALSE, &error); + if (dec->map) { + dec->transaction_id = g_strdup(transaction_id); + dec->file = g_strdup(file); + return &dec->task; + } else { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + return NULL; + } +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_task_notification.c b/mms-lib/src/mms_task_notification.c new file mode 100644 index 0000000..2a36439 --- /dev/null +++ b/mms-lib/src/mms_task_notification.c @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_task.h" +#include "mms_util.h" +#include "mms_codec.h" +#include "mms_handler.h" +#include "mms_file_util.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_task_notification_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-task-notification"); + +/* Class definition */ +typedef MMSTaskClass MMSTaskNotificationClass; +typedef struct mms_task_notification { + MMSTask task; + MMSPdu* pdu; + GBytes* push; +} MMSTaskNotification; + +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)) + +/** + * Generates dummy task id if necessary. + */ +static +void +mms_task_notification_make_id( + MMSTask* task) +{ + if (!task->id) { + char* tmpl = g_strconcat(task->config->root_dir, + "/" MMS_MESSAGE_DIR "/XXXXXX" , NULL); + char* dir = g_mkdtemp_full(tmpl, MMS_DIR_PERM); + if (dir) task->id = g_path_get_basename(dir); + g_free(tmpl); + } +} + +/** + * Writes the datagram to a file in the message directory. + */ +static +gboolean +mms_task_notification_write_file( + MMSTaskNotification* ind, + const char* file) +{ + char* dir; + gboolean ok; + mms_task_notification_make_id(&ind->task); + dir = mms_task_dir(&ind->task); + ok = mms_write_bytes(dir, file, ind->push, NULL); + g_free(dir); + return ok; +} + +/** + * Handles M-Notification.ind PDU + */ +static +void +mms_task_notification_ind( + MMSTaskNotification* ind) +{ + MMSTask* task = &ind->task; + const struct mms_notification_ind* ni = &ind->pdu->ni; + char* id; + +#if MMS_LOG_DEBUG + char expiry[128]; + strftime(expiry, sizeof(expiry), "%Y-%m-%dT%H:%M:%S%z", + localtime(&ni->expiry)); + expiry[sizeof(expiry)-1] = '\0'; + + MMS_DEBUG("Processing M-Notification.ind"); + MMS_DEBUG(" From: %s", ni->from); + if (ni->subject) MMS_DEBUG(" Subject: %s", ni->subject); + MMS_DEBUG(" Size: %d bytes", ni->size); + MMS_DEBUG(" Location: %s", ni->location); + MMS_DEBUG(" Expiry: %s", expiry); +#endif /* MMS_LOG_DEBUG */ + + id = mms_handler_message_notify(task->handler, task->imsi, + mms_strip_address_type(ni->from), ni->subject, ni->expiry, ind->push); + if (id) { + if (id[0]) { + MMS_DEBUG(" Database id: %s", id); + if (task->id) { + /* Remove temporary directory and files */ + char* dir = mms_task_dir(task); + char* file = mms_task_file(task, MMS_NOTIFICATION_IND_FILE); + remove(file); + remove(dir); + g_free(file); + g_free(dir); + g_free(task->id); + } + task->id = id; + + /* Schedule the download task */ + if (!mms_task_queue_and_unref(task->delegate, + mms_task_retrieve_new(task->config, task->handler, + task->id, task->imsi, ind->pdu))) { + mms_handler_message_receive_state_changed(task->handler, id, + MMS_RECEIVE_STATE_DOWNLOAD_ERROR); + } + } else { + g_free(id); + } + } else if (!mms_task_retry(task)) { + mms_task_notification_make_id(task); + mms_task_queue_and_unref(task->delegate, + mms_task_notifyresp_new(task->config, task->handler, task->id, + task->imsi, ind->pdu->transaction_id, + MMS_MESSAGE_NOTIFY_STATUS_REJECTED)); + } + + if (task->config->keep_temp_files) { + mms_task_notification_write_file(ind, MMS_NOTIFICATION_IND_FILE); + } +} + +/** + * Handles M-Delivery.ind PDU + */ +static +void +mms_task_delivery_ind( + MMSTaskNotification* ind) +{ + MMS_DEBUG("Processing M-Delivery.ind PDU"); + MMS_DEBUG(" MMS message id: %s", ind->pdu->di.msgid); + if (ind->task.config->keep_temp_files) { + mms_task_notification_write_file(ind, MMS_DELIVERY_IND_FILE); + } +} + +/** + * Handles M-Read-Orig.ind PDU + */ +static +void +mms_task_read_orig_ind( + MMSTaskNotification* ind) +{ + MMS_DEBUG("Processing M-Read-Orig.ind"); + MMS_DEBUG(" MMS message id: %s", ind->pdu->ri.msgid); + if (ind->task.config->keep_temp_files) { + mms_task_notification_write_file(ind, MMS_READ_ORIG_IND_FILE); + } +} + +/** + * Handles unrecognized PDU + */ +static +void +mms_task_notification_unrecornized( + const MMSConfig* config, + GBytes* push) +{ + if (config->attic_enabled) { + char* attic_dir = NULL; + int i; + for (i=0; i<100; i++) { + g_free(attic_dir); + attic_dir = g_strdup_printf("%s/" MMS_ATTIC_DIR "/%03d", + config->root_dir, i); + if (!g_file_test(attic_dir, G_FILE_TEST_IS_DIR)) break; + } + mms_write_bytes(attic_dir, MMS_UNRECOGNIZED_PUSH_FILE, push, NULL); + g_free(attic_dir); + } +} + +/** + * Runs the task + */ +static +void +mms_task_notification_run( + MMSTask* task) +{ + MMSTaskNotification* ind = MMS_TASK_NOTIFICATION(task); + switch (ind->pdu->type) { + case MMS_MESSAGE_TYPE_NOTIFICATION_IND: + mms_task_notification_ind(ind); + break; + case MMS_MESSAGE_TYPE_DELIVERY_IND: + mms_task_delivery_ind(ind); + break; + case MMS_MESSAGE_TYPE_READ_ORIG_IND: + mms_task_read_orig_ind(ind); + break; + default: + MMS_INFO("Ignoring MMS push PDU of type %u", ind->pdu->type); + mms_task_notification_unrecornized(task->config, ind->push); + break; + } + if (task->state == MMS_TASK_STATE_READY) { + mms_task_set_state(task, MMS_TASK_STATE_DONE); + } +} + +static +void +mms_task_notification_finalize( + GObject* object) +{ + MMSTaskNotification* ind = MMS_TASK_NOTIFICATION(object); + g_bytes_unref(ind->push); + mms_message_free(ind->pdu); + G_OBJECT_CLASS(mms_task_notification_parent_class)->finalize(object); +} + +static +void +mms_task_notification_class_init( + MMSTaskNotificationClass* klass) +{ + klass->fn_run = mms_task_notification_run; + G_OBJECT_CLASS(klass)->finalize = mms_task_notification_finalize; +} + +static +void +mms_task_notification_init( + MMSTaskNotification* notification) +{ +} + +/* Create MMS notification task */ +MMSTask* +mms_task_notification_new( + const MMSConfig* config, + MMSHandler* handler, + const char* imsi, + GBytes* bytes) +{ + MMSPdu* pdu = mms_decode_bytes(bytes); + if (pdu) { + MMSTaskNotification* ind; + + /* Looks like a legitimate MMS Push PDU */ +#if MMS_LOG_DEBUG + MMS_DEBUG(" MMS version: %u.%u", (pdu->version & 0x70) >> 4, + pdu->version & 0x0f); + if (pdu->transaction_id) { + MMS_DEBUG(" MMS transaction id: %s", pdu->transaction_id); + } +#endif /* MMS_LOG_DEBUG */ + + ind = mms_task_alloc(MMS_TYPE_TASK_NOTIFICATION, + config, handler, "Notification", NULL, imsi); + ind->push = g_bytes_ref(bytes); + ind->pdu = pdu; + if (pdu->type == MMS_MESSAGE_TYPE_NOTIFICATION_IND) { + ind->task.deadline = pdu->ni.expiry; + } + return &ind->task; + } else { + MMS_ERR("Unable to parse MMS push data"); + mms_task_notification_unrecornized(config, bytes); + return NULL; + } +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_task_notifyresp.c b/mms-lib/src/mms_task_notifyresp.c new file mode 100644 index 0000000..f1d2cd2 --- /dev/null +++ b/mms-lib/src/mms_task_notifyresp.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_task.h" +#include "mms_log.h" +#include "mms_codec.h" +#include "mms_file_util.h" + +static +char* +mms_task_notifyresp_create_pdu_file( + const MMSConfig* config, + const char* id, + const char* transaction_id, + MMSNotifyStatus status) +{ + char* path = NULL; + char* dir = mms_message_dir(config, id); + int fd = mms_create_file(dir, MMS_NOTIFYRESP_IND_FILE, &path); + if (fd >= 0) { + MMSPdu* pdu = g_new0(MMSPdu, 1); + pdu->type = MMS_MESSAGE_TYPE_NOTIFYRESP_IND; + pdu->version = MMS_VERSION; + pdu->transaction_id = g_strdup(transaction_id); + pdu->nri.notify_status = status; + if (!mms_message_encode(pdu, fd)) { + g_free(path); + path = NULL; + } + mms_message_free(pdu); + close(fd); + } + g_free(dir); + return path; +} + +/** + * Create MMS retrieve confirmation task + */ +MMSTask* +mms_task_notifyresp_new( + const MMSConfig* cfg, + MMSHandler* handler, + const char* id, + const char* imsi, + const char* tx_id, + MMSNotifyStatus ns) +{ + char* path = mms_task_notifyresp_create_pdu_file(cfg, id, tx_id, ns); + if (path) { + MMSTask* task = mms_task_upload_new(cfg, handler, "NotifyResp", + id, imsi, path); + g_free(path); + return task; + } + return NULL; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_task_publish.c b/mms-lib/src/mms_task_publish.c new file mode 100644 index 0000000..a4b4ffc --- /dev/null +++ b/mms-lib/src/mms_task_publish.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_task.h" +#include "mms_handler.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_task_publish_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-task-publish"); + +/* Class definition */ +typedef MMSTaskClass MMSTaskPublishClass; +typedef struct mms_task_publish { + MMSTask task; + MMSMessage* msg; +} MMSTaskPublish; + +G_DEFINE_TYPE(MMSTaskPublish, mms_task_publish, MMS_TYPE_TASK); +#define MMS_TYPE_TASK_PUBLISH (mms_task_publish_get_type()) +#define MMS_TASK_PUBLISH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_TYPE_TASK_PUBLISH, MMSTaskPublish)) + +static +void +mms_task_publish_run( + MMSTask* task) +{ + MMSTaskPublish* pub = MMS_TASK_PUBLISH(task); + if (mms_handler_message_received(task->handler, pub->msg)) { + mms_task_set_state(task, MMS_TASK_STATE_DONE); + } else { + mms_task_set_state(task, MMS_TASK_STATE_SLEEP); + } +} + +static +void +mms_task_publish_finalize( + GObject* object) +{ + MMSTaskPublish* pub = MMS_TASK_PUBLISH(object); + mms_message_unref(pub->msg); + G_OBJECT_CLASS(mms_task_publish_parent_class)->finalize(object); +} + +static +void +mms_task_publish_class_init( + MMSTaskPublishClass* klass) +{ + klass->fn_run = mms_task_publish_run; + G_OBJECT_CLASS(klass)->finalize = mms_task_publish_finalize; +} + +static +void +mms_task_publish_init( + MMSTaskPublish* publish) +{ +} + +/* Create MMS publish task */ +MMSTask* +mms_task_publish_new( + const MMSConfig* config, + MMSHandler* handler, + MMSMessage* msg) +{ + MMS_ASSERT(msg && msg->id); + if (msg && msg->id) { + MMSTaskPublish* pub = mms_task_alloc(MMS_TYPE_TASK_PUBLISH, + config, handler, "Publish", msg->id, NULL); + pub->msg = mms_message_ref(msg); + return &pub->task; + } else { + return NULL; + } +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_task_read.c b/mms-lib/src/mms_task_read.c new file mode 100644 index 0000000..d9c1359 --- /dev/null +++ b/mms-lib/src/mms_task_read.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_task.h" +#include "mms_log.h" +#include "mms_codec.h" +#include "mms_file_util.h" + +static +char* +mms_task_read_create_pdu_file( + const MMSConfig* config, + const char* id, + const char* message_id, + const char* to, + MMSReadStatus status) +{ + char* path = NULL; + char* dir = mms_message_dir(config, id); + int fd = mms_create_file(dir, MMS_READ_REC_IND_FILE, &path); + if (fd >= 0) { + MMSPdu* pdu = g_new0(MMSPdu, 1); + pdu->type = MMS_MESSAGE_TYPE_READ_REC_IND; + pdu->version = MMS_VERSION; + pdu->ri.rr_status = (status == MMS_READ_STATUS_DELETED) ? + MMS_MESSAGE_READ_STATUS_DELETED : MMS_MESSAGE_READ_STATUS_READ; + pdu->ri.msgid = g_strdup(message_id); + pdu->ri.to = g_strdup(to); + time(&pdu->ri.date); + if (!mms_message_encode(pdu, fd)) { + g_free(path); + path = NULL; + } + mms_message_free(pdu); + close(fd); + } + g_free(dir); + return path; +} + +/** + * Create MMS read report task + */ +MMSTask* +mms_task_read_new( + const MMSConfig* cfg, + MMSHandler* h, + const char* id, + const char* imsi, + const char* message_id, + const char* to, + MMSReadStatus rs) +{ + char* path = mms_task_read_create_pdu_file(cfg, id, message_id, to, rs); + if (path) { + MMSTask* task = mms_task_upload_new(cfg, h, "Read", id, imsi, path); + g_free(path); + return task; + } + return NULL; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_task_retrieve.c b/mms-lib/src/mms_task_retrieve.c new file mode 100644 index 0000000..e49a6e7 --- /dev/null +++ b/mms-lib/src/mms_task_retrieve.c @@ -0,0 +1,321 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_task.h" +#include "mms_connection.h" +#include "mms_file_util.h" +#include "mms_handler.h" +#include "mms_codec.h" +#include "mms_util.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_task_retrieve_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-task-retrieve"); + +/* Class definition */ +typedef MMSTaskClass MMSTaskRetrieveClass; +typedef struct mms_task_retrieve { + MMSTask task; + MMSHttpTransfer* tx; + char* uri; + char* transaction_id; + gulong got_chunk_signal_id; + guint bytes_received; + guint status_code; +} MMSTaskRetrieve; + +G_DEFINE_TYPE(MMSTaskRetrieve, mms_task_retrieve, MMS_TYPE_TASK); +#define MMS_TYPE_TASK_RETRIEVE (mms_task_retrieve_get_type()) +#define MMS_TASK_RETRIEVE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_TYPE_TASK_RETRIEVE, MMSTaskRetrieve)) + +#define mms_task_retrieve_state(t,rs) \ + mms_handler_message_receive_state_changed((t)->task.handler,\ + (t)->task.id, rs) + +static +void +mms_task_retrieve_got_chunk( + SoupMessage* message, + SoupBuffer* chunk, + MMSTaskRetrieve* retrieve); + +static +void +mms_task_retrieve_run( + MMSTask* task) +{ + mms_task_set_state(task, MMS_TASK_STATE_NEED_CONNECTION); +} + +static +void +mms_task_retrieve_finish_transfer( + MMSTaskRetrieve* retrieve) +{ + if (retrieve->tx) { + g_signal_handler_disconnect(retrieve->tx->message, + retrieve->got_chunk_signal_id); + retrieve->got_chunk_signal_id = 0; + mms_http_transfer_free(retrieve->tx); + retrieve->tx = NULL; + } +} + +static +void +mms_task_retrieve_got_chunk( + SoupMessage* message, + SoupBuffer* buf, + MMSTaskRetrieve* retrieve) +{ + retrieve->bytes_received += buf->length; + MMS_VERBOSE("%u bytes", retrieve->bytes_received); + if (retrieve->tx && + write(retrieve->tx->fd, buf->data, buf->length) != (int)buf->length) { + MMS_ERR("Write error: %s", strerror(errno)); + mms_task_retrieve_finish_transfer(retrieve); + mms_task_set_state(&retrieve->task, MMS_TASK_STATE_SLEEP); + } +} + +static +void +mms_task_retrieve_finished( + SoupSession* session, + SoupMessage* message, + gpointer user_data) +{ + MMSTaskRetrieve* retrieve = user_data; + MMS_ASSERT(retrieve->tx && (retrieve->tx->session == session)); + if (retrieve->tx && (retrieve->tx->session == session)) { + MMS_TASK_STATE next_state = MMS_TASK_STATE_SLEEP; + MMSTask* task = &retrieve->task; + const MMSConfig* config = task->config; + retrieve->status_code = message->status_code; + MMS_DEBUG("Retrieve status %u", retrieve->status_code); + mms_task_retrieve_finish_transfer(retrieve); + if (SOUP_STATUS_IS_SUCCESSFUL(retrieve->status_code)) { + char* file = mms_task_file(task, MMS_RETRIEVE_CONF_FILE); + + /* Content retrieved successfully */ + MMS_DEBUG("Retrieved %s", retrieve->uri); + next_state = MMS_TASK_STATE_DONE; + mms_task_retrieve_state(retrieve, MMS_RECEIVE_STATE_DECODING); + + /* Queue the decoding task */ + mms_task_queue_and_unref(task->delegate, + mms_task_decode_new(task->config, task->handler, task->id, + task->imsi, retrieve->transaction_id, file)); + + g_free(file); + } else { + + /* Will retry if this was an I/O error, otherwise we consider + * it a permanent failure */ + if (SOUP_STATUS_IS_TRANSPORT_ERROR(retrieve->status_code)) { + mms_task_retrieve_state(retrieve, MMS_RECEIVE_STATE_DEFERRED); + } else { + next_state = MMS_TASK_STATE_DONE; + MMS_WARN("Retrieve error %u", retrieve->status_code); + } + } + + if (!config->keep_temp_files) { + char* dir = mms_task_dir(task); + char* file = g_strconcat(dir, "/" MMS_RETRIEVE_CONF_FILE, NULL); + remove(file); + remove(dir); + g_free(file); + g_free(dir); + } + + /* Switch the state */ + mms_task_set_state(task, next_state); + } else { + MMS_VERBOSE_("ignoring stale completion message"); + } +} + +static +void +mms_task_retrieve_start( + MMSTaskRetrieve* retrieve, + MMSConnection* connection) +{ + MMSTask* task = &retrieve->task; + char* dir = mms_task_dir(task); + char* file = NULL; + int fd; + MMS_ASSERT(mms_connection_is_open(connection)); + + /* Cleanup any leftovers */ + mms_task_retrieve_finish_transfer(retrieve); + retrieve->bytes_received = 0; + + /* Create new temporary file */ + fd = mms_create_file(dir, MMS_RETRIEVE_CONF_FILE, &file); + if (fd >= 0) { + /* Set up the transfer */ + retrieve->tx = mms_http_transfer_new(task->config, + connection, "GET", retrieve->uri, fd); + if (retrieve->tx) { + /* Start the transfer */ + SoupMessage* message = retrieve->tx->message; + MMS_DEBUG("%s -> %s", retrieve->uri, file); + soup_message_body_set_accumulate(message->response_body, FALSE); + retrieve->got_chunk_signal_id = g_signal_connect(message, + "got-chunk", G_CALLBACK(mms_task_retrieve_got_chunk), + retrieve); + soup_session_queue_message(retrieve->tx->session, message, + mms_task_retrieve_finished, retrieve); + } + } + + if (retrieve->tx) { + mms_task_set_state(task, MMS_TASK_STATE_TRANSMITTING); + mms_task_retrieve_state(retrieve, MMS_RECEIVE_STATE_RECEIVING); + } else { + retrieve->status_code = SOUP_STATUS_NONE; + mms_task_set_state(task, MMS_TASK_STATE_DONE); + close(fd); + } + + g_free(file); + g_free(dir); +} + +static +void +mms_task_retrieve_transmit( + MMSTask* task, + MMSConnection* connection) +{ + if (task->state != MMS_TASK_STATE_TRANSMITTING) { + mms_task_retrieve_start(MMS_TASK_RETRIEVE(task), connection); + } +} + +static +void +mms_task_retrieve_cancel( + MMSTask* task) +{ + mms_task_retrieve_finish_transfer(MMS_TASK_RETRIEVE(task)); + MMS_TASK_CLASS(mms_task_retrieve_parent_class)->fn_cancel(task); +} + +static +void +mms_task_retrieve_network_unavailable( + MMSTask* task) +{ + mms_task_retrieve_finish_transfer(MMS_TASK_RETRIEVE(task)); + mms_task_set_state(task, MMS_TASK_STATE_SLEEP); +} + +/** + * First stage of deinitialization (release all references). + * May be called more than once in the lifetime of the object. + */ +static +void +mms_task_retrieve_dispose( + GObject* object) +{ + MMSTaskRetrieve* retrieve = MMS_TASK_RETRIEVE(object); + mms_task_retrieve_finish_transfer(retrieve); + G_OBJECT_CLASS(mms_task_retrieve_parent_class)->dispose(object); +} + +/** + * Final stage of deinitialization + */ +static +void +mms_task_retrieve_finalize( + GObject* object) +{ + MMSTaskRetrieve* retrieve = MMS_TASK_RETRIEVE(object); + if (!SOUP_STATUS_IS_SUCCESSFUL(retrieve->status_code)) { + mms_task_retrieve_state(retrieve, MMS_RECEIVE_STATE_DOWNLOAD_ERROR); + } + g_free(retrieve->uri); + g_free(retrieve->transaction_id); + G_OBJECT_CLASS(mms_task_retrieve_parent_class)->finalize(object); +} + +/** + * Per class initializer + */ +static +void +mms_task_retrieve_class_init( + MMSTaskRetrieveClass* klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + object_class->dispose = mms_task_retrieve_dispose; + object_class->finalize = mms_task_retrieve_finalize; + klass->fn_run = mms_task_retrieve_run; + klass->fn_cancel = mms_task_retrieve_cancel; + klass->fn_transmit = mms_task_retrieve_transmit; + klass->fn_network_unavailable = mms_task_retrieve_network_unavailable; +} + +/** + * Per instance initializer + */ +static +void +mms_task_retrieve_init( + MMSTaskRetrieve* retrieve) +{ + retrieve->status_code = SOUP_STATUS_CANCELLED; +} + +/* Create MMS retrieve task */ +MMSTask* +mms_task_retrieve_new( + const MMSConfig* config, + MMSHandler* handler, + const char* id, + const char* imsi, + const MMSPdu* pdu) +{ + const time_t now = time(NULL); + + MMS_ASSERT(pdu); + MMS_ASSERT(pdu->type == MMS_MESSAGE_TYPE_NOTIFICATION_IND); + MMS_ASSERT(pdu->transaction_id); + if (pdu->ni.expiry > now) { + MMSTaskRetrieve* retrieve = mms_task_alloc(MMS_TYPE_TASK_RETRIEVE, + config, handler, "Retrieve", id, imsi); + retrieve->task.deadline = pdu->ni.expiry; + retrieve->uri = g_strdup(pdu->ni.location); + retrieve->transaction_id = g_strdup(pdu->transaction_id); + return &retrieve->task; + } else { + MMS_ERR("Message already expired"); + } + return NULL; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_task_upload.c b/mms-lib/src/mms_task_upload.c new file mode 100644 index 0000000..62f9a64 --- /dev/null +++ b/mms-lib/src/mms_task_upload.c @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_task.h" +#include "mms_connection.h" +#include "mms_file_util.h" +#include "mms_util.h" +#include + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_task_upload_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-task-upload"); + +#define MMS_UPLOAD_MAX_CHUNK (2048) + +/* Class definition */ +typedef MMSTaskClass MMSTaskUploadClass; +typedef struct mms_task_upload { + MMSTask task; + MMSHttpTransfer* tx; + gulong wrote_headers_signal_id; + gulong wrote_chunk_signal_id; + gsize bytes_total; + gsize bytes_sent; + char* file; +} MMSTaskUpload; + +G_DEFINE_TYPE(MMSTaskUpload, mms_task_upload, MMS_TYPE_TASK); +#define MMS_TYPE_TASK_UPLOAD (mms_task_upload_get_type()) +#define MMS_TASK_UPLOAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_TYPE_TASK_UPLOAD, MMSTaskUpload)) + +static +void +mms_task_upload_finish_transfer( + MMSTaskUpload* up) +{ + if (up->tx) { + SoupMessage* message = up->tx->message; + g_signal_handler_disconnect(message, up->wrote_headers_signal_id); + g_signal_handler_disconnect(message, up->wrote_chunk_signal_id); + mms_http_transfer_free(up->tx); + up->wrote_headers_signal_id = 0; + up->wrote_chunk_signal_id = 0; + up->tx = NULL; + } +} + +static +void +mms_task_upload_finished( + SoupSession* session, + SoupMessage* msg, + gpointer user_data) +{ + MMSTaskUpload* up = user_data; + MMS_ASSERT(up->tx && (up->tx->session == session)); + if (up->tx && (up->tx->session == session)) { + MMS_TASK_STATE next_state; + MMSTask* task = &up->task; + MMS_DEBUG("Upload status %u", msg->status_code); + if (SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) { + next_state = MMS_TASK_STATE_DONE; + } else { + /* Will retry if this was an I/O error, otherwise we consider + * it a permanent failure */ + if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)) { + next_state = MMS_TASK_STATE_SLEEP; + } else { + next_state = MMS_TASK_STATE_DONE; + MMS_WARN("Upload failure %u", msg->status_code); + } + } + mms_task_set_state(task, next_state); + } else { + MMS_VERBOSE_("ignoring stale completion message"); + } +} + +static +void +mms_task_upload_write_next_chunk( + SoupMessage* msg, + MMSTaskUpload* up) +{ +#if MMS_LOG_VERBOSE + if (up->bytes_sent) MMS_VERBOSE("%u bytes", (guint)up->bytes_sent); +#endif + MMS_ASSERT(up->tx && up->tx->message == msg); + if (up->tx && + up->tx->message == msg && + up->bytes_total > up->bytes_sent) { + int nbytes; + void* chunk; + gsize len = up->bytes_total - up->bytes_sent; + if (len > MMS_UPLOAD_MAX_CHUNK) len = MMS_UPLOAD_MAX_CHUNK; + chunk = g_malloc(len); + nbytes = read(up->tx->fd, chunk, len); + if (nbytes > 0) { + up->bytes_sent += nbytes; + soup_message_body_append_take(msg->request_body, chunk, nbytes); + return; + } + } + soup_message_body_complete(msg->request_body); +} + +static +gboolean +mms_task_upload_start( + MMSTaskUpload* up, + MMSConnection* connection) +{ + int fd; + MMS_ASSERT(mms_connection_is_open(connection)); + mms_task_upload_finish_transfer(up); + up->bytes_sent = 0; + fd = open(up->file, O_RDONLY); + if (fd >= 0) { + struct stat st; + int err = fstat(fd, &st); + if (!err) { + /* Set up the transfer */ + up->bytes_total = st.st_size; + up->tx = mms_http_transfer_new(up->task.config, connection, + "POST", connection->mmsc, fd); + if (up->tx) { + /* Headers */ + SoupMessage* msg = up->tx->message; + soup_message_headers_set_content_type( + msg->request_headers, + MMS_CONTENT_TYPE, NULL); + soup_message_headers_set_content_length( + msg->request_headers, + st.st_size); + + /* Connect the signals */ + up->wrote_headers_signal_id = + g_signal_connect(msg, "wrote_headers", + G_CALLBACK(mms_task_upload_write_next_chunk), up); + up->wrote_chunk_signal_id = + g_signal_connect(msg, "wrote_chunk", + G_CALLBACK(mms_task_upload_write_next_chunk), up); + + /* Start the transfer */ + MMS_DEBUG("%s -> %s (%u bytes)", up->file, + connection->mmsc, (guint)up->bytes_total); + soup_session_queue_message(up->tx->session, msg, + mms_task_upload_finished, up); + return TRUE; + } + } else { + MMS_ERR("Can't stat %s: %s", up->file, strerror(errno)); + } + close(fd); + } else { + MMS_WARN("Failed to open %s: %s", up->file, strerror(errno)); + } + return FALSE; +} + +static +void +mms_task_upload_transmit( + MMSTask* task, + MMSConnection* conn) +{ + if (task->state != MMS_TASK_STATE_TRANSMITTING) { + mms_task_set_state(task, + mms_task_upload_start(MMS_TASK_UPLOAD(task), conn) ? + MMS_TASK_STATE_TRANSMITTING : MMS_TASK_STATE_DONE); + } +} + +static +void +mms_task_upload_run( + MMSTask* task) +{ + mms_task_set_state(task, MMS_TASK_STATE_NEED_CONNECTION); +} + +static +void +mms_task_upload_network_unavailable( + MMSTask* task) +{ + MMSTaskUpload* up = MMS_TASK_UPLOAD(task); + mms_task_upload_finish_transfer(up); + mms_task_set_state(task, MMS_TASK_STATE_SLEEP); +} + +static +void +mms_task_upload_cancel( + MMSTask* task) +{ + mms_task_upload_finish_transfer(MMS_TASK_UPLOAD(task)); + MMS_TASK_CLASS(mms_task_upload_parent_class)->fn_cancel(task); +} + +/** + * First stage of deinitialization (release all references). + * May be called more than once in the lifetime of the object. + */ +static +void +mms_task_upload_dispose( + GObject* object) +{ + MMSTaskUpload* up = MMS_TASK_UPLOAD(object); + mms_task_upload_finish_transfer(up); + G_OBJECT_CLASS(mms_task_upload_parent_class)->dispose(object); +} + +/** + * Final stage of deinitialization + */ +static +void +mms_task_upload_finalize( + GObject* object) +{ + MMSTaskUpload* up = MMS_TASK_UPLOAD(object); + if (!up->task.config->keep_temp_files) { + mms_remove_file_and_dir(up->file); + } + g_free(up->file); + G_OBJECT_CLASS(mms_task_upload_parent_class)->finalize(object); +} + +/** + * Per class initializer + */ +static +void +mms_task_upload_class_init( + MMSTaskUploadClass* klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + klass->fn_run = mms_task_upload_run; + klass->fn_transmit = mms_task_upload_transmit; + klass->fn_network_unavailable = mms_task_upload_network_unavailable; + klass->fn_cancel = mms_task_upload_cancel; + object_class->dispose = mms_task_upload_dispose; + object_class->finalize = mms_task_upload_finalize; +} + +/** + * Per instance initializer + */ +static +void +mms_task_upload_init( + MMSTaskUpload* up) +{ +} + +/** + * Create MMS upload task + */ +MMSTask* +mms_task_upload_new( + const MMSConfig* config, + MMSHandler* handler, + const char* name, + const char* id, + const char* imsi, + const char* file) +{ + MMSTaskUpload* up = mms_task_alloc(MMS_TYPE_TASK_UPLOAD, + config, handler, name, id, imsi); + up->file = g_strdup(file); + MMS_ASSERT(g_file_test(up->file, G_FILE_TEST_IS_REGULAR)); + return &up->task; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_util.c b/mms-lib/src/mms_util.c new file mode 100644 index 0000000..bd72dcf --- /dev/null +++ b/mms-lib/src/mms_util.c @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_util.h" +#include "mms_lib_util.h" +#include "mms_connection.h" +#include "mms_codec.h" + +#ifndef _WIN32 +# include +# include +# include +#endif + +/* Appeared in libsoup somewhere between 2.41.5 and 2.41.90 */ +#ifndef SOUP_SESSION_LOCAL_ADDRESS +# define SOUP_SESSION_LOCAL_ADDRESS "local-address" +#endif + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_util_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-util"); + +/** + * Strips leading spaces and "/TYPE=" suffix from the string. + */ +char* +mms_strip_address_type( + char* address) +{ + if (address) { + char* type = g_strrstr(g_strstrip(address), "/TYPE="); + if (type) *type = 0; + } + return address; +} + +/** + * Splits comma-separated list of addresses into an array of string pointers. + * Strips "/TYPE=" suffix from each address. Caller needs to deallocate the + * returned list with g_strfreev. + */ +char** +mms_split_address_list( + const char* addres_list) +{ + char** list = NULL; + if (addres_list && addres_list[0]) { + int i; + list = g_strsplit(addres_list, ",", 0); + for (i=0; list[i]; i++) { + list[i] = mms_strip_address_type(list[i]); + } + } else { + list = g_new(char*, 1); + list[0] = NULL; + } + return list; +} + +/** + * Allocates and decodes WAP push PDU. Returns NULL if decoding fails. + */ +MMSPdu* +mms_decode_bytes( + GBytes* bytes) +{ + MMSPdu* pdu = NULL; + if (bytes) { + gsize len = 0; + const guint8* data = g_bytes_get_data(bytes, &len); + pdu = g_new0(MMSPdu, 1); + if (!mms_message_decode(data, len, pdu)) { + mms_message_free(pdu); + pdu = NULL; + } + } + return pdu; +} + +/** + * Utility to converts string URI into SoupURI + */ +SoupURI* +mms_parse_http_uri( + const char* raw_uri) +{ + SoupURI* uri = NULL; + if (raw_uri) { + static const char* http = "http://"; + const char* uri_to_parse; + char* tmp_uri = NULL; + if (g_str_has_prefix(raw_uri, http)) { + uri_to_parse = raw_uri; + } else { + uri_to_parse = tmp_uri = g_strconcat(http, raw_uri, NULL); + } + uri = soup_uri_new(uri_to_parse); + if (!uri) { + MMS_ERR("Could not parse %s as a URI", uri_to_parse); + } + g_free(tmp_uri); + } + return uri; +} + +/** + * Sets up new SOUP session + */ +static +SoupSession* +mms_create_http_session( + const MMSConfig* cfg, + MMSConnection* conn) +{ + SoupSession* session = NULL; + + /* Determine address of the MMS interface */ + if (conn->netif && conn->netif[0]) { +#ifndef _WIN32 + struct ifreq ifr; + int fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd >= 0) { + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, conn->netif, IFNAMSIZ-1); + if (ioctl(fd, SIOCGIFADDR, &ifr) >= 0) { + SoupAddress* local_address = soup_address_new_from_sockaddr( + &ifr.ifr_addr, sizeof(ifr.ifr_addr)); +# if MMS_LOG_DEBUG + char buf[128]; + int af = ifr.ifr_addr.sa_family; + buf[0] = 0; + if (af == AF_INET) { + struct sockaddr_in* addr = (void*)&ifr.ifr_addr; + inet_ntop(af, &addr->sin_addr, buf, sizeof(buf)); + } else if (af == AF_INET6) { + struct sockaddr_in6* addr = (void*)&ifr.ifr_addr; + inet_ntop(af, &addr->sin6_addr, buf, sizeof(buf)); + } else { + snprintf(buf, sizeof(buf), "

", af); + } + buf[sizeof(buf)-1] = 0; + MMS_DEBUG("MMS interface address %s", buf); +# endif /* MMS_LOG_DEBUG */ + MMS_ASSERT(local_address); + session = soup_session_async_new_with_options( + SOUP_SESSION_LOCAL_ADDRESS, local_address, + NULL); + g_object_unref(local_address); + } else { + MMS_ERR("Failed to query IP address of %s: %s", + conn->netif, strerror(errno)); + } + close(fd); + } +#endif /* _WIN32 */ + } else { + MMS_WARN("MMS interface is unknown"); + } + + if (!session) { + /* No local address so bind to any interface */ + session = soup_session_async_new(); + } + + if (conn->mmsproxy && conn->mmsproxy[0]) { + SoupURI* proxy_uri = mms_parse_http_uri(conn->mmsproxy); + if (proxy_uri) { + MMS_DEBUG("MMS proxy %s", conn->mmsproxy); + g_object_set(session, SOUP_SESSION_PROXY_URI, proxy_uri, NULL); + soup_uri_free(proxy_uri); + } + } + + if (cfg->user_agent) { + g_object_set(session, SOUP_SESSION_USER_AGENT, cfg->user_agent, NULL); + } + + return session; +} + +/** + * Create HTTP transfer context. + */ +MMSHttpTransfer* +mms_http_transfer_new( + const MMSConfig* config, + MMSConnection* connection, + const char* method, + const char* uri, + int fd) +{ + SoupURI* soup_uri = soup_uri_new(uri); + if (soup_uri) { + MMSHttpTransfer* tx = g_new(MMSHttpTransfer, 1); + tx->session = mms_create_http_session(config, connection); + tx->message = soup_message_new_from_uri(method, soup_uri); + tx->connection = mms_connection_ref(connection); + tx->fd = fd; + soup_uri_free(soup_uri); + soup_message_set_flags(tx->message, + SOUP_MESSAGE_NO_REDIRECT | + SOUP_MESSAGE_NEW_CONNECTION); + /* We shouldn't need this extra reference but otherwise + * SoupMessage gets deallocated too early. Not sure why. */ + g_object_ref(tx->message); + return tx; + } + return NULL; +} + +/** + * Deallocates HTTP transfer context created by mms_http_transfer_new() + */ +void +mms_http_transfer_free( + MMSHttpTransfer* tx) +{ + if (tx) { + soup_session_abort(tx->session); + g_object_unref(tx->session); + g_object_unref(tx->message); + mms_connection_unref(tx->connection); + close(tx->fd); + g_free(tx); + } +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/src/mms_util.h b/mms-lib/src/mms_util.h new file mode 100644 index 0000000..ae9a3fa --- /dev/null +++ b/mms-lib/src/mms_util.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_UTIL_H +#define JOLLA_MMS_UTIL_H + +#include "mms_lib_types.h" +#include + +typedef struct mms_http_transfer { + MMSConnection* connection; + SoupSession* session; + SoupMessage* message; + int fd; +} MMSHttpTransfer; + +char* +mms_strip_address_type( + char* address); + +char** +mms_split_address_list( + const char* addres_list); + +MMSPdu* +mms_decode_bytes( + GBytes* bytes); + +SoupURI* +mms_parse_http_uri( + const char* raw_uri); + +MMSHttpTransfer* +mms_http_transfer_new( + const MMSConfig* config, + MMSConnection* connection, + const char* method, + const char* uri, + int fd); + +void +mms_http_transfer_free( + MMSHttpTransfer* tx); + +/* NULL-resistant variant of g_strstrip */ +G_INLINE_FUNC char* mms_strip(char* str) + { return str ? g_strstrip(str) : NULL; } + +#endif /* JOLLA_MMS_UTIL_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/Makefile b/mms-lib/test/Makefile new file mode 100644 index 0000000..2506b5c --- /dev/null +++ b/mms-lib/test/Makefile @@ -0,0 +1,8 @@ +# -*- Mode: makefile-gmake -*- + +all: +%: + @$(MAKE) -C mms_codec $* + @$(MAKE) -C read_report $* + @$(MAKE) -C retrieve $* + @$(MAKE) -C retrieve_cancel $* diff --git a/mms-lib/test/common/Makefile b/mms-lib/test/common/Makefile new file mode 100644 index 0000000..99d10f9 --- /dev/null +++ b/mms-lib/test/common/Makefile @@ -0,0 +1,163 @@ +# -*- Mode: makefile-gmake -*- + +.PHONY: all debug release clean test test_banner +.PHONY: mms_lib_debug_lib mms_lib_release_lib + +# +# Real test makefile defines EXE and SRC and includes this one. +# + +ifndef SRC +${error SRC not defined} +endif + +ifndef EXE +${error EXE not defined} +endif + +# +# Required packages +# +LIB_PKGS = libwspcodec libsoup-2.4 glib-2.0 +PKGS = $(LIB_PKGS) + +# +# Default target +# + +all: debug release + +# +# Directories +# + +SRC_DIR = . +COMMON_DIR = ../common +BUILD_DIR = build +DEBUG_BUILD_DIR = $(BUILD_DIR)/debug +RELEASE_BUILD_DIR = $(BUILD_DIR)/release + +# +# Code coverage +# + +ifndef GCOV +GCOV = 0 +endif + +ifneq ($(GCOV),0) +BASE_FLAGS += --coverage +endif + +# +# mms-lib +# + +MMS_LIB_LIB = libmms.a +MMS_LIB_DIR = ../.. +MMS_LIB_BUILD_DIR = $(MMS_LIB_DIR)/build +MMS_LIB_DEBUG_LIB = $(MMS_LIB_BUILD_DIR)/debug/$(MMS_LIB_LIB) +MMS_LIB_RELEASE_LIB = $(MMS_LIB_BUILD_DIR)/release/$(MMS_LIB_LIB) +MMS_LIB_MAKE = $(MAKE) --no-print-directory -C $(MMS_LIB_DIR) GCOV=$(GCOV) + +# +# Tools and flags +# + +CC = $(CROSS_COMPILE)gcc +LD = $(CC) +DEBUG_FLAGS = $(BASE_FLAGS) -g +RELEASE_FLAGS = $(BASE_FLAGS) -O2 +DEBUG_DEFS = -DDEBUG +RELEASE_DEFS = +WARNINGS = -Wall +LIBS = $(shell pkg-config --libs $(LIB_PKGS)) +CFLAGS = $(shell pkg-config --cflags $(PKGS)) -I$(MMS_LIB_DIR)/include \ + -I$(MMS_LIB_DIR)/src -I$(COMMON_DIR) -MMD + +DEBUG_CFLAGS = $(WARNINGS) $(DEBUG_FLAGS) $(DEBUG_DEFS) $(CFLAGS) +RELEASE_CFLAGS = $(WARNINGS) $(RELEASE_FLAGS) $(RELEASE_DEFS) $(CFLAGS) +DEBUG_LIBS = $(MMS_LIB_DEBUG_LIB) $(LIBS) +RELEASE_LIBS = $(MMS_LIB_RELEASE_LIB) $(LIBS) + +# +# Files +# + +DEBUG_OBJS = \ + $(SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) \ + $(COMMON_SRC:%.c=$(DEBUG_BUILD_DIR)/%.o) +RELEASE_OBJS = \ + $(SRC:%.c=$(RELEASE_BUILD_DIR)/%.o) \ + $(COMMON_SRC:%.c=$(RELEASE_BUILD_DIR)/%.o) + +# +# Dependencies +# + +DEBUG_DEPS = mms_lib_debug_lib +RELEASE_DEPS = mms_lib_release_lib +DEBUG_EXE_DEPS = $(MMS_LIB_DEBUG_LIB) $(DEBUG_BUILD_DIR) +RELEASE_EXE_DEPS = $(MMS_LIB_RELEASE_LIB) $(RELEASE_BUILD_DIR) +DEPS = $(DEBUG_OBJS:%.o=%.d) $(RELEASE_OBJS:%.o=%.d) +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(DEPS)),) +-include $(DEPS) +endif +endif + +# +# Rules +# + +DEBUG_EXE = $(DEBUG_BUILD_DIR)/$(EXE) +RELEASE_EXE = $(RELEASE_BUILD_DIR)/$(EXE) + +debug: $(DEBUG_DEPS) $(DEBUG_EXE) + +release: $(RELEASE_DEPS) $(RELEASE_EXE) + +clean: + $(MAKE) -w -C $(MMS_LIB_DIR) clean + rm -fr $(BUILD_DIR) $(SRC_DIR)/*~ + +test_banner: + @echo "===========" $(EXE) "=========== " + +test: test_banner debug + @$(DEBUG_EXE) + +mms_lib_debug_lib: + @$(MMS_LIB_MAKE) debug + +mms_lib_release_lib: + @$(MMS_LIB_MAKE) release + +$(MMS_LIB_DEBUG_LIB): mms_lib_debug_lib + +$(MMS_LIB_RELEASE_LIB): mms_lib_release_lib + +$(DEBUG_BUILD_DIR): + mkdir -p $@ + +$(RELEASE_BUILD_DIR): + mkdir -p $@ + +$(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 : $(COMMON_DIR)/%.c + $(CC) -c $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ + +$(RELEASE_BUILD_DIR)/%.o : $(COMMON_DIR)/%.c + $(CC) -c $(RELEASE_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ + +$(DEBUG_EXE): $(DEBUG_EXE_DEPS) $(DEBUG_OBJS) + $(LD) $(DEBUG_FLAGS) $(DEBUG_OBJS) $(DEBUG_LIBS) -o $@ + +$(RELEASE_EXE): $(RELEASE_EXE_DEPS) $(RELEASE_OBJS) + $(LD) $(RELEASE_FLAGS) $(RELEASE_OBJS) $(RELEASE_LIBS) -o $@ + strip $@ diff --git a/mms-lib/test/common/test_connection.c b/mms-lib/test/common/test_connection.c new file mode 100644 index 0000000..0828e67 --- /dev/null +++ b/mms-lib/test/common/test_connection.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_connection.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_connection_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-connection-test"); + +typedef MMSConnectionClass MMSConnectionTestClass; +typedef MMSConnection MMSConnectionTest; + +G_DEFINE_TYPE(MMSConnectionTest, mms_connection_test, MMS_TYPE_CONNECTION); +#define MMS_TYPE_CONNECTION_TEST (mms_connection_test_get_type()) +#define MMS_CONNECTION_TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_TYPE_CONNECTION_TEST, MMSConnectionTest)) + +static +gboolean +mms_connection_test_set_state( + MMSConnection* test, + MMS_CONNECTION_STATE state) +{ + if (test->state != state && test->state != MMS_CONNECTION_STATE_CLOSED) { + test->state = state; + if (test->delegate && + test->delegate->fn_connection_state_changed) { + test->delegate->fn_connection_state_changed(test->delegate, test); + } + } + return TRUE; +} + +static +gboolean +test_connection_test_open( + void* param) +{ + MMSConnectionTest* test = param; + mms_connection_test_set_state(test, test->netif ? + MMS_CONNECTION_STATE_OPEN : MMS_CONNECTION_ERROR_FAILED); + mms_connection_unref(test); + return FALSE; +} + +MMSConnection* +mms_connection_test_new( + const char* imsi, + unsigned short port) +{ + MMSConnectionTest* test = g_object_new(MMS_TYPE_CONNECTION_TEST, NULL); + test->imsi = g_strdup(imsi); + test->mmsc = g_strdup("http://mmsc"); + if (port) { + test->mmsproxy = g_strdup_printf("127.0.0.1:%hu", port); + test->netif = g_strdup("lo"); + } + test->state = MMS_CONNECTION_STATE_OPENING; + g_idle_add(test_connection_test_open, mms_connection_ref(test)); + return test; +} + +static +void +mms_connection_test_close( + MMSConnection* test) +{ + mms_connection_test_set_state(test, MMS_CONNECTION_STATE_CLOSED); +} + +/** + * Per class initializer + */ +static +void +mms_connection_test_class_init( + MMSConnectionTestClass* klass) +{ + klass->fn_close = mms_connection_test_close; +} + +/** + * Per instance initializer + */ +static +void +mms_connection_test_init( + MMSConnectionTest* conn) +{ + MMS_VERBOSE_("%p", conn); +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/common/test_connection.h b/mms-lib/test/common/test_connection.h new file mode 100644 index 0000000..3c432a6 --- /dev/null +++ b/mms-lib/test/common/test_connection.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_CONNECTION_H +#define TEST_CONNECTION_H + +#include "mms_connection.h" + +MMSConnection* +mms_connection_test_new( + const char* imsi, + unsigned short port); + +#endif /* TEST_CONNECTION_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/common/test_connman.c b/mms-lib/test/common/test_connman.c new file mode 100644 index 0000000..c4212ad --- /dev/null +++ b/mms-lib/test/common/test_connman.c @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_connman.h" +#include "test_connection.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_connman_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-connman-test"); + +typedef MMSConnManClass MMSConnManTestClass; +typedef struct mms_connman_test { + MMSConnMan cm; + MMSConnection* connection; + unsigned short port; +} MMSConnManTest; + +G_DEFINE_TYPE(MMSConnManTest, mms_connman_test, MMS_TYPE_CONNMAN); +#define MMS_TYPE_CONNMAN_TEST (mms_connman_test_get_type()) +#define MMS_CONNMAN_TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_TYPE_CONNMAN_TEST, MMSConnManTest)) + +void +mms_connman_test_set_port( + MMSConnMan* cm, + unsigned short port) +{ + MMSConnManTest* test = MMS_CONNMAN_TEST(cm); + test->port = port; +} + +void +mms_connman_test_close_connection( + MMSConnMan* cm) +{ + MMSConnManTest* test = MMS_CONNMAN_TEST(cm); + if (test->connection) { + MMS_DEBUG("Closing connection..."); + mms_connection_close(test->connection); + mms_connection_unref(test->connection); + test->connection = NULL; + } +} + +static +MMSConnection* +mms_connman_test_open_connection( + MMSConnMan* cm, + const char* imsi, + gboolean user_request) +{ + MMSConnManTest* test = MMS_CONNMAN_TEST(cm); + mms_connman_test_close_connection(cm); + if (test->port) { + test->connection = mms_connection_test_new(imsi, test->port); + return mms_connection_ref(test->connection); + } else { + return NULL; + } +} + +static +void +mms_connman_test_dispose( + GObject* object) +{ + MMSConnManTest* test = MMS_CONNMAN_TEST(object); + mms_connman_test_close_connection(&test->cm); +} + +static +void +mms_connman_test_class_init( + MMSConnManTestClass* klass) +{ + klass->fn_open_connection = mms_connman_test_open_connection; + G_OBJECT_CLASS(klass)->dispose = mms_connman_test_dispose; +} + +static +void +mms_connman_test_init( + MMSConnManTest* cm) +{ +} + +MMSConnMan* +mms_connman_test_new() +{ + return g_object_new(MMS_TYPE_CONNMAN_TEST,NULL); +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/common/test_connman.h b/mms-lib/test/common/test_connman.h new file mode 100644 index 0000000..b2e3103 --- /dev/null +++ b/mms-lib/test/common/test_connman.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_CONNMAN_H +#define TEST_CONNMAN_H + +#include "mms_connman.h" + +MMSConnMan* +mms_connman_test_new(void); + +void +mms_connman_test_set_port( + MMSConnMan* cm, + unsigned short port); + +void +mms_connman_test_close_connection( + MMSConnMan* cm); + +#endif /* TEST_CONNMAN_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/common/test_handler.c b/mms-lib/test/common/test_handler.c new file mode 100644 index 0000000..9bbc602 --- /dev/null +++ b/mms-lib/test/common/test_handler.c @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_handler.h" +#include "mms_dispatcher.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_handler_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-handler-test"); + +/* Class definition */ +typedef MMSHandlerClass MMSHandlerTestClass; +typedef struct mms_handler_test { + MMSHandler handler; + unsigned int last_id; + GHashTable* recs; + MMSDispatcher* dispatcher; +} MMSHandlerTest; + +typedef struct mms_handler_record { + char* id; + char* imsi; + MMSMessage* msg; + GBytes* data; + MMS_RECEIVE_STATE receive_state; + guint receive_message_id; + MMSDispatcher* dispatcher; +} MMSHandlerRecord; + +G_DEFINE_TYPE(MMSHandlerTest, mms_handler_test, MMS_TYPE_HANDLER); +#define MMS_TYPE_HANDLER_TEST (mms_handler_test_get_type()) +#define MMS_HANDLER_TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + MMS_TYPE_HANDLER_TEST, MMSHandlerTest)) + +MMS_RECEIVE_STATE +mms_handler_test_receive_state( + MMSHandler* handler, + const char* id) +{ + MMSHandlerTest* test = MMS_HANDLER_TEST(handler); + MMSHandlerRecord* rec = NULL; + if (id) { + rec = g_hash_table_lookup(test->recs, id); + } else if (g_hash_table_size(test->recs) == 1) { + GList* values = g_hash_table_get_values(test->recs); + rec = g_list_first(values)->data; + g_list_free(values); + } + return rec ? rec->receive_state : MMS_RECEIVE_STATE_INVALID; +} + +static +void +mms_handler_test_receive_pending_check( + gpointer key, + gpointer value, + gpointer user_data) +{ + MMSHandlerRecord* rec = value; + gboolean* pending = user_data; + if (rec->receive_message_id) *pending = TRUE; +} + +gboolean +mms_handler_test_receive_pending( + MMSHandler* handler, + const char* id) +{ + MMSHandlerTest* test = MMS_HANDLER_TEST(handler); + MMSHandlerRecord* rec = NULL; + if (id) { + rec = g_hash_table_lookup(test->recs, id); + return rec && rec->receive_message_id; + } else { + gboolean pending = FALSE; + g_hash_table_foreach(test->recs, + mms_handler_test_receive_pending_check, &pending); + return pending; + } +} + +static +void +mms_handler_test_hash_remove_record( + gpointer data) +{ + MMSHandlerRecord* rec = data; + if (rec->receive_message_id) { + g_source_remove(rec->receive_message_id); + rec->receive_message_id = 0; + } + mms_dispatcher_unref(rec->dispatcher); + mms_message_unref(rec->msg); + g_bytes_unref(rec->data); + g_free(rec->imsi); + g_free(rec->id); + g_free(rec); +} + +static +gboolean +mms_handler_test_receive( + gpointer data) +{ + MMSHandlerRecord* rec = data; + MMSDispatcher* disp = rec->dispatcher; + MMS_ASSERT(rec->receive_message_id); + MMS_ASSERT(rec->dispatcher); + MMS_DEBUG("Initiating receive of message %s", rec->id); + rec->receive_message_id = 0; + rec->dispatcher = NULL; + mms_dispatcher_receive_message(disp, rec->id, rec->imsi, TRUE, rec->data); + mms_dispatcher_start(disp); + mms_dispatcher_unref(disp); + return FALSE; +} + +static +char* +mms_handler_test_message_notify( + MMSHandler* handler, + const char* imsi, + const char* from, + const char* subj, + time_t expiry, + GBytes* data) +{ + MMSHandlerTest* test = MMS_HANDLER_TEST(handler); + MMSHandlerRecord* rec = g_new0(MMSHandlerRecord, 1); + unsigned int rec_id = (++test->last_id); + rec->id = g_strdup_printf("%u", rec_id); + rec->imsi = g_strdup(imsi); + rec->receive_state = MMS_RECEIVE_STATE_INVALID; + rec->data = g_bytes_ref(data); + MMS_DEBUG("Push %s imsi=%s from=%s subj=%s", rec->id, imsi, from, subj); + g_hash_table_replace(test->recs, rec->id, rec); + if (test->dispatcher) { + rec->receive_message_id = g_idle_add(mms_handler_test_receive, rec); + rec->dispatcher = mms_dispatcher_ref(test->dispatcher); + return g_strdup(""); + } else { + return g_strdup(rec->id); + } +} + +static +gboolean +mms_handler_test_message_received( + MMSHandler* handler, + MMSMessage* msg) +{ + MMSHandlerTest* test = MMS_HANDLER_TEST(handler); + MMSHandlerRecord* rec = g_hash_table_lookup(test->recs, msg->id); + MMS_DEBUG("Message %s from=%s subj=%s", msg->id, msg->from, msg->subject); + MMS_ASSERT(rec); + if (rec) { + mms_message_unref(rec->msg); + rec->msg = mms_message_ref(msg); + return TRUE; + } else { + return FALSE; + } +} + +static +gboolean +mms_handler_test_message_receive_state_changed( + MMSHandler* handler, + const char* id, + MMS_RECEIVE_STATE state) +{ + MMSHandlerTest* test = MMS_HANDLER_TEST(handler); + MMSHandlerRecord* rec = g_hash_table_lookup(test->recs, id); + if (rec) { + rec->receive_state = state; + MMS_DEBUG("Message %s state %d", id, state); + return TRUE; + } else { + MMS_ERR("Invalid message id %s", id); + return FALSE; + } +} + +void +mms_handler_test_finalize( + GObject* object) +{ + MMSHandlerTest* test = MMS_HANDLER_TEST(object); + mms_dispatcher_unref(test->dispatcher); + g_hash_table_remove_all(test->recs); + g_hash_table_unref(test->recs); + G_OBJECT_CLASS(mms_handler_test_parent_class)->finalize(object); +} + +static +void +mms_handler_test_class_init( + MMSHandlerTestClass* klass) +{ + G_OBJECT_CLASS(klass)->finalize = mms_handler_test_finalize; + klass->fn_message_notify = mms_handler_test_message_notify; + klass->fn_message_received = mms_handler_test_message_received; + klass->fn_message_receive_state_changed = + mms_handler_test_message_receive_state_changed; +} + +static +void +mms_handler_test_init( + MMSHandlerTest* test) +{ + test->recs = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, mms_handler_test_hash_remove_record); +} + +MMSHandler* +mms_handler_test_new() +{ + return g_object_new(MMS_TYPE_HANDLER_TEST, NULL); +} + +void +mms_handler_test_defer_receive( + MMSHandler* handler, + MMSDispatcher* dispatcher) +{ + MMSHandlerTest* test = MMS_HANDLER_TEST(handler); + mms_dispatcher_unref(test->dispatcher); + test->dispatcher = mms_dispatcher_ref(dispatcher); +} + +void +mms_handler_test_reset( + MMSHandler* handler) +{ + MMSHandlerTest* test = MMS_HANDLER_TEST(handler); + g_hash_table_remove_all(test->recs); + mms_dispatcher_unref(test->dispatcher); + test->dispatcher = NULL; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/common/test_handler.h b/mms-lib/test/common/test_handler.h new file mode 100644 index 0000000..c0e0541 --- /dev/null +++ b/mms-lib/test/common/test_handler.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_HANDLER_H +#define TEST_HANDLER_H + +#include "mms_handler.h" + +MMSHandler* +mms_handler_test_new(void); + +MMS_RECEIVE_STATE +mms_handler_test_receive_state( + MMSHandler* handler, + const char* id); + +gboolean +mms_handler_test_receive_pending( + MMSHandler* handler, + const char* id); + +void +mms_handler_test_defer_receive( + MMSHandler* handler, + MMSDispatcher* dispatcher); + +void +mms_handler_test_reset( + MMSHandler* handler); + +#endif /* TEST_HANDLER_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/common/test_http.c b/mms-lib/test/common/test_http.c new file mode 100644 index 0000000..b76f70c --- /dev/null +++ b/mms-lib/test/common/test_http.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_http.h" + +#include "mms_log.h" + +#include + +/* A single HTTP transaction */ +struct test_http { + gint ref_count; + SoupServer* server; + GMappedFile* resp_file; + GBytes* req_bytes; + int resp_status; + char* resp_content_type; +}; + +static +void +test_http_callback( + SoupServer* server, + SoupMessage* msg, + const char* path, + GHashTable* query, + SoupClientContext* context, + gpointer data) +{ + char* uri = soup_uri_to_string(soup_message_get_uri (msg), FALSE); + MMS_VERBOSE("%s %s HTTP/1.%d", msg->method, uri, + soup_message_get_http_version(msg)); + g_free(uri); + if (msg->method == SOUP_METHOD_CONNECT) { + soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED); + } else { + TestHttp* http = data; + if (msg->request_body->length) { + SoupBuffer* request = soup_message_body_flatten(msg->request_body); + if (http->req_bytes) g_bytes_unref(http->req_bytes); + http->req_bytes = g_bytes_new_with_free_func(request->data, + request->length, (GDestroyNotify)soup_buffer_free, request); + } + soup_message_set_status(msg, http->resp_status); + soup_message_headers_set_content_type(msg->response_headers, + http->resp_content_type ? http->resp_content_type : "text/plain", + NULL); + soup_message_headers_append(msg->response_headers, + "Accept-Ranges", "bytes"); + soup_message_headers_append(msg->response_headers, + "Connection", "close"); + if (http->resp_file) { + soup_message_headers_set_content_length(msg->response_headers, + g_mapped_file_get_length(http->resp_file)); + soup_message_body_append(msg->response_body, SOUP_MEMORY_TEMPORARY, + g_mapped_file_get_contents(http->resp_file), + g_mapped_file_get_length(http->resp_file)); + } else { + soup_message_headers_set_content_length(msg->response_headers, 0); + } + } + soup_message_body_complete(msg->request_body); +} + +guint +test_http_get_port( + TestHttp* http) +{ + return soup_server_get_port(http->server); +} + +GBytes* +test_http_get_post_data( + TestHttp* http) +{ + return http->req_bytes; +} + +void +test_http_close( + TestHttp* http) +{ + soup_server_quit(http->server); +} + +TestHttp* +test_http_new( + GMappedFile* resp_file, + const char* resp_content_type, + int resp_status) +{ + TestHttp* http = g_new0(TestHttp, 1); + http->ref_count = 1; + if (resp_file) { + http->resp_file = g_mapped_file_ref(resp_file); + http->resp_content_type = g_strdup(resp_content_type); + } + http->resp_status = resp_status; + http->server = g_object_new(SOUP_TYPE_SERVER, NULL); + MMS_DEBUG("Listening on port %hu", soup_server_get_port(http->server)); + soup_server_add_handler(http->server, NULL, test_http_callback, http, NULL); + soup_server_run_async(http->server); + return http; +} + +TestHttp* +test_http_ref( + TestHttp* http) +{ + if (http) { + MMS_ASSERT(http->ref_count > 0); + g_atomic_int_inc(&http->ref_count); + } + return http; +} + +void +test_http_unref( + TestHttp* http) +{ + if (http) { + MMS_ASSERT(http->ref_count > 0); + if (g_atomic_int_dec_and_test(&http->ref_count)) { + test_http_close(http); + if (http->resp_file) g_mapped_file_unref(http->resp_file); + if (http->req_bytes) g_bytes_unref(http->req_bytes); + g_object_unref(http->server); + g_free(http->resp_content_type); + g_free(http); + } + } +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/common/test_http.h b/mms-lib/test/common/test_http.h new file mode 100644 index 0000000..c0af890 --- /dev/null +++ b/mms-lib/test/common/test_http.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_HTTP_H +#define TEST_HTTP_H + +#include + +/* Local HTTP server for emulating MMSC */ +typedef struct test_http TestHttp; + +TestHttp* +test_http_new( + GMappedFile* get_file, + const char* resp_content_type, + int resp_status); + +TestHttp* +test_http_ref( + TestHttp* http); + +void +test_http_unref( + TestHttp* http); + +guint +test_http_get_port( + TestHttp* http); + +GBytes* +test_http_get_post_data( + TestHttp* http); + +void +test_http_close( + TestHttp* http); + +#endif /* TEST_CONNMAN_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/coverage/run b/mms-lib/test/coverage/run new file mode 100755 index 0000000..610d668 --- /dev/null +++ b/mms-lib/test/coverage/run @@ -0,0 +1,38 @@ +#!/bin/bash +# +# This script requires lcov to be installed +# + +TESTS="mms_codec read_report retrieve retrieve_cancel" +FLAVOR="release" + +pushd `dirname $0` > /dev/null +COV_DIR="$PWD" +pushd .. > /dev/null +TEST_DIR="$PWD" +pushd .. > /dev/null +BASE_DIR="$PWD" +popd > /dev/null +popd > /dev/null +popd > /dev/null + +for t in $TESTS ; do + make -C "$TEST_DIR/$t" clean +done + +for t in $TESTS ; do + make GCOV=1 -C "$TEST_DIR/$t" $FLAVOR || exit 1 +done + +for t in $TESTS ; do + pushd "$TEST_DIR/$t" + build/$FLAVOR/test_$t || exit 1 + popd +done + +FULL_COV="$COV_DIR/full.gcov" +MMSLIB_COV="$COV_DIR/mms-lib.gcov" +rm -f "$FULL_COV" "$MMSLIB_COV" +lcov -c -d "$BASE_DIR/build/$FLAVOR" -b "$BASE_DIR" -o "$FULL_COV" || exit 1 +lcov -e "$FULL_COV" "$BASE_DIR/src/*" -o "$MMSLIB_COV" || exit 1 +genhtml "$MMSLIB_COV" --output-directory "$COV_DIR/results" || exit 1 diff --git a/mms-lib/test/mms_codec/Makefile b/mms-lib/test/mms_codec/Makefile new file mode 100644 index 0000000..b528ac9 --- /dev/null +++ b/mms-lib/test/mms_codec/Makefile @@ -0,0 +1,6 @@ +# -*- Mode: makefile-gmake -*- + +EXE = test_mms_codec +SRC = test_mms_codec.c + +include ../common/Makefile diff --git a/mms-lib/test/mms_codec/data/m-delivery.ind b/mms-lib/test/mms_codec/data/m-delivery.ind new file mode 100644 index 0000000000000000000000000000000000000000..a9334470ede986cda8dcf963f0600ac5b8230277 GIT binary patch literal 52 zcmeBa>z&xj611hBrQ6BF$i&&n%gfQkAl#5)YU6ZmV^a%L11QiBi41VH4e;^vWdH!b C#Saz$ literal 0 HcmV?d00001 diff --git a/mms-lib/test/mms_codec/data/m-notification_1.0.ind b/mms-lib/test/mms_codec/data/m-notification_1.0.ind new file mode 100644 index 0000000000000000000000000000000000000000..ce88f7e0e5dfcd6e5ad2684278bed2d0e1090f9e GIT binary patch literal 125 zcmeBanvrX0kYkx^UTR>Rn_Oa)m6U8~Fx*GbJ5|4MVHZn7Rsc+6GDJihh*9Yn^GS#=wO)V}?Oi$I#OtHmc G3j+X9ktt39 literal 0 HcmV?d00001 diff --git a/mms-lib/test/mms_codec/data/m-notification_1.1.ind b/mms-lib/test/mms_codec/data/m-notification_1.1.ind new file mode 100644 index 0000000000000000000000000000000000000000..f9bcc7d1dd06ecf16c039c110e5d97e8d37ac9db GIT binary patch literal 116 zcmeBan&ISO=u=~#k(;PzZe*gDoS)0kJFz*Vq@=(~U*FK&NYBtx4=8SI zWno}opzrG&jG~XBt+9i(k(v2RU8iJ&wy~*&DNq#{=!ZlGxY`Ez`1&z)HS{qv#(e<* D(HSA5 literal 0 HcmV?d00001 diff --git a/mms-lib/test/mms_codec/data/m-notification_1.2.ind b/mms-lib/test/mms_codec/data/m-notification_1.2.ind new file mode 100644 index 0000000000000000000000000000000000000000..91799ac0a4e424d51c8d03183d0c36ae918b2de0 GIT binary patch literal 114 zcmeBan&FsYkYrg9;pZIhlxpZ19~Q{aJE>E$LEG5W!qmh70`x;716*wbe0=>F+8VnW u`k0x-Cw8zlGBbavZ_X$wDX`Ml&&@4PHZig?G%zqS1atIF;*IPv4F>=Njw15_ literal 0 HcmV?d00001 diff --git a/mms-lib/test/mms_codec/data/m-notifyresp.ind b/mms-lib/test/mms_codec/data/m-notifyresp.ind new file mode 100644 index 0000000000000000000000000000000000000000..33f2edbcb57d235c122b3ec3f4efdd223b08a1f0 GIT binary patch literal 42 xcmeBao{?*4kYkx^UTR>Rn_Oa)m6U8~SE&N>gr~oYi@37s%viOYOL#IX>P3RVq#%xW@74MXl&ukFkRc&)WXyN c3iLxF16*wbe0=>FIvE>VS%OY~_&d7+06bq7aR2}S literal 0 HcmV?d00001 diff --git a/mms-lib/test/mms_codec/data/m-retrieve_1.0.conf b/mms-lib/test/mms_codec/data/m-retrieve_1.0.conf new file mode 100644 index 0000000000000000000000000000000000000000..b66d78eedbeca34a4f93d1ee6cdc6c1be74fc0e7 GIT binary patch literal 14722 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 e5FJ*ASw-5X`hda7_&R5*U$}5yaY|Zr%;CP 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 literal 0 HcmV?d00001 diff --git a/mms-lib/test/mms_codec/data/m-retrieve_1.1.conf b/mms-lib/test/mms_codec/data/m-retrieve_1.1.conf new file mode 100644 index 0000000000000000000000000000000000000000..aabaaf4534daa4694bc01c8741d37e7abe709092 GIT binary patch literal 87560 zcmb@s1z225*Dlz&Yk)v-5AN;|n#O`QPJ+8O4#6eC-QAtw?(XiA-~>(3;7ljy%>U1K zXP!Iv&NI7h*Q&MNT5s9zT2&E2DUveUQrvR#AXzy{ZVqvGTSHbpPHt9Xds{$cY%sj) zSK`4C|4<@7CN3U+9`=7PHg#=fX%S@w#rJ?Pzi@soZeD&#UMUt{=*7avArq zdB@Gq!^_R{PJoM-8xZXuc;q`BHxoSFIbA>9JQF}Mojnsc^JThqx_P>TV!D=M zx^22)CSbY)s?bgW&44DS+ou~?Sy=(ee>~vk7U1LL6yO#3zjzQtSQjSDE(!=Wba1e- zG&Xd$w6|k(vbD4UATS1r693<%!R)MmbN!FHss7kS{hJp4BNatO5wSFts$da2BEB;AN+xaI-XVwt(Jq@>8+>t7>Wvb%Dan5~|{4 z46(Pdq55wVc6M4S3L8^1Xdcwq+1}yr@Baz%H`mfcgi77i-TD6s&(_q``F|fx*4EJ6 z^dC53w*O)!%=Rx+VIzAJkH3r^3?URIE)Wr_KTU1xMD-6LOIvdaCx|hWBo_xKJ3I87 z)ylz~iURVNs0h`6z(XPaCs58%UjJbIx%&tO<6w1$QvENi|0XWX_CJUEAH4d5^#7Yz zod2(03A6oEX~KWInkXtT2n{zd_&-Pi{`Ro{5J7v}f209b*a0E`DfwR?AIyJ740N<~ zLdOeq1kD6fOm|IJPq)oP%!Eu=Lz6832)dwoe$$;Z{?pa06w`4OGoPUX|G$Rqe>6J( z3^R)9_P_D~XihW*RJRps;WraL-2zQe{4-$xj>|t|^{-hqR1*q0-S`jubUPG0g#xNm z4K1xvTQEbUbt#f#yO#|9JE-cj%k}HJ=IiYtsfT`ZLs%=08PK{I|D%I6+;9 zTDQ$a&qP5dqkkOwj1r>Duv4GZ5;NQk*p_s1ua|_k@ z3&r{_pjsb0EBHS~9RNCM{f7YBrT!!Rw@dw}tU`kYOxf{or7z0I)bPa5yk8 z{Qz>Pp9nC2FTlSS3@jWx0wNMJ3Mv{@p#d8J3j+rS3lE2Y01pq<_J-yI;BgReDLEt% zU#S=(Q90sq`p4!XQ%lzL;H%F3qTw=v1fZZ2ye1@iLrX{hmVuF*hnJ6EKv3$PG*AZm z08~>4YiMd|>lmAunweWzS~)qpxVpJ}cm@UqhkX7L8WtCykeHO5lA4y6Ur<<7TvA$A zTUX!E*woz8+S}JZFgP?kGCDgqzp%Kpyt2Bry|cTwfAHh*==|dH>iXvQ?cMz!UN8W- ze`rC!{~`82@WO%ef`x~NgGc(q3kKE=`hmlNN1)_D#FbD%GIV@J#p#cXCmEYt(}P0I zrTPos2r`38K*PO7d;W*oUuOSn!~*_5G5arK|IKR^fDQ)(Z9F&}fEZvPbbq$fG_+=p z;`~lsGc9>dC2=NSRrHp)izDnSVoohEw`y15hz}d-KzXCvs4sLOwgc;GLIw1ros^_v zbf$L45iY{~TL-+{57^;l(IK9FQC!ZupdtEElE}j0(+~Nks40P*pEfQpRZTGoj&`yA zvRYOdrzM(@V!YlIdX=s%7wIouR>}Py+H;dZD3=c$W6J(jz?7K~za}2lGtCZf?8>DF zY;vTT+lQ@k%B&F5p!u!Y+TV}NDw!q2i~!CCb!uujw!NLaHlX>Oy}M@XE~-K@qhnorO^pF z@HB`KEsY18nyhzso@6Wd3YvU%K*V3NFWX5A#V>Hsj(Olk^yLyCn_dwLp~*0=R@3Aj zu=W_Gol4NnT$3SBRF3*JI4Hn7D3l2E`B0T;y4uu`&V3Mh09Fv~(Ec=;S|!PF5J=*v z_p~uOe!vkD`(;F6b>$R9jS)Dx&tLJeu63;S^}3fSS9ER;8i)3YJ*OLo%y$bw zcE4It)`I%btKlQh%K??_QyTm@jj3E7l-Q+R4T1Z)=Fkn-$eFzRUmkd;Sr%kgc;w%S zb}o2yop$52;^*Tm#mzS5y6-W4D=BfOOfrz8(;P=0y2cj>WWm*VRs54y+El6f5^e@E zpTgA5Fa=CSN{F1~G;|BiT^XXhTfVAHpPtwo4ui7Ent2Y0=~21tYF_~L&G0@v3+@n$ zgx7Jrkwd@AH=h$_k&laJsLVFdDV>H!%k>7H6S-e2sLNrVp=LH$HDZ`81K~WvyyfE6 zS;xMEq$?+V46~E7=jW8pXb4?rW{x2S$F zn8ZB$)!lPb0l5K96b7h2ouf~}yCToEU|!otX>jrk&M5_>TQ$2*7x>{FlaH&%ql z63@MbW%7p~nqpptyRT~ZXvt2arWanqqRHx4b#5&rTQX$8gb^SSTve8UjegxxtT+JTavu8tV62qG3A* z4()+ZV>;IY3>1ekIor)zb%inp31k6qxAJ66X-Rw7^^V;lQS4Uyt9v~cJG;If!LWkI zYY%UM7Y|x)YBAQZM=yY>_`Ntfq&ilt1NFkDEQ5m8*hyIpl7(YZqJ5)hov0pt|K|ks zND4*>o9jUa!_M8p@+nId^%~Dlkx-(8>r%{YW(eU6pbmUKf)?g!S@HrnW)}W>i@fbe z5wgI-nz++$9uXs|65-SE;~Tk&MFL7@G~ozOPiIt2gS!vQ%(seTTpVa6!$_9?eCL#+zQ4ke5KgBzaCpzIbf}egu`UyuB|}{U#0#rQYP^p- z7_$WXw$cn;ml`(CzfsC!NQv62)A+6&%t;ldI`l9^;e(itSXIr%mrg-n+6Q1jPOPw3 z#hv1kzBoYNV4_kayVzl+@jwFG+gIweEu68EG`HAba%3D_7B((q;w!{wU~Q@R-z#&W zy0aR@o22)UpPGQ%thF7JEfam)^Tj^nSFfJ7+qMly8F@Z-Z8My1TO%Spks9$o<8cS) zViXpruscBp+RUjMUTO0BmG{=G)rK?%e85PubkRyaFanquw8#DqrBy9(n^A&1Q*8WX2sdH@0qwZMofUp)=s zMvmUmO1^PV(t5ol!BL{d6OeJD<0O#yx_nWdMia;o8%GC^y-eM8x1F%2cUXln45Rr} z@hp(HqZ;+Dw+>biN9PTVQlXAsc&O@n1XBiJSxo0j5%tU>K??E$2t42)s`M~Rp=s{K z$sBS#?RjKsul-dKQA*XuPVF|4Xg~f&5F?YIJa6@gA(aTM+4m*hT#*FNAdL$5@*k)5F zag@dW%{5xdkaSacYu1*-f91JKE?+N8{K8ld?w`EF(a}i#TsjRS9Ot_zpLiH4=4pDOH&b zKiI5(=YrG%h=$_wwMtmx85LVA_o|Tpq_1ElLzFCpkKt$VlT{2Z>+3)w`#$o?3Z1Qj ztq6}D%og&|9AG3rOvV!ihzb(|hxthI28DNj_Ul#?m#qDl^WQr?NEa17E|icKF!{G# zocqOHGPc%`;nfqxltI^w7l2?s&*N*cyWqG9e61YTXq?h(lN(EQnRqN;hLcBkS= z*EiS#j&AM7&S@_k<#5PsEa5PzL@p(+G}bC1v)!@?irUbQ&M$Xw9OI-tIkdy6 zev_?gn2ZsKyi!*>77vA**lBX<`1TbDttrm3u_P2NDc)X#xGNbi&6z+mz9e-eB?_Q+ zeHfN^+1Xv~-$dAl?OQ0w&lZEkL{<7@wA=sI>3yFJkbBJ{pNdE~YCNPCPcB*ajV#iq ze8;dljMGQ$?TvLRO^{h{P2wG9CAfjG9mgBBY{!nD{a74g}9B#J%s?%SStPwCzY%Xg!3EX^d zojb?lRjNK{i`TN5$baxdk)1WCoguoRZ1V+xOMYG!pD&zFm&M>d(tB`K8LqvrKWJST z+-hqP`rII;$?1LL&id*p!Ib)v&X0qB)+jb1@q| zen9JbI-%1RWywc+&OY)?tsQCe(Bqy?bX3fp4qJ!hx=tQ#tWg?Ci&Van?t_|Kl~%{gP?1E;Zjz7~{3Dedjjk#K$(p zs?;$)`$D&*y%SqE#BlyWWGX)*W)*6#Au^PonpgXgG0gt5qUC9Wx}jA?$Yl=iIWcVd z;QFv#hu7Aq(qNO?in;oyPzU)%0Qh4+X7qIQLF4bcyZtk^TfH9AEelW}7dgThFE5N04@76j#Dh3tl&FQRSiVUYksbB`PG>ST)O}=EpdoOTpc#`%unS z*=oNU;or=X5q447i9BI!FfFP?Q4vz=$;{5g2eIRdUyQ5>DW5OhpX&Q`p%}@6aBTr)o_E7 z3AGg9Ju6VLfjapDP*OqYH;gaZ6Zm;uDPJPyIziMkXo=_WOyQQKAsG?n6+E?TO~=B> zum!7ahu@KnUtYTYQQEUxH#C~C&-U5*ceZM40}5@Bvj5-##S4HMWX|H2hnzaKN^2^T zj&!fVQOhZywWyqP;d=d8UXk`)S!V5E&301!TW`gh6h zKke}y5(kdQqqda-abdX&%xwkoJ^jUk-%ZLK1QKu%PxC8dy@ft`?6=qvzV60%vu`+Y zwk<)t=g`0Ogr(n>#{mQn5+drCDx%rcf_1E~ML3yM(JW7ME)6Y_MDT0H7{yf{sB-o| zqN(_*>e6=?JK3#*8u`Z+D^W*;8O~!2NZdN#bqjj(rH#B^4ZuJu%gX@$qh%f>4%S}p z=WR2Ikd3;36Fs{$6*eXcmb74pAf?rn7A3^QT9ROHAZj9A=AaW7hA2z4g4LGu0;4O{ zVyS`{UelEBayUpX{HWjOLJ2U4NbEUGD=(ql9WSeH#LK|$^`lVY9_H}Tm)#^HhFklJ z@2Sp0U}io{?&V>>Z!Jo}GITFl8zX2;eT9$EH|9hkZ_)Qwc+;HzP&{&tln!N2TVKnM zD{iaqR#V!`(XLTa$e{9gUQ@uv^g*q%HqxO6E03|gor;D4mV!Z`_;_j#M_a3W zLkCA|x?S!b21_5WVA_{Obz>6f;LD*;*0J?E@QIE-HhHFrNUZ+qfwa7@MBVY699kF8T-<8Oa|dg7Yct0zVg&e<(GEWAx}Nq(`Es$G2#4yJFb zo$EW03$aWg&8S0d-J0P6WNC(q0xg-JR4%HTjDz`2U75TC&0FsgF~xN1 zSd)?(+p6IB9^}KaR#!)*l^dh?4Gfz|$QM&^XitY@svBeHuMLNvnDVQq4O=Nvwe?#@ z{lg5Jk`|Pb9mJ{g+3@S~HY(zRS^4}YF}M-GWfl-igA*4Od-Q#Kcv4^-Mu(!PxOV$|HKiZwooDFzd$ zFEO3dQ6Eu9u#^9$>Y2E%-ai8LF31;U(pzv2Zu~1veXDn^t{zZA%agGj-l2bQM|5m@+c%`S{MDRVG%2$BxR!qr>TNx5PD){`7I z)6g7X34b9&)dtZfW>S^^%Bkx?wL->Asvvc@>&qB7ySTcS1nPGbdTS(w6BsQaK0(ug zJG6%kPOigt1gDL@^{1V-6J~{Q-OdG1oMrfU?YoG;=Ggccr8=@K+{c}eU~UQE_1hnM znzonG_E8Rf`*>lQwy@i%9K;$&1zpEqx|J=)90L~;>7vKbx(Bf?DlpXK=TlQ32S^`g zVJ%{LOp-v`jG#dX%++-TaqYczJtv}(cTZ7|mz%i|(C!UqaZC=${Ocyw4bbEVZB7AN z@d93o#Gi&tc-B$7=PKDEG+L9dtA!v;GIDb|hkjbAN-pr|&ke;c1}t9`<8qP88M+Hl zNak0i*Rt8$wS*5Wb*j>A_QE3XNL??O>KYIClpt@oR+Mp(wi#vW!p4*95^#YaQ@HHW zaO6E3dpqakx0_^c#&oS5iO7 ze!o(LS+Pu0xGZa1=d9xJW0%%yo5jHoZOf)!XfCPTvvwB`ksum!g)ReRrJs5uCWv8u z$@dfxSD78g`D|m%BciMwPm9_bSF8@PsgbIzGZh7YDWF&kVgj9>@#_!{=W7k5w4O-tltGiwpE#D+A}&QCVpVWMlXpWBtq6hTej{eE;lvOB8X@7n8@bFr{Pd z>cYygv$hA52uwE{npZCX82-HO28zz88y+`Klm*|;yRt={gx^uN-<@rWEwr?DE{v?D zL+n1a0cEkTH9zCgqInO_b=$H4kbxW>14BgutzH>7O9dH0C8h#5B0sd3?QB@y7}Y z+q^q96_srLu4z#?+DY$^`tXaH$Z5lN&eEi0V77^qLVhG@m`$PP$E#=SbrJN44)GI0 z*RzjDL!ov_3@PKEiFWX(?xr9kyLARxk=><4ACC6#QVTh%W<7DzY`eZxu@K4YvI^~p z?dV$Z5W9D|CXF{AW@PVazefBqJZNnpJ0&pr7EWiWU*k1qB~M$(&%^g!^QU|I)oYIh znzSsvgW5h5QUjwvlRJlNOtO~on`}w4srpadH zW|Hg-Re4+2oVzf584($7^it8RDJCico8LwrkB;hlGiU1O4dNoQ{LkPHyeaIxZTtNB zSX{d8ZC zA6+xo%?^Y8?F23!m5Wxi0%}3&Zc`>+dQCS8i4T4Q;<7r%n$oXWYF}#A>;}19RUQ|S z4e;mNX+&acT*07}+6Z%oA@WF7>!fv8E*qFEL zKY7S?qwnJSR&r=v-(8C}=$zJtX-kkw?iwGbU3Ov9%qUFIpckfG5HwuL_kUKlphUCN zz17i!yWMVV`0?=s;h-_ZFbZ|N|K>ExY66S5AvNiUS8{YGcfj@DH`Ik#Ye$w3AFkct zxuL&3gsF}ZXl(Ev5&79=dil1HG8Ff$SHN#*{Qcr%cLDkj`$tVk40^4f?-w@mT{m}pZb$X8jcuXbFv_;)gHV>(J?kS#3 zz8Uk4n#lyXuT|smfg$ljCm2c@e8#yiMeed@?s{)Lp%$ArWvk+70Gmo&->OpDR*%W=e-I3x7~r z0k29eM9rRP=d3C99G5XQ_e1n|dyXw)$wAxAc4_;o+AGfkfei)+8*)UA!- z_kQ%rQRWJpze1`{X>m4J`Q5W%1RP=XHJ96zb=U$?x2zi!c#tWo{BMR_LU(@b8{qtC}3Uvv zbrYkU#yPvn{BOOI9Uw_ZecH2N?E18Q0 z+zh+sE*3vDL(ScVzjN22o63x-P8kYL?aRFNxfR=Hm>v%yoqI>1xV%aj;C+}&7HY{k zff^IRf7DxcbX2H}E13E*)<2lX7~93haLxCHN`iK zz2oQlWz~lX8;_+h8f@)hOy zYmQI@pO}36bkv?IO`2P91?cysqUT)-bBHy6P4V|TPDFoXzAABEc45*6adO9I@zzE} zPqu!q0|L>8WuBbv&kJ=e)Nx1?T-eL-MX51*aOS_x71%B5=Q_Yl$ry9^( zc^E+g?qH#8dm9gQ5Z`nRt8p|W%XYvhh$zoUG)2ccP>oq*D$Ga*a5Hmyh3uE<5x2b- zlB?N>;KJs*(-gPQ1tF#2i3*m*>McASk8s69auA2%jm0tva4;4I`Y+&U+r7Hlfief` zb}sVaIQ?>1Wf5Tw43=AFT>e)de^q!Cag|FZ`y=yH1~gj0CeFtnp?_+YVpIEmr}6D` z@i+y#`d2%c0oB^-kVQ4hW=ri5-ZJAmP5s=-XgJD7$GcgOvC%9|Y=|kqIM3}$AC=PmRY|Fab838tPv5Z zX84Wb84d^O!jUtEJ#>fZhZKxU<@_`$|((SqY?Fy_@A znWcX!UK1jicN=UfaHl3vH6*)apCm?iVvC@}a*@4Q|4BsHE#*P6o`F?hwM|K9VV?U3 z838Sqe-CM?6}Lm{*nkHwynmD@BECp)j51;V&QlW7U09_{QT@`Okmc$|6MCG#|Ko8^ z-K_m7OP}yBz4PBXoT-lz+#!06v*Tlli3vNmGoU99#m?#J)s{H*Nzq?=>I`Mv7>yvG zaX~wDZQq#E;+EF-K->D5_rZDq<{fW4gKL$mky$(V87<|^Zlsb=E7?N~hUyveWl&X%7X ze0y7kQh)9S;_7lHZkiap02upZ&9%eeDYDkSlvYz_8@FgsCc`~+r=`)lYt@Cslfp(n zH(0ES&+P~;iFgb@j+EOLC~uib;BA8%NhoU-B^(y@~Q7st0%v#YHLZgYMB~&tgD4hy#U^|80BjDIve2J zYbqKRw$}vmU%rM5nc}G=NH%_RZi&p_b0?95iMl!w6iLF)x-E-j%^?rG;rvrir65F0quppu{`N$NiB!$6NSCkq=D(s zbACM6tY3TLz{D6NernM3327P2ZfGruH9^ZNj+Z4!n~jkhKJkA2_*P0#U-!g~# zi5WEOyEy(?m|S5U#l+a!RWsq3>E5C#+*Q1spjpmAB0`2|0)DYd-j!VNCtO`&Q{N|- zYPQO=K>C%4d|@uwLd!Uby?#*oI8t0WnfT)moJf24xpjEXvT|R%Kvc0ewMiUn-)uY# zlcPI`cYQ*N(^eLF91{h0Pr%QL>WN#r87*!@V48?oT)tOIjo7IlK=V6!b!^9JW|{U@ zm#rgWqZ{fRG|^Q+i)ukx^jXk!(hDHTrttFtn3N^%FieP>=2MP2(_NU6jG;9_|W^#}5>9mZJk+H5iYF zt#KBiPAP>Jgf3zH7tjL&QG%yD@KQ9FV}1_0_DVi)>1GI+K09)iB3asZM6FCpyQprg z>1nlg)N#V}aUR@-?Nx0E$Jg8p#CLyYit=XoBL5_7Pez(#hM@Pf(~NUX)#%LPiG~CK z0*v4Q8%zmdTe(?$5#?o#?!!pGcvcVJ>;n*udOHJ15(Yl@t z!J{7#K%=gcxooWs)6haVB;z=HXp#2^Lm0k0~mcO~tenyjX4J`AN5P~&}M z(ps0H;e>Xbap>f+e{#w)K08dvs+YChph6eRiXFLPm)linx~Bd9l#wZ+FLrnWU_B%( zxBO}lD2Rw3UE0cIuT2CJNkIo6+fob`P?yGB3%NhmX}>AVXuL>HjT3i&Snj@e5|0|{ zT~Zrk%;~xWkdz}BFU@Ppl%ubeURhm!#~h_<4c%?gb&P@0JGJw4;Lv~0Il8xMZFY>k z#B^Frqe+%CywNl7x-PcD)vI`?E7L}CxpY;Q_O2(_RNBaC-Kasb8u9!C)1<9k)m@I~G;$E=AtGT{I(;=w1@T4I=cbSZluDul~v{)CQ}s$3Pkm>no)& z+u*e(`#IHq|I|2uxPd~%z_}>C85<%RQd>Xa!b2;nr%)kSj?Fl*-o#O580bZQk^^@xwVc@Xh zU1u>|LLFQPrS!#T1fyVt>TYMnCv{{NXq^rOq>=Uv0^z+G1J~=_VENFvI5xAB@fSb# zp~u*cL?$?l3N0~nA9&3w99Y<)kU$^(A`%3Jo!0JzJk_cjgpFc_kfywS%QPj16kO0M zB7)m-fv)14f-f|70tQ+>+Ig4nYNFPw8zV?uz&(W}77mVzUN*x6AMJCLo*P`B$=cnd zQfP*1_iO0F;29ArY&ez-@bQDT2W6O?XbdtoBX+Kf0&@=;TnK~W3dp)R22AyjIJh|N zRgU;jcUiAJcDGnfZEi>>lpj14>L)^B9;Jms$pVWIaP1>Xk%+o0Q?HRLjlMIL`Egy6 zXlCfRe;L3W)?bPCNqJOcuK8~Lc8YeqoRH+LP2l}Z&P1iXj@JUm@+b;D(GGc~flQuN ztwOEB_^8Kd)utFVFxwPOuc3l-xRw=0098yvKjMwhs?J%QZjuqAa9i@nV{yV7-HkQS zt5Y&Njs%>|XLBC2^D1M-lehst0aMlD3uP-5%9gOh^^e?!x&Q^f=Yj&7@Mi1dU5e)A}E^3w)oahEYbA);cGsEwE`Ty z(gR2pq1QD}yk*f-l$kNj*z@F!zf25)ooT8Ig+Y@x=H~m4_E$VLtc4|LU^P?pPh>i~ zzUMrnR*KHQX9~+f1sQfEo?eR!$)CTnvGlZdWEVrk24lvL+rm>^&^$QA z=(uDjEn(_~KQ56Z%@XBN=2`UB-l*6)+pmDz=(fT1flDA2&A_2Nz~eq`GckOu)BXG2 z&e@Jwq0Mn?^E@pRac$}835MzFs@{i@Cf1t!#3M05aZ#`4BJjIVpppa1lhb?GSQWLA zaqqGCrNaTv{YfT)Kql6$E{lU8^)M&u5nk@7!GXXiPao z+HFUec(?9Q{dBe3O$Q;_m($q9>(KD4xkfAc&}3s6fp9j9(hH!hcBd0GU*b=!S0H}kCORNNOt!r9t9VWOF23XwsKV!nZ(NKuG55x|7Dxt+xbv%4kESqhYA}}f z;?{)kYtSNr%_+?rAhpt>4e~K@tr%S=NNn{%ER*F++eKS|D|x#nbFBT#x`~Rt2{PQD zodD^6f!us1$iey;(pQ$RxqviK>JiCKV3r{K;AdG#7io94Eu* zhFV~Let_@Ijc1diI*LT^Cv%{|jfTwfl?IsE15aAuAb78e9sk2Wb{C}@W~RFDm%#92 zc{Y22=8p(17j%!!2TkKLk%1ape{JGstF5z*i4~*u-76cM`#B>Sx7_|cIO@i4qXhu> zpA**B1XE856SNsN;^e%0@R!GW1fkrsdW@9=qnp=J;`zlLuA25ft!k7hpcKMye0=+F z#V6h5=2@8=%R@j@8ZyGqL{*(=OlS+2!b!UL>zWmSmyd8Vh!SqxuxvoYu#@W{_9ZFE-9!qpkPB7ET(0KRgQVf?oH zlzRf}{HxN=ywNr{JHJ&4^fs#m9=T-gNHM0+*2YM`tu(NV`8QIfCtN=>FIl?gtPFF+ zhF#infkW0*wNWnSaS1uApV+NC-ZVsRlzX_n9anc8es%%Hr+a}m3LOe{NgXguBsyr~ zvFh!`dUTtOxr5|fW4pVDE~+42rImZJGD&(Rhnz*d#wDqx{%J^N# znbaiBCL_8F0@pQ41S%BqpDkeq`75J2#Odc&(_V4#SO+yUf2Xcibs8`@7EI5?cBdc&k#F}9G-FIK1`xTa7=dx77zLh4>}{SiYig(g9Xv^IP53(ndS&#+RPl4QI> zf%E$4Ko>`vCN9f_H>9=1y|=7}q|97Q=kW9=eH_fbE&OjJq&v;m`Rh!2d-__6~y!$o*bsN|XPkAudbeCyY`3T2^N9>&PpO#snf{D<22gEh== zM@vz5N>vppGj7Ve#;H%4u&MKkWORmfT@#~RVCp^5_v6mI+LA7XQ@nXMv5uAM>Kft< zXmJ^YW3a~VQN=^5n*#SxXJwZIfWC48AbPiNwthrs){S$IBE{VPJ&^CG0%E!NW-kE6 z2tX*jsf>PUAh6r9T3e(Wjkts!@bv{y)keysn0yirvtAxSK)4I$p599ITmB*Auv}@a zFKDr48X~LRfkOUdg-vkME>>(QUFBLIN1l?jUw+iuIzc4waD;a{Ilgl_VD`<*b1>~I z$xY3j;^4lW`#ncRIog-6_Db2rLG<)k%|7*>NF_FWe14TZ#u9f3E@7m~qWrrt8H>Gn=_c+!$ci5$fA)F?UvP^OaYV`R=r zviB6_%|bDacB)R|)%6$5pJt34=UK%HDKlY@HrGQUVanI4Znk z^w@Z;tb6QurCynMo!_S+O7ldvJK*5}``woDo?Qm4dU-PA*e9WTf;3T`*Bik7GfpA^ z|3QqR<7zXnj=zP9cIp?Qgly=^_xbG~j{^k4P60A4-B*- z{%8Z*$tt=wz?!}{t{XVazBmH_GbOrfWZT?Hp9?>fN<}g>6QP3!mG3l&Kd&d0vp|`F zlH&tDMsBt{hyL&DQ^Q|TXLy;!LZ1tmN2@{t6f~5pGW^>mN2~g^DuqV*NA(Nx-9|1f6g<^VASrc64Pcw{4aJPQbqiRr+kv8Wr$l1BL00`Bq; z(LLg{=GSRIsnFf07ULs&RJ1&_cS9J~0z)v_pWYq`S(wo!I^9GLZun^+#o_q?o9s`| zz(xjmtTWFQF!yE^Q&nlHLsXO`~4?11K>@ z5`)Z8aaJYW;T^=@9A}gtR;5t*y12t#@(doXMozT(u^1;hMP%i*B{XJvza5>nMbFvN zBHxol)cO@XOmJ3HbwIR3ot0?yTW4`I=Iz{0r0kB99sPyX;IDiSg}q^F8t=1Arkc#a zvXkZhE90q)BL6J6uSag@--aAnYTs(WLpK1fC-ilT7fz)*##LYizykD*jAD3)?>6Az z2vSp}knEESoos%mDbA+mh8ylM3_m-MP%SXWt^Rx>T}XBq!N~Fz3=moihm=t(7VPkg z?Py*zefbL3vw^SP@_gnomix8#4RAhM0SBp!y$_Q;5)HYoCs>7UH1rWEv%V9D^*#S? z)nHl>%CaZVP^dj^Fu*_PoA~k93m`aKwuO&^Z}_5`Os`@E$3%fuCM~?;JJzd z{oXT*I0ouHiu0*L6$64JuqHbGqy$OWk8ZS2n-P1_mlgW&%BI*+5kJP?PSdD&wQCt6 zV=mHs>IQ4G(u|gxL1ae7@jbus#D?3g_Mh%lF`nLJVzgUxM(}#Z$mYU?8p4+n)2=B- zn3RZj`+yDUycFlOT2p>W!4@hVt7^Na+O)_Dc`ttOWe1ghA8>72dCkrQ5PcqJf3(cy zvhKsJJou@#mx5L7c|;=(`l5_PiU1KM*0p5ynX|fJ1Oe4|NJyNk;%+2cD53|0dNO#M zCwXX5C{(qgv(FZUR(fkgO+x+2J+#j67Z=NBD|#02L#L3!rshA5oCe~c(`x3@(_am6 z5PlU74jXVND}ZRD;3tM+%;6q4^S&!v9uO|*-AdJUqZh)$*J>@CJj6~yLTaEJjQw`2 ztJW@`j~>rl29!W@6)B(gC!Fxe{#-bxBf*@WYuIgi#?;!fc)|>gvRAz}HxioDG~voT zH`W{7!&ayXjFadd6ipmhudULM4cLJmmrtDkcw4)pW*)G(koNtdm(KVZf5?h!a8lLc z3=eMJfP8p*nMO0rLe)r;i`T<+xGHOK|9+K&Q#by#{tyy*>;yzZlM3y0agsYnSK0g37-Z)yZ3p<0A@FX!HXUe%XFS>@C`Pmf+VPbtou*4hM_XvuwH_o!o>ww#H zUs31V(x#(}IyYfOnVJWqV0;F($AY`px(D|J%G_>#PoLSd@~(=W6IC5;=xpNw*CH^* z%XE_BN{I!l?F4x(wXg(}`1d}3zeDYI!O6<@FOpmwp^$KZjcSvExnGi8mGICNRVMt6 zScehY6mM~1Oml5U%^jlC(B2pYrY%VDWK5#Jz^_j(8~=(>-yP+kT;(gQ=Dg;*-f26$ z>cv!AX&%Ls0YhmR+e4M|c~!5z;*G_qCnnN$IphOXBTmZ=Q69tZ%rAVH8R%ivjiC`& z_R>X&m{nwFxKT0&m9{B>iiqVV-%G)^A;95({7BnpbgRT~(Qb8#9IvKkmIh)Eb`_N*;(yj>JlxPfGtCO8h~V3z%qi#np( zmQ^<9hlrI_ATx`78oemv=U1&j+`3(i!167Tl&*)oB~5KEbq*&^XgB0Wg$DC*rsQJt z;tzkH^E(HQe;Dr*8~wUkIEyfDRlFdhwAfmn@~MOmv{y6vI{QGey6$qmZH=1MDJvv} z=!SuN&X$XPts7v}xLvmvd7Sioa}>ITvyR0gxfz9$cedL@1VN#$J_MOAM$U>Qs`D8Q zwqRke=?euArH1mOZes1JZCL%Tqw7Iq%;Jjh)tPE*NMf%YVPy3z+67Qmwj@Sg~|1HvfHI_ zP2zNL08k~ZuMu{+rc62Yl-F69&2DI~xSfw?M9-^E6m5v4xIb24J~$}tiT4ua)_(S2 z?2lF%Q0|)l_DmP`I#RQEd`K)-4FfU*R6CM?qccks$- zHyADv;9O#s?FCR`na@DgwKNHLT|k$;OZ@zy{_sqA^NTuzTDM4PW%#=uGB7!%T4X*_ zr96JnWwX67H5-X*VHlCm=y;*y`c8IVn7*LqYcDu|KP4JZwd&Wqjjh$SY@VfpuYzp* ztN#xG1ws10{0&Z)uNAr-x!ecc=lRsrytCSj$h#Eq2;lYaR%K9(o?-x-Km&F^tpX;r zXj;T1ft#<&Mk^FsMEazNHmc(zc1Axc+m7KyfE$5OPdUwFK`KS4%KKTjFI-@Cp#jxt zw&pt=B(6p7qOIOF5aHfeOrVk&gcWO6m&TM`Rpr+V~_B&#iNMi%jf1)=oa^ss3~@ zMXefXrMwV{_A?)sDllu&V3u2bF`=3w#{=eGhu*yBLXO+}No2X6I232^HV%I(^>p&5 z(TR>orHm*5uQ{OuF#H_xJd&vg?>7W}E2^5w5N@|C8y>1p2DwiMuv?kX4g;S507~pG zQ*z{WrhwqQOFWX_#|k6ID!S#A5(vj^9&0k^PL}o;U$zo(epZNJ{wE|>zOOd@Sb!Yu z86`9QD=Fka9|mP(#&{rpbi{Ml7E;(Y(#zCm2D(2EYLTG{A^FP=ymzi{{5sBhl{hCc#^$)rdim~-4NAu}8ZxTBnlTN1Dx#)KsyfPfLv4eD?OystyYVZ}By!aA8#*WGf?%gcjh{pA2YM zNjZ}5A#ujk8&6K)S5JR?4Wj<$#d12cN3?!))}*tIYn@UEww=il;41Cs+o3f^=Tw(( zmoyEY+n;WK9xG1%{dEg~pawbU2Ogf4nSY_7Q6%lK5!Z8LG{C@?_C&feDJaU>1Mhyl z>#EUpMY$;Q$V0Cjt_NRXT)WvsmroI8Wf;Q}*!?O(k=rt;eYyTE>{s;_C~rg283P?i&1cDVCB4rG(w0BN$RAomM_rZ>t2Wj?>sZ(KeqF%83QGaN z#%W7xGs30MmYC#~#(zqyX>K0y`I58ak_vhRl06mRM8aZ7! zkL?EF{o!4#f9jXF6~t++{{RyMoyX=M!(F6ph?nW#iV)cMY!0Hi4;3PqSnLi@Vh$^& zxW0zgHhEiU9lM(5H9bykNSN*IM&3r}$OKYgjygT|{7D>2t4KZhgwQrIlF7vs;Fw&UKb>GzK# zhM8GF=x|M3^CGyqRcTp(9X8_>hK}q*Z4Hhc*E@LKRjl<5u2LY(zNncL%O$jq1;Z#} zF}raXrH)u4oA=Yg2dg*~40Zj>GX@*W9?YOq1+qc7HL~ z_fjbY@w1v}3ime29C6JXjiEsx=BV9X34mD86Y6?Yw_D!T0`KYHkLggQyimp+-5K$m zD9NM-73?xG1g1_tg0*x#VA&m$f>F9{LB~pl`sQ4Kj>1`-7I>uTg zt-P(0q|tet{HJyb_5A2~)fzGxj^UhR80qUwj1~vxD%s=prB5;DRc+0WYGw5<3zbMp zMuaiyOJsgkQ5}mDyn~Lz7^`?#_k4@j95LKa^s28StcT?O8@vYt8soBepr~NDk@*wUQ7H;H$~x zf%?{a{hxipMgSlK&*Se|cGt5cG6W9Wh7Ne`RHD3@r;{v6VTJ$#O#(>VzM5E8AsJS1 zoDJKv$NvCcxx2|-$IL->Voou}X)Z4>-drj2BUAU8Mo;D{w4QG}pUfwc*z502>2OrYB!%twdkC*1`bBf$GDKZUvV|>=Odo&#y)1KBy|S}ehAc?r1MBaa#RLo4 zm5{Ro*SGVl(La|7D!W)AINIFv&>8@zsoSItxnMDdJaT_Zsw~aSy92NQ<*>afT}I;O z;aANBDucIo{{XAnpjqTXb}1zMxd+ryeM6x=%RQWmkldCa0t%?Er^B8ozqd`7F&QEN zVUJPQuNBD~DOnxaSd0!21XP+@ybgBX7*BO&-Tdl_I~Ugr+|MJZ^Ea_Y2RwGF*EgSO zEb@@bK?DPlfNKFSRj$|qtaoE_kG=1Tea*(jWsKoZ%g;Hba4n{|%FMCEs-W<5jxqGD z>Ge3Ff+Xr$3ppfUem=cxih*}4oPtGMXhc~+lf_C7XbM>wC zmg?g0M{TGOE1au$YUTdJ&r1pC7Lp~ z*>xy|&B>Ldkyjyy9{nq*mPCdn%Vs0;f_+KGKRWYU`c^PDBR(?{#;WMH?(_wa$9ALU8swwXv&g5TIveS>LQp4035pvXYj5& zNRq-S7DRCy1uVukBRm6w2{qAAtwrQ-2*8toH+A>vLK7{WBTk)3F$I(R%fU6y_?Fr2 zEeb;;vi|^efamk8ao&cNyt&>pfI~4D=i0J0%Z8ZK4SPHuG!h50X?dQRXNo(C~sos zjcAtl!^{tEM*(J1KO%b9Q*s#0jIEUbe8Z7hnq}lS%&|-rnO7NLKhJ8~mNZ$B0tG+; z;FC=V-n1j^%1or4qmpq^T)yOC<%Z*^YD581Lbl*ke7Ma(?8?jvlpg#Fp%}3uEX?HX z?T(dDgZ6+S^3Obm$OrMOrQ-7rOl|)F1FW`?J=PU~!KfNH=eW3r$Rv=iF@VbX1N5r) zaU&ANLopfY&+@4!m72sMb={7YXG%nm2j(xg?`I;K0m*AC^X4o=`=k<2>M12;wjdpZ z{{VY==kPUd;iN6{rsMtU!o6#Qa5qS$eF(?u4HptMCA>ihBy;LHsH3`)LAE?|>Ty)0 z4-A{*{2W7Piu z_3H#!UrL|omjwXFE`h(DZrVjEMTwjs!{7OLB|3R4zWIpL3@`w(RBCc1H}vbDymtql}KyYgEWW<2?@*R!NyI0*E}OZc7GY zF+74slT0HgD)Y^U@_0(irmnxA-J_0@Tb!}*EKW5*kYTQ zdP>8erEVp}aoC}W0v+J9?*9N90B?!x?cjir%&aQ#s*lz8QSZof*_O$OEr8ClRu$hkSn zoSfib)=0SWW-hWW&^S`~HFiB(Wr9E#a9}dT^~QY%y)*_~apjvEao3g3X%rtiGPvE2 z3a@&aB`k!7#~ANX#$GFgDik;#m0b%Zjc$C?_pyw&TN(O_s#*N=x-~rZ#ZNWFvNrQG zGY$#-GVsdtt_a}%3E_T z?s>@mRQd|TMqN%^0-)h>OtxM32P{SgcpmjVtcfcKmN2qoAnybpz|)|Ft<-_e(gt|x zNeHne&Mkrh6b|aV=j&9hzt@%ok}!E}Qr$6PFvo*QYT-9-1+&yT4j7{+^4eqlv$ z2vuh2ITb20YzvSWAI_Q+E8M#(gd+oQ139I(E=d3YNn9S7rM=ir2*XSmz82VET5?dYK@N=4S|~SMM%9^(~v1E@W~^!zM|<`sb}ncFng8 z%elI;s_x^Q15`Qn9SR3Eaf+D!Tjp$q1sp~<8QZ9{JYgCaPzu?xjgVIP8@km z(x3%T0F#`3ezc+t%e0C?0B!qONj#iqo@=hM+R+RnU?vLz!SxxgQqN>@q{WW#*dL$& z09v=wVI{HKxR5efoP+h^tda|)i7wrb-cg+G;}tB?1+`hsil7im;GVwys-5k_F+j+h zl}PG29eQ@+t=mqQ7L2koC+PUOl-!l)8_hAasUZ;oAq1kU{)vYt@e87}x+tz%qWd zS_qa&!D-c$cR$L8oW{8Z?pl-nvu#yzd`F$5JD^rVoPJXeB9P^cufJ0Iux)@H6H z-TS~)b>M?r7I8-uW(HNxI4%5H}A(W;VgGC8IPKs8C;Bq7R$Rr{wE9nPmJswsBh zXM@(NAX5sk;{bf1b*QFaFb4&&qksoErUg-Q?{dyJ08b#3kIJHZwigA^ZT1wgG<(^E ztVVeSd(;fdBrJFUo})CF(a>7oGocdz*c^NNR*klK0SJBMDs{;HK3 zm@a-%oMiX*p$OKWR)ogc67=XCu6=7cb-OXTKeO%68`<*1-=$~Xsm@w>_Ve=N6_a?d z1yZi6_{sT6`g1@XU5(|tOnl3)-Lc40r;p0EQu@*+1t%aM_D&6O+FZjSK__osq#ivh zXfEY1g;2xg?Zq%RbsMN>wLV)RU;*?s1%=E`jRr`4p|THNaaeN1{zl*cK)BucVwt9) zW@i%ZQIJU_W6)ASb}(uXK>{}Y%FYuY^d_{DbUEjbQfr7vS(T$MREFH3gV=C=JJiz2 zBxI29fN|Fp!0HaIZY9_l6TBz@^~uJ5l@76TpJIG4I0T%1E0u-!OSy8`KPb=TPQ8)Z z+1KV)+w%|!2acbpsTwL-T?M;ifI(s2wI5Jv8X&Aymxt%CrE-=Nk#xY4%3B+&Y$oZL z6M!*5%@KT82uUXd5;^9xudXAW-E$K8nP6D(PAW4xCV6g7&<7lftvKAO6;4~!X9w1h z6A2L`j7H^Iv5*BmS7~5r3o&9w0X0dGhK+J}0s7GLZH%bNBfftM28)*8IzC$=jxpD_ z{{XJA^|-OL;Fdj)KDDc7I+SMxxIGVV&Y7w0k(G)sT<*?&X+4IFC^XiXZVw>9^%vU{Xem8ykLRI8sj;`h94y$wQdhRFO84bAo#lRj&$pAOfLD z&IrX{Hl>JC#en1HRFFf@S8n%XFBfe4`Itx}fiMS!SQ+uW1K9r{+T zrw@~DxHee0URMBhtX7VDh}k^NpmTtxlLIKZcPv|X>xz0r>~a-$k)6C#j7o|^;I~r4 zx93vY#`(?z4w))OIixf|Baw=M5ZX>MKsB-CeV)WISn|qxrg8e#X^K{Dp`3%0wNLaF zYAc(Dw~``_h2!Qq$LX2`XDE_3i6cm!R^%*+k@=n}98TASTttz&jtUT}Ycl1QD{-*y zb~zw}+vqCxje7T2sFGUSu`9P6u6_A6L%yTRHsHZQ8RW6g>rgmVnEwEW6|X&-BQle> z<~$CA+t#wCMM<0HBxj7!%S5Hnswp6G(>*ax0?WIG>z``TM3Om*$O5{rJ94735(6WvZ`ub&=kn=S?YL$_ zIme;tNIH%rZY7tkF$NLYbAeW&MDp2!7UQ`93V}z;++!!D3sH@cU7}TtG2PeNtGq1< zAUgn0P-|8t0h9tt;~1)!agQ+kjhyj$nZNhgD!!>s}v_L&-J)<@eC zjBO>c$FMbeYlW49tYMS^hfsGPsm*84GPpuF2Iz2bF+m?HxHwXyC*FV<6(hYNM&-vD z`Ey!QOTHtwVFQAsX9L%Y$}H`8t`5>V9@Tz3*A{Xi8=bnaIUs%q{N|K*8`#Z;LWNk6 z0~6bW&1*$?5eZPOk&UdpfAx>OVWC~Swh^4sRbA>$_~;v^grjl z3vm-^C{bid6p#ks1`j^9X6YM*0f;9ZYb#8Uq|LJ!``+OH0EJ$jZP^Eav>^`{5z49x zsb)J^jPah}9&#$R{1GHFW_eo*ep01KKJ^rH$kzb2!rA1u?ZkRyQ!m`d3yAZyw;bb~ zb>^5E2w4~vJREX3t$i_>Aur@C&CUxFHlBIF{{RZkic=dYble;Lo`$tF=W!F2RVR~x zy*l$q5F)$XGx=a=k+d8S&ZW7yb;8OOKo|stC-tUWHlyXUM#=#n#07IV^4!GiC7o4? z&&oQ|6FVzuRiP?fkDy#s#zW+l8vr2kPc_SFn%9(}WigSCrA}+1Nz&<6kv%G_emlO|A*gKZQ$k8AanOkWsC>xeEZ94M@Ay*@pDH3TEo@|u_?eUpeJYL2_GO3>I0ST8 z#w%9l=#(L2K#kd)oP9a0d0|4?-5i-8bgAR%NC@qg-7b}b%Aobh&+@KowynwOP6(uGFT^AubT{Bzc>Sti+ung z^5F`^E?Bp(CxP0u-O@nMu~}6}9#}kne~mF2;rx|h8fHRsmd6!$NQI_i;U#$n2n*3p ze?h?SS&2J{2%D~ zlW1Vs3J!2N7j@jE!P~>dRxRUr9ufU!nSZb)f8_)zapO}U~X^* zaas53%EgG_9l7ST;JCO&^313s;FVVK6XqcN0+05=%* zs`9p2ZB47t6V7?7qBZjsN6nP}8m}}ijHp$xM(>-gFtG}0^NN}_XryQR!~%C5Vu4uMk26|H7#*_Tbw@sg@@k!uMAB@Q zMo>LDJ!>j?jngZ;vo~RkW9f>uXjm@LsM+J@O~9-!AkQR1}9 zjQqb^TR1ENMvr#A~j7N+E-#=Qla>;dd1R~qZ?}jHosiq>Cgsr$40B{a|l(zDuF58s1Yyrh| z*Kk=|!y2`+w3~)o9AgK)ShKgXds$oT(6&_L<{A{6>48?(&01wOp#sx!!~*a5{% z0|ZqevU+B>?{4Li&n>31Wkv{(X#Fc1(c(*(+`OwG<7*~Y^)##n8G|gUPEW9_aYpk( z#44#BvU6IxsaCnSlc4}EO6~Qn?IskPOqI?#B=N-wYBuyd^rNbrWRP*iUx=}U9i>@% zlD)sirwF1Mu*^pDftu8@omK+xxCI=Hu+Oznj&4;d!NjWBKX)JfYPkixf&nmH$~onD zsP#Lip7=`|7^4JZl54W?{p@q;Eex}b!-5YUv=VaC#`46j5sB_Vz^B{VTonXD%nmXL z>s{@|rN8zrRS6>>Fz59(b54yG#v>ERyaGUD{HQ>A{k65i$Uuh&B#eWav~-L1h1^2h zTa%3UuI>ohT~SFaK;x0mLtA%{kL>r!Jt~qDJey3hxoN_z48#tAR*})Kmf+^ym~~Oy z_O63L3NM_0UwYm#ZM$YUJa#_x0p|&#>LPF&#JN+I42(x#ZnZw8q~4oS?_nGri9xh} zMAxFkhwXSd&!tuIGB5UN845|qU#$W>t+YGvk-CP%dNxIAX%;u|vlDJzmpCUIN9$b@ z+qtocgAx}foPUL6zM?FaR%B8b9{kj?l`bN=xN?)ou_k%i+|#4dv@sDfw&v(hUTY5h zZm;Is3+)ZrNyqZ5QFv-bfm&;(QlMunMF2y8r)jauKFxB-=adXST9VICzGI&~Fb8G_ zilK39b8U37!Ez*4IKcUc{VSu>G@V*Fe8fg&Je+Yrg}Kpg7R$_%RAKCU{#8#-(x#D% z29G(~IXM1Rzp71l_CgSr1}hxtri1~yV7R0f8HcaK+noa{&h-g z2?SzM<)?g;&+@LG`pv^_Xo8mDvp(cb$igMs)~=A8s-Gdy>_qAcjDPj&4OT#G*lh!YNThk)hK+f3 zF^yU!3fzKt{P9{Z;hU%=*zARmOfkputsMpNc>e%*?+&%oPbm9pf~%f6{3!v)TX<&u z7_mr;H{B(&KOe%PxbW5FPF$FJ@D;1jBXCbUe;R{OU}46@Jo?Zya7RVCR4xK;AMFA^ zDo8Y4Mo9#bM2tZG@WK4+r$$xXlmzbWQCn&z8f7cBya%p^|`p7^?m&kyh}7=DP02de@X!JTT5L@nn?VxRDur!p1tZz zO(yucQ3Ej@y8d<1S~7jPmE$9vb3ReVqLTOiUUl{zhEL%7Rt=iaMB&9{O5J||! zPAg{l(KXdzi~%Q-G3#3za;dvr%BMM@v7Bx8pL+3NTaq)*MP*s(^DDdg45w)a2cEU+ z+KdpJSIP|gR~=<$?<~GpUZ2EB{#0B?FxJ;`sox9j>_F!=S{S5x3W(jCcK|Q{0A9Mg z^pndwo-=|nKMKRN61~%Tb1H!U0CxnBtr zrs>gM#zcv@jyr){dVZ2@no>Ss{DoCNEm5J16VDqFy8%W9M<10lSGu{H-V~A5kyK$+ ze_H999l)uz&N`Ojx$Sjv$U>V(L7Y&4&JsRDs9?cyklG(;PP>K7t$5HK5TR_rhraEAXKvyBqZO_Y| z2YR_+p_nP0MbnngtvzhFt7mpcKopvi&NNkZcuSG~*#v$R0i`tPExfUJ6JPI@)N@Pw)`<1#---odNpCk?JMPX#4n}j$T7vRfucGqZR4V=4V19zJ1F&2k zMrwOkm6*#K8~{dhilH42rzny^h#0UrEUVY?tqW`Ri%nz-;DtC{yo%*zx>a57jODr? zFr0hUyG=#b*p5iY@f=bFSJW;((H7$w3>zDpITd%qSAS)?XOycp2Hm*DWM9tH91JRx zjAE9;6h_}A%xjK-w>0_)>GkWGH5iF6u?JvqNYAxm#T9{spthII1Cq*l_sveau`!s( zlBzyXcMOsI>n{1juplHsk1z9ojWG>*1-h~nb?1NpKi0147qQ0Si-(XgAxdP9J!>e% z3MPE7E-9w+!53q{G`_}y~zY)JG+Y2j_uOK zp>nQ4$W_nlOhh+7W_Be}iT?K>R_29$VQpaXI+m0Xw{n6z^f}FQ_R@asgxi=OyOKsK zOH?Ux0ULg0?bd-Fl=tfX93XITzs|KZ1rHaMIm< z$wXSAT#?81uCConOwMpcaFEVMst-a(^{&psd@1>XrVP3n1@~}rKb27NIYXwiFwQv~ z;-@kXwhZH_s(vSQ8dH!5L;Q^Za)I7UDAqxQJQA&vKRS<0&@3-nVK9~OP6=a9w2|7y zPVfNssPxPE?e6AL6F4n^z>p8*DFHUE9+9WpNXh0Bq%JYv*y6eELf!9SQ){{~Mt)?Q@@yh|)9kQg759v#F;sm#~D7JsRzzP95{I=BY1sh0K-Ps!M1d&^iNk7)R z{SnErAL$#02O&-?%906gu8iO`Ow3y?@`3q^?sQFJ_6tD)k{NmotFA}jDWE!?cHb5X zRf#)?L0rFvoz~`9%N`%N$E9xF>M46_sU%3ddE8jGO<-xxAl1lEof$?*UAQ@+ZXFKd z{4)KV@9OJLwmF@GoRSYdl}hSwHfR^ohkChY*tlVkPTthO$=BhD*-}e|RtKi;e=5zm zwv^f^Sw_qram{S%wouC{l*9{x!yNwrjc2{Ql3NYTLaul#idF`CyrR$yG4WBFGvqffTs`2I0lSJQu_M#C5+ahhOV7pSd_{*=p`)pP?m{3?l?<{+TrqncFN zoDZhzLr9t_BbC@lRfg_{skun6$Cj&%o&W>Zn{4Uk9D&RF(IOz!RDy7OQW<6BZ?>x* zn@0fWy*tE(9^4V0gZk3lLmEntgUaKYX1c0uLj#YO*Xuygcv9(z2wicGnD?%-W=4g9 zT#Q$mXctz|$feyz4l#ng{cF)}S{sW!$jU}LHtI|cd?G`sIaD~@r?p)V8tNc~11vhy z-N2DfTqxvqqjW~%ED@ZqLr7-E6_XqcQ^GFMM#Z2GH^g8i`baa3{{ULMr%E2; zCLX`io8q`Yi+Jn-{c4_xGBm04eAx%|qo5rn`+;iXy>gmd$ZjPJaBxQ_is^MX32wl5 zu4hDsIpmbc26^v70+s!dFeLidIpR2!#LNiE9=`R`lO7Hge=Juyucl#>7y}(Y8W0@SyDGu~ zAe{C+>Ex@h7~-qI0f>web5reXg1N?MdV(ZK5kmzWu*U|i*+S3)2O#>6l>{hD^PGKZ z-vLVu=j%xh#Ktf|-oqqz;;N;*kWNB?>fh~S6+CLqf)J74=BxIQ5ucNvat#F7sEXi~ zFZ zGTjgPHEPn`;9NRq+pqGVL+64RoFLn`ra%;t*rbY9HpuJ+O)QacJf+XB+9A6z^cWtL zASzyH^O(PP89u_O+v(CR#>pdP1aepq1#X>HK>MYQL^TxJ-eh}6t_h}q$eufBCMzY% z;C~8(%|iCD-Kc2Y)mOd?3{#WOa^ah}03Q9$k##S;))zdX=M1hz0FM6Jmre+WbT z^Gk1U5sbf@cMdk1y%w9Og(VSK6Q7&E=T@z(Sz=)_Dls|Z2l-P3VzRQZ^s6WxmjPSr zgHm2Zu`U4(&TBxG}gNM?M#WOAt|k?o3;?RO0uAY-+-APTj4Z?*Rj*#|uH zRiOEtuIzpk>>#vRwzmX}2x>?O^!TPTjN(NH7-uRgxUkc$nk8?NB1a@in&DBENhCKP-OWgsPO4R2 zPzm6c;8VCAjrF@*f{UpIUZ9p*Zj8_itnUJ>?p$QHF{`zN8W{^KK*f zvqBlMdo93y?st1Da4L)3%IGpM3Bd)kRpq}E00U>9c{Ll%o>*hX53gEbV(6S(nD;nb zo~OMd-7%e5Ib}YW6-3Px>l(9e3VH)dEzuY@(BWsOwj$bQ`T;aX+ej~K*j|ZHwEp8AbNqC=dNQn7VIAKTn=`F z#Q;##(l-Tn$Q!TAp1*~6z8Ja*8Gwnpa9OfC`_}_+cF7*d?e^n<%Gj=#L%)Jm5zO)| z*!$e)tqcyz{Ct~${nBCehUOtYo+X{{U$xs-8ti&hcO6 z9FCNQ#tsNSN~ayb@|Pdo6%4oO8R?I$AS!s3ci6WCoPS#6bX&qN6*x#I&Kwaw_)p;}y!PuJ;I^$Vtw&5z5R`jcGl znJOuf$mgE;qz1!I8KnT@D0t0tc9RG-r(ukcLFe36iEkV`5Kh(@7_37fT|j3!C$4>Q zK+)IgH%07DK?7;5Z65F?LB~BD)o+~E8;H}u%Gb<83d7wvE zXE`b|Gsmr6d5BT+zS0@TwTB#dmjUzZiqwEAs3D0xXa;K+ z+&MhswPNbyd0nBh4_dymoZy4cdV7@Hy8}Mrgd>=6>Zc&%(yhRbASF;Ats0!UB}ZSS zGTM1Ot+)hYn2CXrMYr^Y8N2poDEgqa+3xPQQ^M0QXz?0q?)MaMt^Vynlfr$q6d z3~8UGM2@a-Lm$SbMNz;&J1C0m~7vFSsI@ zh9#x5Hch${?x5AEe$NXL<*JU@TvMWf%MH(feYvR~*%X|%PpvTxk>hpYPyO}9WzMRs z+qRMJD&vi$sF{HD6+-L<=Omw60LQ;YeuqCnMUKT%IVbB&cAN$b2Q>|{>cVVu@oyZl_5a&6(o9c#@Q0*J%FZ0 zvXhO2Z>h)l)sekN1DX(v5kj#I&P!E0uwAk+7yYBfTTHV2+o{1+@WUhAQxR6yRwo{F zHajT*3c7bT0O#t|q7(>NBJuvnpt>9a#Cr+=$h}b<%FJ`mbAejcplk#x{{Y`vssRBq5U2{o3SeJA?4YE4{Y5xC1GSNV1{BDdh{w(NH9cZ>Jbpw{13y$`0Ay`H z?^bkIt#28_mKY~)-fGsa#TW;RzA^x-8f0+2u`H^`AH)R!b4L7LOv@q^T>ap=tIwyT zw!gZVvA{SnRWA)`9RZMRNK54<@wy4T1Qe8ik~>0FdDKiXS?ox>nj zvNMz!R>cD?NqUaWmcXj=-6qquiRsd-yn$N;9-ZpDunOHrKf-AYw1hm&;1xObtr2j; zY0n^f))Y^IP8jp+T5&p*3|F^$0M-`{>%k+8Rz&kn3b18h4;!+jsOLYG0;-|u^g~w zU=OLR0do@^C<3HuW!w9(aqejWdiqo_x~m2rrE^?j1zk7(?CAy{{Ye3_lKW)%CKiuZJFEdYf;r0V5rBr%~N}LQ2d~&K7x=G-Pu@@ z#{kxR#5KTWU@_2vS7nWfBO@8=MOJG?N8cpi0nRqD{*(-`)`=_`E_Y)&BQ;4NNN3=j zoE+AIJWUu_+%dpYW z_p7mdoB`H@X}N*e!|>-@<+8=iO{YIrm}`7X~Fjt2&Q0dypTt3)SgHH06uS}TrtUk-yc&^7$tB| z$_KthG$A8ZE!++{#aWCZwh3%hQCqsVI4kR#vLZRa+njaH06lgG#^X|}s<6jH-k}i8 z4gpWajZft|fLN*e8e%3AF5%8|>S|&mEEs@lnSG>VJX6f&a7t$s#8`GrZRkFgmv*Rk z3}kzX(G$w}!m5v@MLZ1o4(pRZ9L>@rW4H&kI?^->z#|W>YrUc%Ie*rnD;UlRBkN2I ztHdEl9C6%=&$dmnwnF6k=C^KPiO`ab_*Q%oNA{1DN~iFk5q{lWln{WAU~0;)#mOO0 zy;-%41sQ+Nq@5!m`PSX8GI5t_Qgbz0N*Z0)~`h96a#^ZU^*pO(B(%S z)I5pU56Y2}H&cMMQIIQe#C|jgm_MK&l@c>?$O5Z}z&|?!pIU-h8vt%*qy@FObR-5} z%C1{p5<;^vZ>43xS2-zrBVaG&C;|GLJDh|hRJwNY2~C3}bDEVW4x<j+z#(@pxTb*V?VAwbk`6s7vM~UB;|8hPT{g@~#Ypaq2*@UY5?4^C zBxe-_bD#kA{3jmT>xndqQr$!`BRysnlK9mU!_xxyOmM-{{W3S znXq<{KDY@B8YE1bMH(GtmTQwTCH>upTS;uzxQUVbSO4~w=)yR;AU7&I6R7)Q_BR`c~iHniAG4~VfGM7MU|E!k zL1K5573F&RQx!Mz5dH?CYuJ%+Nd$XQZ>gh6fUoXI;)Dd|6;(MxPreOOo-dp3fHCV@ z{$P=F>*-Y|fI9L@{b&Q8k_6m&IX?9T)tbCOmn4DHHGbyXV-g#^RFO*|QIK)h6ah-k z6hhn;!S$^Xv>{#(Zfc#nGCLj!KBBIow$q0>?TSEY#Ew@5fF9YYk_f@vTR)9CBz?HZ z&MM4q*uhYKhO{h?3O?!M@Tla^Ad#B1!#}~#`_&VS^-bOvE$0$2?N8Yu135p9 z4GWNdQ;I}JRsJFPW{`$DHq(X8LLuDP+6S&hT}d4Y%COLZjvG{0wd;c`D3aCZlTK$D(wb3leItE&>s zew84%IoxxR>rl(OIh&rX#wRy+njm;V4-nqWD>41Wq>M6V&hI6pyBZ7#!daf(q4dwC7` znqMj}UVV)M7-L4`3O@>PwNiTztqz+=!96NGNw@D0#NvSx%WoQ|EWggPnmEzP1#|xB z6?14S%!uCE%|v8$Z=Ah%I9y%(FFs>1TC|Kl7)FALh|Y*IdW&xKB%%`$y(TgUVT{oQ z(R+{HB}DICL=asN5-oWoB4_7$zt=g}`}^y6&UOv??Va4kzxK)9lwqc()QYSho$fUHDvkF)*&txnR;4tBkh7Ms7FX%6c zGqO(4Ls1OP;#H&{w5Igh69S2+*&SzcJ?I8@87A5dU^)m84&@{Tec*QdOS4-*VjLR7 zTDg!0Fengo?uk#mdH6{L_AM0fXPYx4P5tcxc117+l1DpWN+`4jT#0B9WZOD;4!38= zmm+6CMp3sKAED8C2gbDJeJb%j%?=u>9Th1ehTg{U1oPQ?;I1w-s``9?61IOjb|0%W z`+CQyK%JKA=qwMMoXV?!^8{Z15J`g-d#R(M4LL=6HQhws$D=b4d1Nfz(oo6E&F72q zLt;Cz)~WeP)k-mm0rfE zf!xM8v$5jp?IQ{WYwLiC<;zs`yVpB+C^oW2&NDzZwp!QBXKlg;ZWylrzb3`D55{y)%Dq1QS_NN=} zFvRPSUj&q1;6grc>}%R<*1T2YE&Ros!Us|)4uzDl`f}D1X4mYgBW*)sFii6wCNm!? zsu&6Bd8SNE;xkpLPFgNuJ@iBUYnVYxDCt_z&x}M0nBsWhY_^Vv_ND)VG=;f=s5*t7k}tq}Gr-;fvA!O^XNg05<7hvK~d zfJh`jlbbXQ=O&*aG!blEjrTV%_w9dd7b}xwy7xh@i;0!?lVOe-!2=T0cJ5j`OVgY< zkELLCQqvT+p<#RppIpsw8M4SlL~-^ZLJj_{50-imhXRBVH8c}nYgbjU==zh0Dkca z##-Pde5rA~doj%v=wV_u?5%N1^eewa=A!m(V;NrMEm-q@Sek7e^XT$Uk z;@%|>+(Nn_cQLSwcowpMe$J3O)2(b*zw%!UvCb*d`0jU4JHr+QGYC4`H$oxUZY1g3 zcXyjg^a$L;F9jPs*QU7N&MncO{_|8Jt@LtgoLpl*&Ab&YbKy*)-+-1`HbS<0RMI{z zZ&67I1NQ9gGwK=Su8clgl_};`;@Eh}ox)}6rNdluOV8xe=gc~(5&Z`g1Wa3`0*vwc z^@D*Bd;^d7!c4C_OAD;mz?n5$t8{VU(N@=wF=s7E_8CJnYq#4atk>Aed?rU!>w9i~ z8A$3G*iuxD=HU$g$_t)Q5Zw-tYm8CkJT1o!d?(l$zv}yQ?o(ZTGlJgLz6L~>M)xj_ z(8mEIDSBax8VzQ(c}-sRN+f1zu+Yj~##Au^Wa^yMq^3Mo?SUme)Lg8&XA=6=K#p}B zstp#m|NTRXfEQ;>uel5sB(U?*~IRjjK|41P&uZ;>Dhz0cNvD?vp+=&kkmxT z@9wh`JAb=6M91-E1jO(;DW-r#^`?64zLhbXBE$4&@PQavh_(n6BLIdZqJf*Ta%da( zbaJgcd)VgcGg%N`^CO%IvTGO^FmC2~wq3=QnQ%vdl0V?5ZD1;Tmyhv0qBKm?H`coz_&iZXbm;w zNd=NW7Y5@m%cZJ}A*!pH`6}fkg_;c?4gMC)WBHZIbxJcq@ggg^EZ(Cq^zy(`kQg&i zEGQC=2&2m_Bvr$9F9A7^ls`w&a)0ZyQg3;)1xKk)vK28%+M;R3oUKsvE zG!9@u-dM{RO-?n*WM+RP2N& zhK1n)sc)G$Z2+61c7*l@{L-Wa;i2x@eKiqB4}#98H_!*de;I>qWcr_uae3bY5)6k% znd|_F84pzUT>5u^J^C2|Tf2eYk)Uzx0uQ>GIIy5O>dz`TEaIs2H}sjeS{K0*mAs+; zpIPF{O4JYKpINrJb?yCfp`mIe0lwKF(d+0-Vbp!eI6t;RRXLp2h2T1L93z3#9S;=h zdMZe3?(sq4xyd>dlDV-bs0PHhDFR~^SM5bcOHcH>#5&~4>@_mPK*?Sx%=Q`yi1}TH zF-mdvCR?P~h1rkjXXC zNh-|#{+Kpadk1-38U@J@KZD_ds@Hy~-3bSQ4PGETLr=?+4@sUwhJRd-k5@YH%6$#D znc5OH9xNsig!~g)asxm*V7`9&O%kEb89~Bo#h(HTO(p`k#-g8^597wuQ#nmSBqDha z$BK*xFv&H?K^LFFlzISq zMqYwG^aNH-P)CUX5k*0R#yZ6tUb}^9yXFN+cCoVo9pC^DRVw)F`l3Ui7q>u#wC?p3H0HvbUS-<=cWEpC@`f1(J2aAsi>%1>aFbYroe*7WkcC>L$;HF`!xs#lKL zGzx>dO$&<-XeYUwMOKhXJmR}(xezQ;lJB}e0S~`si9A}gM8EP>>1Tb3s7m=~>@~dH zI})qm#Z#K3gm^mEpT;rV)|V3B@VD*0mE^|<7&wzOC*3$^irX+Ms$BKJ1t*yq-mN{p zsk8NFMR}4;GE()|D0Di$UO2@2e6F6ml-sh3w>*40p5aho=cvGYl_0>xb*M+Ov6AE| ze{`A)jr7vf-!cM?q6g;lsgs7T=WHd42r!_EgRY*>=3RX(|8%cS={hBiqHMAf0$x){ z+HI&|Z6qG?x%ZOEx_AFV^|zqZFdZ9jTC_^78zCcG1Gl{3k3 zHB>FPY~Z%1VU+dL!?%_Ju}x>)#Q-`*e}P|rPzaN=vc?gWdbINKDLC_M!h0qze;>sv z>jXQtp6v>Salai25UJ7a5Ll#S_aH3XbJg>oS+`dHTX!%fp~s=2x=X(!uJ$1^ZVmP{Lyc2ip`mNs_WTlQ7_Yx#d~O;|(>b4)5Vg1Q zt&lgJdf76W&))whd*JT4=8pn_+uj%&ftX37Y6_V#8Cl}H%xc;A2GH0z9d(BE(C$x@ zh)I9N2$4G4zzbav!pU%Q^19aol`h~fv!?N0f;t8AwUp}}j?XckNIx6kg{ zcyQW5ai@U$U1;ph<}yj%wv@e35oku_g|2aVKbpG=gkhz--=91b`tHPNQ&?}SSYl}- zDDEAO_bQstLlB}6$Rvzy8_CHnI_~ke!}MB+6Ns)RNjYnM8k^aJ`t$L~*WW^Xz;2rQ zm_~v4joP1Broh`cg%p&v9U^WRSBq}x{?&RR_}b62OJ<@7@$z@vbP?NwLC{kH5<1Z( zd-pzx3TaM-;;M22y=HOUYnh=Rxl|ESJ2wphm-~~lobY&B6rCGLaB2?&B5c#-2{;SG}Z3W*K z{T0Os%{upSCE&f#_QHuLZu)t={U+UThKL4CV1x^2K#`uF1J=-v-Vo|Y%Bhk8weCoS zeuRRi*-X01dlP$qyNY+OnS+hnTltA7UUTAyT#&TP4%c}J@N|;ode151vfugw5f1Ea z1R#7L+!0Qb*A-BAr;vz!yu^I5yFf7#`ollOXSp}7&GW3}{N^F%Ok!1v25!V4pof-3 zm4}#gLbb6^vSFq;i0h9rRLuk^r%3oDTeCNE(}bGWmoLMA zk=|z+!`$mpx+&#+lU|Ozlx#Gh`wAwLE2`Hq{;I@q7HsyG&oW6yJoAJ2j^LTFR^wqj zsQA6GcSQNYjnqxk(3tR-tlvu)d4@)eND|vc(bo$Z#C_y~XN%}$e(Oq{hqq1BS3p7& zHMWcbZJfmHcCk8xl^#9Er6XuX5&q8tBvYstJVO#^zQ}8_MxbV}p6e_FfanRzdQv}= zQ&!>m9Q(Nu=8SI?u_*|1Cc&(FQQ_0H^MbMB9vZNj8?`${AgjPx`!GdR#kKF#n4y8( z(m}h^(hr!S8+VjBKEUJYGn`XRWp3czw~ag$wI7cEvqvUUD>Z-sa7$#lfQS%qqPk*G z5m7MH=eGcc!*d~nQX#E^!AdI=4mLIYfDN&`Lo-@4u4t@#ayO_BKb67*+M-lwG~7_8 zrN=8Hr0+miU_BnA3g>zGMhlC&=trTOg1~&o%N}WE+@Q zQIzux9GQf{xIGixmQZKX%_rFi$!_fH(Z?1>kWP~M zB@D?c%0{&_BWn7rovFQGU_(|~&rr;u-{#Xb!!#Y~m9cv|Ug}=rdh}Y^OaVV~)xh+8 z{$AS{ zACR8%CJV(*0{0=&R;ci&2n3f5+rrxv(IN=i0M(9wraBf3f0v+1+O+kW6HrA)Dn?++ zy>TT+lCmYN$g}))xX6pIq9rV(j92&*J+s13Bq&&kBzVx{G^@7ljG^}Jv+pHOvkkNc zA>Rs7yK}R^)YP_Le6U0WVRMtqeWs`E!i5I6!xOiLVL04RGHf_1F$xLG9;Y+>X^e$% zw<-NJ5EJ(w!hY2iIwUiv=Nic=D~%0F5M5abO6oR{N)zzZjpR95om1kF(vRaJjv@|YD>Gx9jh0AG*V@Hx69}8aJKYMb``z=nSyMneq|;g9HO0e) zkQ2La7KJ$&~AEcqmQG7nwtdl(}RllfLBHiCqKm45x*Koh`)_ zL_Lz9l--$fR8(d?&25HL{GVAqIj2bAImH$6nMBEneW&=@N{JxD@5z>*a~fGekvsdk z(mKtFf}#EsA2Z3u)PIOM$-ha-{-Hb05%<7A{$mPy2u3lPy4I8l|Bb3iUr6}v`f^d4 zE7qv6l8zF?g0+7DEW_y~48oXsE4szAE8_Y~TsR)nl99lNm(yLZLki?o`xbux0S)IT zaJYNvf}~WH2flLWmVPhKW|){Ypbm3Uk@CV^=rV)&w+7Y6D5Ygk-ukA{FmM?tj?k+= zjbqSpLU27TSDG-?>SU3Ly5yVD?V(M;g95E-@L{?;GG(gM(yGXBWo990<8vdDLLC|T zx9klGqsy9QQNz!zf;(6+1g=$3T2>aj+*g@I{r;%b{*v}ITqHP$R2Ud>jP6kYY>7wC@( z&0we>LKvm$r7IR$J>>WDAVB9+B%W_J9m;=ZGtrLul=CiY8}gC2GE4RY+CeeKM7SpJ zU9~8%^(o}dOJF!>ui<|ocXTG1e8PLtpZl=yp627>P>x4(q@0zM-;1LSfiT!zbC)L( zZ|;fjxsDo(Gc*9J&wiw1Cb0{fAZVxJmtQaV9P^tj%zX#eEDfyQC?VsD5F))OH1f2- zKCl~RXhnIoH-XsrfL+oEG%k=|Xm_y%#Q~^ZErXv0^5bd5PhuM=y#fu@V3C3$vNQl3 z&FR3J8VmvHAOg;-%yjQF1aei#zt|<6N%G!8%PTY(VwjCop>UIZU-r26oPN9@&C7!d zLPWuV)!XNIfm~I0!$>VfT&Z^PpZ={jC8DymO5JIJW0y>{!Zwm>empgYW$ zJH;ITQSR_JAUY%KyP%wR8Jti9FZt5^G|IPAvkH zbz#P&@~XJw=TFJBrMU{@s$d2bR3}**Cxxh>L)Lse230S(mRfA;_jv=b365XQagcAe z%+=Zp$Tto%BE9_u^Ne9&I@yZs&^bSp$Z+tPvhY~?8RbQ3K8}4JwXBXpmS~Kt!3;

y2NNNX2K4~Y5&?Y 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 literal 0 HcmV?d00001 diff --git a/mms-lib/test/mms_codec/data/m-retrieve_1.2.conf b/mms-lib/test/mms_codec/data/m-retrieve_1.2.conf new file mode 100644 index 0000000000000000000000000000000000000000..5f815917c59eac61411822df44a55b589ef9b994 GIT binary patch literal 137388 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%0DI<{1 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 + g_error_free(error); + } + return FALSE; +} + +static +gboolean +test_files( + const char* files[], + int count, + gboolean (*parse)(GBytes* bytes, struct mms_message* msg)) +{ + int i; + gboolean ok = TRUE; + for (i=0; i +#include + +#define RET_OK (0) +#define RET_ERR (1) +#define RET_TIMEOUT (2) + +typedef struct test { + MMSDispatcherDelegate delegate; + MMSConnMan* cm; + MMSHandler* handler; + MMSDispatcher* disp; + GMainLoop* loop; + guint timeout_id; + TestHttp* http; + int ret; +} Test; + +static +void +test_done( + MMSDispatcherDelegate* delegate, + MMSDispatcher* dispatcher) +{ + Test* test = MMS_CAST(delegate,Test,delegate); + if (test->ret == RET_OK) { + const void* resp_data = NULL; + gsize resp_len = 0; + GBytes* reply = test_http_get_post_data(test->http); + if (reply) resp_data = g_bytes_get_data(reply, &resp_len); + if (resp_len > 0) { + MMSPdu* pdu = g_new0(MMSPdu, 1); + if (mms_message_decode(resp_data, resp_len, pdu)) { + if (pdu->type != MMS_MESSAGE_TYPE_READ_REC_IND) { + test->ret = RET_ERR; + MMS_ERR("Unexpected PDU type %u", pdu->type); + } + } else { + test->ret = RET_ERR; + MMS_ERR("Can't decode PDU"); + } + mms_message_free(pdu); + } + } + MMS_INFO("%s", (test->ret == RET_OK) ? "OK" : "FAILED"); + g_main_loop_quit(test->loop); +} + +static +gboolean +test_timeout( + gpointer data) +{ + Test* test = data; + test->timeout_id = 0; + test->ret = RET_TIMEOUT; + MMS_INFO("TIMEOUT"); + if (test->http) test_http_close(test->http); + mms_connman_test_close_connection(test->cm); + mms_dispatcher_cancel(test->disp, NULL); + return FALSE; +} + +static +void +test_init( + Test* test, + const MMSConfig* config) +{ + test->cm = mms_connman_test_new(); + test->handler = mms_handler_test_new(); + test->disp = mms_dispatcher_new(config, test->cm, test->handler); + 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->http = test_http_new(NULL, NULL, SOUP_STATUS_OK); + mms_connman_test_set_port(test->cm, test_http_get_port(test->http)); + test->ret = RET_ERR; +} + +static +void +test_finalize( + Test* test) +{ + if (test->timeout_id) { + g_source_remove(test->timeout_id); + test->timeout_id = 0; + } + test_http_close(test->http); + test_http_unref(test->http); + mms_connman_test_close_connection(test->cm); + mms_connman_unref(test->cm); + mms_handler_unref(test->handler); + mms_dispatcher_unref(test->disp); + g_main_loop_unref(test->loop); +} + +static +int +test_read_report( + const MMSConfig* config) +{ + Test test; + test_init(&test, config); + if (mms_dispatcher_send_read_report(test.disp, "1", "IMSI", + "MessageID", "+358501111111", MMS_READ_STATUS_READ)) { + if (mms_dispatcher_start(test.disp)) { + test.ret = RET_OK; + g_main_loop_run(test.loop); + } else { + MMS_INFO("FAILED"); + } + } else { + MMS_INFO("FAILED"); + } + test_finalize(&test); + return test.ret; +} + +int main(int argc, char* argv[]) +{ + int ret; + MMSConfig config; + char* tmpd = g_mkdtemp(g_strdup("/tmp/test_retrieve_XXXXXX")); + mms_lib_init(); + mms_lib_default_config(&config); + config.idle_secs = 0; + config.root_dir = tmpd; + mms_log_default.name = "test_read_report"; + if (argc > 1 && !strcmp(argv[1], "-v")) { + mms_log_default.level = MMS_LOGLEVEL_VERBOSE; + } else { + mms_log_default.level = MMS_LOGLEVEL_INFO; + mms_util_log.level = + mms_task_decode_log.level = + mms_task_retrieve_log.level = + mms_task_notification_log.level = MMS_LOGLEVEL_NONE; + mms_log_stdout_timestamp = FALSE; + } + MMS_VERBOSE("Temporary directory %s", tmpd); + ret = test_read_report(&config); + remove(tmpd); + g_free(tmpd); + return ret; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/retrieve/Makefile b/mms-lib/test/retrieve/Makefile new file mode 100644 index 0000000..4c05429 --- /dev/null +++ b/mms-lib/test/retrieve/Makefile @@ -0,0 +1,7 @@ +# -*- Mode: makefile-gmake -*- + +EXE = test_retrieve +SRC = test_retrieve.c +COMMON_SRC = test_connection.c test_connman.c test_handler.c test_http.c + +include ../common/Makefile diff --git a/mms-lib/test/retrieve/data/DeliveryInd/m-delivery.ind b/mms-lib/test/retrieve/data/DeliveryInd/m-delivery.ind new file mode 100644 index 0000000000000000000000000000000000000000..a9334470ede986cda8dcf963f0600ac5b8230277 GIT binary patch literal 52 zcmeBa>z&xj611hBrQ6BF$i&&n%gfQkAl#5)YU6ZmV^a%L11QiBi41VH4e;^vWdH!b C#Saz$ literal 0 HcmV?d00001 diff --git a/mms-lib/test/retrieve/data/Expired/m-notification.ind b/mms-lib/test/retrieve/data/Expired/m-notification.ind new file mode 100644 index 0000000000000000000000000000000000000000..4555cbf433f4a0df472c6a7944561ca687a45fdf GIT binary patch literal 129 zcmeBan&ISW9Apw^G9gP2+u4 Re_{TG9T%G}Y`xgP004}>DGdMs literal 0 HcmV?d00001 diff --git a/mms-lib/test/retrieve/data/GarbagePush/garbage b/mms-lib/test/retrieve/data/GarbagePush/garbage new file mode 100644 index 0000000..e41b2a5 --- /dev/null +++ b/mms-lib/test/retrieve/data/GarbagePush/garbage @@ -0,0 +1 @@ +This is not a valid WAP push PDU diff --git a/mms-lib/test/retrieve/data/GarbageRetrieve/garbage b/mms-lib/test/retrieve/data/GarbageRetrieve/garbage new file mode 100644 index 0000000..b5185eb --- /dev/null +++ b/mms-lib/test/retrieve/data/GarbageRetrieve/garbage @@ -0,0 +1 @@ +This is not a valid m-Retrieve.conf PDU diff --git a/mms-lib/test/retrieve/data/GarbageRetrieve/m-notification.ind b/mms-lib/test/retrieve/data/GarbageRetrieve/m-notification.ind new file mode 100644 index 0000000000000000000000000000000000000000..ce88f7e0e5dfcd6e5ad2684278bed2d0e1090f9e GIT binary patch literal 125 zcmeBanvrX0kYkx^UTR>Rn_Oa)m6U8~Fx*GbJ5|4MVHZn7Rsc+6GDJihh*9Yn^GS#=wO)V}?Oi$I#OtHmc G3j+X9ktt39 literal 0 HcmV?d00001 diff --git a/mms-lib/test/retrieve/data/NotAllowed/m-notification.ind b/mms-lib/test/retrieve/data/NotAllowed/m-notification.ind new file mode 100644 index 0000000000000000000000000000000000000000..91799ac0a4e424d51c8d03183d0c36ae918b2de0 GIT binary patch literal 114 zcmeBan&FsYkYrg9;pZIhlxpZ19~Q{aJE>E$LEG5W!qmh70`x;716*wbe0=>F+8VnW u`k0x-Cw8zlGBbavZ_X$wDX`Ml&&@4PHZig?G%zqS1atIF;*IPv4F>=Njw15_ literal 0 HcmV?d00001 diff --git a/mms-lib/test/retrieve/data/NotAllowed/not-allowed.html b/mms-lib/test/retrieve/data/NotAllowed/not-allowed.html new file mode 100644 index 0000000..adc45b9 --- /dev/null +++ b/mms-lib/test/retrieve/data/NotAllowed/not-allowed.html @@ -0,0 +1,18 @@ + + + + +Restricted request + +


+
+

HTTP Error 403: The service you requested is restricted

+
+

The service you requested is restricted and not available to your browser

+The restriction can be based on your IP-address, hostname, browser software, +time-of-day or other variables. Most likely you requested a service that was +made available to a restricted subnet. +
+
+ diff --git a/mms-lib/test/retrieve/data/NotFound/m-notification.ind b/mms-lib/test/retrieve/data/NotFound/m-notification.ind new file mode 100644 index 0000000000000000000000000000000000000000..820e689004e87978a1cfe6d2d96e5998f516c762 GIT binary patch literal 131 zcmeBan&ISW9Apw^OuJ{0loSHeJ|yv4H^q1jQ + + + +Document not found + +
+
+

HTTP Error 404: The requested document was not found

+
+

The document you requested does not exist at this site

+
+
+ diff --git a/mms-lib/test/retrieve/data/ReadOrigInd/m-read-orig.ind b/mms-lib/test/retrieve/data/ReadOrigInd/m-read-orig.ind new file mode 100644 index 0000000000000000000000000000000000000000..dd3fce778d1d2556919e849da3969471322054d3 GIT binary patch literal 79 zcmeC_=$+Wg611g$dZ%QAwy~*&sR0z|heQUr+6MUe`Z07nc^H{EJ9&9Inizx|GE4`l OGckdvGelB1y8!^aHWoVo literal 0 HcmV?d00001 diff --git a/mms-lib/test/retrieve/data/SoonExpired/m-notification.ind b/mms-lib/test/retrieve/data/SoonExpired/m-notification.ind new file mode 100644 index 0000000000000000000000000000000000000000..3be1e75895c914973f608f1d9e0e477371b5ffed GIT binary patch literal 129 zcmeBan&ISW9Apw^G9gP2+u4 Re_{TG9T%G}Y`xgP00507DGvYu literal 0 HcmV?d00001 diff --git a/mms-lib/test/retrieve/data/Success/m-acknowledge.ind b/mms-lib/test/retrieve/data/Success/m-acknowledge.ind new file mode 100644 index 0000000000000000000000000000000000000000..961578cd37e56725e58e00ef57d41aac5a91d1cd GIT binary patch literal 33 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 z zPl??WK79k%>c@WlqUHAz-`yCd)E?H}DA@K{r0PTZ?px#jC7w}Xcl>T>imgk$AdOFy zvw>r6tOz4cUb}TH5OwKm@3+w%-E98SePOLBL9Ug39qX)|TC^7J6c0a6ouFOM%)71Y zIUCGk?DYdQR!GRuS}@w0)AZ@{*4EaobF(8D)RJduKt_@3W6cv(_HXJo@Wu^UqGtM~dkCWEn@3LJ zCuR+wCF?rHOWZzv_LcONF83<6y~}mv@$S-$XWvs!C9TP`%x)VMs0`g5R@(|Ppn81r zQ!+e?{Q4bc(_p%9Q2Q?iTpn)DVv6Hc4ZCt;XYO*hQ>a~GvPv}-$GJCVqP8?BK27g$ z+c^$?0wN|~SkRPi|FhK(5dPh3o!9R^xmwpli-O*y?@6bkn0@tw*6vsNU0tThqzr%$kD_H3U}c>7!6p4m``o#k1%+Q>CaKl4^zdDylSPE6(%d z$*amgKxu{!y1PeT`?V&FYs;Gr-%;87qI!2VcEF0Ffv_7g;=eD0&YIK8&KEJRq%YxT zTp2CruaMihGtbyj%DDyk1`TynN&)kRt2<`XV3q2D|4u~EFyo84mm@BE_t2=E3pG9IhHjFVV+0RBF?!j)^YvjJ+cUcBT{G_< zdGLFrrhok=eHoo7tS!~Yzth`HzR2m?wIJ96>-@)-N9KT^?>%iGTG&U zNlS`M$kPjq?rL9&9k<(zDc&bjE2LHdUv)U%{{f0zkm^~yOY!XCc-~ZRRaH<0xO*HW zz`0Npa4cQ_46r>Faxzb3L$_cn zTg)lUH|MkUbB@Z1(vDEp+#XRkwWV|g3&s5DMI8&r#;Yyk9`Wjli<`FB+EUj!^kc>d z&)$_rHKTabh_M=!>`W()ZJc<`yc4|y`N%sPK5~c4aue+(ylAS-zx$DI(y`mhau5~> zO~s^*bCVfD#r8yrk+hv^LV4|S{5wy(>8>N&#hnM#jO&qzHm^Xff=|8f=FLw&YorVW zqlYyYEIf{QlF#P0c+2Tz8|y9h`WF>Vfg?}$pBCRPxpIH^lg-0RDK`pSN*Z3}*gP1$ z8x4+(v~X#SVNP%LE34O=#-zG@qtaGQsRnb~awt~Q!i9g*2oD5~Ly>dGPO@c%apf023 z9B102j3A$Rbo<6)>yLU# z4BQs!=~dyD2`<{*QM|>^Tx0puKHV@U7H1ys{{Ysika^MS4{~G9?EIU$XWo^7+>YIM zbfz@1$9o;N!dbyN1A*84DyY7g5f(ug}F6OvN)S^0q1_3|Tg&yK9Y8NeQBnpwM zd5wddjC83rSzgw~<%l70MlwC>gqHU=MH*?aP?9j6Dp{hMNL_Ajn8q+poo*&?Cuk*$ao&_z+cZJLvqg?R za>MIR$Oh?BL^SzurCE`(?!az2JOQ35*0ZYYE`?Y&2IG!SIQ=TMrL;0zJjzx?3dLDs zWa*xBpK7wLg;E=7&porB^ZM1ta$dyQ0!)0|&R$H7SrQMdg)eC<5ev21ow@TD3$LK?X=k4Z8=+JAUZL_)^0!&Niz3;-Kvu zADbun{&io>P0%L)0QG?EBcQ;fg@Gq01I#Icagqt=-k6IsI?JbCub8mo3R{3a@X7pZ z8q!oS&t?@YXtiqln5YFv=OMnI=kTk#Y^nCR zMtS1{C*R-v=CWd+Y@kdS931?<7{{S#v zbH`KZQCrONw%F!E=%hF@43@_jA5eN#tpHyTPLfS((gjyG$QTddJmh1qT8_%)06@TU zqXRtRs9#9)Ok$oHizSKS(5e)A!}FG^2QrKX2L4azZ*!jjxB zJ&(0Y9yL|k<-@M=kyr_LEwL#w5=a;*+5Z40t-*g6mNI<3qhMTSrmf|hzw*g`toORB7b4<1?8e78GP-Zz* z+5ExNc{NYO)1=yb08JCPk-^x&@!K^iG2I$Aa=~zkb|h$^D}q{GrB5G)Sc+K4^S;qC zMHkBZ?l4rI$FM%t&S;3YIz`2}KQWMTk(_+FAQM~fqFcSR%N^>EGEX&?)C`_@gXAO*C`O0R0NGYjCZXpA@|{6X zat04fJFUwpdVe-WhqA-5WC4#1f)x4mAdg)xnr0qs$|cQGR}!m4m`M14gl{?Kwp*B?@U z#+&47EHSl0usO)*6&#luk((vMOEw-@OlZ92K2SN$Xhw?G*?Dbzh6C>@+m12)DxuMf zT&u}*97+KM5Ig51pRG%&AhFY!i4thgE>sSqZ~~@q<=Nb%?ptW^(fN{F77dv9ZU;Wx z`&4UjJcnuW$Wep2SaH+VtKNWSwGV=2ZHjsMNEy!u-n6gD*n|*1PfYd|pF+~qt`F{` zV)ouw%d?iodt;h=ORmabvBw7iBtHE}a>fIE}zO_8pW{95_I zmi1AJb;OD_RgLh>&y^%+9QLW_F%4WRBAK^v#GK>#Qd+PJX|7G**@=yxZh9P2ndED> zf#X8JXN=UghCl5g@((*W+#k2nnl`QMl9-vKA1NWbRHb$@OJ@?^i&lwI$;L|q{V8q) zBI)glt2pj4j+GSFk3G{|LA%ZB22_7K%x1Zc{K<@*@&OEgN_GpD#ISkI9C103f4IEy z_|OpFag&Abx%`EiPl=G0GgujWR+S}1;0%+3Dtmn_N24v{G*gmDXyf^v8;%Ga4OCNm651e$ zOCx^b;hc}|kkz?uVX{B;tJMxhLV%!w@0!litnN^Gl0T5G{{Spg`IG%B)tI%MGsPb5 zt+emS!Tf7@!rPg-T$PsCtFM_X%6L0ee@cQ|MVv+=Nl+mKGZD@|4AzJP7z2-`JGW6) z%7t?$`#kyPQ?Xp&lgnrGsb1fI`sZmI)SP4T=~tKzdFG%!@H%?cB#CAea5BXo&IVK; zxI5A#F8zx#@6SNEt0O*4I3M!Kdi^RG?aInuesaX)9gT3E14EXV%M(evrvTLQ+JB+U z<(%xt8TB+OeBqh;F>G_`j8&OP{?589$iV(|z=ds*2TmAgoF3+(zPUDq7s<&v;QYA# zD)Vv^k@tN)>ZR?vTsUcEDnP*FlUX;ZOJZCCz?|gw%~ziD%DRppFFS|?l6#u48Gc`w z5sYNh8VDql&SF{D?%?r4y~fJ{7oIuws!`lX+OtAH@`iZFwOMKA8N?~Hah8-1=}ir2 zk~FUHq=)^YPx7Xd>`sN$19;#HV3Fh0kolO6Bi*on8R?JL^ruHUF$GD$@3fk&HR21T zjKU0!k{bZvbC2ay8{BM~_TC%Nn=e*9t(IM_lloF>a#`G1v@zX=l3%&225$Jy!ALGHr7O`5~C=5{a zZZVv5Sz+Z27TQV7r#Sh^G?x)Pb3&IPi}_%k-1jtTxEmJwot?g(Ar{eW$xJk-Bo^nt zp{Sbv119L;h%i^e?%Xn@ZOA$6*0ZePhsM6OU&|IzcCzDZ% zTY!!rMSaRhgagn9J+Tt)nW3O>j*egk3k0;D9 z+elxVIU=i>v0B6Q^3y^XsQuRpS%QonIIYV|TV{z2k)z1OvtnLB=hC^g5~)#daOg4j zSwZL1nzbbNa71QFV);jShG2TG}7c@&nVE~RUK zCAKLMG@-H&WAgF!9et}p#(%T~eM-@;kbuhVAW$=ofDSwURWF^VG-e^ET|}_@51c|LsEf>kXhPIjsc`UMo5Xu1DSn`cTz|oy&McW6~)5g zRSxxRmcck4xUF@8Z>O4jd!39FH^6=LMRXd)m8O$?EtX}NnAM1y zA~Nq7I2?oWmi))36@@*al>X(~ITxI%{*`e^l8^dS9$c{7%N$Bvsbt)vaK~}aTCW|z zh%ebmONQO%m%?y+a(~WiQq6DRQUuX43{LqY4&SXSS_xgGonv_zQU2x`52h9o5{QaY)?6=aa{Nm0m2q z1IkHplnTxt+}_ULWbX~`I3#L=-=Y{|K>c%l-^6U5{Z<*>mX6u zESHgo2L$292+lf;9@NcB&HzZYyM|~1`AbTQfA5mnt!+zIzPSKgd5RPO0O?q_8zqqk#W(Op7iTt%D5x`KAaEt+aJ!OXq89ruOS)k{mGfYu?W93A~+47-6g6sgtPJaq@&aDRYb8RDSELSW>(~M@Ip6Y2Q zj!|zDp=_XdPzL9Zl-0|Vb*RB3y}S@as7@7-anpqzDOeF*wUuZ|lG(PV3gn)7$u$aH zi-=xWp&v2E;Bas~bM01q##?wT-U}t#gbmQ{c|FcpjMgR4mNy=12aGBa<&F?zILP3i zU#B=cQEtUtv8Y^1vZJhQHi8K)oP8<{4t5FT$_kZj>dLvnt9Nb;4Ew%9p#5`DX$}5` zBRJh4Js5PXuc2K_2HhvTOP0CX(YHex=LgsEsV0Mdr5)p3LGtw(#%c)WXs_ac=MoH( z4n2E*6(o(jQWoq13^UCN;7x55zuJQ3b~57|clW898Kv{vA|)-Ko4*xjOwz9Inamcd zZNb2hvW%Zh9%|e=E%Hr|vM@pXNJD=kNpmiPx(y=M+T@6gaAGg3HAxxl zuEaw)CML)7sP1fa1iz1MozIp?$?}^WewEfHy=GGaa8Kh?4QAVD3p$Uf#aFUj!<^%_ z;Vc&^`?ec_&PG3_N36Rn7KIaW*~rJWb=UqQTSN;JytBB<#Ef~YNus>fWHRbVn*6_h=5e%8%a2)LS1CD<>(X>|cfRAxfIRl|I`0de9B9ahsh2RRa z1Zx03SljgPS}5CMZ*l7c#j)kG`@hTl>aLq@92V2&R#q|-vu;W0&u%KqmSM{i>7HsZ zFnBdck;?oW@k_toKT2Q=k{HpI#~_jQrYnlhNcN^2^MQ(f;M@QQ*OO65;RYO!rg{9S zh{iW?G-@`m3W}ib#y?JI7q;OPfC1=9$p*7`E;GjfcA!fZc?dp&xH+^s(k`3m`UuMr z(+WS&=}Nb(Lnwsdx{bti_Qoo*%^x^!K8BTUl|jlA@6wW!9g(1yhtC3C$`5_n?@-*! z6QGg(a9pLSgC7$+lgGA-o~1I z+lyhAmQt<6az`)Bjhq4b)w|nPp5xDHQ+WUY2Wq)z0SaVB1o|G89nI8Z<&*_%ecr#7 zUWkjcF4ov9w1t_8BxH8v)wYSZXKQil)awhRbs_p?zF0K_K zMfsGrNa;y;GD~3~Q-&D)Ijsre!OIT4$*lXURCvz{N3f}JMJW-(J-~%AaX%n`%R^Et z%o$Idm&oV`%lxXSz7QcmS`bco zV*GkkR|*ZWW7q3Ra0#F0F&;6rFBB&FgYq|{lWn*;3ZHoTQK!i$zIo$lB#uQHNz|1; zF!Uqe^EF1^TT5$Tf?3EQ@WdQ`nX5W^RyNEzVs19>PdVcmJ)qI6;yfJV>;F~@xM&o~;b6b>KFf){2Z4Co0M z^d_LXeTgF+E(UPDs-mn7qdweRwZg@AGNWu_SmRKj0CHOd9Pl~8CqJHr)w1dKk=)z@ z$j2dAV{jZc2UhAkudh8Tn!A>3okTs2!v^RTvIqE9^`l)*8MQr+AYx+yiv#ZL2`XMaoA*N^ z&4K>_0Vc8`x@jROv%76PXNEuGKMI}Y)aq##2`%N{ zBvZY#;N%>Vzd_tk>^P=hYne<&IPbP52r1?;>(pYZvq*w9-V~P@eaEh9Nvv<9j7xJ2 zQe&%iWA*j?Y7ey}sFBYD1w)*u!+wALYL=Mvv88UPz%;k9ux{r)z0GJx9keYMohp+) z0xL(1p4=a(tnD^rg``Bfk~rCacX70V3w7u@Jogo9-(A%1C0l!aWdjD9+1UhCKT1skECY?985C0e|QXR{qx3?Vd!s{?47(_*yu@>)#+B@Tun1 zU9O{&Xkm#lmsr#dzbPNX*OS(ws=RDC_Y+MS8lv_6;*P%6a?=~%pW&=4YvXNcsmMqS z(r%AE{VDz!)gJnJ)=;WeGTdjTMRK@FGhSrP3t^Q97|6|N>O^^kx`4IJSnEo7b-);{ z-E!(XcLDgy`g`J{P?1VX<;^XGw%1rvzb+1O?^OJx0Q`gUsWd6pNN&QM;YNR2s`s#r zjm?q%$*kOEWHi>Lok^7~ZL=9+&M{Ky0esbE6;oKbNVNNBazJhe8K-DBX)VH{kWMmq zHGHo35^BZE!WLBH4C3H zPw9%4P3%5&X(|5zPKS^AcOUyTbJvE@J?l#}kjv+=E42K;9B^@udeWZr$<=L`=gIpR z8NvJ6YNtJ^xsb@rHh%Nty`}U+z|{G z5W^H3M)dL#M(q)25`SX8HzSEz zMn>k(^Q=U=dvWAQP!&IP5Wt*cs5q{s3mL9rXyj*&58mWt`&MSTquSZ&!J<;q`HP2R z&w6W6ZrTenfS{k5Fh(=!QCVC?b!O5ODmPlscf5Xw5)DOxo%al$mIV3fu&@HZwC2^xz0x&y(*JMaCJ*ZXdJsP zRU;wE9Qu7~OXYa=h$eVuiZC$7R4Oyiwkl$-u7=s)T51-tz_G6E3QjnV;(X_U zzNB@(1forIEW`Lz@%WydJ?OZOqUz?(IND3G7T$jPgVWNvdzrtrBrB&_Tfqo8Gx=%> z>~Y6G=cQV=(Qa;?XVo_c1Qk|0RclRcUM;H}K&U-e8-FpHp_!IiWOm;%{p822j52fH zu7w`IrCm#G;hKAK{{T$aEZ@?UTSUaGOCbLMWrD}~9!(dpib}a`1<5_S)0x!?4pmM$ z8Ro4UNWdy(ofG@AHwW>@^s4IwD#vKrJ1YzW^gU1IMZ&~uDzN+ChSQ(rQ3jEl5yhYP zk3W#jTvSr5yFm0)g+GTX9gmgXe`qKF%ug@ms{{UcM z52^nE>zcOeHf8dzKIwmu{sW<*MgeI?2f1_L`zD@9>s<{`Hym2Q+i+l46Tcsa*H4Qa|}bDWP&dvnRk^(Wr7Em7kHtFb4u z9xFt%BL4M3UYoPi>r58e$wSw-YMxG^%swr%E*l}oJoObO{{SqJCn|f?OB%5%+qW-2 z{d$}^MLUM%9S?Eqn$a=}H!$H@qXerQ;Nt`7%~5-0Y_c~1suvK5 z$-^*h#NdzR?M}dDNp1#s#XS(wsKmubT`atZw^jMsM)#ugPZsO|@9s`K13JOHL~%eG1U>J;KW zR$8!(*qI%e1!41TAP;T@R=JQgw<|moGk*hb01v}&^`~j}iadp#jGr(B9)M@ky0aX9 zUdCLbb|aJcb`^B}>)29!yPkV*05@@n(C*33K8CHz`wr3wY~uw@bdu@TzIH@^ycxhl zfGRm{WDT)O;ks_EIV>)8&S@oV~+NTf49j#UpHS zASC|pr&EqTl@+e7G%%EwF!6!6pd^oR#%WsHj^QSvTHTUKJj7whG5-KwDjQ~wFkK^! zfgi*(O?hnP1g)W20mtsw1pXZ>M^Cl2TUh3jH1kO0lb&c^31+eEaaY>as2Cad2&dxg}`pSV*@y=Guwm>Zi8*Ia!C8mezjH+LTF=_BMrm( zYDLg+eE(>q#Aywoca(w)O+&-gA}i2fZ{R zJv&2=2@5-X*x+z>{$SKoc{1wa6PDVfF*xVb`qi0kVbtRb6vi1;g1Py56_0;yBHS}f z0gw;8hm%>vJzPQ-4Ekh z7CM~P(FolYlpYD=01OZBisg z!m(gD80%Fm^=pGD62yi+pCBNQ&Z_ga!DLu%I!R?|UJzZ0X5@7>X|&nrRWiTGgQFbd z=|I$%97QgEf}1|1=G~D$bi{q)z!CJU?KV=eY8^Hu0G2zwMOcO_W|6X_>^o}))_Kx0 zqGyqFoyU{;)$3X1Wms+3<~b%tt*F9D-bBhu+8UP+G(R<(!6J7Bc^{5yqw2pm@9h;> z_Xh{_t1?_Aq+VpLfzT)%ljsFzU0h7pOd3{CkYvV49e%xQq|FutFlx;#YZEJ^SwhSX zO=pcZ_Sttp?;B&G0I%vRqwxO#mdf)lnb#O#2l6$sB*ZQUem<0)JL(+PIqMd7wFXbU z>sY=nBx!6=kp5!rBeCb2?$T|Mo_?ZZOMNhK zjb*x)O)dcnG>2rY=X&sRt%2j*(oFh+3|yip%kUEj`@+7(fiV*bk!U({2jZ<`K0zju*a{{TX! zB2hb(Abj8T$RFe|DlO-d<#Ybg2!F<=f;9?GWRuxZkbY}XNDlLqNJp!>IsI^G0tRPh z==*=#UBmM=F7MrtyL0HQSpNXuH7XX`cE6qM6~O-h$9Sk2Shgfs;2xwQKlt_y06rbS z9pI@FsugVGhPSZ`8?&c6AY;xch{{YZ| z{&WE8a-biPJ&6q8lVFNd^Fj&4NBh!_eY$iwE0~@#j8Xc)-jX+0HB}! z3Y{EG$XfARKi-?C{yg8(fejI~e=%i=Pw;T0{y!}+e)y3Blq0L-ck6@v>CSV+GKOF7 z#z_bM`A|Pvo)|xOxuEinKJi5#s}n$uV%jp+(2xdp566!6Iw;4>x6sr!vM{rV?jLYe zO?rZ04;{1GxlV%1MBEi@5&G27ByK)+JI7p{(_)cj`>a0$QtcSv9Q6bWb`bLybvSQP zPe$GHwgV2-$laTV!nd!jNa?t9&N<_;r(hJPb>W9f1fMq2FvF;(s};bIVEUehoKq(w zf;v(GST`)7tA9VOSD6+~%ut6NdH(?GRi$(HWg|Ymv^s9bd~zreknv<>5NU{j5=p@w zu~#kz)6d@Z1k_u14o4!DfQmK-Qi=|GpMJHgZ4wj*9ODO{=Tsq4ylz~dP>JuSYTn0Shx*w%x>i13dVTj#M;f=s@YdIQifq{)rT&m^2S{#xE z8=X;jn%2bQ0A0G_6( zlRn>4K52Z+!18tuznyBx*D|ieiX?0fWMj|eT+G)ItUCb(k73R$p%-lMBj7r)2N8^) z%M}o9?o^ewGPS5KRpJuLt~op)82VHevG4oL?egatiMUFJMTw*w=8-mKU>+_qWJ zjErL+hG|VOiEm^ula&R%aZsD(Oza%`04Q5zk@J!VLP*|E=T{LThBJs=hf?zVpng>< z7b}>~Ys-m1U%0-wrzO4Ys>U$Kju;Fm{7qVYNJEm6AkS!&6ZzFkjYo145VIaLA*afg z>{oAK7L&0^q>!^`95!*yb~~HOW4U8YWtj2$*A4dDghwkb-Mw}w;;w0$3Dg(QxS5a~ zAD9yD`Sks3N^Z|WC9daDZ!A+rOb!`yjqAuHd)1Z0rUzf^RIP$qs=%%`B7nI(@F~r7 zft=yO;AG<&u9VEIL3HgBkl7o32lB3NR~zJV7>0gH7_N%qLpTlcZT|pgn#-Qk%*l_F zQzV$k1#goay83q&F^!o` zoacxK`VooYDVN>3vQBV+#<8Ihgp3w_tH{FO5u<+0eo$(i#gy>MLddE~>7KupX5ZXN zb2J`i@gi=+GVSY+@TWs9=h`EC$=TwJo)mj}QghT4N6Qt#Cvzr!K>q;iR4wL=?usq^4raF64qQ(bo^r!<8S#65_*+}}2@uJ>a zP)=fe4_&|GTJxkn)IsHQh8e2p1tpr-KO|510sRd)&lv-3E>FJ|w_$7c*)~Q23)PQ7 zTHn}lDr8PW0nS&7o>s?ml!4@byKl5-(=~b|y>uvyBOQGY;ajn3uE6bh_Vy&6ew7r~ zw@?$dJ>dTUb-~Z!)}J6L6s&aAh0Kz+`491R#ao^v0KUw>ul1_WZFtvfa$uagDNq|b zaD9O5P+VQy+YQqfT=BINC-tP{knM8XT#YKyF*-;PoCo6so_%Q-T7pL0ORD1?GyJOp z&hC9r_fx`=rqdvpvtfWZ>5pGd^w8GAD2)*HJ<6mL?g;m- z+dUdMVNi~{SAYWs$MdR>m@^kn(4ujhiMN15Dk_|*8T1D~jc&&RKn5UUJ!Ho}fl*U= zPY>OJAN`{d{{Z8E)|hUjZF$8J5ar}SY;%M*3Dd3}i| z`39ytOM|%`NBy(|^&*=RTa)|ALZ3tB{{U7sEM=KS;;*su4{lbyBvGtDc!u zIsC$}^Q91si7w5Y^HK3<#L(67B{@e3o2bzEov z031{N=?tMfpJ+P+d85%h$NpprwQXW~>7KR9tZqmn0~-KRI$%`szh?X2&ZC8cE_xqK^r!951pXtnP>C8fWx*XO74~r{ z`ZujGN)sYdIPaddk9T@rS5m`neqJ*}1a9w+RUi<+dKv_bt%ez1&FS^7b_<4&0tJ3Z z%Q3*~TS_imWu%Tgj(~3dbt$G6v22`!o}DW{P`wtw0Vw&sdBs2M`@-;1y#5_HE#xWUP;8Pw|q!zs4RoL@@N&N>j=`}d5;t@s;PqY_JP1g~5k_{D2V>f}sNfk9*$2e{);xH z_LKbam-)Q2mC5PBAJ(VqycqbU|*S$7aWs$=>Bv|M`$sWYgbr6&bH#54ZIRKU!$-pDq)~YO^ z#7q%L$DE);kItl6M1-_~r)4?F`G@7wr+yGL?;H#K8{d)i6qA!4h{>7>2;A$jKp!bP zi2P}7<5@D3O^Cf0k8{unvzG}+cGweTi?)DL^`w&(oMe1G5qQF_pvtZvZFH` zkQipW6_$n?n;u{TB;X2cZMc~aU*Yx@LFWVnKgHLc)fL{LZFUtv;O8KmQv+7w<)Ve0 zXK3o!;YX?Vu4aD{tk&|25QbN5A#hoke|rRD9kJUK>9uE;Cyd0Q7!XGH$3Kl`!?F^l zIFJ<>Q;g!4_%k&wu-Zvz=JCr`-Me0r74Yw|i| zf73Pp01AA%-P~~&dG;v4Bq$%qQni5T;EmQkLjM53PJfcr7YGh_JcIrLD}Pa3(&{%? z5rkyV_}BOSqy)~X=Q$zy|e&noBrq*4C>p)sl9kz*eu(Bs{rU+8O{j^0N+ zkUv_omW{?sehXC4u5=%7iC6cR5s&v}{{Z4vpql=~smzi${0>9?MP;p`XAD64wOL&~ zO66lM^g`7(9mPw#L(EaBKGA=R8k#Ldk-kVA{S`<4%4zoYep=+kE znkiL1WSm9(g$N1|!+96XK#hBsM340#)wWSIXE!k)U*8w~6oE2et^>?ndTfve=z#_WAv#RE9Ou5__bwUS#Fqqlti!vK11p8d;RnL>KLuVa&*-m z?J3XlrxUXy&as2*$^A_LJM9dug}j9Kf!xx81#)n{$$m3gckX9wmuK%TPdy`Lo5I(C!N@a$UVu$W?exfvXb(GPdGh=DQloDHya$e zxQ#aw3xVy{w~^HjGEcBQD+()kkOEtA2P2Bm`%3@>Q4)Q)#V9KScP`5=)%g*d=s>J( zNu-phm*n8>9dlP1Ze+$Vi{7E02%;hGrvQ#d<5#&RbXEbB7nE+sag5cQFE%KAvuGKV z{H^LUQ%7@Z+42vX!;E8ZKaEwm*4 zhp**Wa^Ky|#f`+Cm{WmOio3D?_i|4(b0JvWmr${c3j1&*j1FWET1vw^QrcQC=fmU+@OiP&BnoVo;zFwqLF&J;5Z`ycYi=+C?udf8`=h7f=~z-p zC-!u*q^E`XaoGK6)9>e=1`=ROiPRhi$@J}2LR;LLk?d@jLd2=s;NXmZKU#0v1dLFP zt=Q+U(zB+$i_9UItK=S?IQ?m`OCd6C8A5WT_Vwep^sU^|Aw`p3yAY_`im}OTjz0>> zy|t5KG7bRgS7O|`GD^?S1F)ns2V$7WJ-ur;E1D?S$cdOAx__l=Y0?t=S}!pNKR0iB zRS}>Z0()^%rdWKVYWq^Za*Zirjzu0*>^_J5Y2qc0B1|G;2l2=VKc7nH@3lznS(Y>A zN;t-PeNAG|dvkQ}=E~(*ACMEb@}WxG65_g@2Bob^35q6y-2mrgs!!%W`qi6>Cp+bp zoRQR==Be6gH#bTOM}$4k6`-0twhWE-jH`X*+sE^y@4FJR(F+=27}uQhv<|eF%pL@d zW7xw1h&_3z?ir2fUo;{hTp-|_j()W*;LMmEcYj(o0=3fI1Z77NqJi?F;Nw2D>x+Gm zTW)RJgE=KeN#J$sk8IV8^2|V8gXQM~G@6I{n_hY=e@e-ei@I8Dwj-`wlUCedXEjd2 zh=Ab#01>NukJM9QEk-_Gy=mxr)G@al)SIw+^`w{&ayHyDn7sKa@_GTIA`ETc%(lNT!M@w-B?_HFTNj)m7M=H3)jB|C8;JHvv zJ!u?rI(7brx)N41BTJj8xZZFEK2lftRMxk1PFW=^RCL_isibwH%msGix&C!X3wfid z!h%m=DYq@;z-DoT82X-jdiSPEO~8#b`SMBKzA^I-yd2{lsoW9+bsfC#9N6BV9!>%F z%|e#x7@?l%FBGXDUe6s>*3 z(8$v4BD9Ty5Ca_JB=hvEM%Q^eIX;3uO=&8tFYe}Se|9)={OPK*D-j%5Oh4P3X#F!) z5M?#Am~!zrAMMBxRhXo=MZri5`>~h#3Uio~CQExr-_}PAX%cljEzD8>0M{#X{Q0KX zkuoV|%x)Lj8*RU-rP*?TpDy8ttIiO9K$?r^&&w_Br~Q+(e>z_xNjZ|s%=eN}pXE|A zLoK-Et*C$Yo6SF^3c=SR8m)>bWKh~@WofGA=wt#=OcYlRcg{`s8_0)&{1~d8bO5bHI^4U#0dYpfa zI{@~dVZqdGPTU9A1;*&{bV2EN@Bld%$KPc{{Uq`{b~kC(B@rP{(@8e4Ivji zyP?WKX&1Rn;-Q#G0rT}lkNuTUzt*7Nr#b!Y#FG26vwupKF{iG4t9EnkANbK>ktCL& z{MwDv{R^D_RU;iYt0dPA>cIa1T9iqiBGSux7uvt$Qlyu7`E=;l{@Rc5pbs{e&3km& zkCk|;;@!&SnErKg2;^i^7mRRCNYN?+ZYByk^{y)$Ucq7`w~4&m9&!tHtDk8Z{n#vh zhZRWOSi-*{X&cZCW}-Tzyoh2&UV}YqlSnr&pt)i|0T;2R%M4L`*AoTLy<<;xEaMVR zaC;B_wL${z+Mxb4xsY<3X7!U%82M1fqu(UfddAJ156Y)YHX|f$ z_odHa@{OBPx|Or%I{P6YRZ=9C@^VS;$0oHRv;)^QCzg@tp#F6ZLs2sp7Aw~Wi~-)I zTQYv|=ku!zZVaW@EP9O8t{WdQMf_@RG>Buej31h$+X`d>&U)gYdErubIXLa>Rn6&Q zb|x3K8imnj7}_RgP)>NuaZ)s@gEC4KdIQa6n~5A9#{<+e0OxIAwbM(5cRN8D;PXb24Ov20c~|CgN99q&9_L_r zIO42crr>3p8D2r0k$|JO6&&~Nv;Usb)<#J`I`g^ zf*@Ioo}GnR(yh`-AAfRaY@uRinaOUH%|_}#zD1^d!Z|D3{{XLBDW$GYmdvBmHEtVd zp-r(U1HB?->~i*AADU7c<0z-EJl5T|lWS~Ltb3b1Tbk0x98+8GFV>lr+a3{Beoz3c z{ad78kMyk!;8t#~a?ua1C$QtW&RygCRZcnMpZE=0x;U5<{qO5g-9qx+2F4XY!Tc%H zedNi>&w3ukqTT*D!0qW(FOTk^=b&n_f6#N=`qUD@@~lEIJLH;(tCg{8!Lbu#uH#oQ zbCJ+g7O?D$hGCL(PMvN-{{W-JBt1ziFh5+?I&7PkS=AApkIFlmqdultab|)0ZzGO> z&wonGSyk?&`)iOu#t&+URqvERmJnoOkP0t+f@dbrAmmszK~2 zAFBOnmeL6=(SX1pRf7)5l52uvfS$eE=s&G)wj#q(8b?$?mOKGVACncCnMjgNS^0 zm+OpvrkYj|*y4EC=Yr8O-SBDte0@CV6#oFzDEEJjI7M@x-C0E#{{U&hs}ZfzFVFU9 z$FM)+ObY4cxZU=Pw?2pp{{TTz$c)(n)_F($Hjn{RODccMO+*i9!2baC)n-c>3Ey#Z zDfbP}=|TWVCr(AJoMYT)`qYMXL58@sjl2133I4SdaoVXqO_b6fUCBqN!ixDb2L03mxR+{ifsfHDW*Q1NV{zA4C2$N|WtAWzxgzfb6{o zR8!CPKbjCA^k$GE9h5|AflvYjLN8JSC?cW=2%&c=B27>uy$T{kLPu1Tsv;mAr8h-D z1nDBZBfbObz2E!$-}}G!y|>@KebtZH6*)y|0d&-`(bIy!%i8kw(NUX9?UR~z* z`e^fLvD@Y)=V!Bi1Qclyp`HD9aeGR^D(X6U!35$%_aS+eU@rPQH>A z(KpC7rT-d4q4T7#$zGGTEwDE9IEU@Z{$^ zma=?-#Z*r}e0*kv5SVtMG)%cfMQ}>{8oJBzW7x+JT&p=V^k(9V15}Wh8U>>)6_ni~ zw4nHm)AWwD#~Nhp{xT0Swz=%_`RUtAw|9(1!2;!P(itCAB^-+_vHKErU%A9*>8kuMKLqE z*g?6+8d{*TUo5t(D&!O2WfB@iFz$)bKtCEDSBMJVI=|cF+T=PkHIYQ06Umq0m)9gH zMq&Y8Uba_`FA)>E`_;(xoi2z>F)9defhEyYW0Jh{9Qn`2{gCnIHM!8)h?Q+c&N^7| z*}Z7I)n1o4pmi#X$x`8TT!7gL{oYnz#s^W?9ycchz0S!$i6&|f4X_1~$O0xxai9m4 z$Lc1ftAl@ncy0shH70U$aNl2t#f?p5Kj{vTl4Q$|~pb>pe;Czg}m9Vdu*)cRh zpMQp@IX*_-1VaCzOIrK={c~2&JcNSPEY6G-IUd*iF3Z2H8i$a6WIQsH_iDyj%_A@S ztin^Z7#;4Srik<+L2Wf2s&CNk!CSqNo~j{1FU^{>JilYRq4kLwzOco5P0$1>(>qdf zRc3%&-%cmk!*@>vmc8Z6H5jj}K-Kf=HKE6}Q@ia8TZ+ik6gIaL(i$U+Pb|~ z5uytS&O|I8|MVa&?;Yz2v%*xdXCGBrBga)}hfd`lztzvpuViVRMv!Pj3uD@V=UG=@ z37xHq$uD3n81&SAX65MEW8VG&%>^J3 z-TQY-A?0-WhESHy%bz+#_oIy-ThjW+J{;$n&)-cCvt-=ZP5Eqh`t-|p`Qpe=ul8;M zw-oh0Y}$(_d6!v%(Twt(@)eP@Iv(i#i#r2%=%4OCfA(PBG&tIDW>n(G!1K_9Pm{YQ z?2d-}=T>5`=)kD_{jonf(qp$C@b;2~jf5l0Rc5bqnlCQ3jJ@IwV_eP+)X5Qk|0;Dh z-);2~C`@5`L4^8XA{f{%%3hG{T5T5Zx47{2g3dI2TUy%6m<~0pH{Dc_qNIOMSvl9N zo>|8wk6$UM75Hz|QNQ`YX0#;o4(U4Zw>7=4+hdzAu(pG5wg-91((t=)FIwKDfo>45 ze)_Dc^?mWwFEIB3r{Fr0+t!Ci&1XAZ&$1ANyRpLKV6kcr=WB% zrS;8@W1`CfgYB*0m-)N>6w;@-MpQG~vnF+)jd=$?ze%Y5qDK*UHg#_+L42=@w>Mkf z(&gagg(;;Herf&}*LYu7C;ecLozgpaSMF+i-s_+*5li*bEa%2z%Mf7q#oqGP3Z0ET zPnL{YkpAK_q#Ug)>O$f`5_kJ(Sr0zvX=TXsZkeV#Imxs$rqX>^aEayZd|WnY95lyw zxzW_6cy8ruP@ZyjSa32Qd-_}D(emnjU^*79^Mj-iTvY0H06dT_O+5rmr*C%zZy9w< zw=$j$%-Z`J91YSI^O5a*XKor?*4Q6kQ55haI+#*&~~> zfd{}UVj7VKZH2NI@0bQZ&zdxTpzu+7@N%p2C8dAu!IQlaSRJA9y`hIr+*ENWr?*k*_L(1rYy%kNaz8}@ zy8@8d=Na%H&I`OlzT^7gSQm@u$IkWlX;Rg3FKG5abfv;qdmS9|;-zG|U-z3dUkxhh zrx`VmH-C2d{)Y6u!r+#^o3OrPe2c)cysbCxZSZy$M!7)POK6ezoBh8U)pLgU0GqW{ z$cDyReBgp~T>E_bbuAJUGk|cEElnW_lsj)u^F9I=>xLPr<^{DKBx7Qh%1?a*cd0C@ zv2@qU$0EAi&rnQKDVcUvKZ)_7JO$}3?Jg9$0_QeQzh7D_d5>B*xgJu>TJ4A=zrsK` zouPg98n8EE43f}KkhrQUH*U1i?NIkd?sdHHxGjq#EIhC{SwSlP6Kf&hxB1Es7K$n@ z`fh|&-LdIrK&mqPQniLsp?5TFE$wVmf$cz7ZFyE)W2(DQ&-KxoUFH&F-gem96fi6F889c!G?&$F|^rU{*#-@S2cZ0 zgtG9_Ds_mtE)yLOTfw^wQxsjSVoy($e7h1JmYF%7b<;2zAHVOTtq|Q4mUdn2TNt?G zLh?Pw#IO4#_WhzKkvD-(=V#itQqUO?2I95E1%`d-?f2L`h0#2t^!dB;V3yYz_KMep zBB&}_nziu639hJ(eZRT z*%r?7eaxN_f2&H{zP=ONBYH>2i*9>r6mp7*&5jf7w;pH9jO0&^do-i#*YoEt+o@CP z*s!tCH(d;m)eF+HsPQdrfGDYW%C*#*=r(ZV6_}satjojS{=o|c9z7V$#n7YF8-)|~ zpmYfH@p!$_yKLMN!MPSvr?}@+9^FVOFv~IZg}NG|i@A#vR?dF!PsX+}hqhFs%nQC> zj?su2g|x*Lfv@@%c{$R3vw4AA>f`e;vM?VRgJ1ZVz}ieHKRER;L#Fu75cHAsjRw!s z2QIm7XLc$}s$(7dw0lp!1%V1JmmSIc1rnrOC)29()8rJJQxo?|Tpg!$ zU8$jOEbv&AFaM;I-3KPm=hEKdwh4-ot%ua6y(Iqq>?TqWLAT#}T1E!0RqNP6cG8e0D zs_A0M$64xMHwgu7aK}QV0~_QO%%yu@JRZB{fvtI|ygJ@6 zzkQHYm(>*)J38F<6GX<3&t2*oC5%G%3=G%v?k=%=kQHt@1HQCVqbgl2s#(i)z+E}$ zvM|o8qw&nad~md0%2rjw*iG%)FUGkwJ7}k6rTC}YrjdhR-uzg|$`0KxqzHX{4>CRS z{+uuhFnz1eF)x*ORA%yk zQn@*oO$M%X?$%GxtH=Y>ESu7MMa@+k&bYg%_0~1fmVqV-&f$m8g9egoN2B`KOwR9B z3@L8`w`QCV7E^SUE?Czc%t3cd3`owkjWa*`g?Ej}PP7@0mOVJ2XxZ);$L#Tre$ssN zZDt>yXconrLYuOC>a<|t`_J=_PYU-xgLQ*B6Fpv%Z$VHZY&$zoDKYWEZ$q#922XYI zo(CRD!|e>&uFwDjv7TB}O+7EBkCzD9#c`u8c_sZn9Z&{0lLU?2UiOIZ1NRzFwfXuD z_iKt`RoID4E2IlEB2g`)(c0;k61+q4cisF9y8^tv-8+Egb^7v3e{ESmFy&7WjjmEu z1?{HCUHp`Pk}1gXQE$Uf(BrDK+Hw1ReAWlwmL)g0#%_u(nNB6eR<`*%+`Ui8tn~+g z5?v@v^;vp?r_z)y(onC|p-d%YCl7jGK<*XX*#zqHG=9JZx?d)GFn{a^LL;I=c_4H< zJzyBC9O}Svq5PG{mQ7V~j(7OQ=r>a(ACl#D@wck;Mqtb|-6=S!)&zORm31pw zi^fyhvI%P+dnM;3;`WJPQ{R=YzFe5mt&|~p&uMiYo8bV_VI-T z-Q&&viyE*G_g0s0DwaqMZg{V^Xgv)Q*G+;1#Ru0~#X=daxnlfwY* z@6j;Da!wDv!x4}kT&2%}N9aB#Yt9gtEH2xnn)Ye*zK=TlV=4JlzVG6}BFro*p`l@g zw(8^=;RhV&KrB=(y7Pj4B*Cr6U+v|@9J24zh

(GL+IkYbw{d=aFA^EG&#R7@ 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 CyBQq- literal 0 HcmV?d00001 diff --git a/mms-lib/test/retrieve/data/Success/parts/text_0011.txt b/mms-lib/test/retrieve/data/Success/parts/text_0011.txt new file mode 100644 index 0000000..52a8d4e --- /dev/null +++ b/mms-lib/test/retrieve/data/Success/parts/text_0011.txt @@ -0,0 +1 @@ +Вид с крыши \ No newline at end of file diff --git a/mms-lib/test/retrieve/data/Success/parts/text_0021.txt b/mms-lib/test/retrieve/data/Success/parts/text_0021.txt new file mode 100644 index 0000000..9f5d07e --- /dev/null +++ b/mms-lib/test/retrieve/data/Success/parts/text_0021.txt @@ -0,0 +1 @@ +Дворцовый мост \ No newline at end of file diff --git a/mms-lib/test/retrieve/data/UnsupportedPush/unsupported b/mms-lib/test/retrieve/data/UnsupportedPush/unsupported new file mode 100644 index 0000000000000000000000000000000000000000..33f2edbcb57d235c122b3ec3f4efdd223b08a1f0 GIT binary patch literal 42 xcmeBao{?*4kYkx^UTR>Rn_Oa)m6U8~ +#include + +#define RET_OK (0) +#define RET_ERR (1) +#define RET_TIMEOUT (2) + +#define MMS_MESSAGE_TYPE_NONE (0) + +#define DATA_DIR "data/" + +typedef struct test_desc { + const char* name; + const char* dir; + const char* ni_file; + const char* rc_file; + unsigned int status; + const char* content_type; + MMS_RECEIVE_STATE expected_state; + enum mms_message_type reply_msg; + int flags; + +#define TEST_PUSH_HANDLING_FAILURE_OK (0x01) +#define TEST_DEFER_RECEIVE (0x02) + +} TestDesc; + +typedef struct test { + const TestDesc* desc; + MMSDispatcherDelegate delegate; + MMSConnMan* cm; + MMSHandler* handler; + MMSDispatcher* disp; + GMappedFile* notification_ind; + GMappedFile* retrieve_conf; + GMainLoop* loop; + guint timeout_id; + TestHttp* http; + int ret; +} Test; + +static const TestDesc retrieve_tests[] = { + { + "Success", + NULL, + "m-notification.ind", + "m-retrieve.conf", + SOUP_STATUS_OK, + MMS_CONTENT_TYPE, + MMS_RECEIVE_STATE_DECODING, + MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, + 0 + },{ + "DeferSuccess", + "Success", + "m-notification.ind", + "m-retrieve.conf", + SOUP_STATUS_OK, + MMS_CONTENT_TYPE, + MMS_RECEIVE_STATE_DECODING, + MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, + TEST_DEFER_RECEIVE + },{ + "Expired", + NULL, + "m-notification.ind", + NULL, + SOUP_STATUS_NOT_FOUND, + NULL, + MMS_RECEIVE_STATE_DOWNLOAD_ERROR, + MMS_MESSAGE_TYPE_NONE, + 0 + },{ + "SoonExpired", + NULL, + "m-notification.ind", + NULL, + SOUP_STATUS_TRY_AGAIN, + NULL, + MMS_RECEIVE_STATE_DOWNLOAD_ERROR, + MMS_MESSAGE_TYPE_NONE, + 0 + },{ + "NotAllowed", + NULL, + "m-notification.ind", + "not-allowed.html", + SOUP_STATUS_BAD_REQUEST, + "text/html", + MMS_RECEIVE_STATE_DOWNLOAD_ERROR, + MMS_MESSAGE_TYPE_NONE, + 0 + },{ + "NotFound", + NULL, + "m-notification.ind", + "not-found.html", + SOUP_STATUS_NOT_FOUND, + "text/html", + MMS_RECEIVE_STATE_DOWNLOAD_ERROR, + MMS_MESSAGE_TYPE_NONE, + 0 + },{ + "GarbageRetrieve", + NULL, + "m-notification.ind", + "garbage", + SOUP_STATUS_OK, + MMS_CONTENT_TYPE, + MMS_RECEIVE_STATE_DECODING_ERROR, + MMS_MESSAGE_TYPE_NOTIFYRESP_IND, + 0 + },{ + "GarbagePush", + NULL, + "garbage", + NULL, + 0, + NULL, + MMS_RECEIVE_STATE_INVALID, + MMS_MESSAGE_TYPE_NONE, + TEST_PUSH_HANDLING_FAILURE_OK + },{ + "UnsupportedPush", + NULL, + "unsupported", + NULL, + 0, + NULL, + MMS_RECEIVE_STATE_INVALID, + MMS_MESSAGE_TYPE_NONE, + TEST_PUSH_HANDLING_FAILURE_OK + },{ + "ReadOrigInd", + NULL, + "m-read-orig.ind", + NULL, + 0, + NULL, + MMS_RECEIVE_STATE_INVALID, + MMS_MESSAGE_TYPE_NONE, + 0 + },{ + "DeliveryInd", + NULL, + "m-delivery.ind", + NULL, + 0, + NULL, + MMS_RECEIVE_STATE_INVALID, + MMS_MESSAGE_TYPE_NONE, + 0 + } +}; + +static +void +test_finish( + Test* test) +{ + const char* name = test->desc->name; + if (test->ret == RET_OK) { + MMS_RECEIVE_STATE state; + state = mms_handler_test_receive_state(test->handler, NULL); + if (state != test->desc->expected_state) { + test->ret = RET_ERR; + MMS_ERR("Test %s state %d, expected %d", name, state, + test->desc->expected_state); + } else { + const void* resp_data = NULL; + gsize resp_len = 0; + GBytes* reply = test_http_get_post_data(test->http); + if (reply) resp_data = g_bytes_get_data(reply, &resp_len); + if (resp_len > 0) { + if (test->desc->reply_msg) { + MMSPdu* pdu = g_new0(MMSPdu, 1); + if (mms_message_decode(resp_data, resp_len, pdu)) { + if (pdu->type != test->desc->reply_msg) { + test->ret = RET_ERR; + MMS_ERR("Test %s reply %u, expected %u", name, + pdu->type, test->desc->reply_msg); + } + } else { + test->ret = RET_ERR; + MMS_ERR("Test %s can't decode reply message", name); + } + mms_message_free(pdu); + } else { + test->ret = RET_ERR; + MMS_ERR("Test %s expects no reply", name); + } + } else if (test->desc->reply_msg) { + test->ret = RET_ERR; + MMS_ERR("Test %s expects reply", name); + } + } + } + MMS_INFO("Test %s %s", name, (test->ret == RET_OK) ? "OK" : "FAILED"); + mms_handler_test_reset(test->handler); + g_main_loop_quit(test->loop); +} + +static +void +test_done( + MMSDispatcherDelegate* delegate, + MMSDispatcher* dispatcher) +{ + Test* test = MMS_CAST(delegate,Test,delegate); + if (!mms_handler_test_receive_pending(test->handler, NULL)) { + test_finish(test); + } +} + +static +gboolean +test_timeout( + gpointer data) +{ + Test* test = data; + test->timeout_id = 0; + test->ret = RET_TIMEOUT; + MMS_INFO("Test %s TIMEOUT", test->desc->name); + if (test->http) test_http_close(test->http); + mms_connman_test_close_connection(test->cm); + mms_dispatcher_cancel(test->disp, NULL); + return FALSE; +} + +static +gboolean +test_init( + Test* test, + const MMSConfig* config, + const TestDesc* desc) +{ + gboolean ok = FALSE; + GError* error = NULL; + const char* dir = desc->dir ? desc->dir : desc->name; + char* ni = g_strconcat(DATA_DIR, dir, "/", desc->ni_file, NULL); + char* rc = desc->rc_file ? g_strconcat(DATA_DIR, dir, "/", + desc->rc_file, NULL) : NULL; + memset(test, 0, sizeof(*test)); + test->notification_ind = g_mapped_file_new(ni, FALSE, &error); + if (test->notification_ind) { + if (rc) test->retrieve_conf = g_mapped_file_new(rc, FALSE, &error); + if (test->retrieve_conf || !rc) { + 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(config, test->cm, test->handler); + 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->http = test_http_new(test->retrieve_conf, + test->desc->content_type, test->desc->status); + mms_connman_test_set_port(test->cm, test_http_get_port(test->http)); + if (desc->flags & TEST_DEFER_RECEIVE) { + mms_handler_test_defer_receive(test->handler, test->disp); + } + test->ret = RET_ERR; + ok = TRUE; + } else { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + } + g_mapped_file_unref(test->notification_ind); + } else { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + } + g_free(ni); + g_free(rc); + return ok; +} + +static +void +test_finalize( + Test* test) +{ + if (test->timeout_id) { + g_source_remove(test->timeout_id); + test->timeout_id = 0; + } + if (test->http) { + test_http_close(test->http); + test_http_unref(test->http); + } + mms_connman_test_close_connection(test->cm); + mms_connman_unref(test->cm); + mms_handler_unref(test->handler); + mms_dispatcher_unref(test->disp); + g_main_loop_unref(test->loop); + g_mapped_file_unref(test->notification_ind); + if (test->retrieve_conf) g_mapped_file_unref(test->retrieve_conf); +} + +static +int +test_retrieve_once( + const MMSConfig* config, + const TestDesc* desc) +{ + Test test; + if (test_init(&test, config, desc)) { + GBytes* push = g_bytes_new_static( + g_mapped_file_get_contents(test.notification_ind), + g_mapped_file_get_length(test.notification_ind)); + if (mms_dispatcher_handle_push(test.disp, "TestConnection", push)) { + if (mms_dispatcher_start(test.disp)) { + test.ret = RET_OK; + g_main_loop_run(test.loop); + } else { + MMS_INFO("Test %s FAILED", desc->name); + } + } else { + if (desc->flags & TEST_PUSH_HANDLING_FAILURE_OK) { + MMS_INFO("Test %s OK", desc->name); + test.ret = RET_OK; + } else { + MMS_INFO("Test %s FAILED", desc->name); + } + } + g_bytes_unref(push); + test_finalize(&test); + return test.ret; + } else { + return RET_ERR; + } +} + +static +int +test_retrieve( + const MMSConfig* config, + const char* name) +{ + int i, ret; + if (name) { + const TestDesc* found = NULL; + for (i=0, ret = RET_ERR; iname, name)) { + ret = test_retrieve_once(config, test); + found = test; + break; + } + } + if (!found) MMS_ERR("No such test: %s", name); + } else { + for (i=0, ret = RET_OK; i 1 && !strcmp(argv[1], "-v")) { + mms_log_default.level = MMS_LOGLEVEL_VERBOSE; + memmove(argv + 1, argv + 2, (argc-2)*sizeof(argv[0])); + argc--; + } else { + mms_log_default.level = MMS_LOGLEVEL_INFO; + mms_util_log.level = + mms_task_decode_log.level = + mms_task_retrieve_log.level = + mms_task_notification_log.level = MMS_LOGLEVEL_NONE; + mms_log_stdout_timestamp = FALSE; + } + + if (argc == 2 && argv[1][0] != '-') { + test_name = argv[1]; + } + + if (argc == 1 || test_name) { + int ret; + char* tmpd = g_mkdtemp(g_strdup("/tmp/test_retrieve_XXXXXX")); + MMS_VERBOSE("Temporary directory %s", tmpd); + config.root_dir = tmpd; + config.idle_secs = 0; + ret = test_retrieve(&config, test_name); + remove(tmpd); + g_free(tmpd); + return ret; + } else { + printf("Usage: test_retrieve [-v] [TEST]\n"); + return RET_ERR; + } +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/retrieve_cancel/Makefile b/mms-lib/test/retrieve_cancel/Makefile new file mode 100644 index 0000000..c41b0b1 --- /dev/null +++ b/mms-lib/test/retrieve_cancel/Makefile @@ -0,0 +1,7 @@ +# -*- Mode: makefile-gmake -*- + +EXE = test_retrieve_cancel +SRC = test_retrieve_cancel.c test_connman.c test_handler.c +COMMON_SRC = test_connection.c + +include ../common/Makefile diff --git a/mms-lib/test/retrieve_cancel/test_connman.c b/mms-lib/test/retrieve_cancel/test_connman.c new file mode 100644 index 0000000..adc46bd --- /dev/null +++ b/mms-lib/test/retrieve_cancel/test_connman.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_connman.h" +#include "test_connection.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_connman_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-connman-test"); + +typedef MMSConnManClass MMSConnManTestClass; +typedef struct mms_connman_test { + MMSConnMan cm; + mms_connman_connection_requested_cb connection_requested_cb; + void* connection_requested_param; + gboolean fail; +} MMSConnManTest; + +G_DEFINE_TYPE(MMSConnManTest, mms_connman_test, MMS_TYPE_CONNMAN); +#define MMS_TYPE_CONNMAN_TEST (mms_connman_test_get_type()) +#define MMS_CONNMAN_TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_TYPE_CONNMAN_TEST, MMSConnManTest)) + +void +mms_connman_set_connection_requested_cb( + MMSConnMan* cm, + mms_connman_connection_requested_cb cb, + void* param) +{ + MMSConnManTest* test = MMS_CONNMAN_TEST(cm); + test->connection_requested_cb = cb; + test->connection_requested_param = param; +} + +MMSConnection* +mms_connman_test_open_connection( + MMSConnMan* cm, + const char* imsi, + gboolean user_request) +{ + MMSConnManTest* test = MMS_CONNMAN_TEST(cm); + if (test->fail) { + if (test->connection_requested_cb) { + test->connection_requested_cb(cm, + test->connection_requested_param); + } + return NULL; + } else { + test->fail = TRUE; + return mms_connection_test_new(imsi, 0); + } +} + +static +void +mms_connman_test_class_init( + MMSConnManTestClass* klass) +{ + klass->fn_open_connection = mms_connman_test_open_connection; +} + +static +void +mms_connman_test_init( + MMSConnManTest* cm) +{ +} + +MMSConnMan* +mms_connman_test_new() +{ + return g_object_new(MMS_TYPE_CONNMAN_TEST,NULL); +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/retrieve_cancel/test_connman.h b/mms-lib/test/retrieve_cancel/test_connman.h new file mode 100644 index 0000000..33a6508 --- /dev/null +++ b/mms-lib/test/retrieve_cancel/test_connman.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_CONNMAN_H +#define TEST_CONNMAN_H + +#include "mms_connman.h" + +MMSConnMan* +mms_connman_test_new(void); + +typedef +void +(*mms_connman_connection_requested_cb)( + MMSConnMan* cm, + void* param); + +void +mms_connman_set_connection_requested_cb( + MMSConnMan* cm, + mms_connman_connection_requested_cb cb, + void* param); + +#endif /* TEST_CONNMAN_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/retrieve_cancel/test_handler.c b/mms-lib/test/retrieve_cancel/test_handler.c new file mode 100644 index 0000000..4ab8c42 --- /dev/null +++ b/mms-lib/test/retrieve_cancel/test_handler.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_handler.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_handler_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-handler-test"); + +/* Class definition */ +typedef MMSHandlerClass MMSHandlerTestClass; +typedef struct mms_handler_test { + MMSHandler handler; + mms_handler_message_id_cb message_id_cb; + void* message_id_param; +} MMSHandlerTest; + +G_DEFINE_TYPE(MMSHandlerTest, mms_handler_test, MMS_TYPE_HANDLER); +#define MMS_TYPE_HANDLER_TEST (mms_handler_test_get_type()) +#define MMS_HANDLER_TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + MMS_TYPE_HANDLER_TEST, MMSHandlerTest)) + +static +char* +mms_handler_test_message_notify( + MMSHandler* handler, + const char* imsi, + const char* from, + const char* subject, + time_t expiry, + GBytes* push) +{ + MMSHandlerTest* test = MMS_HANDLER_TEST(handler); + return test->message_id_cb ? + test->message_id_cb(handler, test->message_id_param) : + NULL; +} + +static +gboolean +mms_handler_test_message_received( + MMSHandler* handler, + MMSMessage* msg) +{ + MMS_DEBUG("Message %s received", msg->id); + return TRUE; +} + +static +gboolean +mms_handler_test_message_receive_state_changed( + MMSHandler* handler, + const char* id, + MMS_RECEIVE_STATE state) +{ + MMS_DEBUG("Message %s state %d", id, state); + return TRUE; +} + +static +void +mms_handler_test_class_init( + MMSHandlerTestClass* klass) +{ + klass->fn_message_notify = mms_handler_test_message_notify; + klass->fn_message_received = mms_handler_test_message_received; + klass->fn_message_receive_state_changed = + mms_handler_test_message_receive_state_changed; +} + +static +void +mms_handler_test_init( + MMSHandlerTest* test) +{ +} + +MMSHandler* +mms_handler_test_new() +{ + return g_object_new(MMS_TYPE_HANDLER_TEST, NULL); +} + +void +mms_handler_set_message_id_cb( + MMSHandler* handler, + mms_handler_message_id_cb cb, + void* param) +{ + MMSHandlerTest* test = MMS_HANDLER_TEST(handler); + test->message_id_cb = cb; + test->message_id_param = param; +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/retrieve_cancel/test_handler.h b/mms-lib/test/retrieve_cancel/test_handler.h new file mode 100644 index 0000000..d81f802 --- /dev/null +++ b/mms-lib/test/retrieve_cancel/test_handler.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_HANDLER_H +#define TEST_HANDLER_H + +#include "mms_handler.h" + +MMSHandler* +mms_handler_test_new(void); + +typedef +char* +(*mms_handler_message_id_cb)( + MMSHandler* handler, + void* param); + +void +mms_handler_set_message_id_cb( + MMSHandler* handler, + mms_handler_message_id_cb cb, + void* param); + +#endif /* TEST_HANDLER_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-lib/test/retrieve_cancel/test_retrieve_cancel.c b/mms-lib/test/retrieve_cancel/test_retrieve_cancel.c new file mode 100644 index 0000000..5ef27e8 --- /dev/null +++ b/mms-lib/test/retrieve_cancel/test_retrieve_cancel.c @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_connman.h" +#include "test_handler.h" + +#include "mms_log.h" +#include "mms_lib_util.h" +#include "mms_dispatcher.h" + +#define RET_OK (0) +#define RET_ERR (1) +#define RET_TIMEOUT (2) + +typedef struct test_desc { + const char* name; + const guint8* pdu; + gsize pdusize; + int flags; + +#define TEST_ASYNC_CANCEL (0x01) +#define TEST_ACCEPT_MSG (0x02) + +} TestDesc; + +typedef struct test { + const TestDesc* desc; + MMSDispatcherDelegate delegate; + MMSConnMan* cm; + MMSHandler* handler; + MMSDispatcher* disp; + GBytes* pdu; + GMainLoop* loop; + guint cancel_id; + guint timeout_id; + char* id; + int ret; +} Test; + +static +void +test_done( + MMSDispatcherDelegate* delegate, + MMSDispatcher* dispatcher) +{ + Test* test = MMS_CAST(delegate,Test,delegate); + MMS_INFO("%s test %s", test->desc->name, (test->ret == RET_OK) ? + "OK" : "FAILED"); + g_main_loop_quit(test->loop); +} + +static +gboolean +test_timeout( + gpointer data) +{ + Test* test = data; + test->timeout_id = 0; + test->ret = RET_TIMEOUT; + MMS_INFO("%s test TIMEOUT", test->desc->name); + mms_dispatcher_cancel(test->disp, NULL); + return FALSE; +} + +static +void +test_init( + Test* test, + const MMSConfig* config, + const TestDesc* desc) +{ + memset(test, 0, sizeof(*test)); + test->desc = desc; + test->cm = mms_connman_test_new(); + test->handler = mms_handler_test_new(); + test->disp = mms_dispatcher_new(config, test->cm, test->handler); + test->pdu = g_bytes_new_static(desc->pdu, desc->pdusize); + test->loop = g_main_loop_new(NULL, FALSE); + test->delegate.fn_done = test_done; + mms_dispatcher_set_delegate(test->disp, &test->delegate); + test->timeout_id = g_timeout_add_seconds(10, test_timeout, test); + test->ret = RET_ERR; +} + +static +void +test_finalize( + Test* test) +{ + if (test->timeout_id) { + g_source_remove(test->timeout_id); + test->timeout_id = 0; + } + mms_connman_unref(test->cm); + mms_handler_unref(test->handler); + mms_dispatcher_unref(test->disp); + g_bytes_unref(test->pdu); + g_main_loop_unref(test->loop); + g_free(test->id); +} + +static +char* +test_msg_id( + MMSHandler* handler, + void* param) +{ + Test* test = param; + MMS_ASSERT(!test->id); + if (test->id) { + test->ret = RET_ERR; + g_main_loop_quit(test->loop); + return NULL; + } else if (test->desc->flags & TEST_ACCEPT_MSG) { + return g_strdup(test->id = g_strdup("21285")); + } else { + return NULL; + } +} + +static +gboolean +test_cancel( + void* param) +{ + Test* test = param; + test->cancel_id = 0; + MMS_DEBUG("Asynchronous cancel %s", test->id); + mms_dispatcher_cancel(test->disp, test->id); + return FALSE; +} + +static +void +test_connect( + MMSConnMan* cm, + void* param) +{ + Test* test = param; + if (test->desc->flags & TEST_ASYNC_CANCEL) { + if (!test->cancel_id) { + test->cancel_id = g_idle_add_full(G_PRIORITY_HIGH, + test_cancel, test, NULL); + } + } else { + MMS_DEBUG("Synchronous cancel %s", test->id ? test->id : "all"); + mms_dispatcher_cancel(test->disp, test->id); + } +} + +static +int +test_once( + const MMSConfig* config, + const TestDesc* desc) +{ + Test test; + MMS_VERBOSE(">>>>>>>>>>>>>> %s <<<<<<<<<<<<<<", desc->name); + test_init(&test, config, desc); + if (mms_dispatcher_handle_push(test.disp, "IMSI", test.pdu)) { + mms_connman_set_connection_requested_cb(test.cm, test_connect, &test); + mms_handler_set_message_id_cb(test.handler, test_msg_id, &test); + if (mms_dispatcher_start(test.disp)) { + test.ret = RET_OK; + g_main_loop_run(test.loop); + } + } + test_finalize(&test); + return test.ret; +} + +static +int +test( + const MMSConfig* config) +{ + /* + * WSP header: + * application/vnd.wap.mms-message + * MMS headers: + * X-Mms-Message-Type: M-Notification.ind + * X-Mms-Transaction-Id: Ad0b9pXNC + * X-Mms-MMS-Version: 1.2 + * From: +358540000000/TYPE=PLMN + * X-Mms-Delivery-Report: No + * X-Mms-Message-Class: Personal + * X-Mms-Message-Size: 137105 + * X-Mms-Expiry: +259199 sec + * X-Mms-Content-Location: http://mmsc42:10021/mmsc/4_2?Ad0b9pXNC + */ + static const guint8 plus_259199_sec[] = { + 0x8c,0x82,0x98,0x41,0x64,0x30,0x62,0x39,0x70,0x58,0x4e,0x43, + 0x00,0x8d,0x92,0x89,0x19,0x80,0x2b,0x33,0x35,0x38,0x35,0x34, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x2f,0x54,0x59,0x50,0x45, + 0x3d,0x50,0x4c,0x4d,0x4e,0x00,0x86,0x81,0x8a,0x80,0x8e,0x03, + 0x02,0x17,0x91,0x88,0x05,0x81,0x03,0x03,0xf4,0x7f,0x83,0x68, + 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6d,0x6d,0x73,0x63,0x34,0x32, + 0x3a,0x31,0x30,0x30,0x32,0x31,0x2f,0x6d,0x6d,0x73,0x63,0x2f, + 0x34,0x5f,0x32,0x3f,0x41,0x64,0x30,0x62,0x39,0x70,0x58,0x4e, + 0x43,0x00 + }; + + /* + * WSP header: + * application/vnd.wap.mms-message + * MMS headers: + * X-Mms-Message-Type: M-Notification.ind + * X-Mms-Transaction-Id: Ad0b9pXNC + * X-Mms-MMS-Version: 1.2 + * From: +358540000000/TYPE=PLMN + * X-Mms-Delivery-Report: No + * X-Mms-Message-Class: Personal + * X-Mms-Message-Size: 137105 + * X-Mms-Expiry: +1 sec + * X-Mms-Content-Location: http://mmsc42:10021/mmsc/4_2?Ad0b9pXNC + */ + static const guint8 plus_1_sec[] = { + 0x8c,0x82,0x98,0x41,0x64,0x30,0x62,0x39,0x70,0x58,0x4e,0x43, + 0x00,0x8d,0x92,0x89,0x19,0x80,0x2b,0x33,0x35,0x38,0x35,0x34, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x2f,0x54,0x59,0x50,0x45, + 0x3d,0x50,0x4c,0x4d,0x4e,0x00,0x86,0x81,0x8a,0x80,0x8e,0x03, + 0x02,0x17,0x91,0x88,0x03,0x81,0x01,0x01,0x83,0x68,0x74,0x74, + 0x70,0x3a,0x2f,0x2f,0x6d,0x6d,0x73,0x63,0x34,0x32,0x3a,0x31, + 0x30,0x30,0x32,0x31,0x2f,0x6d,0x6d,0x73,0x63,0x2f,0x34,0x5f, + 0x32,0x3f,0x41,0x64,0x30,0x62,0x39,0x70,0x58,0x4e,0x43,0x00 + }; + + static const TestDesc tests[] = { + { + "AsyncCancel", plus_259199_sec, sizeof(plus_259199_sec), + TEST_ASYNC_CANCEL | TEST_ACCEPT_MSG + },{ + "SyncCancel", plus_259199_sec, sizeof(plus_259199_sec), + TEST_ACCEPT_MSG + },{ + "NoHandler", plus_1_sec, sizeof(plus_1_sec), 0 + } + }; + + int i, ret = RET_OK; + for (i=0; i 1 && !strcmp(argv[1], "-v")) { + mms_log_stdout_timestamp = TRUE; + mms_log_default.level = MMS_LOGLEVEL_VERBOSE; + } else { + mms_log_stdout_timestamp = FALSE; + mms_log_default.level = MMS_LOGLEVEL_INFO; + } + return test(&config); +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/Makefile b/mms-ofono/Makefile new file mode 100644 index 0000000..acce7d1 --- /dev/null +++ b/mms-ofono/Makefile @@ -0,0 +1,127 @@ +# -*- Mode: makefile -*- + +.PHONY: clean all debug release + +# Required packages +PKGS = glib-2.0 gio-2.0 gio-unix-2.0 + +# +# Default target +# + +all: debug release + +# +# Sources +# + +SRC = \ + mms_ofono_manager.c \ + mms_ofono_modem.c \ + mms_ofono_context.c \ + mms_ofono_connection.c \ + mms_ofono_connman.c +GEN_SRC = \ + org.ofono.Modem.c \ + org.ofono.Manager.c \ + org.ofono.SimManager.c \ + org.ofono.ConnectionManager.c \ + org.ofono.ConnectionContext.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) +WARN = -Wall +ARFLAGS = rc +INCLUDES = -I$(SRC_DIR) -I$(INCLUDE_DIR) -I$(MMS_LIB_INCLUDE) -I$(GEN_DIR) -I. +CFLAGS = $(INCLUDES) $(shell pkg-config --cflags $(PKGS)) -MMD +DEBUG_FLAGS = -g +RELEASE_FLAGS = -O2 +DEBUG_DEFS = -DDEBUG +RELEASE_DEFS = +DEBUG_CFLAGS = $(DEBUG_FLAGS) $(DEBUG_DEFS) $(CFLAGS) +RELEASE_CFLAGS = $(RELEASE_FLAGS) $(RELEASE_DEFS) $(CFLAGS) + +# +# 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-ofono.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 $(WARN) $(DEBUG_CFLAGS) -MT"$@" -MF"$(@:%.o=%.d)" $< -o $@ + +$(RELEASE_BUILD_DIR)/%.o : $(SRC_DIR)/%.c + $(CC) -c $(WARN) $(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-ofono/include/mms_ofono_connman.h b/mms-ofono/include/mms_ofono_connman.h new file mode 100644 index 0000000..7788e81 --- /dev/null +++ b/mms-ofono/include/mms_ofono_connman.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_CONNMAN_OFONO_H +#define JOLLA_MMS_CONNMAN_OFONO_H + +#include +#include "mms_connman.h" + +MMSConnMan* +mms_connman_ofono_new(void); + +#endif /* JOLLA_MMS_CONNMAN_OFONO_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/include/mms_ofono_log.h b/mms-ofono/include/mms_ofono_log.h new file mode 100644 index 0000000..f7030d4 --- /dev/null +++ b/mms-ofono/include/mms_ofono_log.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_OFONO_LOG_H +#define JOLLA_MMS_OFONO_LOG_H + +#include "mms_log.h" + +#define MMS_OFONO_LOG_MODULES(log) \ + log(mms_ofono_modem_log)\ + log(mms_ofono_manager_log)\ + log(mms_ofono_context_log) + +MMS_OFONO_LOG_MODULES(MMS_LOG_MODULE_DECL) + +#endif /* JOLLA_MMS_OFONO_LOG_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/mms-ofono.pro b/mms-ofono/mms-ofono.pro new file mode 100644 index 0000000..d1e4002 --- /dev/null +++ b/mms-ofono/mms-ofono.pro @@ -0,0 +1,130 @@ +TEMPLATE = lib +CONFIG += staticlib +CONFIG -= qt +CONFIG += link_pkgconfig +PKGCONFIG += 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 + +CONFIG(debug, debug|release) { + DEFINES += DEBUG + DESTDIR = $$_PRO_FILE_PWD_/build/debug +} else { + DESTDIR = $$_PRO_FILE_PWD_/build/release +} + +SOURCES += \ + src/mms_ofono_connection.c \ + src/mms_ofono_connman.c \ + src/mms_ofono_context.c \ + src/mms_ofono_manager.c \ + src/mms_ofono_modem.c + +HEADERS += \ + src/mms_ofono_connection.h \ + src/mms_ofono_context.h \ + src/mms_ofono_manager.h \ + src/mms_ofono_modem.h \ + src/mms_ofono_names.h \ + src/mms_ofono_types.h + +HEADERS += \ + include/mms_ofono_connman.h \ + include/mms_ofono_log.h + +# org.ofono.Manager +MANAGER_XML = $$DBUS_SPEC_DIR/org.ofono.Manager.xml +MANAGER_GENERATE = gdbus-codegen --generate-c-code \ + org.ofono.Manager $$MANAGER_XML +MANAGER_H = org.ofono.Manager.h +org_ofono_Manager_h.input = MANAGER_XML +org_ofono_Manager_h.output = $$MANAGER_H +org_ofono_Manager_h.commands = $$MANAGER_GENERATE +org_ofono_Manager_h.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_ofono_Manager_h + +MANAGER_C = org.ofono.Manager.c +org_ofono_Manager_c.input = MANAGER_XML +org_ofono_Manager_c.output = $$MANAGER_C +org_ofono_Manager_c.commands = $$MANAGER_GENERATE +org_ofono_Manager_c.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_ofono_Manager_c +GENERATED_SOURCES += $$MANAGER_C + +# org.ofono.ConnectionManager +CONNECTION_MANAGER_XML = $$DBUS_SPEC_DIR/org.ofono.ConnectionManager.xml +CONNECTION_MANAGER_GENERATE = gdbus-codegen --generate-c-code \ + org.ofono.ConnectionManager $$CONNECTION_MANAGER_XML +CONNECTION_MANAGER_H = org.ofono.ConnectionManager.h +org_ofono_ConnectionManager_h.input = CONNECTION_MANAGER_XML +org_ofono_ConnectionManager_h.output = $$CONNECTION_MANAGER_H +org_ofono_ConnectionManager_h.commands = $$CONNECTION_MANAGER_GENERATE +org_ofono_ConnectionManager_h.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_ofono_ConnectionManager_h + +CONNECTION_MANAGER_C = org.ofono.ConnectionManager.c +org_ofono_ConnectionManager_c.input = CONNECTION_MANAGER_XML +org_ofono_ConnectionManager_c.output = $$CONNECTION_MANAGER_C +org_ofono_ConnectionManager_c.commands = $$CONNECTION_MANAGER_GENERATE +org_ofono_ConnectionManager_c.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_ofono_ConnectionManager_c +GENERATED_SOURCES += $$CONNECTION_MANAGER_C + +# org.ofono.ConnectionContext +CONNECTION_CONTEXT_XML = $$DBUS_SPEC_DIR/org.ofono.ConnectionContext.xml +CONNECTION_CONTEXT_GENERATE = gdbus-codegen --generate-c-code \ + org.ofono.ConnectionContext $$CONNECTION_CONTEXT_XML +CONNECTION_CONTEXT_H = org.ofono.ConnectionContext.h +org_ofono_ConnectionContext_h.input = CONNECTION_CONTEXT_XML +org_ofono_ConnectionContext_h.output = $$CONNECTION_CONTEXT_H +org_ofono_ConnectionContext_h.commands = $$CONNECTION_CONTEXT_GENERATE +org_ofono_ConnectionContext_h.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_ofono_ConnectionContext_h + +CONNECTION_CONTEXT_C = org.ofono.ConnectionContext.c +org_ofono_ConnectionContext_c.input = CONNECTION_CONTEXT_XML +org_ofono_ConnectionContext_c.output = $$CONNECTION_CONTEXT_C +org_ofono_ConnectionContext_c.commands = $$CONNECTION_CONTEXT_GENERATE +org_ofono_ConnectionContext_c.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_ofono_ConnectionContext_c +GENERATED_SOURCES += $$CONNECTION_CONTEXT_C + +# org.ofono.SimManager +SIM_MANAGER_XML = $$DBUS_SPEC_DIR/org.ofono.SimManager.xml +SIM_MANAGER_GENERATE = gdbus-codegen --generate-c-code \ + org.ofono.SimManager $$SIM_MANAGER_XML +SIM_MANAGER_H = org.ofono.SimManager.h +org_ofono_SimManager_h.input = SIM_MANAGER_XML +org_ofono_SimManager_h.output = $$SIM_MANAGER_H +org_ofono_SimManager_h.commands = $$SIM_MANAGER_GENERATE +org_ofono_SimManager_h.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_ofono_SimManager_h + +SIM_MANAGER_C = org.ofono.SimManager.c +org_ofono_SimManager_c.input = SIM_MANAGER_XML +org_ofono_SimManager_c.output = $$SIM_MANAGER_C +org_ofono_SimManager_c.commands = $$SIM_MANAGER_GENERATE +org_ofono_SimManager_c.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_ofono_SimManager_c +GENERATED_SOURCES += $$SIM_MANAGER_C + +# org.ofono.Modem +MODEM_XML = $$DBUS_SPEC_DIR/org.ofono.Modem.xml +MODEM_GENERATE = gdbus-codegen --generate-c-code \ + org.ofono.Modem $$MODEM_XML +MODEM_H = org.ofono.Modem.h +org_ofono_Modem_h.input = MODEM_XML +org_ofono_Modem_h.output = $$MODEM_H +org_ofono_Modem_h.commands = $$MODEM_GENERATE +org_ofono_Modem_h.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_ofono_Modem_h + +MODEM_C = org.ofono.Modem.c +org_ofono_Modem_c.input = MODEM_XML +org_ofono_Modem_c.output = $$MODEM_C +org_ofono_Modem_c.commands = $$MODEM_GENERATE +org_ofono_Modem_c.CONFIG = no_link +QMAKE_EXTRA_COMPILERS += org_ofono_Modem_c +GENERATED_SOURCES += $$MODEM_C diff --git a/mms-ofono/spec/org.ofono.ConnectionContext.xml b/mms-ofono/spec/org.ofono.ConnectionContext.xml new file mode 100644 index 0000000..a0cc069 --- /dev/null +++ b/mms-ofono/spec/org.ofono.ConnectionContext.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + diff --git a/mms-ofono/spec/org.ofono.ConnectionManager.xml b/mms-ofono/spec/org.ofono.ConnectionManager.xml new file mode 100644 index 0000000..6c20187 --- /dev/null +++ b/mms-ofono/spec/org.ofono.ConnectionManager.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mms-ofono/spec/org.ofono.Manager.xml b/mms-ofono/spec/org.ofono.Manager.xml new file mode 100644 index 0000000..de11b3e --- /dev/null +++ b/mms-ofono/spec/org.ofono.Manager.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff --git a/mms-ofono/spec/org.ofono.MessageManager.xml b/mms-ofono/spec/org.ofono.MessageManager.xml new file mode 100644 index 0000000..23d2d05 --- /dev/null +++ b/mms-ofono/spec/org.ofono.MessageManager.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mms-ofono/spec/org.ofono.Modem.xml b/mms-ofono/spec/org.ofono.Modem.xml new file mode 100644 index 0000000..80be1a9 --- /dev/null +++ b/mms-ofono/spec/org.ofono.Modem.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + diff --git a/mms-ofono/spec/org.ofono.NetworkRegistration.xml b/mms-ofono/spec/org.ofono.NetworkRegistration.xml new file mode 100644 index 0000000..69dd7ec --- /dev/null +++ b/mms-ofono/spec/org.ofono.NetworkRegistration.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/mms-ofono/spec/org.ofono.SimManager.xml b/mms-ofono/spec/org.ofono.SimManager.xml new file mode 100644 index 0000000..23fc87b --- /dev/null +++ b/mms-ofono/spec/org.ofono.SimManager.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mms-ofono/src/mms_ofono_connection.c b/mms-ofono/src/mms_ofono_connection.c new file mode 100644 index 0000000..b050f31 --- /dev/null +++ b/mms-ofono/src/mms_ofono_connection.c @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_ofono_connection.h" +#include "mms_ofono_context.h" +#include "mms_ofono_modem.h" +#include "mms_ofono_names.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_connection_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-ofono-connection"); + +/* Generated headers */ +#include "org.ofono.ConnectionContext.h" + +typedef MMSConnectionClass MMSOfonoConnectionClass; + +G_DEFINE_TYPE(MMSOfonoConnection, mms_ofono_connection, MMS_TYPE_CONNECTION); +#define MMS_TYPE_OFONO_CONNECTION (mms_ofono_connection_get_type()) +#define MMS_OFONO_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_TYPE_OFONO_CONNECTION, MMSOfonoConnection)) + +MMSConnection* +mms_ofono_connection( + MMSOfonoConnection* ofono) +{ + return &ofono->connection; +} + +void +mms_ofono_connection_cancel( + MMSOfonoConnection* ofono) +{ + if (ofono->connection.state <= MMS_CONNECTION_STATE_OPENING) { + mms_ofono_connection_set_state(ofono, MMS_CONNECTION_STATE_FAILED); + } else { + mms_ofono_connection_set_state(ofono, MMS_CONNECTION_STATE_CLOSED); + } +} + +gboolean +mms_ofono_connection_set_state( + MMSOfonoConnection* ofono, + MMS_CONNECTION_STATE state) +{ + if (ofono->connection.state != state) { + if (ofono->connection.state == MMS_CONNECTION_STATE_FAILED || + ofono->connection.state == MMS_CONNECTION_STATE_CLOSED) { + /* These are terminal states, can't change those */ + return FALSE; + } else if (ofono->connection.state > state) { + /* Can't move back to a previous state */ + return FALSE; + } + if (state == MMS_CONNECTION_STATE_FAILED || + state == MMS_CONNECTION_STATE_CLOSED) { + /* Stop listening for property changes */ + if (ofono->property_change_signal_id) { + g_signal_handler_disconnect(ofono->proxy, + ofono->property_change_signal_id); + ofono->property_change_signal_id = 0; + } + } + ofono->connection.state = state; + if (ofono->connection.delegate && + ofono->connection.delegate->fn_connection_state_changed) { + ofono->connection.delegate->fn_connection_state_changed( + ofono->connection.delegate, &ofono->connection); + } + } + return TRUE; +} + +static +void +mms_ofono_connection_property_changed( + OrgOfonoConnectionContext* proxy, + const char* key, + GVariant* variant, + MMSOfonoConnection* ofono) +{ + MMSConnection* conn = &ofono->connection; + MMS_ASSERT(proxy == ofono->proxy); + GVariant* value = g_variant_get_variant(variant); + MMS_VERBOSE("%p %s %s", conn, conn->imsi, key); + if (!strcmp(key, OFONO_CONTEXT_PROPERTY_ACTIVE)) { + gboolean active = g_variant_get_boolean(value); + if (active) { + MMS_DEBUG("Connection %s opened", conn->imsi); + mms_ofono_connection_set_state(ofono, MMS_CONNECTION_STATE_OPEN); + } else { + mms_ofono_connection_set_state(ofono, MMS_CONNECTION_STATE_CLOSED); + } + } else if (!strcmp(key, OFONO_CONTEXT_PROPERTY_SETTINGS)) { + GVariant* interfaceValue = g_variant_lookup_value(value, + OFONO_CONTEXT_SETTING_INTERFACE, G_VARIANT_TYPE_STRING); + g_free(conn->netif); + if (interfaceValue) { + conn->netif = g_strdup(g_variant_get_string(interfaceValue, NULL)); + MMS_DEBUG("Interface: %s", conn->netif); + g_variant_unref(interfaceValue); + } else { + conn->netif = NULL; + } + } else if (!strcmp(key, OFONO_CONTEXT_PROPERTY_MMS_PROXY)) { + g_free(conn->mmsproxy); + conn->mmsproxy = g_strdup(g_variant_get_string(value, NULL)); + MMS_DEBUG("MessageProxy: %s", conn->mmsproxy); + } else if (!strcmp(key, OFONO_CONTEXT_PROPERTY_MMS_CENTER)) { + g_free(conn->mmsc); + conn->mmsc = g_strdup(g_variant_get_string(value, NULL)); + MMS_DEBUG("MessageCenter: %s", conn->mmsc); + } else { + MMS_ASSERT(strcmp(key, OFONO_CONTEXT_PROPERTY_TYPE)); + } + g_variant_unref(value); +} + +MMSOfonoConnection* +mms_ofono_connection_new( + MMSOfonoContext* context, + gboolean user_request) +{ + GError* error = NULL; + GVariant* properties = NULL; + if (org_ofono_connection_context_call_get_properties_sync(context->proxy, + &properties, NULL, &error)) { + GVariant* value; + MMSOfonoConnection* ofono; + MMSConnection* conn; + + ofono = g_object_new(MMS_TYPE_OFONO_CONNECTION, NULL); + conn = &ofono->connection; + + conn->user_connection = user_request; + g_object_ref(ofono->proxy = context->proxy); + ofono->context = context; + ofono->connection.state = context->active ? + MMS_CONNECTION_STATE_OPEN : MMS_CONNECTION_STATE_OPENING; + + value = g_variant_lookup_value(properties, + OFONO_CONTEXT_PROPERTY_ACTIVE, G_VARIANT_TYPE_BOOLEAN); + if (value) { + if (g_variant_get_boolean(value)) { + ofono->connection.state = MMS_CONNECTION_STATE_OPEN; + } + g_variant_unref(value); + } + value = g_variant_lookup_value(properties, + OFONO_CONTEXT_PROPERTY_MMS_PROXY, G_VARIANT_TYPE_STRING); + if (value) { + conn->mmsproxy = g_strdup(g_variant_get_string(value, NULL)); + MMS_DEBUG("MessageProxy: %s", conn->mmsproxy); + g_variant_unref(value); + } + value = g_variant_lookup_value(properties, + OFONO_CONTEXT_PROPERTY_MMS_CENTER, G_VARIANT_TYPE_STRING); + if (value) { + conn->mmsc = g_strdup(g_variant_get_string(value, NULL)); + MMS_DEBUG("MessageCenter: %s", conn->mmsc); + g_variant_unref(value); + } + value = g_variant_lookup_value(properties, + OFONO_CONTEXT_PROPERTY_SETTINGS, G_VARIANT_TYPE_VARDICT); + if (value) { + GVariant* netif = g_variant_lookup_value(value, + OFONO_CONTEXT_SETTING_INTERFACE, G_VARIANT_TYPE_STRING); + if (netif) { + conn->netif = g_strdup(g_variant_get_string(netif, NULL)); + MMS_DEBUG("Interface: %s", conn->netif); + g_variant_unref(netif); + } + g_variant_unref(value); + } + + /* Listen for property changes */ + ofono->property_change_signal_id = g_signal_connect( + ofono->proxy, "property-changed", + G_CALLBACK(mms_ofono_connection_property_changed), + conn); + conn->imsi = g_strdup(context->modem->imsi); + g_variant_unref(properties); + return ofono; + } else { + MMS_ERR("Error getting connection properties: %s", MMS_ERRMSG(error)); + if (error) g_error_free(error); + return NULL; + } +} + +MMSOfonoConnection* +mms_ofono_connection_ref( + MMSOfonoConnection* ofono) +{ + if (ofono) mms_connection_ref(&ofono->connection); + return ofono; +} + +void +mms_ofono_connection_unref( + MMSOfonoConnection* ofono) +{ + if (ofono) mms_connection_unref(&ofono->connection); +} + +static +void +mms_ofono_connection_close( + MMSConnection* connection) +{ + MMSOfonoConnection* ofono = MMS_OFONO_CONNECTION(connection); + if (ofono->context) mms_ofono_context_set_active(ofono->context, FALSE); +} + +/** + * First stage of deinitialization (release all references). + * May be called more than once in the lifetime of the object. + */ +static +void +mms_ofono_connection_dispose( + GObject* object) +{ + MMSOfonoConnection* ofono = MMS_OFONO_CONNECTION(object); + if (ofono->property_change_signal_id) { + g_signal_handler_disconnect(ofono->proxy, + ofono->property_change_signal_id); + ofono->property_change_signal_id = 0; + } + if (ofono->proxy) { + g_object_unref(ofono->proxy); + ofono->proxy = NULL; + } + G_OBJECT_CLASS(mms_ofono_connection_parent_class)->dispose(object); +} + +/** + * Per class initializer + */ +static +void +mms_ofono_connection_class_init( + MMSOfonoConnectionClass* klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS(klass); + klass->fn_close = mms_ofono_connection_close; + object_class->dispose = mms_ofono_connection_dispose; +} + +/** + * Per instance initializer + */ +static +void +mms_ofono_connection_init( + MMSOfonoConnection* conn) +{ + MMS_VERBOSE_("%p", conn); +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/src/mms_ofono_connection.h b/mms-ofono/src/mms_ofono_connection.h new file mode 100644 index 0000000..d30b1c2 --- /dev/null +++ b/mms-ofono/src/mms_ofono_connection.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_CONNECTION_OFONO_H +#define JOLLA_MMS_CONNECTION_OFONO_H + +#include "mms_connection.h" +#include "mms_ofono_types.h" + +struct mms_ofono_connection { + MMSConnection connection; + MMSOfonoContext* context; + struct _OrgOfonoConnectionContext* proxy; + gulong property_change_signal_id; +}; + +MMSOfonoConnection* +mms_ofono_connection_new( + MMSOfonoContext* context, + gboolean user_request); + +MMSOfonoConnection* +mms_ofono_connection_ref( + MMSOfonoConnection* connection); + +void +mms_ofono_connection_unref( + MMSOfonoConnection* connection); + +void +mms_ofono_connection_cancel( + MMSOfonoConnection* connection); + +gboolean +mms_ofono_connection_set_state( + MMSOfonoConnection* connection, + MMS_CONNECTION_STATE state); + +#endif /* JOLLA_MMS_CONNECTION_OFONO_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/src/mms_ofono_connman.c b/mms-ofono/src/mms_ofono_connman.c new file mode 100644 index 0000000..6651ba7 --- /dev/null +++ b/mms-ofono/src/mms_ofono_connman.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_ofono_connman.h" +#include "mms_ofono_connection.h" +#include "mms_ofono_manager.h" +#include "mms_ofono_modem.h" +#include "mms_ofono_names.h" +#include "mms_connection.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_connman_log +#include "mms_lib_log.h" +MMS_LOG_MODULE_DEFINE("mms-ofono-connman"); + +typedef MMSConnManClass MMSOfonoConnManClass; +typedef struct mms_ofono_connman { + GObject cm; + guint ofono_watch_id; + GDBusConnection* bus; + MMSOfonoManager* man; +} MMSOfonoConnMan; + +G_DEFINE_TYPE(MMSOfonoConnMan, mms_ofono_connman, MMS_TYPE_CONNMAN); +#define MMS_TYPE_OFONO_CONNMAN (mms_ofono_connman_get_type()) +#define MMS_OFONO_CONNMAN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + MMS_TYPE_OFONO_CONNMAN, MMSOfonoConnMan)) + +/** + * Creates a new connection or returns the reference to an aready active one. + * The caller must release the reference. + */ +static +MMSConnection* +mms_ofono_connman_open_connection( + MMSConnMan* cm, + const char* imsi, + gboolean user_request) +{ + MMSOfonoConnMan* ofono = MMS_OFONO_CONNMAN(cm); + MMSOfonoModem* modem = mms_ofono_manager_modem_for_imsi(ofono->man, imsi); + if (modem) { + MMSOfonoContext* mms = modem->mms_context; + if (mms) { + if (!mms->connection) { + mms->connection = mms_ofono_connection_new(mms, user_request); + } + if (mms->connection && !mms->active) { + mms_ofono_context_set_active(mms, TRUE); + } + return mms_connection_ref(&mms->connection->connection); + } + } else { + MMS_DEBUG("SIM %s is not avialable", imsi); + } + return NULL; +} + +static +void +mms_connman_ofono_appeared( + GDBusConnection* bus, + const gchar* name, + const gchar* owner, + gpointer self) +{ + MMSOfonoConnMan* ofono = self; + MMS_DEBUG("Name '%s' is owned by %s", name, owner); + MMS_ASSERT(!ofono->man); + mms_ofono_manager_free(ofono->man); + ofono->man = mms_ofono_manager_new(bus); +} + +static +void +mms_connman_ofono_vanished( + GDBusConnection* bus, + const gchar* name, + gpointer self) +{ + MMSOfonoConnMan* ofono = self; + MMS_DEBUG("Name '%s' has disappeared", name); + mms_ofono_manager_free(ofono->man); + ofono->man = NULL; +} + +/** + * Creates oFono connection manager + */ +MMSConnMan* +mms_connman_ofono_new() +{ + GError* error = NULL; + GDBusConnection* bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (bus) { + MMSOfonoConnMan* ofono = g_object_new(MMS_TYPE_OFONO_CONNMAN, NULL); + ofono->bus = bus; + ofono->ofono_watch_id = g_bus_watch_name_on_connection(bus, + OFONO_SERVICE, G_BUS_NAME_WATCHER_FLAGS_NONE, + mms_connman_ofono_appeared, mms_connman_ofono_vanished, + ofono, NULL); + MMS_ASSERT(ofono->ofono_watch_id); + return &ofono->cm; + } else { + MMS_ERR("Failed to connect to system bus: %s", MMS_ERRMSG(error)); + g_error_free(error); + return NULL; + } +} + +/** + * First stage of deinitialization (release all references). + * May be called more than once in the lifetime of the object. + */ +static +void +mms_ofono_connman_dispose( + GObject* object) +{ + MMSOfonoConnMan* ofono = MMS_OFONO_CONNMAN(object); + MMS_VERBOSE_(""); + if (ofono->ofono_watch_id) { + g_bus_unwatch_name(ofono->ofono_watch_id); + ofono->ofono_watch_id = 0; + } + if (ofono->man) { + mms_ofono_manager_free(ofono->man); + ofono->man = NULL; + } + if (ofono->bus) { + g_object_unref(ofono->bus); + ofono->bus = NULL; + } + G_OBJECT_CLASS(mms_ofono_connman_parent_class)->dispose(object); +} + +/** + * Per class initializer + */ +static +void +mms_ofono_connman_class_init( + MMSOfonoConnManClass* klass) +{ + klass->fn_open_connection = mms_ofono_connman_open_connection; + G_OBJECT_CLASS(klass)->dispose = mms_ofono_connman_dispose; +} + +/** + * Per instance initializer + */ +static +void +mms_ofono_connman_init( + MMSOfonoConnMan* cm) +{ +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/src/mms_ofono_context.c b/mms-ofono/src/mms_ofono_context.c new file mode 100644 index 0000000..5166428 --- /dev/null +++ b/mms-ofono/src/mms_ofono_context.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_ofono_context.h" +#include "mms_ofono_modem.h" +#include "mms_ofono_connection.h" +#include "mms_ofono_names.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_ofono_context_log +#include "mms_ofono_log.h" +MMS_LOG_MODULE_DEFINE("mms-ofono-context"); + +/* Generated headers */ +#include "org.ofono.ConnectionContext.h" + +static +void +mms_ofono_context_property_changed( + OrgOfonoConnectionContext* proxy, + const char* key, + GVariant* variant, + MMSOfonoContext* context) +{ + MMS_ASSERT(proxy == context->proxy); + if (!strcmp(key, OFONO_CONTEXT_PROPERTY_ACTIVE)) { + GVariant* value = g_variant_get_variant(variant); + context->active = g_variant_get_boolean(value); + MMS_VERBOSE_("%p %s = %d", context, key, context->active); + g_variant_unref(value); + if (context->active) { + if (context->connection && !mms_ofono_connection_set_state( + context->connection, MMS_CONNECTION_STATE_OPEN)) { + /* Connection is in a wrong state? */ + context->connection->context = NULL; + mms_ofono_connection_unref(context->connection); + context->connection = NULL; + } + if (!context->connection) { + context->connection = mms_ofono_connection_new(context, FALSE); + } + } else if (context->connection) { + context->connection->context = NULL; + mms_ofono_connection_unref(context->connection); + context->connection = NULL; + } + } else { + MMS_VERBOSE_("%p %s", context, key); + MMS_ASSERT(strcmp(key, OFONO_CONTEXT_PROPERTY_TYPE)); + } +} + +static +void +mms_ofono_context_set_active_done( + GObject* proxy, + GAsyncResult* result, + gpointer user_data) +{ + GError* error = NULL; + MMSOfonoContext* context = user_data; + gboolean ok = org_ofono_connection_context_call_set_property_finish( + ORG_OFONO_CONNECTION_CONTEXT(proxy), result, &error); + + if (!ok) { + MMSOfonoConnection* ofono = context->connection; + if (ofono && ofono->connection.state == MMS_CONNECTION_STATE_OPENING) { + /* Connection failed to open, fire state change event and drop + * our reference to it */ + context->connection = NULL; + ofono->context = NULL; + MMS_ERR("Connection %s failed: %s", ofono->connection.imsi, + MMS_ERRMSG(error)); + + mms_ofono_connection_set_state(ofono, MMS_CONNECTION_STATE_FAILED); + mms_ofono_connection_unref(ofono); + } + } + + if (error) g_error_free(error); +} + +void +mms_ofono_context_set_active( + MMSOfonoContext* context, + gboolean active) +{ + GCancellable* cancel; + GAsyncReadyCallback cb; + gpointer data; + if (active) { + MMS_DEBUG("Opening connection %s", context->modem->imsi); + if (context->set_active_cancel) { + g_cancellable_cancel(context->set_active_cancel); + g_object_unref(context->set_active_cancel); + } + cancel = context->set_active_cancel = g_cancellable_new(); + cb = mms_ofono_context_set_active_done; + data = context; + } else { + MMS_DEBUG("Closing connection %s", context->modem->imsi); + cancel = NULL; + cb = NULL; + data = NULL; + if (context->connection) { + MMSOfonoConnection* ofono = context->connection; + context->connection = NULL; + ofono->context = NULL; + mms_ofono_connection_set_state(ofono,MMS_CONNECTION_STATE_CLOSED); + mms_ofono_connection_unref(ofono); + } + } + org_ofono_connection_context_call_set_property(context->proxy, + OFONO_CONTEXT_PROPERTY_ACTIVE, g_variant_new_variant( + g_variant_new_boolean(active)), cancel, cb, data); +} + +MMSOfonoContext* +mms_ofono_context_new( + MMSOfonoModem* modem, + const char* path, + GVariant* properties) +{ + GError* error = NULL; + OrgOfonoConnectionContext* proxy; + proxy = org_ofono_connection_context_proxy_new_sync(modem->bus, + G_DBUS_PROXY_FLAGS_NONE, OFONO_SERVICE, path, NULL, &error); + if (proxy) { + MMSOfonoContext* context = g_new0(MMSOfonoContext, 1); + GVariant* value = g_variant_lookup_value( + properties, OFONO_CONTEXT_PROPERTY_ACTIVE, + G_VARIANT_TYPE_BOOLEAN); + if (value) { + context->active = g_variant_get_boolean(value); + g_variant_unref(value); + } + context->path = g_strdup(path); + context->proxy = proxy; + context->modem = modem; + + /* Subscribe for PropertyChanged notifications */ + context->property_change_signal_id = g_signal_connect( + proxy, "property-changed", + G_CALLBACK(mms_ofono_context_property_changed), + context); + + return context; + } else { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + return NULL; + } +} + +void +mms_ofono_context_free( + MMSOfonoContext* context) +{ + if (context) { + if (context->connection) { + context->connection->context = NULL; + mms_ofono_connection_cancel(context->connection); + mms_ofono_connection_unref(context->connection); + } + if (context->set_active_cancel) { + g_cancellable_cancel(context->set_active_cancel); + g_object_unref(context->set_active_cancel); + } + if (context->proxy) { + g_signal_handler_disconnect(context->proxy, + context->property_change_signal_id); + g_object_unref(context->proxy); + } + g_free(context->path); + g_free(context); + } +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/src/mms_ofono_context.h b/mms-ofono/src/mms_ofono_context.h new file mode 100644 index 0000000..be527af --- /dev/null +++ b/mms-ofono/src/mms_ofono_context.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_OFONO_CONTEXT_H +#define JOLLA_MMS_OFONO_CONTEXT_H + +#include "mms_ofono_types.h" + +struct mms_ofono_context { + MMSOfonoModem* modem; + char* path; + gboolean active; + struct _OrgOfonoConnectionContext* proxy; + gulong property_change_signal_id; + MMSOfonoConnection* connection; + GCancellable* set_active_cancel; +}; + +MMSOfonoContext* +mms_ofono_context_new( + MMSOfonoModem* modem, + const char* path, + GVariant* properties); + +void +mms_ofono_context_set_active( + MMSOfonoContext* context, + gboolean active); + +void +mms_ofono_context_free( + MMSOfonoContext* context); + +#endif /* JOLLA_MMS_OFONO_CONTEXT_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/src/mms_ofono_manager.c b/mms-ofono/src/mms_ofono_manager.c new file mode 100644 index 0000000..697ef3f --- /dev/null +++ b/mms-ofono/src/mms_ofono_manager.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_ofono_manager.h" +#include "mms_ofono_modem.h" +#include "mms_ofono_names.h" +#include "mms_ofono_names.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_ofono_manager_log +#include "mms_ofono_log.h" +MMS_LOG_MODULE_DEFINE("mms-ofono-manager"); + +/* Generated headers */ +#include "org.ofono.Manager.h" + +struct mms_ofono_manager { + GDBusConnection* bus; + GHashTable* modems; + OrgOfonoManager* proxy; + gulong modem_added_signal_id; + gulong modem_removed_signal_id; +}; + +static +void +mms_ofono_manager_set_modems( + MMSOfonoManager* ofono, + GVariant* modems) +{ + GVariantIter iter; + GVariant* child; + MMS_DEBUG("%u modem(s) found", (guint)g_variant_n_children(modems)); + g_hash_table_remove_all(ofono->modems); + + for (g_variant_iter_init(&iter, modems); + (child = g_variant_iter_next_value(&iter)) != NULL; + g_variant_unref(child)) { + + MMSOfonoModem* modem; + const char* path = NULL; + GVariant* properties = NULL; + + g_variant_get(child, "(&o@a{sv})", &path, &properties); + MMS_ASSERT(path); + MMS_ASSERT(properties); + + modem = mms_ofono_modem_new(ofono->bus, path, properties); + if (modem) g_hash_table_replace(ofono->modems, modem->path, modem); + g_variant_unref(properties); + } +} + +static +void +mms_ofono_manager_modem_added( + OrgOfonoManager* proxy, + const char* path, + GVariant* properties, + MMSOfonoManager* ofono) +{ + MMSOfonoModem* modem; + MMS_VERBOSE_("%p %s", ofono, path); + MMS_ASSERT(proxy == ofono->proxy); + g_hash_table_remove(ofono->modems, path); + modem = mms_ofono_modem_new(ofono->bus, path, properties); + if (modem) g_hash_table_replace(ofono->modems, modem->path, modem); +} + +static +void +mms_ofono_manager_modem_removed( + OrgOfonoManager* proxy, + const char* path, + MMSOfonoManager* ofono) +{ + MMS_VERBOSE_("%p %s", ofono, path); + MMS_ASSERT(proxy == ofono->proxy); + g_hash_table_remove(ofono->modems, path); +} + +static +void +mms_ofono_manager_hash_remove_modem( + gpointer data) +{ + mms_ofono_modem_free(data); +} + +MMSOfonoManager* +mms_ofono_manager_new( + GDBusConnection* bus) +{ + GError* error = NULL; + OrgOfonoManager* proxy = org_ofono_manager_proxy_new_sync(bus, + G_DBUS_PROXY_FLAGS_NONE, OFONO_SERVICE, "/", NULL, &error); + if (proxy) { + GVariant* modems = NULL; + if (org_ofono_manager_call_get_modems_sync(proxy, &modems, + NULL, &error)) { + + MMSOfonoManager* ofono = g_new0(MMSOfonoManager, 1); + ofono->proxy = proxy; + g_object_ref(ofono->bus = bus); + ofono->modems = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, mms_ofono_manager_hash_remove_modem); + + /* Subscribe for ModemAdded/Removed notifications */ + ofono->modem_added_signal_id = g_signal_connect( + proxy, "modem-added", + G_CALLBACK(mms_ofono_manager_modem_added), + ofono); + ofono->modem_removed_signal_id = g_signal_connect( + proxy, "modem-removed", + G_CALLBACK(mms_ofono_manager_modem_removed), + ofono); + + mms_ofono_manager_set_modems(ofono, modems); + g_variant_unref(modems); + return ofono; + + } else { + MMS_ERR("Can't get list of modems: %s", MMS_ERRMSG(error)); + g_error_free(error); + } + g_object_unref(proxy); + } else { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + } + return NULL; +} + +static +gboolean +mms_ofono_manager_modem_imsi_find_cb( + gpointer key, + gpointer value, + gpointer user_data) +{ + MMSOfonoModem* modem = value; + const char* imsi = user_data; + MMS_ASSERT(imsi); + return modem->imsi && !strcmp(modem->imsi, imsi); +} + +MMSOfonoModem* +mms_ofono_manager_modem_for_imsi( + MMSOfonoManager* ofono, + const char* imsi) +{ + return ofono ? g_hash_table_find(ofono->modems, + mms_ofono_manager_modem_imsi_find_cb, (void*)imsi) : NULL; +} + +void +mms_ofono_manager_free( + MMSOfonoManager* ofono) +{ + if (ofono) { + if (ofono->proxy) { + g_signal_handler_disconnect(ofono->proxy, + ofono->modem_added_signal_id); + g_signal_handler_disconnect(ofono->proxy, + ofono->modem_removed_signal_id); + g_object_unref(ofono->proxy); + } + g_hash_table_destroy(ofono->modems); + g_object_unref(ofono->bus); + g_free(ofono); + } +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/src/mms_ofono_manager.h b/mms-ofono/src/mms_ofono_manager.h new file mode 100644 index 0000000..76e40ae --- /dev/null +++ b/mms-ofono/src/mms_ofono_manager.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_OFONO_MANAGER_H +#define JOLLA_MMS_OFONO_MANAGER_H + +#include "mms_ofono_types.h" + +MMSOfonoManager* +mms_ofono_manager_new( + GDBusConnection* bus); + +void +mms_ofono_manager_free( + MMSOfonoManager* ofono); + +MMSOfonoModem* +mms_ofono_manager_modem_for_imsi( + MMSOfonoManager* ofono, + const char* imsi); + +#endif /* JOLLA_MMS_OFONO_MANAGER_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/src/mms_ofono_modem.c b/mms-ofono/src/mms_ofono_modem.c new file mode 100644 index 0000000..95bef9a --- /dev/null +++ b/mms-ofono/src/mms_ofono_modem.c @@ -0,0 +1,392 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_ofono_modem.h" +#include "mms_ofono_names.h" + +/* Logging */ +#define MMS_LOG_MODULE_NAME mms_ofono_modem_log +#include "mms_ofono_log.h" +MMS_LOG_MODULE_DEFINE("mms-ofono-modem"); + +/* Generated headers */ +#include "org.ofono.Modem.h" +#include "org.ofono.SimManager.h" +#include "org.ofono.ConnectionManager.h" + +typedef struct mms_context_info { + char* path; + GVariant* properties; +} MMSContextInfo; + +static +MMSContextInfo* +mms_context_info_new( + const char* path, + GVariant* properties) +{ + MMSContextInfo* info = g_new(MMSContextInfo, 1); + info->path = g_strdup(path); + g_variant_ref(info->properties = properties); + return info; +} + +void +mms_context_info_free( + MMSContextInfo* info) +{ + if (info) { + g_variant_unref(info->properties); + g_free(info->path); + g_free(info); + } +} + +static +void +mms_ofono_modem_disconnect_sim_proxy( + MMSOfonoModem* modem) +{ + if (modem->sim_proxy) { + g_signal_handler_disconnect(modem->sim_proxy, + modem->sim_property_change_signal_id); + g_object_unref(modem->sim_proxy); + modem->sim_proxy = NULL; + } +} + +static +void +mms_ofono_modem_disconnect_gprs_proxy( + MMSOfonoModem* modem) +{ + if (modem->gprs_proxy) { + g_signal_handler_disconnect(modem->gprs_proxy, + modem->gprs_context_added_signal_id); + g_signal_handler_disconnect(modem->gprs_proxy, + modem->gprs_context_removed_signal_id); + g_object_unref(modem->gprs_proxy); + modem->gprs_proxy = NULL; + } +} + +static +MMSContextInfo* +mms_ofono_modem_find_mms_context( + OrgOfonoConnectionManager* proxy) +{ + GError* error = NULL; + MMSContextInfo* mms_context = NULL; + GVariant* contexts = NULL; + if (org_ofono_connection_manager_call_get_contexts_sync(proxy, + &contexts, NULL, &error)) { + GVariantIter iter; + GVariant* child; + MMS_VERBOSE(" %d context(s)", (guint)g_variant_n_children(contexts)); + for (g_variant_iter_init(&iter, contexts); + !mms_context && (child = g_variant_iter_next_value(&iter)); + g_variant_unref(child)) { + + const char* path = NULL; + GVariant* properties = NULL; + g_variant_get(child, "(&o@a{sv})", &path, &properties); + if (properties) { + GVariant* value = g_variant_lookup_value(properties, + OFONO_CONTEXT_PROPERTY_TYPE, G_VARIANT_TYPE_STRING); + if (value) { + const char* type = g_variant_get_string(value, NULL); + if (path && type && !strcmp(type, OFONO_CONTEXT_TYPE_MMS)) { + mms_context = mms_context_info_new(path, properties); + } + g_variant_unref(value); + } + g_variant_unref(properties); + } + } + g_variant_unref(contexts); + } else { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + } + return mms_context; +} + +static +void +mms_ofono_modem_gprs_context_added( + OrgOfonoConnectionManager* proxy, + const char* path, + GVariant* properties, + MMSOfonoModem* modem) +{ + GVariant* value = g_variant_lookup_value(properties, + OFONO_CONTEXT_PROPERTY_TYPE, G_VARIANT_TYPE_STRING); + const char* type = g_variant_get_string(value, NULL); + MMS_VERBOSE_("%p %s", modem, path); + MMS_ASSERT(proxy == modem->gprs_proxy); + if (type && !strcmp(type, OFONO_CONTEXT_TYPE_MMS)) { + MMS_DEBUG("MMS context %s created", path); + } + g_variant_unref(value); +} + +static +void +mms_ofono_modem_gprs_context_removed( + OrgOfonoConnectionManager* proxy, + const char* path, + MMSOfonoModem* modem) +{ + MMS_VERBOSE_("%p %s", modem, path); + MMS_ASSERT(proxy == modem->gprs_proxy); + if (modem->mms_context && g_strcmp0(modem->mms_context->path, path)) { + MMS_DEBUG("MMS context %s removed", path); + } +} + +static +char* +mms_ofono_modem_query_imsi( + OrgOfonoSimManager* proxy) +{ + char* imsi = NULL; + GError* error = NULL; + GVariant* properties = NULL; + if (org_ofono_sim_manager_call_get_properties_sync(proxy, &properties, + NULL, &error)) { + GVariant* imsi_value = g_variant_lookup_value(properties, + OFONO_SIM_PROPERTY_SUBSCRIBER_IDENTITY, G_VARIANT_TYPE_STRING); + if (imsi_value) { + imsi = g_strdup(g_variant_get_string(imsi_value, NULL)); + g_variant_unref(imsi_value); + } + g_variant_unref(properties); + } else { + MMS_ERR("%s", MMS_ERRMSG(error)); + g_error_free(error); + } + return imsi; +} + +static +void +mms_ofono_modem_sim_property_changed( + OrgOfonoSimManager* proxy, + const char* key, + GVariant* value, + MMSOfonoModem* modem) +{ + MMS_VERBOSE_("%p %s", modem, key); + MMS_ASSERT(proxy == modem->sim_proxy); + if (!strcmp(key, OFONO_SIM_PROPERTY_SUBSCRIBER_IDENTITY)) { + GVariant* variant = g_variant_get_variant(value); + g_free(modem->imsi); + modem->imsi = g_strdup(g_variant_get_string(variant, NULL)); + g_variant_unref(variant); + MMS_VERBOSE("IMSI: %s", modem->imsi); + } +} + +static +void +mms_ofono_modem_scan_interfaces( + MMSOfonoModem* m, + GVariant* ifs) +{ + GError* error = NULL; + gboolean sim_interface = FALSE; + gboolean gprs_interface = FALSE; + + if (ifs) { + GVariantIter iter; + GVariant* child; + for (g_variant_iter_init(&iter, ifs); + (child = g_variant_iter_next_value(&iter)) && + (!sim_interface || !gprs_interface); + g_variant_unref(child)) { + const char* ifname = NULL; + g_variant_get(child, "&s", &ifname); + if (ifname) { + if (!strcmp(ifname, OFONO_SIM_INTERFACE)) { + MMS_VERBOSE(" Found %s", ifname); + sim_interface = TRUE; + } else if (!strcmp(ifname, OFONO_GPRS_INTERFACE)) { + MMS_VERBOSE(" Found %s", ifname); + gprs_interface = TRUE; + } + } + } + } + + /* org.ofono.SimManager */ + if (m->imsi) { + g_free(m->imsi); + m->imsi = NULL; + } + if (sim_interface) { + if (!m->sim_proxy) { + m->sim_proxy = org_ofono_sim_manager_proxy_new_sync(m->bus, + G_DBUS_PROXY_FLAGS_NONE, OFONO_SERVICE, m->path, NULL, &error); + if (m->sim_proxy) { + /* Subscribe for PropertyChanged notifications */ + m->sim_property_change_signal_id = g_signal_connect( + m->sim_proxy, "property-changed", + G_CALLBACK(mms_ofono_modem_sim_property_changed), + m); + } else { + MMS_ERR("SimManager %s: %s", m->path, MMS_ERRMSG(error)); + g_error_free(error); + } + } + if (m->sim_proxy) { + m->imsi = mms_ofono_modem_query_imsi(m->sim_proxy); + MMS_VERBOSE("IMSI: %s", m->imsi ? m->imsi : ""); + } + } else if (m->sim_proxy) { + mms_ofono_modem_disconnect_sim_proxy(m); + } + + /* org.ofono.ConnectionManager */ + if (gprs_interface) { + MMSContextInfo* context_info = NULL; + if (!m->gprs_proxy) { + m->gprs_proxy = org_ofono_connection_manager_proxy_new_sync(m->bus, + G_DBUS_PROXY_FLAGS_NONE, OFONO_SERVICE, m->path, NULL, &error); + if (m->gprs_proxy) { + /* Subscribe for ContextAdded/Removed notifications */ + m->gprs_context_added_signal_id = g_signal_connect( + m->gprs_proxy, "context-added", + G_CALLBACK(mms_ofono_modem_gprs_context_added), + m); + m->gprs_context_removed_signal_id = g_signal_connect( + m->gprs_proxy, "context-removed", + G_CALLBACK(mms_ofono_modem_gprs_context_removed), + m); + } else { + MMS_ERR("ConnectionManager %s: %s", m->path, MMS_ERRMSG(error)); + g_error_free(error); + } + } + if (m->gprs_proxy) { + context_info = mms_ofono_modem_find_mms_context(m->gprs_proxy); + } + if (context_info) { + MMS_VERBOSE("MMS context: %s", context_info->path); + if (m->mms_context && + !g_strcmp0(context_info->path, m->mms_context->path)) { + mms_ofono_context_free(m->mms_context); + m->mms_context = NULL; + } + if (!m->mms_context) { + m->mms_context = mms_ofono_context_new(m, context_info->path, + context_info->properties); + } + mms_context_info_free(context_info); + } else { + MMS_VERBOSE("No MMS context"); + if (m->mms_context) { + mms_ofono_context_free(m->mms_context); + m->mms_context = NULL; + } + } + } else if (m->gprs_proxy) { + mms_ofono_modem_disconnect_gprs_proxy(m); + if (m->mms_context) { + mms_ofono_context_free(m->mms_context); + m->mms_context = NULL; + } + } +} + +static +void +mms_ofono_modem_property_changed( + OrgOfonoModem* proxy, + const char* key, + GVariant* variant, + MMSOfonoModem* modem) +{ + MMS_VERBOSE_("%p %s", modem, key); + MMS_ASSERT(proxy == modem->proxy); + if (!strcmp(key, OFONO_MODEM_PROPERTY_INTERFACES)) { + GVariant* value = g_variant_get_variant(variant); + mms_ofono_modem_scan_interfaces(modem, value); + g_variant_unref(value); + } +} + +MMSOfonoModem* +mms_ofono_modem_new( + GDBusConnection* bus, + const char* path, + GVariant* properties) +{ + GError* error = NULL; + MMSOfonoModem* modem = NULL; + OrgOfonoModem* proxy = org_ofono_modem_proxy_new_sync(bus, + G_DBUS_PROXY_FLAGS_NONE, OFONO_SERVICE, path, NULL, &error); + if (proxy) { + GVariant* interfaces = g_variant_lookup_value(properties, + OFONO_MODEM_PROPERTY_INTERFACES, G_VARIANT_TYPE_STRING_ARRAY); + modem = g_new0(MMSOfonoModem, 1); + MMS_DEBUG("Modem path '%s'", path); + MMS_VERBOSE_("%p '%s'", modem, path); + modem->path = g_strdup(path); + modem->proxy = proxy; + g_object_ref(modem->bus = bus); + + /* Check what we currently have */ + mms_ofono_modem_scan_interfaces(modem, interfaces); + g_variant_unref(interfaces); + + /* Register to receive PropertyChanged notifications */ + modem->property_change_signal_id = g_signal_connect( + proxy, "property-changed", + G_CALLBACK(mms_ofono_modem_property_changed), + modem); + } else { + MMS_ERR("%s: %s", path, MMS_ERRMSG(error)); + g_error_free(error); + } + return modem; +} + +void +mms_ofono_modem_free( + MMSOfonoModem* modem) +{ + if (modem) { + MMS_VERBOSE_("%p '%s'", modem, modem->path); + mms_ofono_modem_disconnect_sim_proxy(modem); + mms_ofono_modem_disconnect_gprs_proxy(modem); + mms_ofono_context_free(modem->mms_context); + if (modem->proxy) { + g_signal_handler_disconnect(modem->proxy, + modem->property_change_signal_id); + g_object_unref(modem->proxy); + } + g_object_unref(modem->bus); + g_free(modem->path); + g_free(modem->imsi); + g_free(modem); + } +} + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/src/mms_ofono_modem.h b/mms-ofono/src/mms_ofono_modem.h new file mode 100644 index 0000000..516e6ad --- /dev/null +++ b/mms-ofono/src/mms_ofono_modem.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_OFONO_MODEM_H +#define JOLLA_MMS_OFONO_MODEM_H + +#include "mms_ofono_context.h" + +struct mms_ofono_modem { + GDBusConnection* bus; + char* path; + + struct _OrgOfonoModem* proxy; + gulong property_change_signal_id; + + struct _OrgOfonoSimManager* sim_proxy; + gulong sim_property_change_signal_id; + char* imsi; + + struct _OrgOfonoConnectionManager* gprs_proxy; + gulong gprs_context_added_signal_id; + gulong gprs_context_removed_signal_id; + + MMSOfonoContext* mms_context; +}; + +MMSOfonoModem* +mms_ofono_modem_new( + GDBusConnection* bus, + const char* path, + GVariant* properties); + +void +mms_ofono_modem_free( + MMSOfonoModem* modem); + +#endif /* JOLLA_MMS_OFONO_MODEM_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/src/mms_ofono_names.h b/mms-ofono/src/mms_ofono_names.h new file mode 100644 index 0000000..11a510c --- /dev/null +++ b/mms-ofono/src/mms_ofono_names.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_OFONO_NAMES_H +#define JOLLA_MMS_OFONO_NAMES_H + +#define OFONO_SERVICE "org.ofono" + +#define OFONO_MANAGER_INTERFACE OFONO_SERVICE ".Manager" +#define OFONO_MODEM_INTERFACE OFONO_SERVICE ".Modem" +#define OFONO_SIM_INTERFACE OFONO_SERVICE ".SimManager" +#define OFONO_GPRS_INTERFACE OFONO_SERVICE ".ConnectionManager" +#define OFONO_CONTEXT_INTERFACE OFONO_SERVICE ".ConnectionContext" + +#define OFONO_MODEM_PROPERTY_INTERFACES "Interfaces" +#define OFONO_SIM_PROPERTY_SUBSCRIBER_IDENTITY "SubscriberIdentity" + +#define OFONO_CONTEXT_PROPERTY_ACTIVE "Active" +#define OFONO_CONTEXT_PROPERTY_MMS_PROXY "MessageProxy" +#define OFONO_CONTEXT_PROPERTY_MMS_CENTER "MessageCenter" + +#define OFONO_CONTEXT_PROPERTY_SETTINGS "Settings" +#define OFONO_CONTEXT_SETTING_INTERFACE "Interface" + +#define OFONO_CONTEXT_PROPERTY_TYPE "Type" +#define OFONO_CONTEXT_TYPE_MMS "mms" + +#endif /* JOLLA_MMS_OFONO_NAMES_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/mms-ofono/src/mms_ofono_types.h b/mms-ofono/src/mms_ofono_types.h new file mode 100644 index 0000000..6627a77 --- /dev/null +++ b/mms-ofono/src/mms_ofono_types.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013-2014 Jolla Ltd. + * + * 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_OFONO_TYPES_H +#define JOLLA_MMS_OFONO_TYPES_H + +#include +#include "mms_lib_util.h" + +typedef struct mms_ofono_manager MMSOfonoManager; +typedef struct mms_ofono_modem MMSOfonoModem; +typedef struct mms_ofono_context MMSOfonoContext; +typedef struct mms_ofono_connection MMSOfonoConnection; + +#endif /* JOLLA_MMS_OFONO_TYPES_H */ + +/* + * Local Variables: + * mode: C + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/rpm/mms-engine.spec b/rpm/mms-engine.spec new file mode 100644 index 0000000..45c723a --- /dev/null +++ b/rpm/mms-engine.spec @@ -0,0 +1,53 @@ +Name: mms-engine +Summary: MMS engine +Version: 1.1.0 +Release: 1 +Group: Communications/Telephony and IM +License: GPLv2 +URL: https://github.com/nemomobile/mms-engine +Source0: %{name}-%{version}.tar.bz2 +Requires: dbus +Requires: ofono + +BuildRequires: python +BuildRequires: pkgconfig(glib-2.0) >= 2.32 +BuildRequires: pkgconfig(libsoup-2.4) >= 2.38 +BuildRequires: pkgconfig(libwspcodec) >= 2.0 + +%define src mms-engine +%define exe mms-engine +%define dbusname org.nemomobile.MmsEngine +%define dbusconfig %{_datadir}/dbus-1/system-services +%define dbuspolicy %{_sysconfdir}/dbus-1/system.d + +# Activation method: +%define pushconfig %{_sysconfdir}/ofono/push_forwarder.d +#define pushconfig {_sysconfdir}/push-agent +#Requires: push-agent >= 1.1 + +%description +MMS engine + +%prep +%setup -q -n %{name}-%{version} + +%build +make -C %{src} release + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}%{_sbindir} +mkdir -p %{buildroot}%{dbusconfig} +mkdir -p %{buildroot}%{dbuspolicy} +mkdir -p %{buildroot}%{pushconfig} +cp %{src}/build/release/%{exe} %{buildroot}%{_sbindir}/ +cp %{src}/%{dbusname}.service %{buildroot}%{dbusconfig}/ +cp %{src}/%{dbusname}.dbus.conf %{buildroot}%{dbuspolicy}/%{dbusname}.conf +cp %{src}/%{dbusname}.push.conf %{buildroot}%{pushconfig}/%{dbusname}.conf + +%files +%defattr(-,root,root,-) +%config %{dbuspolicy}/%{dbusname}.conf +%config %{pushconfig}/%{dbusname}.conf +%{dbusconfig}/%{dbusname}.service +%{_sbindir}/%{exe}

UJX;zo>{W@HjY-e)S!~&-;|0{$ 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 literal 0 HcmV?d00001 diff --git a/mms-lib/test/retrieve/data/Success/parts/0 b/mms-lib/test/retrieve/data/Success/parts/0 new file mode 100644 index 0000000..cf85a6a --- /dev/null +++ b/mms-lib/test/retrieve/data/Success/parts/0 @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mms-lib/test/retrieve/data/Success/parts/131200181.jpg b/mms-lib/test/retrieve/data/Success/parts/131200181.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fe09b04fa165b5ac13325e90b129efe02d9247b5 GIT binary patch literal 44022 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 Vc%wh-H8c3j{{YvbiaD6k|Ji3GL)-uW literal 0 HcmV?d00001 diff --git a/mms-lib/test/retrieve/data/Success/parts/140100041.jpg b/mms-lib/test/retrieve/data/Success/parts/140100041.jpg new file mode 100644 index 0000000000000000000000000000000000000000..da06184d601b565f0ace18f1acd6500f874b3482 GIT binary patch literal 38063 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