diff --git a/CHANGELOG.md b/CHANGELOG.md index 10a646a..c11282f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - on connect retry, requery jwt only if it failed before - put two timestamps in connection health file; start conn and current - change health file update interval to 240sec +- sendMessage to check cloud status == ONLINE before sending ## [1.0.2] - 2019-02-08 - Refactored connection.c and updated corresponding unit tests diff --git a/src/connection.c b/src/connection.c index b8a4d65..07ae9f0 100644 --- a/src/connection.c +++ b/src/connection.c @@ -815,8 +815,8 @@ void close_and_unref_connection(noPollConn *conn) reason_len = (int) strlen (reason); status = CloseNormalClosure; } - nopoll_conn_close_ext(conn, status, reason, reason_len); get_parodus_cfg()->cloud_status = CLOUD_STATUS_OFFLINE; + nopoll_conn_close_ext(conn, status, reason, reason_len); ParodusInfo("cloud_status set as %s after connection close\n", get_parodus_cfg()->cloud_status); } } diff --git a/src/nopoll_helpers.c b/src/nopoll_helpers.c index df32465..70ebc0f 100644 --- a/src/nopoll_helpers.c +++ b/src/nopoll_helpers.c @@ -26,6 +26,7 @@ #include "nopoll_helpers.h" #include "nopoll_handlers.h" #include "time.h" +#include "config.h" /*----------------------------------------------------------------------------*/ /* Macros */ @@ -49,59 +50,33 @@ void setMessageHandlers() nopoll_conn_set_on_close(get_global_conn(), (noPollOnCloseHandler)listenerOnCloseMessage, NULL); } +static int cloud_status_is_online (void) +{ + const char *status = get_parodus_cfg()->cloud_status; + if (NULL == status) + return false; + return (strcmp (status, CLOUD_STATUS_ONLINE) == 0); +} + /** To send upstream msgs to server ***/ void sendMessage(noPollConn *conn, void *msg, size_t len) { int bytesWritten = 0; - static int connErr=0; - long timeDiff = 0; + + if (!cloud_status_is_online ()) { + ParodusError("Failed to send msg upstream as connection is not OK\n"); + OnboardLog("Failed to send msg upstream as connection is not OK\n"); + return; + } ParodusInfo("sendMessage length %zu\n", len); - if(nopoll_conn_is_ok(conn) && nopoll_conn_is_ready(conn)) + bytesWritten = sendResponse(conn, msg, len); + ParodusPrint("Number of bytes written: %d\n", bytesWritten); + if (bytesWritten != (int) len) { - //bytesWritten = nopoll_conn_send_binary(conn, msg, len); - bytesWritten = sendResponse(conn, msg, len); - ParodusPrint("Number of bytes written: %d\n", bytesWritten); - if (bytesWritten != (int) len) - { - ParodusError("Failed to send bytes %zu, bytes written were=%d (errno=%d, %s)..\n", len, bytesWritten, errno, strerror(errno)); - } - connErr = 0; - } - else - { - ParodusError("Failed to send msg upstream as connection is not OK\n"); - OnboardLog("Failed to send msg upstream as connection is not OK\n"); - - if(get_interface_down_event()) - { - ParodusError("Unable to connect to server since interface is down\n"); - } - else - { - if (connErr == 0) - { - getCurrentTime(connStuck_startPtr); - ParodusInfo("Conn got stuck, initialized the first timer\n"); - connErr = 1; - } - else - { - getCurrentTime(connStuck_endPtr); - timeDiff = timeValDiff(connStuck_startPtr, connStuck_endPtr); - ParodusPrint("checking timeout difference:%ld\n", timeDiff); - - if( timeDiff >= (10*60*1000)) - { - ParodusError("conn got stuck for over 10 minutes; crashing service.\n"); - OnboardLog("conn got stuck for over 10 minutes; crashing service.\n"); - kill(getpid(),SIGTERM); - } - - } - } + ParodusError("Failed to send bytes %zu, bytes written were=%d (errno=%d, %s)..\n", len, bytesWritten, errno, strerror(errno)); } } diff --git a/tests/mock_event_handler.c b/tests/mock_event_handler.c new file mode 100644 index 0000000..8a65d35 --- /dev/null +++ b/tests/mock_event_handler.c @@ -0,0 +1,104 @@ +/* + * If not stated otherwise in this file or this component's Licenses.txt file the + * following copyright and licenses apply: + * + * Copyright 2016 RDK Management + * Copyright [2014] [Cisco Systems, Inc.] + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/* This is a test version of event_handler.c that can be used + * to simulate interface down, interface up event + * You overwrite event_handler.c in the src diectory with this + * version. It will generate interface down / interface up events + * at random intervals between 60 secs and 124 secs + */ + +#include "parodus_log.h" +#include "event_handler.h" +#include "connection.h" +#include "config.h" +#include "heartBeat.h" +#include +#include +#include +#include +#include "time.h" +#include "close_retry.h" + +extern bool g_shutdown; + +static pthread_t sysevent_tid; + +static void start_interface_down (void) +{ + set_interface_down_event(); + ParodusInfo("Interface_down_event is set\n"); + pause_heartBeatTimer(); +} + +static void end_interface_down (void) +{ + reset_interface_down_event(); + ParodusInfo("Interface_down_event is reset\n"); + resume_heartBeatTimer(); + set_close_retry(); +} + +// waits from 60 to 124 secs +int wait_random (const char *msg) +{ + #define HALF_SEC 500000l + long delay = (random() >> 5) + 60000000l; + long secs, usecs; + struct timeval timeout; + + secs = delay / 1000000; + usecs = delay % 1000000; + ParodusInfo ("Waiting %ld secs %ld usecs for %s\n", secs, usecs, msg); + + while (!g_shutdown) { + timeout.tv_sec = 0; + if (delay <= HALF_SEC) { + timeout.tv_usec = delay; + select (0, NULL, NULL, NULL, &timeout); + return 0; + } + timeout.tv_usec = HALF_SEC; + delay -= HALF_SEC; + select (0, NULL, NULL, NULL, &timeout); + } + return -1; +} + + +static void *parodus_sysevent_handler (void *data) +{ + while (!g_shutdown) { + if (wait_random ("interface down") != 0) + break; + start_interface_down (); + wait_random ("interface up"); + end_interface_down (); + } + ParodusInfo ("Exiting event handler\n"); + return data; +} + +void EventHandler() +{ + ParodusInfo ("RAND_MAX is %ld (0x%lx)\n", RAND_MAX, RAND_MAX); + srandom (getpid()); + + pthread_create(&sysevent_tid, NULL, parodus_sysevent_handler, NULL); +} diff --git a/tests/test_conn_interface.c b/tests/test_conn_interface.c index e149798..d553e70 100644 --- a/tests/test_conn_interface.c +++ b/tests/test_conn_interface.c @@ -120,6 +120,10 @@ bool get_interface_down_event (void) return false; } +void set_interface_down_event (void) +{ +} + int wait_while_interface_down (void) { return 0; diff --git a/tests/test_nopoll_helpers.c b/tests/test_nopoll_helpers.c index 663972d..bebb956 100644 --- a/tests/test_nopoll_helpers.c +++ b/tests/test_nopoll_helpers.c @@ -23,6 +23,7 @@ #include "../src/parodus_log.h" #include "../src/nopoll_helpers.h" +#include "../src/config.h" /*----------------------------------------------------------------------------*/ /* Macros */ @@ -32,7 +33,9 @@ /*----------------------------------------------------------------------------*/ /* File Scoped Variables */ /*----------------------------------------------------------------------------*/ - static noPollConn *conn; + static noPollConn *conn = NULL; + static ParodusCfg cfg; + /*----------------------------------------------------------------------------*/ /* Mocks */ /*----------------------------------------------------------------------------*/ @@ -54,6 +57,12 @@ nopoll_bool nopoll_conn_is_ready( noPollConn *conn ) return (nopoll_bool)mock(); } +ParodusCfg *get_parodus_cfg(void) +{ + function_called(); + return &cfg; +} + int __nopoll_conn_send_common (noPollConn * conn, const char * content, long length, nopoll_bool has_fin, long sleep_in_header, noPollOpCode frame_type) { UNUSED(has_fin); UNUSED(sleep_in_header); UNUSED(frame_type); UNUSED(content); @@ -212,13 +221,8 @@ void test_sendMessage() { int len = strlen("Hello Parodus!"); - expect_value(nopoll_conn_is_ok, (intptr_t)conn, (intptr_t)conn); - will_return(nopoll_conn_is_ok, nopoll_true); - expect_function_call(nopoll_conn_is_ok); - - expect_value(nopoll_conn_is_ready, (intptr_t)conn, (intptr_t)conn); - will_return(nopoll_conn_is_ready, nopoll_true); - expect_function_call(nopoll_conn_is_ready); + cfg.cloud_status = CLOUD_STATUS_ONLINE; + expect_function_calls (get_parodus_cfg, 1); expect_value(__nopoll_conn_send_common, (intptr_t)conn, (intptr_t)conn); expect_value(__nopoll_conn_send_common, length, len); @@ -228,81 +232,23 @@ void test_sendMessage() sendMessage(conn, "Hello Parodus!", len); } -void connStuck_sendMessage() +void test_sendMessageOffline() { - int len = strlen("Hello Parodus!"); - - /* Initialize the timer when connection gets stuck */ - expect_value(nopoll_conn_is_ok, (intptr_t)conn, (intptr_t)NULL); - will_return(nopoll_conn_is_ok, nopoll_false); - expect_function_call(nopoll_conn_is_ok); - - expect_function_call(getCurrentTime); - sendMessage(NULL, "Hello Parodus!", len); - - /* When connection recovers within 10 mins, it should be able to re-connect */ - expect_value(nopoll_conn_is_ok, (intptr_t)conn, (intptr_t)NULL); - will_return(nopoll_conn_is_ok, nopoll_false); - expect_function_call(nopoll_conn_is_ok); - - expect_function_call(getCurrentTime); - - will_return(timeValDiff, 5*60*1000); - expect_function_call(timeValDiff); - - expect_value(nopoll_conn_is_ok, (intptr_t)conn, (intptr_t)conn); - will_return(nopoll_conn_is_ok, nopoll_true); - expect_function_call(nopoll_conn_is_ok); - - expect_value(nopoll_conn_is_ready, (intptr_t)conn, (intptr_t)conn); - will_return(nopoll_conn_is_ready, nopoll_true); - expect_function_call(nopoll_conn_is_ready); - - expect_value(__nopoll_conn_send_common, (intptr_t)conn, (intptr_t)conn); - expect_value(__nopoll_conn_send_common, length, len); - will_return(__nopoll_conn_send_common, len); - expect_function_calls(__nopoll_conn_send_common, 1); - + int len = strlen("Hello Parodus!"); + + cfg.cloud_status = CLOUD_STATUS_OFFLINE; + expect_function_calls (get_parodus_cfg, 1); sendMessage(conn, "Hello Parodus!", len); - - /* When timer exceeds more than 10 mins kill the process */ - expect_value(nopoll_conn_is_ok, (intptr_t)conn, (intptr_t)NULL); - will_return(nopoll_conn_is_ok, nopoll_false); - expect_function_call(nopoll_conn_is_ok); - - sendMessage(NULL, "Hello Parodus!", len); - - expect_function_call(getCurrentTime); - - sendMessage(NULL, "Hello Parodus!", len); - - expect_value(nopoll_conn_is_ok, (intptr_t)conn, (intptr_t)NULL); - will_return(nopoll_conn_is_ok, nopoll_false); - expect_function_call(nopoll_conn_is_ok); - - expect_function_call(getCurrentTime); - - will_return(timeValDiff, 10*60*1000); - expect_function_call(timeValDiff); - - will_return(kill, 1); - expect_function_call(kill); - - sendMessage(NULL, "Hello Parodus!", len); + } void err_sendMessage() { int len = strlen("Hello Parodus!"); - expect_value(nopoll_conn_is_ok, (intptr_t)conn, (intptr_t)conn); - will_return(nopoll_conn_is_ok, nopoll_true); - expect_function_call(nopoll_conn_is_ok); - - expect_value(nopoll_conn_is_ready, (intptr_t)conn, (intptr_t)conn); - will_return(nopoll_conn_is_ready, nopoll_true); - expect_function_call(nopoll_conn_is_ready); - + cfg.cloud_status = CLOUD_STATUS_ONLINE; + expect_function_calls (get_parodus_cfg, 1); + expect_value(__nopoll_conn_send_common, (intptr_t)conn,(intptr_t) conn); expect_value(__nopoll_conn_send_common, length, len); will_return(__nopoll_conn_send_common, len-2); @@ -320,11 +266,13 @@ void err_sendMessageConnNull() { int len = strlen("Hello Parodus!"); - expect_value(nopoll_conn_is_ok, (intptr_t)conn, (intptr_t)NULL); - will_return(nopoll_conn_is_ok, nopoll_false); - expect_function_call(nopoll_conn_is_ok); + cfg.cloud_status = CLOUD_STATUS_ONLINE; + expect_function_calls (get_parodus_cfg, 1); - expect_function_call(getCurrentTime); + expect_value(__nopoll_conn_send_common, (intptr_t)conn, NULL); + expect_value(__nopoll_conn_send_common, length, len); + will_return(__nopoll_conn_send_common, len); + expect_function_calls(__nopoll_conn_send_common, 1); sendMessage(NULL, "Hello Parodus!", len); } @@ -349,7 +297,7 @@ int main(void) cmocka_unit_test(err_sendResponseFlushWrites), cmocka_unit_test(err_sendResponseConnNull), cmocka_unit_test(test_sendMessage), - cmocka_unit_test(connStuck_sendMessage), + cmocka_unit_test(test_sendMessageOffline), cmocka_unit_test(err_sendMessage), cmocka_unit_test(err_sendMessageConnNull), cmocka_unit_test(test_reportLog),