diff --git a/mms-lib/src/mms_task_http.c b/mms-lib/src/mms_task_http.c index b3e4597..64c0fad 100644 --- a/mms-lib/src/mms_task_http.c +++ b/mms-lib/src/mms_task_http.c @@ -20,6 +20,8 @@ #include +#include + #ifndef _WIN32 # include # include @@ -178,6 +180,46 @@ mms_http_create_session( SoupURI* proxy_uri = mms_http_uri_parse(conn->mmsproxy); if (proxy_uri) { GDEBUG("MMS proxy %s", conn->mmsproxy); + if (proxy_uri->host[0] == '0' || strstr(proxy_uri->host, ".0")) { + /* + * Some operators provide IP address of the MMS proxy + * prepending zeros to each number shorter then 3 digits, + * e.g. "192.168.094.023" instead of "192.168.94.23". + * That may look nicer but it's actually wrong because + * the numbers starting with zeros are interpreted as + * octal numbers. In the example above 023 actually means + * 16 and 094 is not a valid number at all. + * + * In addition to publishing these broken settings on their + * web sites, some of the operators send them over the air, + * in which case we can't even blame the user for entering + * an invalid IP address. We better be prepared to deal with + * those. + * + * Since nobody in the world seems to be actually using the + * octal notation to write an IP address, let's remove the + * leading zeros if we find them in the host part of the MMS + * proxy URL. + */ + char* host; + char** parts = g_strsplit(proxy_uri->host, ".", -1); + guint count = g_strv_length(parts); + if (count == 4) { + char** ptr = parts; + while (*ptr) { + char* part = *ptr; + while (part[0] == '0' && isdigit(part[1])) { + memmove(part, part+1, strlen(part)); + } + *ptr++ = part; + } + host = g_strjoinv(".", parts); + GDEBUG("MMS proxy host %s => %s", proxy_uri->host, host); + soup_uri_set_host(proxy_uri, host); + g_free(host); + } + g_strfreev(parts); + } g_object_set(session, SOUP_SESSION_PROXY_URI, proxy_uri, NULL); soup_uri_free(proxy_uri); } @@ -266,7 +308,9 @@ mms_task_http_receive_progress( MMSTaskHttpPriv* priv = http->priv; MMSHttpTransfer* tx = priv->tx; if (tx) { - GASSERT(tx->bytes_received <= tx->bytes_to_receive); + /* Some operators don't provide Content-Length */ + GASSERT(!tx->bytes_to_receive || + tx->bytes_received <= tx->bytes_to_receive); mms_transfer_list_transfer_receive_progress(http->transfers, http->task.id, priv->transfer_type, tx->bytes_received, tx->bytes_to_receive); diff --git a/mms-lib/test/common/test_connection.c b/mms-lib/test/common/test_connection.c index fa683ab..8481a34 100644 --- a/mms-lib/test/common/test_connection.c +++ b/mms-lib/test/common/test_connection.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2016 Jolla Ltd. + * Copyright (C) 2013-2017 Jolla Ltd. * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify @@ -74,8 +74,8 @@ mms_connection_test_set_state( MMSConnection* mms_connection_test_new( const char* imsi, - unsigned short port, - gboolean proxy) + const char* proxy, + unsigned short port) { MMSConnectionTest* test = g_object_new(MMS_TYPE_CONNECTION_TEST, NULL); MMSConnection* conn = &test->connection; @@ -84,7 +84,7 @@ mms_connection_test_new( conn->netif = test->netif = g_strdup("lo"); if (proxy) { test->mmsc = g_strdup("http://mmsc"); - test->mmsproxy = g_strdup_printf("127.0.0.1:%hu", port); + test->mmsproxy = g_strdup_printf("%s:%hu", proxy, port); } else { test->mmsc = g_strdup_printf("http://127.0.0.1:%hu", port); } diff --git a/mms-lib/test/common/test_connection.h b/mms-lib/test/common/test_connection.h index c34e40d..1abfaef 100644 --- a/mms-lib/test/common/test_connection.h +++ b/mms-lib/test/common/test_connection.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2017 Jolla Ltd. + * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -9,7 +10,6 @@ * 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 @@ -20,8 +20,8 @@ MMSConnection* mms_connection_test_new( const char* imsi, - unsigned short port, - gboolean proxy); + const char* proxy, + unsigned short port); #endif /* TEST_CONNECTION_H */ diff --git a/mms-lib/test/common/test_connman.c b/mms-lib/test/common/test_connman.c index c42e42d..ce0d635 100644 --- a/mms-lib/test/common/test_connman.c +++ b/mms-lib/test/common/test_connman.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2016 Jolla Ltd. + * Copyright (C) 2013-2017 Jolla Ltd. * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify @@ -25,7 +25,7 @@ typedef struct mms_connman_test { MMSConnMan cm; MMSConnection* conn; unsigned short port; - gboolean proxy; + char* proxy; char* default_imsi; gboolean offline; mms_connman_test_connect_fn connect_fn; @@ -58,15 +58,24 @@ mms_connman_test_make_busy( g_idle_add(mms_connman_test_busy_cb, test); } +void +mms_connman_test_set_proxy( + MMSConnMan* cm, + const char* proxy, + unsigned short port) +{ + MMSConnManTest* test = MMS_CONNMAN_TEST(cm); + test->proxy = g_strdup(proxy); + test->port = port; +} + void mms_connman_test_set_port( MMSConnMan* cm, unsigned short port, gboolean proxy) { - MMSConnManTest* test = MMS_CONNMAN_TEST(cm); - test->port = port; - test->proxy = proxy; + return mms_connman_test_set_proxy(cm, proxy ? "127.0.0.1" : NULL, port); } void @@ -133,7 +142,7 @@ mms_connman_test_open_connection( return NULL; } else { mms_connman_test_make_busy(test); - test->conn = mms_connection_test_new(imsi, test->port, test->proxy); + test->conn = mms_connection_test_new(imsi, test->proxy, test->port); if (test->connect_fn) test->connect_fn(test->connect_param); return mms_connection_ref(test->conn); } @@ -153,7 +162,9 @@ void mms_connman_test_finalize( GObject* object) { - g_free(MMS_CONNMAN_TEST(object)->default_imsi); + MMSConnManTest* test = MMS_CONNMAN_TEST(object); + g_free(test->proxy); + g_free(test->default_imsi); G_OBJECT_CLASS(mms_connman_test_parent_class)->finalize(object); } diff --git a/mms-lib/test/common/test_connman.h b/mms-lib/test/common/test_connman.h index b8e062f..89b5218 100644 --- a/mms-lib/test/common/test_connman.h +++ b/mms-lib/test/common/test_connman.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2013-2014 Jolla Ltd. + * Copyright (C) 2013-2017 Jolla Ltd. + * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -9,7 +10,6 @@ * 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 @@ -25,6 +25,12 @@ void MMSConnMan* mms_connman_test_new(void); +void +mms_connman_test_set_proxy( + MMSConnMan* cm, + const char* proxy, + unsigned short port); + void mms_connman_test_set_port( MMSConnMan* cm, diff --git a/mms-lib/test/coverage/run b/mms-lib/test/coverage/run index 2923dc7..8402220 100755 --- a/mms-lib/test/coverage/run +++ b/mms-lib/test/coverage/run @@ -33,9 +33,13 @@ for t in $TESTS ; do popd done +# LCOV 1.10 has branch coverage disabled per default +LCOV_OPT="--rc lcov_branch_coverage=1" +GENHTML_OPT="--branch-coverage" + 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 +lcov $LCOV_OPT -c -d "$BASE_DIR/build/$FLAVOR" -b "$BASE_DIR" -o "$FULL_COV" || exit 1 +lcov $LCOV_OPT -e "$FULL_COV" "$BASE_DIR/src/*" -o "$MMSLIB_COV" || exit 1 +genhtml $GENHTML_OPT -t mms-engine "$MMSLIB_COV" --output-directory "$COV_DIR/results" || exit 1 diff --git a/mms-lib/test/test_retrieve/test_retrieve.c b/mms-lib/test/test_retrieve/test_retrieve.c index 45b25d8..2b7ee57 100644 --- a/mms-lib/test/test_retrieve/test_retrieve.c +++ b/mms-lib/test/test_retrieve/test_retrieve.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2016 Jolla Ltd. + * Copyright (C) 2013-2017 Jolla Ltd. * Contact: Slava Monich * * This program is free software; you can redistribute it and/or modify @@ -35,7 +35,8 @@ #define MMS_MESSAGE_TYPE_NONE (0) -#define DATA_DIR "data/" +#define DATA_DIR "data/" +#define LOCALHOST "127.0.0.1" #define TEST_TIMEOUT (10) /* seconds */ @@ -57,6 +58,7 @@ typedef struct test_desc { enum mms_message_type reply_msg; const TestPartDesc* parts; unsigned int nparts; + const char* proxy; int flags; #define TEST_PUSH_HANDLING_FAILURE_OK (0x01) @@ -130,6 +132,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DECODING, MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, TEST_PARTS(retrieve_success1_parts), + "0127.000.000.001", 0 },{ "Success2", /* Generated by Nokia C6 (Symbian "Belle") */ @@ -142,6 +145,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DECODING, MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, TEST_PARTS(retrieve_success2_parts), + "127.0.0.001", 0 },{ "Success3", /* Generated by Nokia N9 */ @@ -154,6 +158,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DECODING, MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, TEST_PARTS(retrieve_success3_parts), + LOCALHOST, 0 },{ "QuotedPrintable", /* quoted-printable transfer encoding for text */ @@ -166,6 +171,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DECODING, MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, TEST_PARTS(retrieve_transfer_encoding_parts), + LOCALHOST, 0 },{ "Base64", /* Base64 transfer encoding for text */ @@ -178,6 +184,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DECODING, MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, TEST_PARTS(retrieve_transfer_encoding_parts), + LOCALHOST, 0 },{ "InvalidSubject", @@ -190,6 +197,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DECODING, MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, TEST_PARTS(retrieve_invalid_subject), + LOCALHOST, 0 },{ "DeferSuccess", @@ -202,6 +210,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DECODING, MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, TEST_PARTS(retrieve_success1_parts), + LOCALHOST, TEST_DEFER_RECEIVE },{ "CancelReceive", @@ -214,6 +223,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DECODING, MMS_MESSAGE_TYPE_ACKNOWLEDGE_IND, TEST_PARTS(retrieve_success1_parts), + LOCALHOST, TEST_DEFER_RECEIVE | TEST_CANCEL_RECEIVED },{ "Expired1", @@ -226,6 +236,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DOWNLOAD_ERROR, MMS_MESSAGE_TYPE_NONE, TEST_PARTS_NONE, + LOCALHOST, 0 },{ "Expired2", @@ -238,6 +249,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_INVALID, MMS_MESSAGE_TYPE_NOTIFYRESP_IND, TEST_PARTS_NONE, + LOCALHOST, TEST_REJECT_RECEIVE },{ "SoonExpired", @@ -250,6 +262,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DOWNLOAD_ERROR, MMS_MESSAGE_TYPE_NONE, TEST_PARTS_NONE, + LOCALHOST, 0 },{ "Offline", @@ -262,6 +275,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DOWNLOAD_ERROR, MMS_MESSAGE_TYPE_NONE, TEST_PARTS_NONE, + LOCALHOST, TEST_OFFLINE },{ "Timeout", @@ -274,6 +288,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DOWNLOAD_ERROR, MMS_MESSAGE_TYPE_NONE, TEST_PARTS_NONE, + LOCALHOST, TEST_CONNECTION_FAILURE },{ "NotAllowed", @@ -286,6 +301,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DOWNLOAD_ERROR, MMS_MESSAGE_TYPE_NONE, TEST_PARTS_NONE, + LOCALHOST, 0 },{ "NotFound", @@ -298,6 +314,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DOWNLOAD_ERROR, MMS_MESSAGE_TYPE_NONE, TEST_PARTS_NONE, + LOCALHOST, 0 },{ "MessageNotFound", @@ -310,6 +327,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DOWNLOAD_ERROR, MMS_MESSAGE_TYPE_NONE, TEST_PARTS_NONE, + LOCALHOST, 0 },{ "GarbageRetrieve", @@ -322,6 +340,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_DECODING_ERROR, MMS_MESSAGE_TYPE_NOTIFYRESP_IND, TEST_PARTS_NONE, + LOCALHOST, 0 },{ "GarbagePush", @@ -334,6 +353,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_INVALID, MMS_MESSAGE_TYPE_NONE, TEST_PARTS_NONE, + LOCALHOST, TEST_PUSH_HANDLING_FAILURE_OK },{ "UnsupportedPush", @@ -346,6 +366,7 @@ static const TestDesc retrieve_tests[] = { MMS_RECEIVE_STATE_INVALID, MMS_MESSAGE_TYPE_NONE, TEST_PARTS_NONE, + LOCALHOST, TEST_PUSH_HANDLING_FAILURE_OK } }; @@ -624,8 +645,8 @@ test_init( if (!(desc->flags & TEST_CONNECTION_FAILURE)) { 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), TRUE); + mms_connman_test_set_proxy(test->cm, desc->proxy, + test_http_get_port(test->http)); } if (desc->flags & TEST_OFFLINE) { mms_connman_test_set_offline(test->cm, TRUE);