tizen 2.3 release tizen_2.3 submit/tizen_2.3/20150202.061854 tizen_2.3_release
authorjk7744.park <jk7744.park@samsung.com>
Sat, 31 Jan 2015 07:32:27 +0000 (16:32 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Sat, 31 Jan 2015 07:32:27 +0000 (16:32 +0900)
40 files changed:
CMakeLists.txt [new file with mode: 0644]
client/include/smartbonding-client.h [new file with mode: 0644]
client/src/smartbonding-client.c [new file with mode: 0644]
client/test/smartbonding-test.c [new file with mode: 0644]
include/multirat_SB_http.h [new file with mode: 0644]
include/multirat_block_manager.h [new file with mode: 0644]
include/multirat_conf.h [new file with mode: 0644]
include/multirat_connection.h [new file with mode: 0644]
include/multirat_data_buffer.h [new file with mode: 0644]
include/multirat_decode_http.h [new file with mode: 0644]
include/multirat_file_buffer.h [new file with mode: 0644]
include/multirat_file_manager.h [new file with mode: 0644]
include/multirat_file_stream.h [new file with mode: 0644]
include/multirat_file_thread.h [new file with mode: 0644]
include/multirat_libapi.h [new file with mode: 0644]
include/multirat_multisocket.h [new file with mode: 0644]
include/multirat_poll_thread.h [new file with mode: 0644]
include/multirat_process.h [new file with mode: 0644]
include/multirat_range_request_thread.h [new file with mode: 0644]
include/multirat_watch_dog_thread.h [new file with mode: 0644]
include/multirat_watchthread.h [new file with mode: 0644]
multirat.manifest [new file with mode: 0644]
multirat.pc.in [new file with mode: 0644]
packaging/multirat.spec [new file with mode: 0644]
src/multirat_block_manager.c [new file with mode: 0644]
src/multirat_conf.c [new file with mode: 0644]
src/multirat_connection.c [new file with mode: 0644]
src/multirat_data_buffer.c [new file with mode: 0644]
src/multirat_decode_http.c [new file with mode: 0644]
src/multirat_file_buffer.c [new file with mode: 0644]
src/multirat_file_manager.c [new file with mode: 0644]
src/multirat_file_stream.c [new file with mode: 0644]
src/multirat_file_thread.c [new file with mode: 0644]
src/multirat_libapi.c [new file with mode: 0644]
src/multirat_multisocket.c [new file with mode: 0644]
src/multirat_poll_thread.c [new file with mode: 0644]
src/multirat_process.c [new file with mode: 0644]
src/multirat_range_request_thread.c [new file with mode: 0644]
src/multirat_watch_dog_thread.c [new file with mode: 0644]
src/multirat_watchthread.c [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b7543fa
--- /dev/null
@@ -0,0 +1,114 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET(fw_name "multirat")
+
+PROJECT(${fw_name})
+
+SET(CMAKE_INSTALL_PREFIX /usr)
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(VERSION_MAJOR 0)
+SET(VERSION "${VERSION_MAJOR}.1.0")
+
+SET(INC_DIR include)
+SET(CLIENT_INC_DIR client/include)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include
+       ${CMAKE_SOURCE_DIR}/include
+       ${CMAKE_SOURCE_DIR}/client/include)
+
+#SET(requires "dlog capi-base-common download-provider-interface")
+#MESSAGE(STATUS "PACKAGES : ${requires}")
+#SET(pc_requires "capi-base-common capi-appfw-application")
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(subpkgs REQUIRED
+       dlog
+       glib-2.0
+       dbus-1
+       vconf
+       dbus-glib-1
+       libcares
+       capi-network-connection
+       capi-network-wifi
+)
+
+
+FOREACH(flag ${subpkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}  -Wall")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+
+IF("${ARCH}" STREQUAL "arm")
+    ADD_DEFINITIONS("-DTARGET")
+ENDIF("${ARCH}" STREQUAL "arm")
+
+ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
+ADD_DEFINITIONS("-DSLP_DEBUG")
+ADD_DEFINITIONS("-DSB_LOG_SUPPORT")
+#ADD_DEFINITIONS("-DSB_DETAIL_LOG_SUPPORT")
+ADD_DEFINITIONS("-DTIZEN_UX_SUPPORT")
+ADD_DEFINITIONS("-DTWO_CHUNK")
+
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=/usr/lib")
+
+SET(SOURCES 
+               client/src/smartbonding-client.c
+               src/multirat_block_manager.c
+               src/multirat_file_manager.c
+               src/multirat_data_buffer.c
+               src/multirat_file_buffer.c
+               src/multirat_multisocket.c
+               src/multirat_file_stream.c
+               src/multirat_range_request_thread.c
+               src/multirat_file_thread.c
+               src/multirat_connection.c
+               src/multirat_decode_http.c
+               src/multirat_process.c
+               src/multirat_watch_dog_thread.c
+               src/multirat_watchthread.c
+               src/multirat_poll_thread.c
+               src/multirat_libapi.c
+               src/multirat_conf.c)
+MESSAGE(STATUS "SOURCES : ${SOURCES}")
+ADD_LIBRARY(${fw_name} SHARED ${SOURCES})
+#ADD_LIBRARY(${fw_name} STATIC ${SOURCES})
+
+
+TARGET_LINK_LIBRARIES(${fw_name} ${subpkgs_LDFLAGS})
+SET_TARGET_PROPERTIES(${fw_name} PROPERTIES VERSION ${VERSION})
+SET_TARGET_PROPERTIES(${fw_name} PROPERTIES SOVERSION ${VERSION_MAJOR})
+
+INSTALL(TARGETS ${fw_name} DESTINATION lib)
+INSTALL(
+        DIRECTORY ${INC_DIR}/ DESTINATION include/multirat
+        FILES_MATCHING
+        PATTERN "${INC_DIR}/multirat_process.h"
+               PATTERN "${INC_DIR}/multirat_SB_http.h"
+        PATTERN "${INC_DIR}/multirat_conf.h"
+               PATTERN "${INC_DIR}/multirat_libapi.h"
+               )
+INSTALL(
+       DIRECTORY ${CLIENT_INC_DIR}/ DESTINATION include/multirat
+       FILES_MATCHING PATTERN "${CLIENT_INC_DIR}/smartbonding-client.h"
+       )
+
+SET(PC_NAME ${fw_name})
+SET(PC_REQUIRED ${pc_requires})
+SET(PC_LDFLAGS -l${fw_name})
+SET(PC_CFLAGS -I\${includedir}/system)
+
+CONFIGURE_FILE(
+    multirat.pc.in
+    ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc
+    @ONLY
+)
+#CONFIGURE_FILE(
+#      LICENSE.APLv2
+#    ${fw_name}
+#    @ONLY
+#)
+
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION lib/pkgconfig)
+#INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name} DESTINATION share/license)
+
diff --git a/client/include/smartbonding-client.h b/client/include/smartbonding-client.h
new file mode 100644 (file)
index 0000000..fdcf9ae
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Smart bonding service client
+ *
+ * Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __SMARTBONDING_CLIENT_H__
+#define __SMARTBONDING_CLIENT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define INET_ADDRSTRLENG 50
+
+typedef enum {
+       SMBD_ERR_NONE = 0x00,
+       SMBD_ERR_UNKNOWN = -999,
+       SMBD_ERR_POLICY_OFF,
+       SMBD_ERR_PERMISSION_DENIED,
+       SMBD_ERR_IN_PROGRESS,
+       SMBD_ERR_INVALID_PARAMETER,
+} smbd_err_t;
+
+typedef enum {
+       SMBD_EVENT_USER_OPTION_OK,
+       SMBD_EVENT_USER_OPTION_CANCEL,
+       SMBD_EVENT_CELLULAR_INFO,
+       SMBD_EVENT_WIFI_INFO,
+       SMBD_EVENT_SMARTBONDING_STATUS,
+       SMBD_EVENT_DATA,
+} smbd_event_t;
+
+typedef struct {
+       char *dev_name;
+       char *ip_addr;
+       char *proxy;
+       int sig_strength;
+       char *active;
+} smbd_cellular_info_t;
+
+typedef struct {
+       char proxy[INET_ADDRSTRLENG];
+       char dns_1[INET_ADDRSTRLENG];
+       char dns_2[INET_ADDRSTRLENG];
+} smbd_cellular_profile_info_t;
+
+typedef struct
+{
+       /** Event Status */
+       smbd_err_t Error;
+       /** Asynchronous event */
+       smbd_event_t Event;
+       /* Event data */
+       void *EventData;
+} smbd_event_info_t;
+
+/**
+ * @brief This callback will receive different types of event data.
+ * @param[out] event_info All information related to the event
+ *             SMBD_EVENT_USER_OPTION_OK - For popup OK button press
+ *             SMBD_EVENT_USER_OPTION_CANCEL - For popup CANCEL button press
+ *                     Second parameter 'user_data' will have the data sent
+ *                     during the smart_bonding_start() API
+ *             SMBD_EVENT_CELLULAR_INFO - Cellular event with all data
+ *                     smbd_cellular_info_t in event's EventData
+ *             SMBD_EVENT_WIFI_INFO - Wi-Fi event with its signal strength
+ *                     in event's EventData
+ *             SMBD_EVENT_SMARTBONDING_STATUS - Smartbonding status event
+ *                     with its current status in event's EventData
+ * @param[out] user_data The data sent by the caller during smart_bonding_start() API
+ *             in case of SMBD_EVENT_USER_OPTION_OK/SMBD_EVENT_USER_OPTION_CANCEL
+ * See also smart_bonding_start()
+ */
+typedef void(*smartbonding_cb)(smbd_event_info_t event_info, void *user_data);
+
+/**
+ * @brief API to initialize smart bonding library.
+ * This init call is mandatory before using any other smart bonding APIs.
+ * @return 0 if initialization successful, otherwise negative error value.
+ * @retval #SMBD_ERR_NONE  Successful
+ */
+int smart_bonding_init(void);
+
+/**
+ * @brief API to de-initialize smart bonding library.
+ * This de-init call is mandatory after the usage of smart bonding module.
+ * @return 0 if de-initialization successful, otherwise negative error value.
+ * @retval #SMBD_ERR_NONE  Successful
+ */
+int smart_bonding_deinit(void);
+
+/**
+ * @brief API to start smart bonding.
+ * @param[in] file_name The name of the file being downloaded
+ * @param[in] file_size The size of the file being downloaded
+ * @param[in] callback The callback which will receive user's choice of selection
+ * @param[in] user_data The user data sent by the caller
+ * @return 0 on success, otherwise negative error value.
+ * @retval #SMBD_ERR_NONE  Successful
+ */
+int smart_bonding_start(char *file_name, int file_size,
+               smartbonding_cb callback, void *user_data);
+
+/**
+ * @brief API to stop smart bonding.
+ * @param[in] user_data The user data sent by the caller, same as the one
+ *                     sent to the smart_bonding_start() API
+ * @return 0 on success, otherwise negative error value.
+ * @retval #SMBD_ERR_NONE  Successful
+ */
+int smart_bonding_stop(void *user_data);
+
+void smart_bonding_notify_interface_usage(const char *message);
+
+void get_proxy_ip_port(char *proxy_ip, int *proxy_port);
+
+void get_dns_ip(char *dns_1, char *dns_2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SMARTBONDING_CLIENT_H__ */
diff --git a/client/src/smartbonding-client.c b/client/src/smartbonding-client.c
new file mode 100644 (file)
index 0000000..b2bc303
--- /dev/null
@@ -0,0 +1,710 @@
+/*
+ * Smart bonding service client
+ *
+ * Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#include <glib.h>
+#include <errno.h>
+#include <gio/gio.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#include "multirat_SB_http.h"
+#include "smartbonding-client.h"
+
+#define DBUS_REPLY_TIMEOUT (120 * 1000)
+#define SMBD_SERVICE_DBUS              "net.smartbonding"
+#define SMBD_PATH_DBUS                 "/org/tizen/smartbonding"
+#define SMBD_SERVICE_INTERFACE         "org.tizen.smartbonding"
+#define SMBD_SIGNAL_PROPERTYCHANGED    "PropertyChanged"
+#define SMBD_SIGNAL_USERRESPONSE       "UserResponse"
+#define SMBD_SIGNAL_VALUE_CELLULAR     "cellular_device_info"
+#define SMBD_SIGNAL_VALUE_WIFI         "wifi_device_info"
+#define SMBD_SIGNAL_VALUE_SMARTBONDING "smartbonding"
+#define SMBD_SIGNAL_VALUE_DATA         "data"
+#define SMBD_SIGNAL_VALUE_USERRESPONSE "user_response"
+#define VCONF_SMART_BONDING_POLICY "file/private/wifi/network_bonding"
+
+typedef enum {
+       SMART_BONDING_WIFI_ONLY = 0x00,
+       SMART_BONDING_SPEED_PRIORITIZED = 0x01,
+} SMART_BONDING_TYPES;
+
+struct gdbus_connection_data {
+       GDBusConnection *connection;
+       int conn_ref_count;
+       GCancellable *cancellable;
+};
+
+struct _smartbonding_cb_s {
+       smartbonding_cb cb;
+       void *action_user_data;
+};
+
+typedef struct {
+       smartbonding_cb cb;
+       void *user_data;
+       guint32 handle;
+} event_info_t;
+
+static GSList *handle_list = NULL;
+static struct _smartbonding_cb_s smartbonding_callbacks = { 0, };
+static struct gdbus_connection_data gdbus_conn = { NULL, 0, NULL };
+static guint gdbus_conn_sub_id_smbd_cellular = 0;
+//static guint gdbus_conn_sub_id_smbd_wifi = 0;
+static guint gdbus_conn_sub_id_smbd_smartbonding = 0;
+static guint gdbus_conn_sub_id_smbd_user = 0;
+static smbd_cellular_profile_info_t smbd_cellular_profile_info;
+
+static GDBusConnection *_dbus_get_gdbus_conn(void)
+{
+       return gdbus_conn.connection;
+}
+
+void get_proxy_ip_port(char *proxy_ip, int *proxy_port)
+{
+       if(strcmp(smbd_cellular_profile_info.proxy,"") == 0)
+               return;
+       else
+       {
+               int len = 0;
+               char *temp = NULL;
+               temp = strchr(smbd_cellular_profile_info.proxy,':');
+               if(temp != NULL)
+               {
+                       len = (int)(temp - smbd_cellular_profile_info.proxy);
+                       memcpy(proxy_ip, smbd_cellular_profile_info.proxy, len);
+                       *proxy_port = atoi(smbd_cellular_profile_info.proxy + len + 1);
+
+                       SECURE_DB_INFO("Proxy IP %s", proxy_ip);
+                       SECURE_DB_INFO("Proxy PORT %d", *proxy_port);
+               }
+       }
+       return;
+}
+
+void get_dns_ip(char *dns_1, char *dns_2)
+{
+       if((strcmp(smbd_cellular_profile_info.dns_1,"")))
+       {
+               memcpy(dns_1,smbd_cellular_profile_info.dns_1, strlen(smbd_cellular_profile_info.dns_1));
+               SECURE_DB_INFO("DNS %s", smbd_cellular_profile_info.dns_1);
+       }
+       if((strcmp(smbd_cellular_profile_info.dns_2,"")))
+       {
+               memcpy(dns_2,smbd_cellular_profile_info.dns_2, strlen(smbd_cellular_profile_info.dns_2));
+               SECURE_DB_INFO("DNS %s", smbd_cellular_profile_info.dns_2);
+       }
+       return;
+}
+
+static GCancellable *_dbus_get_gdbus_cancellable(void)
+{
+       return gdbus_conn.cancellable;
+}
+
+static guint32 _handle_remove_with_user_data(void *data)
+{
+       GSList *list = handle_list;
+       guint32 handle_id = 0;
+
+       while (list) {
+               event_info_t *temp = (event_info_t *)list->data;
+               if (temp->user_data == data) {
+                       TIZEN_LOGD("Removed the handle - [%d] from the list", temp->handle);
+
+                       /* Get the handle id to pass the same to daemon for cleanup */
+                       handle_id = temp->handle;
+                       handle_list = g_slist_remove(handle_list, temp);
+                       g_free(temp);
+                       break;
+               }
+
+               list = g_slist_next(list);
+       }
+
+       return handle_id;
+}
+
+static void _handle_remove_post_event_send(guint handle, gboolean user_option)
+{
+       GSList *list = handle_list;
+       smbd_event_info_t event_info = { 0, };
+
+       while (list) {
+               event_info_t *temp = (event_info_t *)list->data;
+               if (temp->handle != handle) {
+                       list = g_slist_next(list);
+                       continue;
+               }
+
+               if (temp->cb != NULL) {
+                       if (user_option) {
+                               TIZEN_LOGD("Sending SMBD_EVENT_USER_OPTION_OK");
+
+                               event_info.Event = SMBD_EVENT_USER_OPTION_OK;
+                               event_info.Error = SMBD_ERR_NONE;
+
+                               temp->cb(event_info, temp->user_data);
+                       } else {
+                               TIZEN_LOGD("Sending SMBD_EVENT_USER_OPTION_CANCEL");
+
+                               event_info.Event = SMBD_EVENT_USER_OPTION_CANCEL;
+                               event_info.Error = SMBD_ERR_NONE;
+
+                               temp->cb(event_info, temp->user_data);
+                       }
+               }
+
+               break;
+       }
+}
+
+static int __error_string_to_enum(const char *error)
+{
+       TIZEN_LOGD("Passed error value [%s]\n", error);
+
+       if (error == NULL)
+               return SMBD_ERR_UNKNOWN;
+
+       else if (NULL != strstr(error, ".PermissionDenied"))
+               return SMBD_ERR_PERMISSION_DENIED;
+       else if (NULL != strstr(error, ".InProgress"))
+               return SMBD_ERR_IN_PROGRESS;
+       return SMBD_ERR_UNKNOWN;
+}
+
+static void __dbus_reply(GObject *source_object, GAsyncResult *res,
+               gpointer user_data)
+{
+       GDBusConnection *conn = NULL;
+       GError *error = NULL;
+       smbd_err_t Error = SMBD_ERR_NONE;
+       //GVariant *dbus_result;
+
+       TIZEN_LOGD("DBus reply callback\n");
+
+       conn = G_DBUS_CONNECTION (source_object);
+       //dbus_result = g_dbus_connection_call_finish(conn, res, &error);
+       g_dbus_connection_call_finish(conn, res, &error);
+       if (error != NULL) {
+               TIZEN_LOGD("Smartbonding action failed. Error Msg [%s]\n", error->message);
+               Error = __error_string_to_enum(error->message);
+               g_error_free(error);
+       }
+
+       if (Error != SMBD_ERR_NONE) {
+               TIZEN_LOGD("Smartbonding action failed. Error [%d]\n", Error);
+       } else {
+               TIZEN_LOGD("Smartbonding action success.");
+       }
+}
+
+static int __invoke_dbus_method_nonblock(const char *dest, const char *path,
+               char *interface_name, char *method, GVariant *params,
+               GAsyncReadyCallback notify_func)
+{
+       GDBusConnection *connection;
+
+       TIZEN_LOGD("Sending dbus request");
+       connection = _dbus_get_gdbus_conn();
+       if (connection == NULL) {
+               TIZEN_LOGD("GDBusconnection is NULL!!\n");
+               return SMBD_ERR_UNKNOWN;
+       }
+
+       g_dbus_connection_call(connection,
+                               dest,
+                               path,
+                               interface_name,
+                               method,
+                               params,
+                               NULL,
+                               G_DBUS_CALL_FLAGS_NONE,
+                               DBUS_REPLY_TIMEOUT,
+                               _dbus_get_gdbus_cancellable(),
+                               (GAsyncReadyCallback) notify_func,
+                               NULL);
+
+       return SMBD_ERR_NONE;
+}
+
+static GVariant *__invoke_dbus_method(const char *dest, const char *path,
+               char *interface_name, char *method, GVariant *params,
+               int *dbus_error)
+{
+       GError *error = NULL;
+       GVariant *reply = NULL;
+       *dbus_error = SMBD_ERR_NONE;
+       GDBusConnection *connection;
+
+       connection = _dbus_get_gdbus_conn();
+       if (connection == NULL) {
+               TIZEN_LOGD("GDBusconnection is NULL\n");
+
+               *dbus_error = SMBD_ERR_UNKNOWN;
+               return reply;
+       }
+
+       reply = g_dbus_connection_call_sync(connection,
+                       dest,
+                       path,
+                       interface_name,
+                       method,
+                       params,
+                       NULL,
+                       G_DBUS_CALL_FLAGS_NONE,
+                       DBUS_REPLY_TIMEOUT,
+                       _dbus_get_gdbus_cancellable(),
+                       &error);
+       if (reply == NULL) {
+               if (error != NULL) {
+                       TIZEN_LOGD("g_dbus_connection_call_sync() failed."
+                                       "error [%d: %s]\n",
+                                       error->code, error->message);
+                       g_error_free(error);
+               } else {
+                       TIZEN_LOGD("g_dbus_connection_call_sync() failed.\n");
+               }
+
+               *dbus_error = SMBD_ERR_UNKNOWN;
+
+               return NULL;
+       }
+
+       return reply;
+}
+
+static int __dbus_create_gdbus_call(void)
+{
+       GError *error = NULL;
+
+       if (gdbus_conn.connection != NULL) {
+               TIZEN_LOGD("Already connection exists");
+               return SMBD_ERR_UNKNOWN;
+       }
+
+       g_type_init();
+
+       gdbus_conn.connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+       if (gdbus_conn.connection == NULL) {
+               TIZEN_LOGD("Failed to connect to the D-BUS daemon: [%s]\n", error->message);
+               g_error_free(error);
+               return SMBD_ERR_UNKNOWN;
+       }
+
+       gdbus_conn.cancellable = g_cancellable_new();
+
+       return SMBD_ERR_NONE;
+}
+
+static int __dbus_close_gdbus_call(void)
+{
+       g_cancellable_cancel(gdbus_conn.cancellable);
+       g_object_unref(gdbus_conn.cancellable);
+       gdbus_conn.cancellable = NULL;
+
+       if (gdbus_conn.conn_ref_count < 1) {
+               /* TODO: Use later. TIZEN_LOGD("There is no pending call\n"); */
+
+               g_object_unref(gdbus_conn.connection);
+               gdbus_conn.connection = NULL;
+       } else {
+               /* TIZEN_LOGD("There are %d pending calls, waiting to be cleared\n",
+                               gdbus_conn.conn_ref_count); */
+
+               g_object_unref(gdbus_conn.connection);
+       }
+
+       return SMBD_ERR_NONE;
+}
+
+static void __dbus_smbd_cellular_signal_filter(GDBusConnection *conn,
+               const gchar *name, const gchar *path, const gchar *interface,
+               const gchar *sig, GVariant *param, gpointer user_data)
+{
+       const char *key = NULL;
+       gchar *field = NULL;
+       gchar *value = NULL;
+       GVariant *var = NULL;
+       GVariantIter *iter = NULL;
+
+       TIZEN_LOGD("Signal PropertyChanged:cellular_device_info received");
+       if (g_strcmp0(sig, SMBD_SIGNAL_PROPERTYCHANGED) == 0) {
+               g_variant_get(param, "(sa{ss})", &key, &iter);
+               TIZEN_LOGD("signal - [%s] key - [%s]", sig, key);
+
+               if (g_strcmp0(key, SMBD_SIGNAL_VALUE_CELLULAR) == 0) {
+                       while ((var = g_variant_iter_next_value(iter))) {
+                               g_variant_get(var, "{ss}", &field, &value);
+                               SECURE_DB_INFO("field - [%s] value [%s]", field, value);
+                               if(strncmp(field,"proxy",5) == 0)
+                                       memcpy(smbd_cellular_profile_info.proxy,value,strlen(value));
+                               else if(strncmp(field,"dns1",4) == 0)
+                                       memcpy(smbd_cellular_profile_info.dns_1,value,strlen(value));
+                               else if(strncmp(field,"dns2",4) == 0)
+                                       memcpy(smbd_cellular_profile_info.dns_2,value,strlen(value));
+                               g_free(field);
+                               g_free(value);
+                               g_variant_unref(var);
+                       }
+
+                       /* ToDo: Need to send the event */
+               }
+
+               g_free((gchar *)key);
+       }
+}
+#if 0
+static void __dbus_smbd_wifi_signal_filter(GDBusConnection *conn,
+               const gchar *name, const gchar *path, const gchar *interface,
+               const gchar *sig, GVariant *param, gpointer user_data)
+{
+       const char *key = NULL;
+       const char *ipaddr = NULL;
+       GVariant *var = NULL;
+       GVariantIter *iter;
+       smbd_event_info_t event_info = { 0, };
+
+       TIZEN_LOGD("Signal PropertyChanged:wifi_device_info received");
+       if (g_strcmp0(sig, SMBD_SIGNAL_PROPERTYCHANGED) == 0) {
+               g_variant_get(param, "(sv)", &key, &var);
+               TIZEN_LOGD("signal - [%s] key - [%s]", sig, key);
+
+               if (g_strcmp0(key, SMBD_SIGNAL_VALUE_WIFI) == 0) {
+                       g_variant_get(var, "s", &ipaddr);
+                       TIZEN_LOGD("value - [%s]", ipaddr);
+
+                       TIZEN_LOGD("Sending SMBD_EVENT_WIFI_INFO");
+
+                       event_info.Event = SMBD_EVENT_WIFI_INFO;
+                       event_info.Error = SMBD_ERR_NONE;
+                       event_info.EventData = (void *)ipaddr;
+
+                       if (smartbonding_callbacks.cb != NULL) {
+                               smartbonding_callbacks.cb(event_info, NULL);
+                       }
+
+                       g_free((gchar *)ipaddr);
+               }
+
+               g_free((gchar *)key);
+               if (NULL != var)
+                       g_variant_unref(var);
+       }
+}
+#endif
+static void __dbus_smbd_smartbonding_signal_filter(GDBusConnection *conn,
+               const gchar *name, const gchar *path, const gchar *interface,
+               const gchar *sig, GVariant *param, gpointer user_data)
+{
+       const char *key = NULL;
+       gboolean smartbonding = FALSE;
+       GVariant *var = NULL;
+       smbd_event_info_t event_info = { 0, };
+
+       TIZEN_LOGD("Signal PropertyChanged:smartbonding received");
+       if (g_strcmp0(sig, SMBD_SIGNAL_PROPERTYCHANGED) == 0) {
+               g_variant_get(param, "(sv)", &key, &var);
+               TIZEN_LOGD("signal - [%s] key - [%s]", sig, key);
+
+               if (g_strcmp0(key, SMBD_SIGNAL_VALUE_SMARTBONDING) == 0) {
+                       g_variant_get(var, "b", &smartbonding);
+                       TIZEN_LOGD("value - [%d]", smartbonding);
+
+                       TIZEN_LOGD("Sending SMBD_EVENT_SMARTBONDING_STATUS");
+
+                       event_info.Event = SMBD_EVENT_SMARTBONDING_STATUS;
+                       event_info.Error = SMBD_ERR_NONE;
+                       event_info.EventData = (void *)smartbonding;
+
+                       if (smartbonding_callbacks.cb != NULL) {
+                               smartbonding_callbacks.cb(event_info, NULL);
+                       }
+               }
+
+               g_free((gchar *)key);
+               if (NULL != var)
+                       g_variant_unref(var);
+       }
+}
+
+static void __dbus_smbd_user_signal_filter(GDBusConnection *conn,
+               const gchar *name, const gchar *path, const gchar *interface,
+               const gchar *sig, GVariant *param, gpointer user_data)
+{
+       const char *key = NULL;
+       gint32 user_option = 0;
+       gint32 handle;
+       //GVariant *var = NULL;
+
+       TIZEN_LOGD("Signal UserResponse received");
+       if (g_strcmp0(sig, SMBD_SIGNAL_USERRESPONSE) == 0) {
+               g_variant_get(param, "(s(iu))", &key, &user_option, &handle);
+               TIZEN_LOGD("signal - [%s] key - [%s]", sig, key);
+               TIZEN_LOGD("user_option - [%d] handle - [%d]", user_option, handle);
+
+               _handle_remove_post_event_send((guint)handle, user_option);
+
+               g_free((gchar *)key);
+               //if (NULL != var)
+               //      g_variant_unref(var);
+       }
+}
+
+static int __dbus_register_signal(void)
+{
+       GDBusConnection *connection = _dbus_get_gdbus_conn();;
+       smbd_err_t Error = SMBD_ERR_NONE;
+
+       gdbus_conn_sub_id_smbd_cellular = g_dbus_connection_signal_subscribe(
+                       connection,
+                       NULL,
+                       SMBD_SERVICE_INTERFACE,
+                       SMBD_SIGNAL_PROPERTYCHANGED,
+                       NULL,
+                       SMBD_SIGNAL_VALUE_CELLULAR,
+                       G_DBUS_SIGNAL_FLAGS_NONE,
+                       __dbus_smbd_cellular_signal_filter,
+                       NULL,
+                       NULL);
+#if 0
+       gdbus_conn_sub_id_smbd_wifi = g_dbus_connection_signal_subscribe(
+                       connection,
+                       NULL,
+                       SMBD_SERVICE_INTERFACE,
+                       SMBD_SIGNAL_PROPERTYCHANGED,
+                       NULL,
+                       SMBD_SIGNAL_VALUE_WIFI,
+                       G_DBUS_SIGNAL_FLAGS_NONE,
+                       __dbus_smbd_wifi_signal_filter,
+                       NULL,
+                       NULL);
+#endif
+       gdbus_conn_sub_id_smbd_smartbonding = g_dbus_connection_signal_subscribe(
+                       connection,
+                       NULL,
+                       SMBD_SERVICE_INTERFACE,
+                       SMBD_SIGNAL_PROPERTYCHANGED,
+                       NULL,
+                       SMBD_SIGNAL_VALUE_SMARTBONDING,
+                       G_DBUS_SIGNAL_FLAGS_NONE,
+                       __dbus_smbd_smartbonding_signal_filter,
+                       NULL,
+                       NULL);
+
+       gdbus_conn_sub_id_smbd_user = g_dbus_connection_signal_subscribe(
+                       connection,
+                       NULL,
+                       SMBD_SERVICE_INTERFACE,
+                       SMBD_SIGNAL_USERRESPONSE,
+                       NULL,
+                       SMBD_SIGNAL_VALUE_USERRESPONSE,
+                       G_DBUS_SIGNAL_FLAGS_NONE,
+                       __dbus_smbd_user_signal_filter,
+                       NULL,
+                       NULL);
+
+       if (gdbus_conn_sub_id_smbd_cellular == 0 ||
+                       //gdbus_conn_sub_id_smbd_wifi == 0 ||
+                       gdbus_conn_sub_id_smbd_smartbonding == 0 ||
+                       gdbus_conn_sub_id_smbd_user == 0) {
+               TIZEN_LOGD("Failed to register signals smbd cellular id(%d) "
+                               //"smbd wifi id(%d)
+                               "smbd smartbonding id(%d) smbd user id(%d)\n",
+                               gdbus_conn_sub_id_smbd_cellular,
+                               //gdbus_conn_sub_id_smbd_wifi,
+                               gdbus_conn_sub_id_smbd_smartbonding,
+                               gdbus_conn_sub_id_smbd_user);
+               Error = SMBD_ERR_UNKNOWN;
+       } else {
+               TIZEN_LOGD("Signals registered successfully");
+       }
+
+       return Error;
+}
+
+static int __dbus_deregister_signal(void)
+{
+       GDBusConnection *connection = _dbus_get_gdbus_conn();
+       smbd_err_t Error = SMBD_ERR_NONE;
+
+       if (connection == NULL) {
+               TIZEN_LOGD("Connection NULL\n");
+               return SMBD_ERR_UNKNOWN;
+       }
+
+       g_dbus_connection_signal_unsubscribe(connection,
+                       gdbus_conn_sub_id_smbd_cellular);
+       /* g_dbus_connection_signal_unsubscribe(connection,
+                       gdbus_conn_sub_id_smbd_wifi); */
+       g_dbus_connection_signal_unsubscribe(connection,
+                       gdbus_conn_sub_id_smbd_smartbonding);
+       g_dbus_connection_signal_unsubscribe(connection,
+                       gdbus_conn_sub_id_smbd_user);
+
+       return Error;
+}
+
+int smart_bonding_init(void)
+{
+       smbd_err_t Error = SMBD_ERR_NONE;
+
+       TIZEN_LOGD("Smartbonding client: Init API");
+
+       Error = __dbus_create_gdbus_call();
+       if (Error != SMBD_ERR_NONE) {
+               TIZEN_LOGD("Connection creation failed - [%d]\n", Error);
+               return Error;
+       }
+
+       Error = __dbus_register_signal();
+       if (Error != SMBD_ERR_NONE) {
+               TIZEN_LOGD("Signal registration failed - [%d]\n", Error);
+               return Error;
+       }
+
+       return SMBD_ERR_NONE;
+}
+
+int smart_bonding_deinit(void)
+{
+       smbd_err_t Error = SMBD_ERR_NONE;
+
+       TIZEN_LOGD("Smartbonding client: De-init API");
+
+       Error = __dbus_deregister_signal();
+       if (Error != SMBD_ERR_NONE) {
+               TIZEN_LOGD("Signal de-registration failed - [%d]\n", Error);
+               return Error;
+       }
+
+       Error = __dbus_close_gdbus_call();
+       if (Error != SMBD_ERR_NONE) {
+               TIZEN_LOGD("Connection close failed - [%d]\n", Error);
+               return Error;
+       }
+
+       return SMBD_ERR_NONE;
+}
+
+int smart_bonding_start(char *file_name, int file_size,
+               smartbonding_cb callback, void *user_data)
+{
+       smbd_err_t Error = SMBD_ERR_NONE;
+       GVariant *params;
+       GVariant *msg;
+       int smartbonding_value;
+       event_info_t *event_info = NULL;
+       guint32 handle = 0;
+
+       TIZEN_LOGD("Smartbonding client: Start smartbonding API");
+       SECURE_DB_INFO("File - [%s] file size - [%d]", file_name, file_size);
+
+       vconf_get_int(VCONF_SMART_BONDING_POLICY, &smartbonding_value);
+
+       if (smartbonding_value == SMART_BONDING_WIFI_ONLY) {
+               TIZEN_LOGD("Smart bonding policy is OFF");
+               return SMBD_ERR_POLICY_OFF;
+       }
+
+       if (callback == NULL) {
+               TIZEN_LOGD("Smart bonding callback not set");
+               return SMBD_ERR_INVALID_PARAMETER;
+       }
+
+       params = g_variant_new("(su)", file_name, file_size);
+
+       msg = __invoke_dbus_method(SMBD_SERVICE_DBUS, SMBD_PATH_DBUS,
+                       SMBD_SERVICE_INTERFACE, "StartBonding", params, &Error);
+       if (msg == NULL) {
+               TIZEN_LOGD("Start smart bonding request failed");
+
+               return Error;
+       }
+
+       g_variant_get(msg, "(u)", &handle);
+       g_variant_unref(msg);
+
+       if (handle <= 0) {
+               TIZEN_LOGD("Start smart bonding request failed."
+                               " Erroneous handle");
+               return SMBD_ERR_UNKNOWN;
+       }
+
+       event_info = g_try_new0(event_info_t, 1);
+       if (event_info == NULL) {
+               TIZEN_LOGD("Start smart bonding request failed."
+                               "Memory allocation failed");
+               return SMBD_ERR_UNKNOWN;
+       }
+       event_info->cb = callback;
+       event_info->user_data = user_data;
+       event_info->handle = handle;
+
+       handle_list = g_slist_append(handle_list, event_info);
+       TIZEN_LOGD("Added the handle - [%d] into the list", handle);
+
+       TIZEN_LOGD("Start smart bonding request successful");
+       return Error;
+}
+
+int smart_bonding_stop(void *user_data)
+{
+       smbd_err_t Error = SMBD_ERR_NONE;
+       guint32 handle_id = 0;
+       GVariant *params;
+
+       TIZEN_LOGD("Smartbonding client: Stop smartbonding API");
+
+       handle_id = _handle_remove_with_user_data(user_data);
+
+       params = g_variant_new("(u)", handle_id);
+
+       Error = __invoke_dbus_method_nonblock(SMBD_SERVICE_DBUS, SMBD_PATH_DBUS,
+                       SMBD_SERVICE_INTERFACE, "StopBonding", params, __dbus_reply);
+       if (Error != SMBD_ERR_NONE) {
+               TIZEN_LOGD("Stop smart bonding request failed");
+               return Error;
+       }
+
+       TIZEN_LOGD("Stop smart bonding request successful");
+
+       return Error;
+}
+
+void smart_bonding_notify_interface_usage(const char *message)
+{
+       smbd_err_t Error = SMBD_ERR_NONE;
+       guint32 handle = 0;
+       GVariant *params;
+       GVariant *msg;
+
+       params = g_variant_new("(s)", message);
+
+       msg = __invoke_dbus_method(SMBD_SERVICE_DBUS, SMBD_PATH_DBUS,
+       SMBD_SERVICE_INTERFACE, "NotifyInterfaceUsage", params, &Error);
+       if (msg == NULL) {
+               TIZEN_LOGD("Notify smart bonding info failed, Error=%d", Error);
+               return;
+       }
+
+       g_variant_get(msg, "(u)", &handle);
+       g_variant_unref(msg);
+       return;
+}
+
diff --git a/client/test/smartbonding-test.c b/client/test/smartbonding-test.c
new file mode 100644 (file)
index 0000000..8c138cb
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+
+#include <glib.h>
+#include <stdio.h>
+
+#include <smartbonding-client.h>
+
+#define FILESIZE 1073741824
+static int data = 143;
+
+gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data);
+
+static void _smart_bonding_start_cb(smbd_event_info_t event, void *user_data)
+{
+       printf("Start smart-bonding cb \n");
+
+       switch (event.Event) {
+       case SMBD_EVENT_USER_OPTION_OK:
+               printf("Event: SMBD_EVENT_USER_OPTION_OK - uid[%d]\n",
+                               (int) user_data);
+               break;
+       case SMBD_EVENT_USER_OPTION_CANCEL:
+               printf("Event: SMBD_EVENT_USER_OPTION_CANCEL - uid[%d]\n",
+                               (int) user_data);
+               break;
+       default:
+               break;
+       }
+}
+
+int test_init_smartbonding(void)
+{
+       printf("Init smart-bonding\n");
+       int ret = smart_bonding_init();
+       if (ret != SMBD_ERR_NONE) {
+               printf("Init smart-bonding API failed\n");
+               return -1;
+       }
+
+       printf("Init smart-bonding API success\n");
+       return 1;
+}
+
+int test_deinit_smartbonding(void)
+{
+       printf("De-init smart-bonding\n");
+       int ret = smart_bonding_deinit();
+       if (ret != SMBD_ERR_NONE) {
+               printf("De-init smart-bonding API failed\n");
+               return -1;
+       }
+
+       printf("De-init smart-bonding API success\n");
+       return 1;
+}
+
+int test_start_smartbonding(void)
+{
+       printf("Start smart-bonding\n");
+       int ret = smart_bonding_start("/filename/test/movie.tar.gz",
+                       FILESIZE, _smart_bonding_start_cb, (void *)data);
+       if (ret != SMBD_ERR_NONE) {
+               printf("Start smart-bonding API failed\n");
+               if (ret == SMBD_ERR_POLICY_OFF) {
+                       printf("Feature vconf "
+                               "(file/private/wifi/network_bonding) is disabled\n");
+               } else if (ret == SMBD_ERR_INVALID_PARAMETER) {
+                       printf("Invalid callback parameter\n");
+               }
+               return -1;
+       }
+
+       printf("Start smart-bonding API success\n");
+       return 1;
+}
+
+int test_stop_smartbonding(void)
+{
+       printf("Stop smart-bonding\n");
+       int ret = smart_bonding_stop((void *)data);
+       if (ret != SMBD_ERR_NONE) {
+               printf("Stop smart-bonding API failed\n");
+               return -1;
+       }
+
+       printf("Stop smart-bonding API success\n");
+       return 1;
+}
+
+
+int main(int argc, char **argv)
+{
+       GMainLoop *mainloop;
+       mainloop = g_main_loop_new (NULL, FALSE);
+
+       GIOChannel *channel = g_io_channel_unix_new(0);
+       g_io_add_watch(channel, (G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL), test_thread, NULL);
+
+       printf("Test Thread created...\n");
+
+       g_main_loop_run (mainloop);
+
+       return 0;
+}
+
+gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data)
+{
+       int rv;
+       char a[10];
+
+       printf("Event received from stdin\n");
+
+       rv = read(0, a, 10);
+
+       if (rv <= 0 || a[0] == '0') {
+               rv = 0;
+
+               rv = test_deinit_smartbonding();
+               if (rv == -1)
+                       printf("Fail to deinitialize.\n");
+
+               exit(1);
+       }
+
+       if (a[0] == '\n' || a[0] == '\r') {
+               printf("\n\n Smart-bonding API Test App\n\n");
+               printf("Options..\n");
+               printf("1       - Initialise smart-bonding\n");
+               printf("2       - Start smart-bonding\n");
+               printf("3       - Stop smart-bonding\n");
+               printf("4       - De-initialise smart-bonding\n");
+               printf("0       - Exit \n");
+
+               printf("ENTER  - Show options menu.......\n");
+       }
+
+       switch (a[0]) {
+       case '1':
+               rv = test_init_smartbonding();
+               break;
+       case '2':
+               rv = test_start_smartbonding();
+               break;
+       case '3':
+               rv = test_stop_smartbonding();
+               break;
+       case '4':
+               rv = test_deinit_smartbonding();
+               break;
+       default:
+               break;
+       }
+
+       if (rv == 1)
+               printf("Operation successful!\n");
+       else
+               printf("Operation failed!\n");
+
+       return TRUE;
+}
+
diff --git a/include/multirat_SB_http.h b/include/multirat_SB_http.h
new file mode 100644 (file)
index 0000000..8117834
--- /dev/null
@@ -0,0 +1,551 @@
+#ifndef MULTIRAT_SB_HTTP_H_
+#define MULTIRAT_SB_HTTP_H_
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <linux/netdevice.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <poll.h>
+
+#define MAX_HISTORY 20
+
+#define CONNECTION_REQ_HEADER            "Connection:"
+#define ACCEPT_RANGE_REQ_HEADER          "Accept-Ranges:"
+#define CONTLEN_REQ_HEADER               "Content-Length:"
+#define RANGELEN_REQ_HEADER_CMP1              "Range: bytes"
+#define RANGELEN_REQ_HEADER_CMP2              "Range:bytes"
+#define RANGELEN_REQ_HEADER              "Range: bytes"
+#define CONTYPE_REQ_HEADER               "Content-Type:"
+#define IF_RANGE                         "If-Range:"
+
+#define LEN_CONNECTION_REQ_HEADER        11
+#define LEN_ACCEPT_RANGE_REQ_HEADER      14
+#define LEN_CONTLEN_REQ_HEADER           15
+#define LEN_RANGELEN_REQ_HEADER_CMP1     12
+#define LEN_RANGELEN_REQ_HEADER_CMP2     11
+//#define LEN_RANGELEN_REQ_HEADER          7
+#define LEN_RANGELEN_REQ_HEADER          6
+#define LEN_CONTYPE_REQ_HEADER           13
+#define LEN_IF_RANGE                     9
+
+#define CONNECTION_RSP_HEADER          "Connection:"
+#define CONTLEN_RSP_HEADER             "Content-Length:"
+#define ACCEPT_RANGE_RSP_HEADER                "Accept-Ranges:"
+#define CONTRANGE_RSP_HEADER           "Content-Range:"
+#define LOCATION_RSP_HEADER            "Location:"
+
+#define LEN_CONNECTION_RSP_HEADER        11
+#define LEN_CONTLEN_RSP_HEADER           15
+#define LEN_ACCEPT_RANGE_RSP_HEADER      14
+#define LEN_CONTRANGE_RSP_HEADER         14
+#define LEN_LOCATION_RSP_HEADER                9
+
+#define END_OF_HEADERS                   "\r\n\r\n"
+#define END_OF_LINE                      "\r\n"
+#define LEN_OF_CRLF                      2
+
+#define HTTP_RSP_SOCKET_ERROR            -2
+#define HTTP_RSP_DECODING_ERROR          -1
+#define HTTP_RSP_DECODING_SUCCESS        0
+#define HTTP_RSP_REDIRECT                                        1
+#define TIME_OUT_MILLISEC                30000
+#define TMAX                             20
+#define INET_ADDRSTRLENG                 50
+#define MAX_CONT_LEN                     50
+#define MICROSECS_IN_SEC                  1000000
+
+#define MAX_INTERFACES                   2
+
+#define STATE_THREAD_RUNNING             1
+#define STATE_THREAD_STOPPED             2
+
+#define THREAD_WAIT                      0
+#define THREAD_EXIT                      1
+#define THREAD_CONTINUE                  2
+
+#define SOCKET_CREATION_FAILED           -1
+#define SOCKET_BIND_FAILED               -2
+
+#define MAX_TEMP_BUFF                    4000
+#define MAX_HEADER_SIZE                  (16 * 1024)
+
+#define B_TRUE                           1
+#define B_FALSE                          0
+
+#define FILE_THREAD      1
+#define MAIN_THREAD      0
+
+#define MAIN_IO_EXCEPTION      1
+#define FILE_IO_EXCEPTION 2
+#define MAIN_COMPLETE 3
+#define FILE_COMPLETE 4
+#define FILE_START 5
+#define MAIN_START 6
+#define FILE_WAIT 7
+#define NO_FILE_THREAD 8
+#define NO_REDIVISION 9
+
+#define FILE_NODE        1
+#define SOCKET_NODE      0
+
+#define CURL_TIMEOUT_MULTIRAT_READ 1
+#define CURL_BLOCK_MULTIRAT_READ 2
+
+#define MAIN_SOCK_READ_ACTIVE 1
+#define MAIN_SOCK_READ_INACTIVE 0
+
+#define SOCKET_NODE_FORCE_EXCEPTION 1
+#define SOCKET_NODE_NORMAL_EXCEPTION 2
+#define SOCKET_NORMAL_EXCEPTION 3
+
+#define DIRECT_WRITE_HEADER "x-direct-write: yes"
+#define DIRECT_WRITE_HEADER_LENGTH (strlen(DIRECT_WRITE_HEADER) + 2) /*Additional 2 is for \r\n*/
+
+#define NOTI_TRIGGER "S"
+#define NOTI_TRIGGER_LENGTH 1
+
+#ifdef SB_LOG_SUPPORT
+#ifndef LOG_TAG
+/* This LOG_TAG should be defined before including dlog.h. Because dlog.h is using it. */
+#define LOG_TAG "multirat"
+#endif
+#include <dlog.h>
+#endif
+
+#ifdef SB_LOG_SUPPORT
+#define TIZEN_LOGD(fmt, args...)               LOGI(fmt, ##args)
+#define SECURE_DB_INFO(fmt, args...)           SECURE_LOGI(fmt, ##args)
+#define SECURE_DB_DEBUG(fmt, args...)          SECURE_LOGD(fmt, ##args)
+#define SECURE_DB_WARN(fmt, args...)           SECURE_LOGW(fmt, ##args)
+#define SECURE_DB_ERROR(fmt, args...)          SECURE_LOGE(fmt, ##args)
+#else
+#define TIZEN_LOGD(fmt, args...)               
+#define SECURE_DB_INFO(fmt, args...)           
+#define SECURE_DB_DEBUG(fmt, args...)          
+#define SECURE_DB_WARN(fmt, args...)           
+#define SECURE_DB_ERROR(fmt, args...)  
+#endif
+
+
+#ifdef SB_DETAIL_LOG_SUPPORT
+#define TIZEN_D_LOGD(fmt, args...) LOGI(fmt, ##args)
+#define SECURE_DB_D_LOGD(fmt, args...) SECURE_LOGI(fmt, ##args)
+
+#else
+#define TIZEN_D_LOGD(fmt, args...)
+#define SECURE_DB_D_LOGD(fmt, args...) 
+#endif
+
+#define CLOSE_SOCKET(socket) \
+{\
+       if(socket > 2)\
+       {\
+       close(socket);\
+       }\
+       else\
+       {\
+               TIZEN_LOGD("Socket is Less Than 2 Value %d", socket);\
+       }\
+}\
+
+typedef char            int8;
+typedef unsigned char   uint8;
+typedef int             int32;
+typedef unsigned int    uint32;
+typedef long long            int64;
+typedef unsigned long long   uint64;
+
+
+typedef enum
+{
+       HTTP_GET = 1,
+       HTTP_POST,
+       HTTP_HEAD
+} eHTTPMsgType;
+
+typedef enum
+{
+       HTTP_VERSION_1_0 = 1,
+       HTTP_VERSION_1_1
+}eHTTPVersion;
+
+typedef struct _interfaceInfo_
+{
+       int8 interface_name[TMAX];
+       int8 ip[INET_ADDRSTRLENG];
+       int8 server_ip[INET_ADDRSTRLENG];
+       int32 server_port ;
+       int32 proxyEnable;
+       int8 proxy_addr[INET_ADDRSTRLENG];
+       int32 proxy_port;
+       int8 dns_1[INET_ADDRSTRLENG];
+       int8 dns_2[INET_ADDRSTRLENG];
+}interfaceInfo;
+
+typedef struct _connection_
+{
+       int32 port;
+       int32 sockId[MAX_INTERFACES];
+       int8 ip_addr[INET_ADDRSTRLENG];
+       interfaceInfo ifaceInfo[MAX_INTERFACES];
+       int32 ip_family;                /*  ip_family = 0 -> ipv4     1 -> ipv6  */
+}connection;
+
+
+typedef struct _httpResp_
+{
+       int8 resp_buff[MAX_HEADER_SIZE];
+       int8 resp_buff_body[MAX_HEADER_SIZE];
+       uint64 resp_header_length;
+       int8 *http;
+       int8 *rspcode;
+       int8 *connection;
+       int8 *contLen;
+       int8 *contRange;
+       int8 *accept_range;
+       int8 *location;
+       int32 acceptFlag;
+       uint64 cLen;
+       uint64 instanceSize;
+}httpResp;
+
+typedef struct _httpReq_
+{
+       eHTTPMsgType method;
+       uint32 reqLen;
+       uint32 req_wo_len;
+       uint64 rangeStart;
+       int8 *url;
+       int8 *req_buff;
+       int8 *req_buff_wo_range;
+       int8 *accept_range;
+       int8 *connection;
+       int8 *contLen;
+       int8 *Rangeheader;
+       int8 *contType;
+       int8 *ifRange;
+       int8 *request[MAX_INTERFACES];
+}httpReq;
+
+typedef enum __State_
+{
+       STATE_NOT_READ = 1,
+       STATE_OCCUPIED,
+       STATE_READING,
+       STATE_BLOCKED,
+       STATE_FULL_READ,
+       STATE_CLEARED
+} eState;
+
+typedef struct _DataBuffer_
+{
+       int32 threadId;
+       int32 socketId;
+       uint32 offset;
+       uint32 totalLen;
+       uint32 estSpeed;
+       uint32 appReadLen;
+       uint32 isContinueChunk;
+       int8 *data;
+       eState state;
+
+       int8 filePath[200];
+       FILE *readFp;   /* File pointer used only for reading */
+       FILE *writeFp;  /* File Pointer used  only for writing */
+       uint64 cthread;
+
+       pthread_mutex_t mut;
+}DataBuffer;
+
+typedef struct _SmartBondingData_ SmartBondingData;
+
+typedef struct _BlockManager_
+{
+       uint32 noOfChunks;
+       uint32 chunkSize;
+       uint32 lastChunkSize;
+       uint32 minSizeToHandover;
+       uint32 threadState[MAX_INTERFACES];
+       uint32 noOfIOExp[MAX_INTERFACES];
+       uint64 rspOffset;
+       uint64 comRspLen;
+       uint64 strtOffset;
+       uint64 speed[MAX_INTERFACES];
+       uint64 headerSpeed[MAX_INTERFACES];
+       int32 prevChunkId[MAX_INTERFACES];
+       int32 minNotReadChunkId;
+       int32 *currentChunkId;
+       pthread_mutex_t mutex;
+       DataBuffer *commBuff;
+       SmartBondingData *SBData;
+}BlockManager;
+
+typedef struct _StatDetails_
+{
+       uint32 speedIndex;
+       uint32 mainSockSpeed;
+       uint32 dataArr[100];
+       uint64 timeT1;
+       uint64 sendTime;
+       uint64 offsetForSpeed;
+       uint64 dataOffset;
+       uint64 main_thread_sendTime;
+       uint64 startTime;
+       uint64 dataStrtTime;
+       uint64 tempTime;
+       uint64 dataOffsetTime;
+       uint64 timeArr[100];
+       uint64 read_start_time;
+}StatDetails;
+
+typedef struct _speedStat_
+{
+       uint32 prev_read;
+       int32 prev_sock_read;
+       uint64 recv_length[2];
+       uint64 start_recv_time[2];
+       uint64 minTimeToCheckStopSlow[2];
+       uint64 prev_recv_time[2];
+       uint64 slow_start_length[2];
+       uint64 slow_start_time[2];
+       uint64 start_speed_check_time;
+       uint64 dataArray[2][MAX_HISTORY];
+       uint64 timeArray[2];
+}speedStat;
+
+typedef struct _CThread_
+{
+       uint64 threadId;
+       int32 threadStatus;
+}CThread;
+
+
+typedef struct _PollThread_
+{
+    uint64 threadId;
+    int32 threadStatus;
+}PollThread;
+
+typedef struct _CURLThread__
+{
+       uint64 threadId;
+       int32 threadStatus;
+}curlThread;
+
+typedef struct _RangeRequestThread_
+{
+       int32 socketId;
+       int32 threadId;
+       int32 firstRngStatus;
+       uint32 headerLen;
+       uint64 compRspLen;
+       uint64 contRngLen;
+       uint32 *compRspRcvdFlag;
+       uint32 minBlockSize;
+       uint32 maxBlockSize;
+       uint32 speedTimeOut;
+       uint32 minDataForSpeed;
+       uint32 blockForSpeed;
+       int8 *reqHeaders;
+       connection *conn;
+       pthread_t pThreadId;
+       BlockManager *blockMgr;
+       DataBuffer *commBuffer;
+       SmartBondingData *SBData;
+}RangeRequestThread;
+
+typedef struct _MultiSocket_
+{
+       int32 currentChunkId;
+       uint32 noOfChunks;
+       uint32 appReadLen;
+       uint32 compRspRcvdFlag;
+       uint64 rspOffset;
+       uint64 compRspLen;
+       uint64 strtOffset;
+       connection *conn;
+       BlockManager *blockMgr;
+       DataBuffer * commBuffer;
+       RangeRequestThread *reqThread[MAX_INTERFACES];
+       SmartBondingData *SBData;
+}MultiSocket;
+
+typedef enum __nodeState_
+{
+       NODE_STATE_NOT_READ = 1,
+       NODE_STATE_DOWNLOADING,
+       NODE_STATE_BLOCKED,
+       NODE_STATE_FULL_READ,
+       NODE_STATE_CLEARED
+}nodeState;
+
+typedef struct _fileBuffer_ fileBuffer;
+
+struct _fileBuffer_
+{
+       int32 socketId; /* if not zero means current file buffer should be read from socket */
+       uint32 nodeType;
+       uint32 bRafMode;
+       uint32 fThread_read;
+       uint64 offset;
+       uint64 startOffset;
+       uint64 endOffset;
+       uint64 totalLen;
+       uint64 appReadLen;
+       uint64 interface;
+       uint64 file_flush_offset; /* Offset that is fflushed already */
+       int8 filePath[200];
+       FILE *readFp;   /* File pointer used only for reading */
+       FILE *writeFp;  /* File Pointer used  only for writing */
+       pthread_mutex_t mut;
+       nodeState state;
+       fileBuffer *next;
+};
+
+typedef struct _randomFileManager_
+{
+       uint32 rspHeaderCheck;
+//     uint64 expectedBytes;
+       uint64 rspRead;         // for main thread response data count
+       uint64 prevRange;
+       SmartBondingData *SBData;
+       FILE *writeFD1;
+       FILE *writeFD2;
+
+}randomFileManager;
+
+typedef struct _fileManager_
+{
+       uint64 *ExpectedBytes;
+       uint64 *rspRead;
+       uint64 totalLen;
+       uint64 strtOffset;
+       uint32 thread_exception;
+       uint32 interface[2];
+       fileBuffer **fbuffer;
+       pthread_mutex_t mutex;
+       SmartBondingData *SBData;
+}fileManager;
+
+typedef struct _fileThread_
+{
+       pthread_t pthreadId;
+       uint32 interface_index;
+       uint32 headerLen;
+       uint32 *compRspRcvdFlag;
+       uint32 status;
+       int32 socketId;
+       int8 *req;
+       uint32 firstRngStatus;
+       uint64 compRspLen;
+       uint64 contRngLen;
+       fileManager *fileMgr;
+       connection *conn;
+       SmartBondingData *SBData;
+}fileThread;
+
+typedef struct _fileStream_
+{
+       uint64 *mainSockExpBytes;
+       uint64 *mainSockRead;
+       uint64 totalLen;
+       uint64 strtOffset;
+       uint32 compRspRcvdFlag;
+       fileManager *fileMgr;
+       fileBuffer *fileBuff;
+       fileThread *fThread;
+       SmartBondingData *SBData;
+}fileStream;
+
+typedef struct _fileCThread_
+{
+       uint64 threadId;
+       int32 threadStatus;
+}fileCThread;
+
+struct _SmartBondingData_
+{
+       int32 socket_fd;
+       uint32 user_option;
+       uint32 dns;
+       uint32 dns_iface;
+       uint32 sync;
+       uint32 cancel;
+       uint32 curl;
+       uint32 timeout;
+       uint32 mainSockExp;
+       uint32 interface_index;
+       uint32 response_check;
+       uint32 response_check_length;
+       uint32 enableMultiRat;
+       uint32 multiRatCheckDone;
+       uint32 mSocketDataBufferReady;
+       uint32 multiSocketThreadStarted;
+       uint32 watch_dog_complete;
+       uint64 response_body_read ;
+       uint64 totalExpectedBytes;
+       uint64 CurlStartTime ;
+       httpReq req;
+       httpResp resp;
+       connection conn;
+       StatDetails stat;
+       CThread *cthread;
+       curlThread *curlThrd;
+       MultiSocket *msocket;
+       pthread_mutex_t tempLock;
+
+       PollThread *PollThrd;
+       int32 trigger_pipefd[2];
+       int32 noti_pipefd[2];
+       uint32 poll_thread_noti_exception;
+       uint32 Libfd;
+
+       int32 con_status;
+       int32  division_count;
+       int32  read_state_check;        //Created to capture state of main read socket
+       uint64 expectedbytes;
+       uint32 fStreamFileBufferReady;
+       uint32 fileThreadStarted;
+       uint32 twoChunk;
+       uint32 socket_check;
+       uint32 testtime;
+       uint32 testcount;
+       uint32 status;
+       uint32 file_status;
+       uint32 node_exception;
+       uint32 support_exception;
+       fileStream *fStream;
+       fileCThread *filecthread;
+       speedStat sStat;
+       uint32 speed[2];
+
+       int8 FileData[100]; /* This Stores the Data to be sent to Curl For File Thread Progress */
+       randomFileManager raFileMngr;
+       int8 rafFileName[200];
+       uint32 bRafMode ;       /* 1 if RAF mode is SET else 0 */
+       uint32 resp_complete ; /* This Indicate that response is received and Decision on RAF is Done */
+       uint64 content_length ;
+       uint64 startOffset; /* Range Start Offset in Ranage Request Header */
+};
+
+typedef struct _MultiSockInput_
+{
+       uint32 chunkSize;
+       uint32 noOfChunks;
+       uint32 lastChunk;
+       uint64 rspOffset;
+       connection *conn;
+}MultiSockInput;
+
+#endif
diff --git a/include/multirat_block_manager.h b/include/multirat_block_manager.h
new file mode 100644 (file)
index 0000000..0312e16
--- /dev/null
@@ -0,0 +1,229 @@
+#ifndef BLOCKMANAGER_H_
+#define BLOCKMANAGER_H_
+
+#include "multirat_SB_http.h"
+
+#define GET_OTHER_THREAD_ID(a)              (((a) + 1) % 2)
+#define SET_SPEED(a, b, c)                  ((c)->speed[(a)] = (b))
+#define SET_HEAD_SPEED(a, b, c)             ((c)->headerSpeed[a] = (b))
+
+/**
+ * @brief                           initialize the block manager
+ * @param[in]         psBlkInfo     Block Manager Info Structure
+ * @param[in]         bmanager      Block Manager Object
+ * @return                          void
+ * @retval                          None
+ */
+void block_manager_init(MultiSocket *mSocket, BlockManager *bmanager,MultiSockInput *mSockInput);
+
+/**
+ * @brief                            assign chunk for current thread
+ * @param[in]           chunkInfo    chunkInformation
+ * @param[in]           threadId     Thread Number
+ * @param[in]           socketId     Socket Number
+ * @param[in]           bmanager     Block Manager Object
+ * @return                           status if chunk assigned
+ * @retval              0            chunk assigned to thread
+ * @retval
+ */
+
+int32 block_manager_get_next_chunk(int64 *chunkInfo,int32 threadId,int32 socketId,
+                 BlockManager *bmanager);
+
+/**
+ * @brief                            get the minimum chunk which is unread
+ * @param[in]          chunkId       chunkInformation
+ * @param[in]          chunkInfo     chunkInformation
+ * @param[in]          threadId      Thread Number
+ * @param[in]          socketId      Socket Number
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           void
+ * @retval                           none
+ * @retval                           none
+ */
+void block_manager_getmin_notread_chunk(int32 chunkId, int64 *chunkInfo, int32 threadId,
+                 int32 socketId, BlockManager *bmanager);
+
+/**
+ * @brief                            min unread chunckID
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           chunkID
+ * @retval             chunkID       when successful
+ * @retval             -1            on error
+ */
+
+int32 block_manager_getmin_notread_chunkId(BlockManager *bmanager);
+
+/**
+ * @brief                            min unread chunckID from last
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           chunkID
+ * @retval             chunckID      when successful
+ * @retval             -1            on error
+ */
+int32 block_manager_get_lastmin_notread_chunkId(BlockManager *bmanager);
+
+/**
+ * @brief                            get the min chunkID which is unread
+ * @param[in]          chunkId       chunkInformation
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           unread chunkID
+ * @retval             chunkID       when successful
+ * @retval             0             on error
+ */
+int32 block_manager_get_min_not_read_jump_case(int32 chunkId,BlockManager *bmanager);
+
+/**
+ * @brief                            Gets next chunkId where request thread
+ *                                   speed is slower than other thread speed
+ * @param[in]          ratio         Ratio of speed for both interfaces
+ * @param[in]          otherId       Thread ID of Other Thread
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           chunkID
+ * @retval             chunkID       when successful
+ * @retval
+ */
+int32 block_manager_handle_slow_case(uint32 ratio, uint32 otherId,BlockManager *bmanager);
+
+/**
+ * @brief                            Gets next chunkId where request thread
+ *                                   speed is faster than other thread speed
+ * @param[in]          ratio         Ratio of both the interfaces speeds
+ * @param[in]          thisSpeed     Request thread Speed
+ * @param[in]          otherSpeed    Speed of other thread
+ * @param[in]          otherBuff     Other Thread last chunk info(data buffer)
+ * @param[in]          otherId       ThreadID of other thread
+ * @param[in]          threadId      Current thread ID
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           chunkID
+ * @retval             chunkID       chunkID when successful
+ * @retval
+ */
+int32 block_manager_handle_fastcase(uint32 ratio, uint64 thisSpeed, uint64 otherSpeed,
+                 DataBuffer *otherBuff, uint32 otherId, int32 threadId, BlockManager *bmanager);
+
+/**
+ * @brief                            Reset the previous ChunkID
+ * @param[in]          threadId      Thread number
+ * @param[in]          chunkId       Chunk Information
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           void
+ */
+void block_manager_io_exception(int32 threadId, int32 chunkId,BlockManager *bmanager);
+
+
+/**
+ * @brief                            Check the status of other thread
+ *                                   downloading chunks
+ * @param[in]          threadId      Thread number
+ * @param[in]          chunkId       Chunk Information
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           status of block manager chunk
+ * @retval             1             block manager chunk is blocked
+ * @retval             0             no chunk blocked
+ */
+uint32 block_manager_checkOtherThread(int32 threadId, int32 chunkId, BlockManager *bmanager, uint32 temp_check);
+
+/**
+ * @brief                            Checks the common buffer status by
+ *                                   checking each data buffer state
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           status of common buffer
+ * @retval             1             wait till app reads some data
+ * @retval             0             ready to download next chunk
+ */
+int32 block_manager_check_buffer_status(BlockManager *bmanager);
+
+
+/**
+ * @brief                            Checks the state if any buffer is still downloading
+ *                                   thread should not exit
+ * @param[in]          bmanager      Block Manager Object
+ * @param[in]          threadId      Thread number
+ * @return                           thread status
+ * @retval             1             Thread can exit
+ * @retval             0             Thread should not exit
+ */
+int32 block_manager_checkAllBufferStatus(BlockManager *bmanager,int32 threadId);
+
+/**
+ * @brief                            if block manager has chunk in not read or
+ *                                   blocked state
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           status of block manager
+ * @retval             1             has chunks in blocked or unread state
+ * @retval             0             no chunks in blocked or unread state
+ */
+int32 block_manager_chunk_present(BlockManager *bmanager);
+
+/**
+ * @brief                            Destroy the mutex
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           void
+ * @retval                           none
+ */
+void  block_manager_exit(BlockManager *bmanager);
+
+/**
+ * @brief                            Check speed of interface in current thread
+ * @param[in]          bmanager      Block Manager Object
+ * @param[in]          threadId      Thread number
+ * @return                           thread status
+ * @retval             0             thread wait
+ * @retval             2             thread continue
+ */
+
+uint32  block_manager_checkSpeed(BlockManager *bmanager,int32 threadId);
+
+/**
+ * @brief                            stops thread during extreme condition
+ * @param[in]          chunkInfo     chunk information
+ * @param[in]          threadId      thread number
+ * @param[in]          socketId      socket number
+ * @param[in]          bmanager      block manager object
+ * @param[in]          otherBuff     data buffer
+ * @param[in]          otherId       other thread id
+ * @param[in]          this speed    speed of current thread interface
+ * @return                           void
+ * @retval                           none
+ */
+void block_manager_handleExtermeCase(int64 *chunkInfo, int32 threadId, int32 socketId,
+                 BlockManager *bmanager, DataBuffer *otherBuff,uint32 otherId,uint64 thisSpeed);
+/**
+ * @brief                            get continious chunk information
+ * @param[in]          chunkInfo     chunk information
+ * @param[in]          threadId      thread number
+ * @param[in]          socketId      socket number
+ * @param[in]          bmanager      block manager object
+ * @return                           void
+ */
+
+void block_manager_getContinueChunk(int64 *chunkInfo, int32 threadId, int32 socketId,
+                 BlockManager *bmanager);
+/**
+ * @brief                            buildContChunk
+ * @param[in]          chunkId       chunk number
+ * @param[in]          startOffset
+ * @param[in]          chunkInfo     chunk information
+ * @param[in]          threadId      thread number
+ * @param[in]          socketId      socket number
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           void
+ */
+
+void buildContChunk(int32 chunkId,uint64 startOffset, int64 *chunkInfo,int32 threadId,
+                 int32 socketId, BlockManager *bmanager);
+/**
+ * @brief                            check for continious chunk in block manager
+ * @param[in]          bmanager      Block Manager Object
+ * @return                           status for continious chunk
+ * @retval             1             continious chunk present
+ * @retval             0             continious chunk not present
+ */
+
+int32 block_manager_isContChunkPresent(BlockManager *bmanager);
+
+int32 get_interface_id(int32 threadId);
+
+#endif /* BLOCKMANAGER_H_ */
+
diff --git a/include/multirat_conf.h b/include/multirat_conf.h
new file mode 100644 (file)
index 0000000..973ed99
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef _MULTIRAT_MAIN__
+#define _MULTIRAT_MAIN__
+
+#include "multirat_SB_http.h"
+
+#define MAX_CONF_VAL_SIZE             (50)
+#define EXPECTED_BYTE                 (524288)
+#define MULTIRAT_BLOCK_DIV            (20)
+#define MULTIRAT_BLOCK_DIV_CON        (10)
+#define MIN_MULTIRAT_BLOCK_SIZE       (1048576)
+#define MIN_MULTIRAT_BLOCK_SIZE_CON   (2*1048576)
+#define MAX_MULTIRAT_BLOCK_SIZE       (5*1024*1024)
+#define SLEEP_TIME                    (100000)
+#define MULTIRAT_UPPER_LIMIT          (5242880)
+#define MULTIRAT_LOWER_LIMIT          (10*1048576)
+#define MULTIRAT_LOWER_LIMIT_TWO_CHUNK (15*1048576)
+#define KEEPALIVE_SUPPORT             0
+#define DEFAULT_INTERFACE             "wlan0"
+#define MAIN_SOCKET_DEFAULT           0  /* Change to 1 if LTE is default */
+#define SPEED_TIMEOUT                 (30)
+#define BLOCK_SIZE_SPEED              (32764)
+#define MIN_SIZE_TO_HANDOVER          (1048576)
+#define MIN_LAST_CHUNK                (3145728)
+#define MIN_DATA_FOR_SPEED            (131072)
+
+#define MAX_JUMP                      (10)
+#define MIN_BLOCK_SIZE                (32768)
+#define MAX_BLOCK_SIZE                (1048576)
+#define MIN_BLOCK_SIZE_SPEED          (4*32768)
+
+#define MULTIRAT_SIZE_THRESHOLD       (30*1048576)
+
+#define MIN_FILE_NODE_SIZE            (20*1048576)/*File thread remain active if filenode>this*/
+#define FILE_THREAD_SOCK_CREATE       1
+#define FILE_THREAD_SOCK_READ         2
+
+#define MULTIRAT_TEMP_THRESHOLD       2
+#define MULTIRAT_CHUNK_SIZE           (20*1048576)
+#define BLOCK_TIME_OUT                (8*1000*1000)
+#define TEMP_TIME_OUT                 (3*1000*1000)
+
+#define LTE_IFACE_NAME                "rmnet0"
+#define WIFI_IFACE_NAME               "wlan0"
+#define LTE                           "lte"
+
+#define WATCH_DOG_CONNECT_TIMEOUT     2
+
+#define USER_OK 1
+#define USER_CANCEL 2
+#define USER_POP_UP 3
+
+/**
+ * @brief                           get intance of multirat configuration
+ * @param[in]                       none
+ * @return                          multirate configuration object
+ */
+struct multirat_configuration* multirat_configuration_get_instance();
+
+/**
+ * @brief                           read the multirate configuartion data
+ * @param[in]                       None
+ * @return
+ * @retval            TRUE          read data Success
+ * @retval            FALSE          read data Failure
+ */
+int multirat_configuration_readdata();
+
+/**
+ * @brief                           get multirat configuartion
+ * @param[in]         data          None
+ * @return                          void
+ * @retval
+ */
+void multirat_configuration_get_configuration(int8 *data);
+
+/**
+ * @brief                           print entry value for multirate configuartion
+ * @param[in]                       void
+ * @return                          void
+ */
+void multirat_configuration_print_entry_value();
+
+/**
+ * @brief                           set the default value for multirate configuartion
+ * @param[in]                       void
+ * @return                          void
+ */
+void multirat_configuration_set_default_value(void);
+
+/**
+ * @brief                           get threshold multirat configuration
+ * @param[in]                       none
+ * @return                          multirate threasold value
+ */
+int32 get_multirat_threshold();
+
+/**
+ * @brief                           get threshold temparature  configuartion
+ * @param[in]                       none
+ * @return                          default temparture
+ */
+int32 get_multirat_temp_threshold();
+
+uint32 lib_init_success(void);
+
+uint32 smartbonding_client_init(void);
+
+#endif
+
+
diff --git a/include/multirat_connection.h b/include/multirat_connection.h
new file mode 100644 (file)
index 0000000..11d29ea
--- /dev/null
@@ -0,0 +1,123 @@
+#ifndef MULTIRAT_CONNECTION_H_
+#define MULTIRAT_CONNECTION_H_
+
+#include "multirat_SB_http.h"
+#include "multirat_watch_dog_thread.h"
+
+enum interfaceName {
+        WIFI_INTERFACE = 0,
+        LTE_INTERFACE,
+        MAX_INTERFACE
+};
+
+
+/**
+ * @brief                              connect to server
+ * @param[in]          threadId        thread number
+ * @param[in]          compRspRcvdFlag response flag
+ * @param[in]          rrthread        range request thread
+ * @return                             socketID
+ * @retval             socketID
+ */
+
+void connect_server(RangeRequestThread *rrthread);
+
+/**
+ * @brief                            connection status of the given
+ *                                   interface
+ * @param[in]          ifr           structure storing interface information
+ * @param[in]          name          name of the interface
+ * @return                           integer indicating connection status
+ * @retval             B_TRUE        if interface is up
+ * @retval             -1            error
+ * @retval             0             error
+ */
+
+int32 connection_interface_status(struct ifreq *ifr, int8 *name);
+
+/**
+ * @brief                            gives the connection status of the interface
+ * @param[in]          ifaceidx      Interface index
+ * @param[in]          name          name of the interface
+  * @param[in]          iptype     ip address type  ipv4 =0 /ipv6 =1
+ * @return                           interface up or not
+ * @retval             B_TRUE        interface is up
+ * @retval             B_FALSE       interface is down
+ */
+
+int32 connection_is_ifaceup(uint32 ifaceidx, interfaceInfo *ifaceInfo, int iptype);
+
+/**
+ * @brief                            connection to the remote address
+ * @param[in]          sockFd        socket FD
+ * @param[in]          remote_addr   remote address after DNS resolution
+ * @param[in]          remote_addr_ip6   remote address after DNS resolution
+ * @param[in]          timeout       time out for connection attempts
+ * @param[in]          SBData        smart bonding handler
+ * @return                           connected to server or not
+ * @retval             -1            error in connection
+ * @retval              0            connected successfully
+ */
+
+int32 connServer (int32 sockFd, struct sockaddr_in *remote_addr,struct sockaddr_in6 *remote_addr_ip6,
+                 uint32 timeout,SmartBondingData *SBData);
+
+/**
+ * @brief                            connection to the remote address
+ * @param[in]          sockFd        socket FD
+ * @param[in]          remote_addr   remote address after DNS resolution
+ * @param[in]          remote_addr_ip6   remote address after DNS resolution
+ * @param[in]          timeout       time out for connection attempts
+ * @param[in]          SBData        smart bonding handler
+ * @return                           connected to server or not
+ * @retval             -1            error in connection
+ * @retval              0            connected successfully
+ */
+
+int32 file_thread_connServer (int32 sockFd, struct sockaddr_in *remote_addr,struct sockaddr_in6 *remote_addr_ip6,
+               uint32 timeout,  SmartBondingData *SBData);
+
+
+
+uint32 is_both_interface_avail(interfaceInfo *ifaceInfo,int iptype);
+
+/**
+ * @brief                            to check if interface is up
+ * @param[in]          ifacename     interface name
+ * @param[in]          ifaceinfo     interface information
+ * @return                           interfae available or not
+ * @retval             B_TRUE        interface available
+ * @retval             B_FALSE       interface not available
+ */
+
+uint32 is_interface_up(int8* ifacename, interfaceInfo *ifaceinfo,int iptype);
+
+/**
+ * @brief                            bind to the address given as param
+ * @param[in]          ip            ip address to bind
+ * @return                           socket FD if successful
+ * @retval             socketFD      socket fd if bind successful
+ * @retval            -2             bind failed
+ */
+
+int32 conn_get_socket_bind(int8 *ip, int ifaceidx, int iptype);
+/**
+ * @brief                           poll in the given socket and timeout
+ * @param[in]          socketId     socketID where polling should happen
+ * @param[in]          timeout      polling timeout
+ * @return                          return values from poll function
+ * @retval             -1           socket error
+ * @retval             0            socket time out
+ * @retval             1            polling done successfully
+ */
+
+int32 conn_poll(int32 socketId, uint32 timeout);
+int32 watchdog_conn_poll(int32 socket, SmartBondingData *SBData);
+void file_thread_connect_server(fileThread *fThread);
+int32 file_thread_conn_poll(int32 socket, SmartBondingData *SBData);
+void PollThread_poll(int32 socket, SmartBondingData *SBData, uint32 timeout_check);
+void lib_conn_poll(int32 socket, SmartBondingData *SBData);
+int32 read_conn_poll(int32 socket, SmartBondingData *SBData);
+int32 get_connection_status(SmartBondingData *SBData);
+
+#endif
diff --git a/include/multirat_data_buffer.h b/include/multirat_data_buffer.h
new file mode 100644 (file)
index 0000000..fe7ae76
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef DATABUFFER_H_
+#define DATABUFFER_H_
+
+#include "multirat_SB_http.h"
+
+#define DATA_BUFFER_GET_STATE(a)        ((a)->state)
+#define DATA_BUFFER_SET_STATE(a, b)     ((b)->state = a)
+#define DATA_BUFFER_GET_BUFFER(a)       ((a)->data + a->offset)
+#define DATA_BUFFER_GET_TOTAL_LEN(a)    ((a)->totalLen)
+#define DATA_BUFFER_GET_READ_RES_LEN(a) ((a)->appReadLen)
+#define DATA_BUFFER_GET_RES_BYTES(a)    ((a)->offset - (a)->appReadLen)
+#define DATA_BUFFER_GET_OFFSET(a)       ((a)->offset)
+#define DATA_BUFFER_GET_EST_SPEED(a)    ((a)->estSpeed)
+#define DATA_BUFFER_GET_THREAD_ID(a)    ((a)->threadId)
+
+/**
+ * @brief                           initialize the data buffer
+ * @param[in]          dbuffer      data buffer
+ * @return                          void
+ * @retval                          none
+ */
+void data_buffer_init(DataBuffer *dbuffer, uint32 noOfChunks, uint64 cthread);
+/**
+ * @brief                           free the memeory for buffer
+ * @param[in]          dbuffer      data buffer
+ * @return                          void
+ */
+
+void data_buffer_freeBuffer(DataBuffer *dbuffer);
+
+/**
+ * @brief                           reads the response from this buffer and
+ *                                  increase the appReadLen
+ * @param[in]         buff          application buffer
+ * @param[in]         size          size of application buffer
+ * @param[in]         dbuffer       data buffer
+ * @return                          number of bytes read from this buffer
+ */
+
+void data_buffer_read_portion(int8 *buff, uint32 size, DataBuffer *dbuffer);
+
+/**
+ * @brief                           add the response to this data buffer
+ * @param[in]          size         size of the response buffer
+ * @param[in]          threadId     threadID from which data is to be added
+ * @param[in]          dbuffer      data buffer
+ * @return                          bytes written into this data buffer
+ */
+
+void data_buffer_add(uint32 size, int32 threadId, int8 *buff, DataBuffer *dbuffer);
+
+/**
+ * @brief                           called when current data buffer is to be
+ *                                  handed over to other thread
+ * @param[in]          threadId     thread ID to from which data is to be added
+ * @param[in]          thisSpeed    other thread speed
+ * @param[in]          dbuffer      data buffer
+ * @return                          void
+ */
+
+void data_buffer_switch_socket(int32 threadId, uint32 thisSpeed,DataBuffer *dbuffer);
+/**
+ * @brief                           initialize data buffer and changes the state
+ * @param[in]          threadId     thread ID to which  data buffer is assigned
+ * @param[in]          size         total size of this data buffer
+ * @param[in]          socketId     socket ID
+ * @param[in]          dbuffer      data buffer
+ * @return                          void
+ */
+
+void data_buffer_init_chunk(int32 threadId, uint32 size, int32 socketId, DataBuffer *dbuffer, int64 *chunkInfo);
+
+/**
+ * @brief                           resets the threadId and changes the state
+ * @param[in]          threadId     threadID to which data buffer is assigned
+ * @param[in]          socketId     socket ID
+ * @param[in]          dbuffer      data buffer
+ * @return                          void
+ */
+
+void data_buffer_reinit_chunk(int32 threadId,int32 socketId, DataBuffer *dbuffer);
+/**
+ * @brief                           destroy the mutex and frees the data buffer
+ * @param[in]          dbuffer      data buffer
+ * @return                          void
+ */
+
+void data_buffer_exit(DataBuffer *dbuffer);
+
+#endif
+
diff --git a/include/multirat_decode_http.h b/include/multirat_decode_http.h
new file mode 100644 (file)
index 0000000..33d92f6
--- /dev/null
@@ -0,0 +1,133 @@
+#ifndef DECODEHTTP_H_
+#define DECODEHTTP_H_
+
+#include "multirat_SB_http.h"
+
+#define MEM_ALLOC(buff,size) \
+        buff = (char*)malloc(size);\
+if(NULL == buff) \
+{\
+        return -1;\
+}\
+memset(buff,0,size);\
+
+#define MEM_ALLOC_RET(buff,size) \
+        buff = (char*)malloc(size);\
+if(NULL == buff) \
+{\
+        return;\
+}\
+memset(buff,0,size);\
+
+#define DECODE_HTTP_RSP_GET_CONT_LEN(a) a->contLen
+#define DECODE_HTTP_RSP_GET_RSP_CODE(a) a->rspcode
+#define DECODE_HTTP_RSP_GET_CONT_RNG(a) a->contRange
+#define DECODE_HTTP_RSP_GET_CONNECTION(a) a->connection
+
+/**
+ * @brief                           initialize HTTP response headers
+ * @param[in]         rspHeaders    Response headers
+ * @param[in]         len           Length of the response headers
+ * @param[in]         dhrsp         structure to store the response
+ * @return                          void
+ * @retval                          none
+ * @retval                          none
+ */
+void decode_http_rsp_init(int8 *rspHeaders, uint32 len, httpResp *dhrsp);
+
+
+/**
+ * @brief                           returns complete response Length in content Range header
+ * @param[in]         contRange     content range
+ * @retval                          pointer to content range header value
+ * @retval
+ * @retval
+ */
+uint64 decode_http_rsp_get_cont_rnglen(int8 *contRange);
+
+/**
+ * @brief                           finds the str string in buf pointer
+ * @param[in]           buff        buffer containing string
+ * @param[in]           str         string to be found
+ * @return                          offset of str if found
+ * @retval
+ * @retval              -1          not found
+ */
+int32 decode_http_find_str(int8 *buff, const char *str);
+
+/**
+ * @brief                            get the value of HTTP Request header
+ * @param[in]           pBuffer      buffer containing HTTP response header
+ * @param[in]           pHeaderVal   Pointer for storing HTTP response header value
+ * @param[in]           offset       offset of HTTP response header value
+ * @return                           success or failure
+ * @retval              0            success
+ * @retval              -1           failure
+ */
+int32 decode_http_getvalue(int8 *pBuffer, int8 **pHeaderVal, uint32 offset);
+
+/**
+ * @brief                           removes the spaces from header value
+ * @param[in]           pBuffer     buffer containing HTTP response header value
+ * @param[in]           pHeaderVal  Pointer for storing HTTP response header value
+ * @return                         void
+ */
+void decode_http_trim(int8 *pBuffer, int8 **pHeaderVal);
+
+/**
+ * @brief                           decodes the HTTP request line and stores
+ *                                  in psHttpReq strcuture
+ * @param[in]           psHttpReq   decoded HTTP request
+ * @param[in]           req         buffer contaning HTTP request
+ * @return
+ * @retval              0           success
+ * @retval              -1          failure
+ */
+int32 decode_req_line(httpReq *psHttpReq, int8 *req);
+
+/**
+ * @brief                           decodes the HTTP Request headers
+ * @param[in]           psHttpReq   decoded HTTP request
+ * @param[in]           headReq     buffer pointing to the HTTP request headers
+ * @return
+ * @retval
+ * @retval
+ */
+int32 decode_headers(httpReq *psHttpReq, int8 *headReq);
+
+/**
+ * @brief                           decodes http request
+ * @param[in]           psHttpReq   decoded HTTP Request
+ * @param[in]           req         http request
+ * @param[in]           reqLen      http request length
+ * @return                          decode status
+ * @retval              -2          decode failure
+ * @retval              0           decode success
+ */
+int32 decode_http_req(httpReq *psHttpReq);
+
+/**
+ * @brief                           process the http response
+ * @param[in]           resp        structure storing http response
+ * @return
+ * @retval              -1          http response decoding error
+ * @retval              0           htt response decoding success
+ */
+int32 process_http_rsp(httpResp *resp);
+
+/**
+ * @brief                           delete http request
+ * @param[in]           SBData      Smartbonding data
+ * @return                          void
+ */
+void delete_http_req(httpReq *req);
+
+/**
+ * @brief                           delete http response
+ * @param[in]          SBData       Smartbonding data
+ * @return                          void
+ */
+void delete_http_rsp(httpResp *resp);
+
+#endif /* DECODEHTTPRSP_H_ */
+
diff --git a/include/multirat_file_buffer.h b/include/multirat_file_buffer.h
new file mode 100644 (file)
index 0000000..9063464
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef FILEBUFFER_H_
+#define FILEBUFFER_H_
+
+#include "multirat_SB_http.h"
+
+void file_buffer_init(fileBuffer *fbuffer, uint32 brafMode);
+
+void file_buffer_exit(fileBuffer *fbuffer);
+
+void file_buffer_init_node(fileBuffer *fbuffer, int64 *chunkInfo, int32 socketId, uint32 nodeType, SmartBondingData *SBData, uint32 fThread_read);
+
+void file_buffer_reinit_node(fileBuffer *fbuffer, uint32 socket, uint32 nodeType);
+
+void file_buffer_add(fileBuffer *fbuffer, int8 *buff, uint64 size,int64 *chunkInfo, uint64 rcvdRsp, SmartBondingData *SBData);
+
+void file_buffer_read_from_file(fileBuffer *fbuffer, int8 *buff, uint64 *size);
+
+void  file_buffer_read_from_socket(fileBuffer *fbuffer, uint32 size);
+
+uint32 file_buffer_getState(fileBuffer *fbuffer);
+
+uint64 file_buffer_noOfRspBytes(fileBuffer *fbuffer);
+
+uint64 file_buffer_getTotalLen(fileBuffer *fbuffer);
+
+uint64 file_buffer_getStrtOffset(fileBuffer *fbuffer);
+
+uint64 file_buffer_getEndOffset(fileBuffer *fbuffer);
+
+uint64 file_buffer_getOffset(fileBuffer *fbuffer);
+
+uint32 file_buffer_getSocketId(fileBuffer *fbuffer);
+
+uint32 file_buffer_getNodeType(fileBuffer *fbuffer);
+
+uint32 file_buffer_getType(fileBuffer *fbuffer);
+
+void file_buffer_setTotalLen(int newLen, fileBuffer *fbuffer);
+
+uint64 file_buffer_getReadRspLen(fileBuffer *fbuffer);
+
+int8* file_buffer_getFile(fileBuffer *fbuffer);
+
+void check_set_filebuff_state(fileBuffer *tempBuff);
+#endif
+
diff --git a/include/multirat_file_manager.h b/include/multirat_file_manager.h
new file mode 100644 (file)
index 0000000..4684909
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef FILEMANAGER_H_
+#define FILEMANAGER_H_
+
+#include "multirat_SB_http.h"
+
+void file_manager_init(fileStream *fStream, fileManager *fileMgr);
+
+fileBuffer *file_manager_getNextChunkForFileThread(int64 *chunkInfo, SmartBondingData *SBData);
+
+fileBuffer *file_manager_getDownloadingNode(fileManager *fileMgr);
+
+fileBuffer *file_manager_getDownloadingFileNode(fileManager *fileMgr);
+
+void file_manager_setSpeed(uint32 index, uint32 speed, SmartBondingData *SBData);
+
+void file_manager_exit(fileManager *fileMgr);
+
+fileBuffer *file_manager_getReadingNode(fileManager *fileMgr);
+
+uint32 file_manager_get_file_thread_interface(fileManager *fileMgr);
+
+uint32 file_manager_get_main_thread_interface(fileManager *fileMgr);
+
+uint32 file_manager_check_main_thread_status(fileManager *fileMgr);
+
+fileBuffer *file_manager_getNextChunkForFileThread_new(int64 *chunkInfo, SmartBondingData *SBData, uint32 index);
+
+uint32 file_manager_divideCont(uint64 remCont, int64 *contInfo, fileManager *fileMgr, uint32 nodeType);
+
+uint32 file_manager_divideRemCont(uint64 remCont, fileManager *fileMgr, uint32 nodeType);
+
+fileBuffer * file_manager_get_next_chunk_handle_file_io_exception(fileManager *fileMgr, int64 *chunkInfo);
+
+fileBuffer * file_manager_get_next_chunk_handle_main_complete(fileManager *fileMgr, int64 *chunkInfo);
+
+fileBuffer * file_manager_get_next_chunk_handle_file_complete(fileManager *fileMgr, int64 *chunkInfo);
+
+void file_manager_update_socket_node(uint64 offset, SmartBondingData *SBData);
+
+void file_manager_SwitchSocketNoData(fileBuffer *tempBuff, fileManager *fileMgr);
+
+fileBuffer *file_manager_SwitchSocketData(fileBuffer *tempBuff, fileManager *fileMgr, int64 *chunkInfo, int ifacechange);
+
+uint32 file_manager_file_node_block_handle(SmartBondingData *SBData);
+#endif /* FILEMANAGER_H_ */
+
diff --git a/include/multirat_file_stream.h b/include/multirat_file_stream.h
new file mode 100644 (file)
index 0000000..2b9ccc5
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef FILESTREAM_H_
+#define FILESTREAM_H_
+
+void file_stream_init(SmartBondingData *SBData);
+
+uint32 file_stream_start(SmartBondingData *SBData);
+
+int32 file_stream_read(int8 *buff, int32 maxAppLen, SmartBondingData *SBData, int32 *my_nread);
+
+void file_stream_exit(fileStream *fStream);
+
+int32 file_stream_read_from_socket(int32 socket, int8 *buff, uint64 toBeRead, int32 *tempLen, SmartBondingData *SBData, uint32 index);
+
+void is_file_stream_read(SmartBondingData *SBData);
+
+void PollThread_poll_buffer(SmartBondingData *SBData);
+#endif /* FILESTREAM_H_ */
diff --git a/include/multirat_file_thread.h b/include/multirat_file_thread.h
new file mode 100644 (file)
index 0000000..3c0ef3e
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef FILETHREAD_H_
+#define FILETHREAD_H_
+
+#include <pthread.h>
+
+void file_thread_init(fileThread *fThread, SmartBondingData *SBData, fileStream *fStream);
+
+uint32 file_thread_start(fileThread *fThread);
+
+void *FileThreadCallBack(void *ptr);
+
+void file_thread_run(fileThread *fThread);
+
+int32 file_thread_range_request_recv_rng_rsp_headers(uint64 *bodyLen, char *blockSize,
+                              uint64 currChunkLen, uint32 *connClose, fileThread *fThread);
+
+int32 file_thread_rebuildReq(char *newRequest, int64 *chunkInfo, fileThread *fThread);
+
+void file_thread_exit(fileThread *fThread);
+
+int file_thread_handleIOExp(fileThread *fThread, uint32 *ifCount ,int32 iptype);
+
+int file_thread_connet_server_interface(fileThread *fThread);
+
+int file_thread_connect_server_interface_first(int32 result, fileThread *fThread);
+
+int32 file_thread_range_request_recv_rng_rsp_headers_first_req(uint64 *bodyLen, char *blockSize, uint64 currChunkLen, uint32 *connClose, fileThread *fThread, int8 *rcvBuff, int32 lengthRcvd);
+#endif /* FILETHREAD_H_ */
+
diff --git a/include/multirat_libapi.h b/include/multirat_libapi.h
new file mode 100644 (file)
index 0000000..a9b1dd1
--- /dev/null
@@ -0,0 +1,273 @@
+#ifndef _MULTIRAT_LIBAPI_H
+#define _MULTIRAT_LIBAPI_H
+#include <pthread.h>
+#include "multirat_SB_http.h"
+
+#define SB_OK                                         -2
+#define SB_WOULD_BLOCK                                -3
+#define SB_ERR                                        -4
+#define SB_EOF                                        -5
+#define SB_TIMEOUT                                    -6
+
+#define CONNECTION_SUCCESS 1
+#define CONNECTION_FAIL 0
+#define CONNECTION_WAIT 2
+
+
+#define MSG_POLL_THREAD_START_SOCK                     "SOCKET_POLL_START"
+#define LEN_MSG_POLL_THREAD_START_SOCK                 17
+#define MSG_POLL_THREAD_START_BUFF                     "BUFFER_POLL_START"
+#define LEN_MSG_POLL_THREAD_START_BUFF                 17
+#define MSG_POLL_THREAD_START_EXCEPTION                "EXCEPTION_POLL_START"
+#define LEN_MSG_POLL_THREAD_START_EXCEPTION            20
+#define MSG_POLL_THREAD_END                            "POLL_END"
+#define LEN_MSG_POLL_THREAD_END                        8
+#define RECV_BUFF_SIZE                                 20
+#define POLL_TIME_OUT_MILLISEC                         100
+#define END_OF_HEADER                                  "\r\n\r\n"
+
+struct SmartBondingHandler
+{
+        /* Session Identifier for SB Library */
+        SmartBondingData *SBData;
+        /* Session Identifier for HTTP Library used for callbacks and closing */
+        void *LibSessionIdentifier;
+        pthread_mutex_t *lock; /* Mutex Lock for sb_read_data and sb_session_close */
+};
+
+/**
+ * @brief                                    Library api to get chunk stored currently in RAF
+ * @param[in]           SBHandler            struct SmartBondingHandler
+ * @param[in]           buffer               currenly written files startOffset-EndOffset
+ * @param[in]           len                  length of buffer
+ * @return              1
+ * @return              0
+*/
+
+uint32 sb_get_cached_chunk(struct SmartBondingHandler *SBHandler, int8* buffer, uint32 len);
+
+/**
+ * @brief                                    Library api to set RAF file name
+ * @param[in]           SBHandler            struct SmartBondingHandler
+ * @param[in]           buffer               file name of RAF
+ * @param[in]           len                  length of file name
+ * @return              1                                       file name set
+ * @return              0                    file name setting failed
+*/
+
+uint32 sb_set_direct_filename(struct SmartBondingHandler *SBHandler, int8 *buffer, uint32 len);
+
+
+/**
+ * @brief                                    Library api to set RAF mode
+ * @param[in]           SBHandler            struct SmartBondingHandler
+ * @return              void
+*/
+
+void sb_set_direct_write_mode(struct SmartBondingHandler *SBHandler);
+
+/**
+ * @brief                                    Library api to send request to server,
+ checks for multirat condition and enables multirat
+ * @param[in]    http_req                    req to be sent to http server
+ * @param[in]    timeout                     timeout to connect server
+ * @param[in]    remote_info                 destinatopn server address
+ * @param[in]    LibraryCallbackFunction     Lib API callback function
+ * @param[in]    LibSessionIdentifier
+ * @return       struct SmartBondingHandler  SBHandler
+ */
+
+struct SmartBondingHandler *sb_request_send(int8 *http_req, uint32 timeout,
+                 struct sockaddr_storage *remote_info, void (*LibraryCallbackFunction)(void *),
+                 void *LibSessionIdentifier);
+
+/**
+ * @brief                                    Library api to send request to server,
+ checks for multirat condition and enables multirat in sync case
+ * @param[in]    http_req                    req to be sent to http server
+ * @param[in]    timeout                     timeout to connect server
+ * @param[in]    remote_info                 destination server address
+ * @return       SmartBondingHandler  SBHandler
+ */
+
+struct SmartBondingHandler *sb_request_send_sync(int8 *http_req, uint32 timeout,
+                 struct sockaddr_storage *remote_info);
+
+/**
+ * @brief                                    Library api to send request to server,
+ checks for multirat condition and enables multirat in curl case
+ * @param[in]    http_req                    req to be sent to http server
+ * @param[in]    timeout                     timeout to connect server
+ * @param[in]    remote_info                 destination server address
+ * @return       struct SmartBondingHandler  SBHandler
+ */
+struct SmartBondingHandler *sb_request_send_curl(int8 *http_req, uint32 timeout,
+                 struct sockaddr_storage *remote_info);
+
+
+/**
+ * @brief                                    Library api call to read response from server
+ * @param[in]           SBHandler            struct SmartBondingHandler
+ * @param[in]           buffer               buffer is used to store response
+ * @param[in]           size                 length of buffer to be read
+ * @param[in]           nread                length of response read
+ * @retval              SB_ERR               returns error in error case
+ * @retval              SB_WOULD_BLOCK       if need to wait to read data
+ * @retval              SB_OK                if data is read successfully
+ * @retval              SB_EOF               if complete data is read
+ */
+int32 sb_read_data(struct SmartBondingHandler *SBHandler, int8 *buffer, uint32 size, int32 *nread);
+
+
+/**
+ * @brief                                    Library api to close the session
+ * @param[in]           SBHandler            struct SmartBondingHandler
+ * @return              true or false
+ * @retval              0                    if SBHandler is NULL
+ * @retval              1                    if successfully session is closed
+ */
+int32 sb_session_close(struct SmartBondingHandler *SBHandler);
+
+
+/**
+ * @brief                                    Initializes SmartBondingHandler structure
+ * @param[in]
+ * @return              SmartBondingHandler
+ */
+struct SmartBondingHandler *smart_bonding_handler_init(void);
+
+
+/**
+ * @brief                                    Deinitializes SmartBondingHandler and
+ SmbSessionIdentifier structure
+ * @param[in]           SBHandler
+ * @return              void
+ */
+void smart_bonding_handler_exit(struct SmartBondingHandler *SBHandler);
+
+
+/**
+ * @brief                                    Deinitializes SmbSessionIdentifier
+ structure
+ * @param[in]           SBSessionIdentifier
+ * @return              void
+ */
+void smart_bonding_session_identifier_exit(SmartBondingData *SBData);
+
+
+/**
+ * @brief                                    poll thread which calls pollthread_run
+ * @param[in]           SBHandler
+ * @return              void
+ */
+void * poll_thread_call_back(void *pArg);
+
+
+/**
+ * @brief                                    poll thread to poll on socket or
+ on common buffer to check for data
+ * @param[in]           SBHandler
+ * @return              void
+ */
+void pollthread_run(SmartBondingData *SBData);
+
+
+/**
+ * @brief                                    reads data from server
+ * @param[in]           socket_fd            socket fd
+ * @param[in]           buffer               buffer to store response
+ * @param[in]           size                 size of buffer
+ * @param[in]           my_nread             length of response received
+ * @param[in]           SBSessionIdentifier  SB Session Identifier
+ * @retval              SB_ERR               returns error in error case
+ * @retval              SB_WOULD_BLOCK       if need to wait to read data
+ * @retval              SB_OK                if data is read successfully
+ * @retval              SB_EOF               if complete data is read
+ */
+int32 read_from_socket_async(int8 *buffer, uint32 size , int32 *my_nread, SmartBondingData *SBData);
+
+
+/**
+ * @brief                                     reads data from server in sync case
+ * @param[in]           socket_fd             socket fd
+ * @param[in]           buffer                buffer to store response
+ * @param[in]           size                  size of buffer
+ * @param[in]           my_nread              length of response received
+ * @param[in]           SBSessionIdentifier   SB Session Identifier
+ * @retval              SB_ERR                returns error in error case
+ * @retval              SB_WOULD_BLOCK        if need to wait to read data
+ * @retval              SB_OK                 if data is read successfully
+ * @retval              SB_EOF                if complete data is read
+ */
+int32 read_from_socket_sync(int8 *buffer, uint32 size , int32 *my_nread, SmartBondingData *SBData);
+
+
+/**
+ * @brief                                     reads data from server in curl case
+ * @param[in]           socket_fd             socket fd
+ * @param[in]           buffer                buffer to store response
+ * @param[in]           size                  size of buffer
+ * @param[in]           my_nread              length of response received
+ * @retval              SB_ERR                returns error in error case
+ * @retval              SB_WOULD_BLOCK        if need to wait to read data
+ * @retval              SB_OK                 if data is read successfully
+ * @retval              SB_EOF                if complete data is read
+ */
+int32 read_from_socket_curl(int8 *buffer, uint32 size ,int32 *my_nread, SmartBondingData *SBData);
+
+
+/**
+ * @brief                                     check if multiple interfaces are available,
+ and send range request to server
+ * @param[in]           SBSessionIdentifier
+ * @retval              0                     on failure
+ * @retval              1                     on success
+ */
+int32 checkinterface_connect(SmartBondingData *SBData);
+
+
+/**
+ * @brief                                     Check whether server supports Range headers,
+ and get request without range header
+ * @param[in]           SBSessionIdentifier
+ */
+void main_socket_go_for_exception(SmartBondingData *SBData);
+
+
+/**
+ * @brief                                     Receives request from Library API call,
+ initializes all required structures and send request to server
+ * @param[in]           http_req              http request received from client
+ * @param[in]           timeout               timeout to connect to the server
+ * @param[in]           remote_info           remote server details like ip and port
+ * @retval              SmartBondingHandler
+ */
+struct SmartBondingHandler *send_request(int8 *http_req, uint32 timeout, struct sockaddr_storage *remote_info);
+
+/**
+ * @brief                                       Handles creation of poll thread, and
+ setting callback functions in async case
+ * @param[in]           SBHandler               Library Handler
+ * @param[in]           LibraryCallbackFunction Lib callback function
+ * @param[in]           LibSessionIdentifier    Lib Session callback function
+ * @return              true or false
+ * @retval              1                       on failure
+ * @retval              0                       on success
+ */
+
+int32 sb_init_async(struct SmartBondingHandler *SBHandler,
+                 void (*LibraryCallbackFunction)(void *), void *LibSessionIdentifier);
+void get_client_socket(SmartBondingData *SBData, uint32 timeout, struct sockaddr_in *serv_addr,struct sockaddr_in6 *serv_addr_ip6);
+int32 read_from_socket(SmartBondingData *SBData,int8 *buffer, int32 size, int32 *my_nread);
+int32 handleMainSocExp(SmartBondingData *SBData, int8 *buffer, uint32 size, int32 *my_nread);
+
+
+int32 sb_request_send_only_curl(struct SmartBondingHandler * SBHandler, int8 *http_req, uint32 len);
+struct SmartBondingHandler *curl_connect_request(uint32 timeout, struct sockaddr_storage *remote_info);
+struct SmartBondingHandler *sb_request_connect_only_curl(uint32 timeout, struct sockaddr_storage *remote_info);
+int32 sb_get_connection_status(struct SmartBondingHandler *SBHandler);
+
+int32 twoChunk_read_from_socket(SmartBondingData *SBData,int8 *buffer, int32 size, int32 *my_nread);
+
+
+#endif
diff --git a/include/multirat_multisocket.h b/include/multirat_multisocket.h
new file mode 100644 (file)
index 0000000..e98f2ba
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef MULTISOCKET_H_
+#define MULTISOCKET_H_
+
+#include "multirat_SB_http.h"
+
+/**
+ * @brief                            multisocket initialization
+ * @param[in]           objmsInput   multisocket object input
+ * @param[in]           objConn      objectConnection
+ * @param[in]           SBData       SmartBonding Data
+ * @retval                           void
+ */
+void multisocket_init(MultiSockInput *mSockInput, SmartBondingData *SBData);
+
+/**
+ * @brief                           start multi socket thread
+ * @param[in]           msocket     multisocket object
+ * @return                     status if multisocket has started
+ * @retval              0           multisocket has started
+ * @retval              1           multisocket has not started
+ */
+
+uint32 multisocket_start(SmartBondingData *SBData);
+
+/**
+ * @brief                            read from multi_socket
+ * @param[in]           appBuff      application buffer
+ * @param[in]           maxAppLen    max application bufferlength
+ * @param[in]           msocket      multisocket object
+ * @return                      length of response read
+ */
+
+int32 multisocket_read(int8 *appBuff,uint32 maxAppLen, SmartBondingData *SBData);
+
+/**
+ * @brief                           read from multisocket during sync operation
+ * @param[in]           appBuff     application buffer
+ * @param[in]           maxAppLen   max application buffer length
+ * @param[in]           msocket     multisocket object
+ * @return                          length of response read
+ */
+
+int32 multisocket_read_sync(int8 *appBuff, uint32 maxAppLen, SmartBondingData *SBData);
+
+/**
+ * @brief                            exitfrom multisocket
+ * @param[in]           msocket      multisocket object
+ * @return                               void
+ */
+void multisocket_exit(MultiSocket *msocket);
+/**
+ * @brief                            get first range request from multisocket
+ * @param[in]           msocket      multisocket object
+ * @return                           first response status
+ * @retval              -2           first response status pending
+ * @retval              -1           first response status failed
+ * @retval              0            first response status success
+ */
+int32 multisocket_get_firstrange_status(MultiSocket *msocket);
+
+int32 read_from_buffer(SmartBondingData *SBData,int8 *buffer, uint32 size, int32 *my_nread);
+
+uint32 is_multirat_read(SmartBondingData *SBData);
+#endif /* MULTISOCKET_H_ */
+
diff --git a/include/multirat_poll_thread.h b/include/multirat_poll_thread.h
new file mode 100644 (file)
index 0000000..9de8172
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _POLL_THREAD_H_
+#define _POLL_THREAD_H_
+
+PollThread* PollThread_init();
+void PollThread_start(SmartBondingData *SBData);
+void *PollThread_entry_function(void *pArg);
+void PollThread_exit(PollThread *PollThrd);
+void PollThread_run_thread(SmartBondingData *SBData);
+
+#endif
diff --git a/include/multirat_process.h b/include/multirat_process.h
new file mode 100644 (file)
index 0000000..021ff29
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef MULTIPROCESS_H_
+#define MULTIPROCESS_H_
+
+#include "multirat_SB_http.h"
+#include "multirat_decode_http.h"
+#include "multirat_range_request_thread.h"
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+/**
+ * @brief                           validate and store http response
+ * @param[in]         rsp           response buffer
+ * @param[in]         headers_len   header length
+ * @param[in]         SBData        smartbonding Data
+ * @return                          void
+ */
+void store_check_http_response(SmartBondingData *SBData);
+
+/**
+ * @brief                           store and process http request
+ * @param[in]           req         request buffer
+ * @param[in]           SBData      smart bonding data object
+ * @return                          void
+ */
+void store_http_request(int8*req, SmartBondingData *SBData);
+
+/**
+ * @brief                           multirat enbaling function
+ * @param[in]         SBData        smart bonding object
+ * @return                          status indicating if multirat is enabled
+ * @retval            1             multirat enabled
+ * @retval            0             multirat not enabled
+ */
+uint32 should_enable_multirat(SmartBondingData *SBData);
+
+/**
+ * @brief                           deallocating memory while exiting from SB
+ * @param[in]         SBData        SmartBondingData
+ * @return                          void
+ */
+void smart_bonding_exit(SmartBondingData *SBData);
+
+/**
+ * @brief                           gives smartbonding object size
+ * @param[in]           SBData      smartbondoing object size
+ * @return                          void
+ */
+void get_object_size(httpResp *resp);
+
+/**
+ * @brief                           gives time in micro seconds
+ * @param[in]                       void
+ * @return                          time in microsec
+ */
+uint64 get_time_in_microsec();
+
+/**
+ * @brief                           get time in seconds
+ * @param[in]         SBData        smart bonding data
+ * @return                          time in seconds
+ */
+uint64 get_time_in_sec();
+
+/**
+ * @brief                           get the temperature level
+ * @param[in]                       void
+ * @return                          temeparure
+ * @retval              0           temparature below threshold
+ * @retval              1           temperature level above threshold
+ */
+int getTempLevel(SmartBondingData *SBData);
+
+/**
+ * @brief                           get serial input output level from dbus
+ * @param[in]                       void
+ * @return                          serial input output level
+ * @retval              -1          error
+ */
+int get_siop_level(void);
+
+/**
+ * @brief                                     Checks whether multirat can be enabled and start watch dog thread
+ * @param[in]           SBSessionIdentifier   session identifier
+ * @param[in]           buffer                received response from server
+ * @param[in]           my_nread              length of response received from server
+ */
+void start_watchdog(SmartBondingData *SBData, int8 *buffer, int32 my_nread);
+
+/**
+ * @brief                                     Adds range header to request recieved from client,
+ and sets length for new req
+ * @param[in]           req                   request received from client
+ * @param[in]           rangeStart            range start
+ * @param[in]           bytesRead             offset
+ * @param[in]           rangeEnd              range end
+ * @param[in]           length                length of new request
+ * @return              newRequest            newRequest with Range Header
+ */
+
+int8 *get_new_req(int8 *req, uint64 rangeStart, uint64 bytesRead, uint64 rangeEnd, uint32 *length, uint32 len, int32 proxy);
+
+
+/**
+ * @brief                                     Handles connection with server,
+ and sends request to server
+ * @param[in]           req                   HTTP req to be sent to server
+ * @param[in]           reqLen                length of req to be sent
+ * @param[in]           socket                socket fd
+ * @param[in]           SBData                to access ip, port and timeout
+ * @retval              -1                    on connect error
+ * @retval               0                    on success
+ */
+int32 send_req(int8 *req, uint32 reqLen,int32 socket, uint32 index, SmartBondingData *SBData);
+
+void reset_stats(StatDetails *stat);
+void getHost(char **host, char *reqHeaders);
+int getDNSInfo(char *host, int iface, SmartBondingData *SBData);
+int handleRedirection(char *location,  uint32 iface, char **reqHeaders, uint32 *headerLen, SmartBondingData *SBData);
+char *getNewRedirectReq(char *host,char *url, char *reqHeaders);
+void decodeLocation(char *loc,char **host,char **url);
+uint32 store_interface_ip_request(char *newReq, SmartBondingData *SBData, uint32 interface_index);
+#endif
diff --git a/include/multirat_range_request_thread.h b/include/multirat_range_request_thread.h
new file mode 100644 (file)
index 0000000..b12fbad
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef RANGEREQUESTTHREAD_H_
+#define RANGEREQUESTTHREAD_H_
+
+#include <pthread.h>
+
+#define CHUNK_INFO_SIZE                         3
+#define MAX_HEADERS_SIZE                        2048
+#define MAX_RANGE_FIELD_LEN                     100
+
+#define FIRST_RSP_STATUS_SUCCESS                0
+#define FIRST_RSP_STATUS_PENDING                -2
+#define FIRST_RSP_STATUS_FAILED                 -1
+
+#define RANGE_REQUEST_THREAD_GET_FIRST_RANGE_STATUS(a) ((a)->firstRngStatus)
+
+/**
+ * @brief                            initialization of range request thread
+ * @param[in]           rrthread     range request thread
+ * @param[in]           threadData   threadData object
+ * @return                           void
+ */
+
+void range_request_thread_init(RangeRequestThread *rrthread, SmartBondingData *SBData);
+
+/**
+ * @brief                           start the range request thread
+ * @param[in]           rrthread    range request thread object
+ * @return                          status if thread is started
+ * @retval              1           range request thread created
+ * @retval              0           error creating range request thread
+ */
+
+uint32 range_request_thread_start(RangeRequestThread *rrthread);
+
+/**
+ * @brief                           callback function while creating rr thread
+ * @param[in]           pArg        arguments passed in callback function
+ * @return                          NULL
+ */
+
+void *range_request_thread_rngreq_thread_callback(void *pArg);
+
+/**
+ * @brief                           range request thread run
+ * @param[in]           rrthread    range request thread object
+ * @return                          void
+ */
+
+void range_request_thread_run(RangeRequestThread *rrthread);
+
+/**
+ * @brief                           range_request_thread_reconnect
+ * @param[in]           newRequest  object to store new request
+ * @param[in]           chunkInfo   chunk information
+ * @param[in]           rrthread    range request thread
+ * @return                          range length and header length
+ */
+
+uint32 range_request_thread_rebuild_req(int8 *newRequest, int64 *chunkInfo,
+                 RangeRequestThread *rrthread);
+
+/**
+ * @brief                           exit the range request thread
+ * @param[in]           rrthread    range request thread object
+ * @return                          void
+ */
+
+void range_request_thread_exit(RangeRequestThread *rrthread);
+
+/**
+ * @brief                           process range request response headers
+ * @param[in]           socket_fd   socket file_descriptor
+ * @param[in]           size        size
+ * @param[in]           timeout     timeout for socket polling
+ * @param[in]           instanceSize size of response instance
+ * @param[in]           currChunkLen currChunkLen
+ * @param[in]           bodylen     response body length
+ * @param[in]           blocksize   blocksize
+ * @param[in]           respLen     length of response
+ * @return                          response decode status
+ * @retval              0           http response decoding success
+ * @retval              -1          http response decoding error
+ * @retval              -2          http response socket error
+ */
+
+int32 range_request_recv_rng_rsp_headers(int32 socket_fd, uint32 size, uint32 timeout, uint64 instanceSize,
+                 uint64 currChunkLen, int32 *bodyLen, int8 *blockSize, uint64 respLen, uint32 *connClose);
+/**
+ * @brief                            validate range request response
+ * @param[in]          instanceSize  instance size
+ * @param[in]          httpRsp       http response
+ * @param[in]          currChunkLen  current chunk len
+ * @param[in]          respLen       response length
+ * @return                           response decode status
+ * @retval             -1            http response decoding error
+ * @retval             0             http response decoding success
+ */
+
+int32 range_request_validate_rsp(uint64 instanceSize, httpResp *httpRsp,
+                 uint64 currChunkLen, uint64 respLen, uint32 *connClose);
+
+#endif /* RANGEREQUESTTHREAD_H_ */
+
diff --git a/include/multirat_watch_dog_thread.h b/include/multirat_watch_dog_thread.h
new file mode 100644 (file)
index 0000000..4c4109c
--- /dev/null
@@ -0,0 +1,130 @@
+#ifndef MULTIRAT_WATCH_DOG_H_
+#define MULTIRAT_WATCH_DOG_H_
+
+#include "multirat_SB_http.h"
+#include "multirat_connection.h"
+
+typedef enum  {
+        THREAD_INIT = 0,
+        THREAD_RUNNING,
+        THREAD_FINISH
+}THREAD_STATUS;
+
+/*struct http_sample  {
+  char *request;
+  int length;
+  }; */
+
+/**
+ * @brief                           initialize cthread
+ * @param[in]         void
+ * @return
+ */
+
+CThread * cthread_init(void);
+
+/**
+ * @brief                            thread function running
+ * @param[in]           cthread      CThread object
+ * @return
+ * @retval
+ * @retval
+ */
+
+void cthread_run_thread(SmartBondingData *SBData);
+
+/**
+ * @brief                           get the bytes from range request header
+ * @param[in]           start       buffer to store the bytes
+ * @param[in]           rangeHeader rangeHeader to decode
+ * @return                          bytes of range request
+ * @retval              1           bytes updated in param start
+ * @retval              0           error
+ */
+
+int32 get_bytesof_range_request(uint64 *start, int8 *rangeHeader);
+
+/**
+ * @brief                           check if connection is keep-alive
+ * @param[in]           SBData      Smart bonding object
+ * @return                          status of connection
+ * @retval              1           connection header is keep alive
+ * @retval              0           connection header is not keep alive
+ */
+
+int32 is_connection_header_keepalive(SmartBondingData *SBData);
+
+/**
+ * @brief                            start the watch_dog_thread
+ * @param[in]         cthread        cthread object
+ * @return                           void
+ */
+
+void cthread_start_thread(SmartBondingData *SBData);
+
+/**
+ * @brief                           watch dog thread entry function
+ * @param[in]         pArg          cthread entry params
+ * @return                          void
+ */
+void * cthread_entry_function (void *pArg);
+
+/**
+ * @brief                           check the status of the thread
+ * @param[in]         cthread       cthread object
+ * @return                          status of cthread
+ * @return             0            thread init
+ * @retval             1            thread running
+ * @retval             2            thread finish
+ */
+int32 cthread_get_thread_status(CThread *cthread);
+
+/**
+ * @brief                           exit the watch dog thread
+ * @param[in]         cthread       cthread object
+ * @return                          void
+ */
+void cthread_exit(CThread *cthread);
+
+/**
+ * @brief                            creat,bind and check the watch dog thread
+ * @param[in]           SBData       smartbonding data object
+ * @return                           status of connection
+ * @retval              0            successful connection
+ * @retval              -1           error
+ */
+int32 watchdog_test_connection_type(SmartBondingData *SBData);
+
+/**
+ * @brief                            calculate no of chunks in watchdog thread
+ * @param[in]           chunkSize    chunk size
+ * @param[in]           noOfChunks   total no of chunks
+ * @param[in]           lastChunk    last chunk
+ * @param[in]           totalSize    total size
+ * @return                           void
+ */
+void multirat_watchdogthread_calnochunks(uint32 chunkSize,uint32 *noOfChunks,uint32 *lastChunk,uint64 totalSize);
+
+/**
+ * @brief                            get request without range from range header
+ * @param[in]           oldReq       old request
+ * @param[in]           newReq       new request
+ * @param[in]           rangeHeader  rangeHeader
+ * @param[in]           rangeStart   range start buffer
+ * @return                           status of getting request from header
+ * @retval              1            successfully removed range header
+ * @retval              0            copied old request to new request
+ * @retval              -1           unseccessful decoding of range request
+ */
+int32 get_req_without_range(int8 *oldReq, int8 *newReq, int8 *rangeHeader, uint64 *rangeStart);
+
+int32 check_speed(SmartBondingData *SBData, uint32 timeT2, uint32 resp_offset,
+                              uint32 resp_len, int8 *recv_buf, int32 socket, uint64 contLength);
+
+void switch_to_watchdog(SmartBondingData *SBData, uint32 resp_offset, uint32 resp_len, int8 *recv_buf, int32 socket);
+
+void file_cthread_run_thread(SmartBondingData *SBData);
+
+int32 file_thread_FirstConnection(SmartBondingData *SBData, fileThread *fThread, int64 *chunkInfo, int8 *recv_buf, int32 *lengthRcvd);
+
+#endif
diff --git a/include/multirat_watchthread.h b/include/multirat_watchthread.h
new file mode 100644 (file)
index 0000000..e2f71a9
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef MULTIRAT_WATCHTHREAD_H_
+#define MULTIRAT_WATCHTHREAD_H_
+
+void smart_bonding_init_speed(SmartBondingData *SBData);
+uint32 speed_calc_check_compare(uint64 *speed_time , SmartBondingData *SBData);
+void sb_calc_speed(SmartBondingData *SBData);
+uint32 getAggSpeed(uint32 *dataArr,uint64 *timeArr);
+void curlThread_run_thread(SmartBondingData *SBData);
+void curlThread_exit(curlThread *curlThrd);
+void *curlThread_entry_function (void *pArg);
+void curlThread_start(SmartBondingData *SBData);
+curlThread* curlThread_init();
+
+#endif
diff --git a/multirat.manifest b/multirat.manifest
new file mode 100644 (file)
index 0000000..f5a44ec
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+        <request>
+                <domain name="_"/>
+        </request>
+</manifest>
diff --git a/multirat.pc.in b/multirat.pc.in
new file mode 100644 (file)
index 0000000..0138481
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=/usr
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: multirat
+Description: Smart Bonding Library
+Version: 1.0
+Requires: dlog dbus-glib-1
+Libs: -L${libdir} -lmultirat
+Cflags: -I${includedir}/multirat
diff --git a/packaging/multirat.spec b/packaging/multirat.spec
new file mode 100644 (file)
index 0000000..da3d2ef
--- /dev/null
@@ -0,0 +1,78 @@
+Name:  multirat        
+Summary:       CAPI for smartbonding
+Version:       0.1.25
+Release:       1
+Group:         Development/Libraries
+License:       TO_BE_FILLED_IN
+URL:   N/A     
+Source0:       %{name}-%{version}.tar.gz
+
+#Requires(post): sys-assert
+#BuildRequires: pkgconfig(capi-base-common)
+#BuildRequires: pkgconfig(bundle)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(dbus-1)
+BuildRequires: pkgconfig(dbus-glib-1)
+BuildRequires: pkgconfig(vconf)
+BuildRequires: pkgconfig(libcares)
+BuildRequires: pkgconfig(capi-network-connection)
+BuildRequires: pkgconfig(capi-network-wifi)
+#BuildRequires: pkgconfig(capi-appfw-application)
+#BuildRequires: pkgconfig(download-provider)
+BuildRequires: cmake
+#BuildRequires: expat-devel
+Requires: dbus-glib
+
+%description
+CAPI for SMARTBONDING
+
+%package devel
+Summary:       smartbonding
+Group:         Development/Libraries
+Requires:      %{name} = %{version}-%{release}
+
+%description devel
+CAPI for SMARTBONDING (developement files)
+
+%prep
+%setup -q
+
+%build
+#cmake . -DCMAKE_INSTALL_PREFIX="/"
+
+#make %{?jobs:-j%jobs}
+
+export LDFLAGS+="-Wl,--rpath=%{_prefix}/lib -Wl,--as-needed"
+mkdir cmake_tmp
+cd cmake_tmp
+LDFLAGS="$LDFLAGS" cmake .. -DCMAKE_INSTALL_PREFIX=%{_prefix}
+cmake .. -DCMAKE_INSTALL_PREFIX=%{_prefix}
+make %{?jobs:-j%jobs}
+
+
+
+%install
+rm -rf %{buildroot}
+cd cmake_tmp
+%make_install
+mkdir -p %{buildroot}/usr/share/license
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files 
+%manifest multirat.manifest
+%attr(755,root,root) 
+%{_libdir}/libmultirat.so* 
+
+%files devel
+%attr(755,root,root) 
+%{_libdir}/pkgconfig/multirat.pc
+/usr/include/multirat/multirat_libapi.h
+/usr/include/multirat/multirat_process.h
+/usr/include/multirat/multirat_SB_http.h
+/usr/include/multirat/multirat_conf.h
+/usr/include/multirat/smartbonding-client.h
+
diff --git a/src/multirat_block_manager.c b/src/multirat_block_manager.c
new file mode 100644 (file)
index 0000000..3bc140e
--- /dev/null
@@ -0,0 +1,617 @@
+#include "multirat_data_buffer.h"
+#include "multirat_conf.h"
+#include "multirat_block_manager.h"
+#include "multirat_process.h"
+
+void block_manager_init(MultiSocket *mSocket, BlockManager *bmanager,MultiSockInput *mSockInput)
+{
+       uint32 i = 0;
+       bmanager->chunkSize = mSockInput->chunkSize;
+       bmanager->noOfChunks = mSocket->noOfChunks;
+       bmanager->comRspLen = mSocket->compRspLen;
+       bmanager->rspOffset = mSocket->rspOffset;
+       bmanager->strtOffset = mSocket->strtOffset;
+       bmanager->lastChunkSize = mSockInput->lastChunk;
+       bmanager->minSizeToHandover = MIN_SIZE_TO_HANDOVER;
+       bmanager->minNotReadChunkId = 0;
+       bmanager->currentChunkId = &(mSocket->currentChunkId);
+
+       /* Initialize of previousChunkID array */
+       for (i = 0; i<MAX_INTERFACES ; i++)
+       {
+               bmanager->prevChunkId[i] = -1;
+               bmanager->speed[i] = 0;
+               bmanager->headerSpeed[i] = 0;
+               bmanager->threadState[i] = STATE_THREAD_RUNNING;
+               bmanager->noOfIOExp[i] = 0;
+       }/* End of for */
+
+       /* Copy the common buffer pointer */
+       bmanager->commBuff = mSocket->commBuffer;
+
+       /* Initialize mutex for calculating next HTTP Chunk */
+       pthread_mutex_init(&(bmanager->mutex),NULL);
+
+       return;
+}
+
+int32 block_manager_get_next_chunk(int64 *chunkInfo, int32 threadId, int32 socketId,
+                                                                                                               BlockManager *bmanager )
+{
+       int32 chunkId = 0;
+       uint32 ratio = 0;
+       uint32 otherId = 0;
+       uint64 thisSpeed = 0;
+       uint64 otherSpeed = 0;
+       DataBuffer *thisBuff = NULL;
+       DataBuffer *otherBuff = NULL;
+
+       TIZEN_D_LOGD("starts ...");
+
+       pthread_mutex_lock(&bmanager->mutex);
+
+       if(bmanager->threadState[threadId] == STATE_THREAD_STOPPED)
+       {
+               pthread_mutex_unlock(&bmanager->mutex);
+               chunkInfo[2] = -1;
+               return 0;
+       }
+       otherId = GET_OTHER_THREAD_ID(threadId);
+
+       if(bmanager->threadState[otherId] == STATE_THREAD_STOPPED)
+       {
+               block_manager_getContinueChunk(chunkInfo,threadId,socketId,bmanager);
+               pthread_mutex_unlock(&bmanager->mutex);
+               return 0;
+       }
+       if ((bmanager->prevChunkId[threadId] == -1) ||
+                       (bmanager->prevChunkId[otherId] == -1))
+       {
+               /* assigning chunk first time to this thread */
+               if (DATA_BUFFER_GET_STATE((bmanager->commBuff + threadId)) ==  STATE_NOT_READ)
+               {
+                       chunkId = threadId;
+                       bmanager->minNotReadChunkId = chunkId + 1;
+               }
+               else
+               {
+                       chunkId = block_manager_getmin_notread_chunkId(bmanager);
+               }
+               if(-1 != chunkId)
+               {
+                       block_manager_getmin_notread_chunk(chunkId, chunkInfo,threadId, socketId, bmanager);
+                       bmanager->prevChunkId[threadId] = chunkId;
+               }/* End of if */
+               else
+               {
+                       chunkInfo[2] = chunkId;
+               }
+               pthread_mutex_unlock(&bmanager->mutex);
+               return 0;
+       }/* End of if */
+
+       thisBuff = bmanager->commBuff + bmanager->prevChunkId[threadId];
+       otherBuff = bmanager->commBuff + bmanager->prevChunkId[otherId];
+
+       thisSpeed = bmanager->speed[threadId];
+       if (DATA_BUFFER_GET_THREAD_ID(thisBuff) != threadId)
+       {
+               /* Socket handover case */
+               TIZEN_D_LOGD("socket handover case");
+               otherSpeed = DATA_BUFFER_GET_EST_SPEED(thisBuff);
+       } /* End of if */
+       else
+       {
+               otherSpeed = bmanager->speed[otherId];
+       } /* End of else */
+
+       if(getTempLevel(bmanager->SBData))
+       {
+               if(thisSpeed > (1.5 * otherSpeed))
+               {
+                       TIZEN_LOGD("Stopping other thread due to temp condition");
+                       block_manager_handleExtermeCase(chunkInfo,threadId,socketId,bmanager,otherBuff,otherId,thisSpeed);
+               }
+               else
+               {
+                       TIZEN_LOGD("Stopping Current thread due to temp condition");
+                       bmanager->threadState[threadId] = STATE_THREAD_STOPPED;
+                       chunkInfo[2] = -1;
+               }
+               pthread_mutex_unlock(&bmanager->mutex);
+               return 0;
+       }
+
+       if ((thisSpeed != 0))
+       {
+               TIZEN_LOGD("thread Id = %d  thisSpeed = %llu otherSpeed = %llu ",threadId, thisSpeed, otherSpeed);
+               if (thisSpeed > otherSpeed)
+               {
+                       //ratio = thisSpeed/otherSpeed;
+                       if ((otherSpeed == 0) || (((thisSpeed > (5 * otherSpeed)) || (bmanager->noOfIOExp[otherId] > 2)) &&
+                                       (bmanager->prevChunkId[threadId] < bmanager->prevChunkId[otherId])))
+                       {
+                               //ratio = 100;
+                               TIZEN_LOGD("handleExtermeCase threadId %d otherId %d Exp %d",
+                                               threadId,otherId,bmanager->noOfIOExp[otherId]);
+                               block_manager_handleExtermeCase(chunkInfo,threadId,socketId,bmanager,otherBuff,otherId,thisSpeed);
+                               pthread_mutex_unlock(&bmanager->mutex);
+                               return 0;
+                       }/* End of if */
+                       else
+                       {
+                               ratio = thisSpeed/otherSpeed;
+                       }/* End of else */
+                       chunkId = block_manager_handle_fastcase(ratio, thisSpeed,
+                                       otherSpeed, otherBuff, otherId, threadId, bmanager);
+               }/* End of if */
+               else
+               {
+                       ratio = otherSpeed/thisSpeed;
+                       chunkId = block_manager_handle_slow_case(ratio, otherId,bmanager);
+               }/* End of else */
+       }/* End of if */
+       else
+       {
+               chunkId = block_manager_getmin_notread_chunkId(bmanager);
+       }/* End of else */
+       if(chunkId != -1)
+       {
+               block_manager_getmin_notread_chunk(chunkId, chunkInfo, threadId,socketId, bmanager);
+               bmanager->prevChunkId[threadId] = chunkId;
+       }/* End of if */
+       else
+       {
+               chunkInfo[2] = chunkId;
+       }
+       pthread_mutex_unlock(&bmanager->mutex);
+       return 0;
+}/* End of getNextChunk() */
+
+void block_manager_handleExtermeCase(int64 *chunkInfo, int32 threadId, int32 socketId,
+                                               BlockManager *bmanager, DataBuffer *otherBuff,uint32 otherId,uint64 thisSpeed)
+{
+       bmanager->threadState[otherId] = STATE_THREAD_STOPPED;
+       data_buffer_switch_socket(threadId,thisSpeed,otherBuff);
+       TIZEN_D_LOGD("Min Chunk %d Prev Chunk %d",bmanager->minNotReadChunkId, bmanager->prevChunkId[otherId]);
+       bmanager->minNotReadChunkId = MIN(bmanager->minNotReadChunkId, bmanager->prevChunkId[otherId]);
+       block_manager_getContinueChunk(chunkInfo,threadId,socketId,bmanager);
+}/* End of block_manager_handleExtermeCase() */
+
+
+void block_manager_getContinueChunk(int64 *chunkInfo, int32 threadId,
+                                                                                                                               int32 socketId, BlockManager *bmanager)
+{
+       int32 chunkId = 0;
+       uint32 state = 0;
+       uint32 startOffset = 0;
+       DataBuffer *blockChunk = NULL;
+
+       if(block_manager_isContChunkPresent(bmanager))
+       {
+               state = DATA_BUFFER_GET_STATE(bmanager->commBuff + bmanager->minNotReadChunkId);
+               if(state == STATE_BLOCKED)
+               {
+                       blockChunk = (bmanager->commBuff + bmanager->minNotReadChunkId);
+                       blockChunk->totalLen = blockChunk->offset;
+                       blockChunk->state = STATE_FULL_READ;
+                       startOffset = blockChunk->totalLen;
+                       chunkId = bmanager->minNotReadChunkId + 1;
+                       bmanager->minNotReadChunkId = chunkId;
+                       //added newly
+                       blockChunk = (bmanager->commBuff + bmanager->minNotReadChunkId);
+                       blockChunk->totalLen = 0;
+               }
+               else if ((state == STATE_CLEARED) || (state == STATE_FULL_READ))
+               {
+                       chunkId = bmanager->minNotReadChunkId + 1;
+               }
+               else
+               {
+                       chunkId = bmanager->minNotReadChunkId;
+               }
+               TIZEN_LOGD("Continuous chunk present %d startOffset %d",chunkId,startOffset);
+               bmanager->threadState[threadId] = STATE_THREAD_STOPPED;
+               blockChunk = (bmanager->commBuff + chunkId);
+               blockChunk->isContinueChunk = 1;
+               blockChunk->threadId = get_interface_id(threadId);
+               chunkInfo[2] = -1;
+       }
+       else
+       {
+               TIZEN_LOGD("getContinueChunk no continous chunk");
+               chunkId = block_manager_getmin_notread_chunkId(bmanager);
+               if(-1 != chunkId)
+               {
+                       block_manager_getmin_notread_chunk(chunkId, chunkInfo,threadId,socketId, bmanager);
+                       bmanager->prevChunkId[threadId] = chunkId;
+               }
+               else
+               {
+                       chunkInfo[2] = chunkId;
+               }
+       }/* End of else */
+       return;
+}/* End of  block_manager_getContinueChunk() */
+
+
+int32 get_interface_id(int32 threadId)
+{
+       int8 *default_iname = DEFAULT_INTERFACE;
+       if (0 == strncasecmp(default_iname, "lte", strlen("lte")))
+       {
+               return (threadId +1) % 2;
+       }
+       else
+       {
+               return threadId;
+       }
+}
+
+int32 block_manager_isContChunkPresent(BlockManager *bmanager)
+{
+       uint32 i = 0;
+       uint32 state = 0;
+
+       if(bmanager->minNotReadChunkId == bmanager->noOfChunks - 1)
+       {
+               TIZEN_D_LOGD("Min Chunk %d",bmanager->minNotReadChunkId);
+               return B_FALSE;
+       }
+
+
+       for (i = bmanager->minNotReadChunkId;i < bmanager->noOfChunks;i++)
+       {
+               state = DATA_BUFFER_GET_STATE(bmanager->commBuff + i);
+               TIZEN_D_LOGD("State of Chunk %d %d",i,state);
+               if (state == STATE_NOT_READ)
+               {
+                       continue;
+               }/* End of if */
+               else if ((state == STATE_BLOCKED) && (i == bmanager->minNotReadChunkId))
+               {
+                       continue;
+               }/* End of else if */
+               else if(((state == STATE_CLEARED) ||
+                               (state == STATE_FULL_READ)) && (i == bmanager->minNotReadChunkId))
+               {
+                       continue;
+               }/* End of else if */
+               else
+               {
+                       return B_FALSE;
+               }/* End of else */
+       }/* End of for */
+       return B_TRUE;
+}/* block_manager_isContChunkPresent */
+
+
+int32 block_manager_handle_fastcase(uint32 ratio, uint64 thisSpeed, uint64 otherSpeed,
+                                               DataBuffer *otherBuff,uint32 otherId,int32 threadId,BlockManager *bmanager)
+{
+       int32 chunkId = 0;
+
+       TIZEN_D_LOGD("block_manager_handle_fastcase\n");
+       chunkId = block_manager_getmin_notread_chunkId(bmanager);
+
+       if (-1 != chunkId)
+       {
+               if (ratio > 10)
+               {
+                       uint32 remLen = (DATA_BUFFER_GET_TOTAL_LEN(otherBuff) -
+                                       DATA_BUFFER_GET_OFFSET(otherBuff)) * 8;
+                       if ((chunkId > bmanager->prevChunkId[otherId]) && (remLen > (bmanager->minSizeToHandover * 8)))
+                       {
+                               if ((otherSpeed == 0)  ||
+                                               ((otherSpeed != 0) && ((remLen/thisSpeed) + bmanager->headerSpeed[threadId])
+                                                               < (remLen/otherSpeed)))
+                               {
+                                       data_buffer_switch_socket(threadId, thisSpeed,
+                                                       otherBuff);
+                                       chunkId = bmanager->prevChunkId[otherId];
+                                       bmanager->minNotReadChunkId = MIN(bmanager->minNotReadChunkId, chunkId);
+                               }/* End of if */
+                       }
+               }/* End of if */
+       }/* End of if */
+       else
+       {
+               /* No more chunk mostly this is last chunk */
+               uint32 remLen = (DATA_BUFFER_GET_TOTAL_LEN(otherBuff) -
+                               DATA_BUFFER_GET_OFFSET(otherBuff)) * 8;
+
+               if((ratio >= 2) && ((remLen/thisSpeed) < (remLen/otherSpeed + 5)) && (remLen > (4 * bmanager->minSizeToHandover)))
+               {
+                       TIZEN_LOGD("block_manager_handle_fastcase handover for last chunk Remaining Length %ld This Thread Speed %d Other Speed %d", remLen, thisSpeed, otherSpeed);
+                       data_buffer_switch_socket(threadId, thisSpeed,otherBuff);
+                       chunkId = bmanager->prevChunkId[otherId];
+                       bmanager->minNotReadChunkId = MIN(bmanager->minNotReadChunkId, chunkId);
+               }
+       }
+       return chunkId;
+}/* End of handleFastCase() */
+
+int32 block_manager_get_min_not_read_jump_case(int32 chunkId, BlockManager *bmanager)
+{
+       int32 i = 0;
+       int32 ret = 0;
+
+       for (i = chunkId; i < bmanager->noOfChunks; i++)
+       {
+               ret = DATA_BUFFER_GET_STATE(bmanager->commBuff + i);
+               if (ret ==  STATE_NOT_READ || ret == STATE_BLOCKED)
+               {
+                       return i;
+               }/* End of if */
+       }/* End of for */
+
+       TIZEN_D_LOGD("JUMP Case Equal to Number of CHUNKS\n");
+       i = block_manager_get_lastmin_notread_chunkId(bmanager);
+       TIZEN_D_LOGD("JUMP Case CHUNK ID got %d",i);
+       return i;
+}/* End of getMinNotReadJumpCase */
+
+int32 block_manager_handle_slow_case(uint32 ratio,uint32 otherId,BlockManager *bmanager)
+{
+       int32 chunkId = block_manager_getmin_notread_chunkId(bmanager);
+
+       if (-1 != chunkId)
+       {
+               if (ratio > 2 && chunkId > bmanager->prevChunkId[otherId])
+               {
+                       bmanager->minNotReadChunkId = MIN(bmanager->minNotReadChunkId, chunkId);
+                       if (ratio > MAX_JUMP)
+                       {
+                               ratio = MAX_JUMP;
+                       }
+                       chunkId = bmanager->prevChunkId[otherId] + ratio;
+                       if (chunkId >= bmanager->noOfChunks)
+                       {
+                               TIZEN_D_LOGD("NO chunks left hence starting from last");
+                               chunkId = block_manager_get_lastmin_notread_chunkId(bmanager);
+                               TIZEN_D_LOGD("chunk ID from last %d",chunkId);
+                       }
+                       else
+                       {
+                               chunkId = block_manager_get_min_not_read_jump_case(chunkId, bmanager);
+                       }
+               }
+       }/* End of if */
+       TIZEN_LOGD("Slow socket got chunk %d",chunkId);
+       return chunkId;
+}/* End of if */
+
+int32 block_manager_get_lastmin_notread_chunkId(BlockManager *bmanager)
+{
+       int32 ret = 0;
+       int32 chunkid = -1;
+       uint32 i = 0;
+
+       for (i = (bmanager->noOfChunks-1); i >= bmanager->minNotReadChunkId; i--)
+       {
+               ret = DATA_BUFFER_GET_STATE(bmanager->commBuff + i);
+               if (ret ==  STATE_NOT_READ || ret == STATE_BLOCKED)
+               {
+                       chunkid = i;
+                       break;
+               }
+       }
+       return chunkid;
+}/* End of getLastMinNotReadChunk() */
+
+int32 block_manager_getmin_notread_chunkId(BlockManager *bmanager)
+{
+       int32 i = 0;
+       int32 ret = 0;
+
+       for (i= bmanager->minNotReadChunkId;i < bmanager->noOfChunks;i++)
+       {
+               ret = DATA_BUFFER_GET_STATE(bmanager->commBuff + i) ;
+               if ((ret ==  STATE_NOT_READ) || (ret == STATE_BLOCKED))
+               {
+                       bmanager->minNotReadChunkId = i+1;
+                       return i;
+               }
+       }
+       return -1;
+}
+
+void block_manager_getmin_notread_chunk(int32 chunkId, int64 *chunkInfo, int32 threadId,
+                                                                                                                                               int32 socketId, BlockManager *bmanager)
+{
+       uint64 range1 = (chunkId * bmanager->chunkSize) + bmanager->rspOffset + bmanager->strtOffset;
+       uint64 range2 = 0;
+
+       if((chunkId == (bmanager->noOfChunks - 1)) && (bmanager->lastChunkSize != 0))
+       {
+               range2 = range1 + bmanager->lastChunkSize - 1;
+       }/* End of if */
+       else
+       {
+               range2 = ((chunkId + 1 ) * bmanager->chunkSize) + bmanager->strtOffset + bmanager->rspOffset - 1;
+       }
+       chunkInfo[1] = MIN(range2, ((bmanager->comRspLen + bmanager->strtOffset)-1));
+
+       if (DATA_BUFFER_GET_STATE(bmanager->commBuff +chunkId) == STATE_BLOCKED)
+       {
+               chunkInfo[0] = range1 + DATA_BUFFER_GET_OFFSET(bmanager->commBuff + chunkId);
+               data_buffer_reinit_chunk(threadId, socketId, bmanager->commBuff + chunkId);
+       }
+       else
+       {
+               chunkInfo[0] = range1;
+               data_buffer_init_chunk(threadId,(chunkInfo[1]-chunkInfo[0] + 1),
+                               socketId, bmanager->commBuff + chunkId, chunkInfo);
+       }
+       TIZEN_D_LOGD("block_manager_getmin_notread_chunk CHUNK LENGTH %llu",
+                       chunkInfo[1] - chunkInfo[0] + 1);
+       chunkInfo[2] = chunkId;
+}
+
+void block_manager_io_exception(int32 threadId, int32 chunkId,BlockManager *bmanager)
+{
+       bmanager->prevChunkId[threadId] = -1;
+       bmanager->minNotReadChunkId = MIN(bmanager->minNotReadChunkId, chunkId);
+}
+
+uint32 block_manager_checkOtherThread(int32 threadId, int32 chunkId,BlockManager *bmanager, uint32 temp_check)
+{
+       uint32 state = 0;
+       uint32 retval = 0;
+       uint32 otherId = 0;
+       DataBuffer *otherBuff = NULL;
+       int8 *default_iname = DEFAULT_INTERFACE;
+       if((temp_check == 1) && (bmanager->threadState[otherId] == STATE_THREAD_RUNNING) && (getTempLevel(bmanager->SBData)))
+       {
+               pthread_mutex_lock(&bmanager->mutex);
+               otherId = GET_OTHER_THREAD_ID(threadId);
+               if(bmanager->threadState[threadId] == STATE_THREAD_STOPPED)
+               {
+                       retval = 0;
+               }
+               else if(bmanager->threadState[otherId] == STATE_THREAD_RUNNING)
+               {
+                       int32 thread = threadId;
+                       if (0 == strncasecmp(default_iname, LTE, strlen(LTE)))
+                       {
+                               thread = (thread + 1) % 2;
+                       }
+                       if(thread)
+                       {
+                               TIZEN_LOGD("Temp More Stopping Current thread as LTE");
+                               bmanager->threadState[threadId] = STATE_THREAD_STOPPED;
+                               retval = 1;
+                       }
+                       else
+                       {
+                               TIZEN_LOGD("Thread %d is stopped due to temp condition and WiFi",otherId);
+                               bmanager->threadState[otherId] = STATE_THREAD_STOPPED;
+                               otherBuff = bmanager->commBuff + bmanager->prevChunkId[otherId];
+                               data_buffer_switch_socket(threadId,bmanager->speed[threadId],otherBuff);
+                               bmanager->minNotReadChunkId = MIN(bmanager->minNotReadChunkId, bmanager->prevChunkId[otherId]);
+                               retval = 0;
+                       }
+               }
+               pthread_mutex_unlock(&bmanager->mutex);
+       }
+       if((0 == retval) && (bmanager->threadState[threadId] == STATE_THREAD_RUNNING))
+       {
+               state = DATA_BUFFER_GET_STATE(bmanager->commBuff + *(bmanager->currentChunkId));
+
+               if(STATE_BLOCKED == state)
+               {
+                       TIZEN_LOGD("Reading chunk %d is blocked\n",*(bmanager->currentChunkId));
+                       return 1;
+               }
+       }
+       return retval;
+}
+
+int32 block_manager_chunk_present(BlockManager *bmanager)
+{
+       uint32 i = 0;
+       uint32 state = 0;
+
+       for (i = bmanager->minNotReadChunkId;i < bmanager->noOfChunks;i++)
+       {
+               state = DATA_BUFFER_GET_STATE(bmanager->commBuff + i);
+               if ((state ==  STATE_NOT_READ) || (state == STATE_BLOCKED))
+               {
+                       return B_TRUE;
+               }
+       }
+       return B_FALSE;
+}
+
+int32 block_manager_checkAllBufferStatus(BlockManager *bmanager, int32 threadId)
+{
+       uint32 i = 0;
+       uint32 state = 0;
+
+       for(i=*(bmanager->currentChunkId);i<bmanager->noOfChunks;i++)
+       {
+               state = DATA_BUFFER_GET_STATE(bmanager->commBuff+i);
+               if((state == STATE_FULL_READ) || (state == STATE_CLEARED))
+               {
+                       continue;
+               }
+               else if(state == STATE_BLOCKED)
+               {
+                       return THREAD_CONTINUE;
+               }
+               else
+               {
+                       return block_manager_checkSpeed(bmanager,threadId);
+               }
+       }
+       return THREAD_EXIT;
+}
+
+uint32 block_manager_checkSpeed(BlockManager *bmanager, int32 threadId)
+{
+       uint32 retval = 0;
+       uint32 thisSpeed = 0;
+       uint32 otherSpeed = 0;
+       uint32 otherId = 0;
+       DataBuffer *otherBuff = NULL;
+
+       thisSpeed = bmanager->speed[threadId];
+       otherId = GET_OTHER_THREAD_ID(threadId);
+       otherSpeed = bmanager->speed[otherId];
+       otherBuff = bmanager->commBuff + bmanager->prevChunkId[otherId];
+
+       if(otherSpeed != 0)
+       {
+               uint32 remLen = DATA_BUFFER_GET_TOTAL_LEN(otherBuff) - DATA_BUFFER_GET_OFFSET(otherBuff);
+               TIZEN_D_LOGD("Block_manager Check Speed Remaining Length %ld This Thread Speed %d Other Speed %d\n", remLen, thisSpeed, otherSpeed );
+               if((thisSpeed > otherSpeed) && ((thisSpeed/otherSpeed) >= 2) &&  (remLen > (4 * bmanager->minSizeToHandover)))
+               {
+                       if(((remLen/thisSpeed) < ((remLen/otherSpeed) + 5)))
+                       {
+                               retval = 2;
+                       }
+               }
+       }
+       else
+       {
+               TIZEN_LOGD("Thread %d is faster than other thread\n",threadId);
+               retval = 2;
+       }
+       return retval;
+}
+
+int32 block_manager_check_buffer_status(BlockManager *bmanager)
+{
+       uint32 i = 0;
+       uint32 state = 0;
+       uint32 count = 0;
+
+       for(i=*(bmanager->currentChunkId);i<bmanager->noOfChunks;i++)
+       {
+               state = DATA_BUFFER_GET_STATE(bmanager->commBuff+i); // need to check
+
+               if(state == STATE_FULL_READ)
+               {
+                       count++;
+               }
+               else if (state == STATE_CLEARED)
+               {
+                       continue;
+               }
+               else
+               {
+                       break;
+               }
+       }
+       if(count >= 2)
+       {
+               return 1;
+       }
+       return 0;
+}
+
+void block_manager_exit(BlockManager *bmanager)
+{
+       TIZEN_LOGD("block_manager_exit\n");
+       pthread_mutex_destroy(&bmanager->mutex);
+}
diff --git a/src/multirat_conf.c b/src/multirat_conf.c
new file mode 100644 (file)
index 0000000..7df2ec3
--- /dev/null
@@ -0,0 +1,54 @@
+#include "multirat_conf.h"
+#include "multirat_SB_http.h"
+#include "multirat_libapi.h"
+#ifdef TIZEN_UX_SUPPORT
+#include "smartbonding-client.h"
+#endif
+
+#include <glib.h>
+
+#ifdef TIZEN_UX_SUPPORT
+static int Lib_Init = SMBD_ERR_INVALID_PARAMETER;
+#endif
+
+
+#ifdef TIZEN_UX_SUPPORT
+uint32 lib_init_success(void)
+{
+       if(Lib_Init != SMBD_ERR_NONE)
+       {
+               return 0;
+       }
+       else
+               return 1;
+}
+
+uint32 smartbonding_client_init(void)
+{
+       if(lib_init_success() != 1)
+       {
+               Lib_Init = smart_bonding_init();
+               if (Lib_Init != SMBD_ERR_NONE) {
+                       TIZEN_LOGD("Smart Bonding Client Library Init Failed");
+                       return 0;
+               }
+               else{
+                       TIZEN_LOGD("Smart Bonding Client Library Init Success");
+                       return 1;
+               }
+       }
+       return 1;
+}
+#endif
+
+int32 get_multirat_threshold()
+{
+       return MULTIRAT_SIZE_THRESHOLD;
+}
+
+
+int32 get_multirat_temp_threshold()
+{
+       return  MULTIRAT_TEMP_THRESHOLD;
+}
+
diff --git a/src/multirat_connection.c b/src/multirat_connection.c
new file mode 100644 (file)
index 0000000..ce2cf92
--- /dev/null
@@ -0,0 +1,813 @@
+#include "multirat_conf.h"
+#include "multirat_process.h"
+#include "multirat_connection.h"
+#include "multirat_libapi.h"
+#include <vconf.h>
+#include <vconf-keys.h>
+
+int32 connection_interface_status(struct ifreq *ifr, char *name)
+{
+       int32 sock = -1;
+       uint32 i = 0;
+       uint32 interfaces = 0;
+       struct ifconf ifconf;
+       struct ifreq ifreq[10];
+
+       sock = socket(AF_INET, SOCK_STREAM, 0);
+       if (sock < 0)
+       {
+               TIZEN_LOGD("Error !!! while creating socket [%d] [%s]", errno, strerror(errno));
+               return -1;
+       }
+
+       ifconf.ifc_buf = (char *) ifreq;
+       ifconf.ifc_len = sizeof ifreq;
+
+       if (ioctl(sock, SIOCGIFCONF, &ifconf) == -1)
+       {
+               TIZEN_LOGD("Error !!! while executing ioctl [%d] [%s]", errno, strerror(errno));
+               CLOSE_SOCKET(sock);
+               return -1;
+       }
+
+       interfaces = ifconf.ifc_len / sizeof(ifreq[0]);
+       TIZEN_LOGD("Number of interfaces [%d]",interfaces);
+
+       for (i = 0; i < interfaces; i++)
+       {
+               TIZEN_D_LOGD("Name of Interface [%s]", ifreq[i].ifr_name);
+               if(!strncmp(ifreq[i].ifr_name, name, strlen(name)))
+               {
+                       ioctl(sock,  SIOCGIFFLAGS, &ifreq[i]);
+                       if((ifreq[i].ifr_flags & IFF_UP)  && (ifreq[i].ifr_flags & IFF_RUNNING))
+                       {
+                               memcpy(ifr,&(ifreq[i]),sizeof(struct ifreq));
+                               CLOSE_SOCKET(sock);
+                               return B_TRUE;
+                       }
+               }
+       }
+       CLOSE_SOCKET(sock);
+       return -1;
+}
+
+int32 connection_is_ifaceup(uint32 ifaceidx, interfaceInfo *ifaceInfo,int iptype)
+{
+       int32 status = 0 ;
+       int8 *default_iname = DEFAULT_INTERFACE;
+       int8 *ifacename = NULL;
+       int8 ip[INET_ADDRSTRLEN] = {0};
+       struct sockaddr_in *address = NULL;
+       struct sockaddr_in6 *address_ip6 = NULL;
+       struct ifreq ifreq;
+
+       if (0 == strncasecmp(default_iname, LTE, strlen(LTE)))
+       {
+               /*
+                * thread  0 should get interface LTE (1)
+                * and thread 1 should get interface WIFI(0)
+                */
+               ifaceidx = (ifaceidx + 1) % 2;
+       }
+
+       if(ifaceidx)
+       {
+               ifacename = LTE_IFACE_NAME;
+       }
+       else
+       {
+               ifacename = WIFI_IFACE_NAME;
+       }
+
+       memset(&ifreq,0,sizeof(struct ifreq));
+       status = connection_interface_status(&ifreq,ifacename);
+
+       if(status == -1)
+       {
+               return B_FALSE ;
+       }
+
+       if(iptype)
+       {
+               address_ip6= (struct sockaddr_in6 *) &ifreq.ifr_addr;
+               if (!inet_ntop(AF_INET6, &address_ip6->sin6_addr, ip, sizeof(ip)))
+               {
+                       TIZEN_LOGD("Error !!! while executing inet_ntop [%d] [%s]", errno, strerror(errno));
+                       return B_FALSE;
+               }
+       }
+       else
+       {
+               address = (struct sockaddr_in *) &ifreq.ifr_addr;
+               if (!inet_ntop(AF_INET, &address->sin_addr, ip, sizeof(ip)))
+               {
+                       TIZEN_LOGD("Error !!! while executing inet_ntop [%d] [%s]", errno, strerror(errno));
+                       return B_FALSE;
+               }
+       }
+
+       memset(ifaceInfo[ifaceidx].ip, 0, INET_ADDRSTRLEN);
+       strcpy(ifaceInfo[ifaceidx].ip,ip);
+
+       return B_TRUE;
+}
+
+int32 file_thread_connServer (int32 sockFd, struct sockaddr_in *remote_addr,struct sockaddr_in6 *remote_addr_ip6, uint32 timeout,
+  SmartBondingData *SBData)
+{
+       //int32 flags = 0;
+       int32 retval = 0;
+       int32 select_ret = 0;
+       uint32 connTimeOut = 0;
+       uint64 connect_start = 0;
+       int8 tmp_ip_addr[INET6_ADDRSTRLEN];
+       int32 connect_status = -1;
+
+       if((0 != timeout))
+       {
+               connTimeOut = MIN(timeout, 60);
+       }
+       else
+       {
+               connTimeOut = 60;
+       }
+
+       //flags = fcntl(sockFd, F_GETFL, 0);
+
+       if(SBData->conn.ip_family)
+       {
+               SECURE_DB_INFO("destIPv6 address [%s]", inet_ntop(AF_INET6,&(remote_addr_ip6->sin6_addr),tmp_ip_addr,INET6_ADDRSTRLEN));
+       }
+       else
+       {
+               SECURE_DB_INFO("destIPv4 address [%s]", inet_ntoa(remote_addr->sin_addr));
+       }
+
+       if(-1 == fcntl(sockFd, F_SETFL, O_NONBLOCK))
+       {
+               TIZEN_LOGD("Error !!! connection FCNTL failed [%d] [%s]", errno, strerror(errno));
+               return -1;
+       }
+
+       if(SBData->conn.ip_family)
+       {
+               connect_status = connect(sockFd, (struct sockaddr *)remote_addr_ip6, sizeof(struct sockaddr_in6));
+       }
+       else
+       {
+               connect_status = connect(sockFd, (struct sockaddr *)remote_addr, sizeof(struct sockaddr_in6));
+       }
+       if(connect_status == -1)
+       {
+               if(errno != EINPROGRESS)
+               {
+                       TIZEN_LOGD("Error !!! connection failure [%d] [%d] [%s]", sockFd, errno, strerror(errno));
+                       return -1;
+               }
+               retval = -1;
+
+               struct timeval tv;
+               fd_set write_fds;
+
+               connect_start = get_time_in_sec();
+               while(((get_time_in_sec() - connect_start) < connTimeOut) && ((SBData->fStream->compRspRcvdFlag)) && ((SBData->status == MAIN_START) || (SBData->file_status == NO_REDIVISION)))
+               {
+                       tv.tv_sec = 1;
+                       tv.tv_usec = 0;
+                       FD_ZERO(&write_fds);
+                       FD_SET(sockFd, &write_fds);
+                       select_ret = select(sockFd + 1, NULL, &write_fds, NULL, &tv);
+                       if(select_ret == 0)
+                       {
+                               TIZEN_LOGD("Time out on select with socket [%d]",sockFd);
+                               continue;
+                       }
+                       else if(select_ret == -1)
+                       {
+                               TIZEN_LOGD("Error !!! select failed [%d] [%s]", errno, strerror(errno));
+                               retval = -1;
+                       }
+                       else if(select_ret == 1)
+                       {
+                               int so_error;
+                               socklen_t slen = sizeof (so_error);
+                               if(getsockopt(sockFd, SOL_SOCKET, SO_ERROR, &so_error, &slen) == 0)
+                               {
+                                       if(so_error)
+                                       {
+                                               TIZEN_LOGD("Error !!! getsockopt failed, so_error is true [%d] [%s]", errno, strerror(errno));
+                                       }
+                                       else
+                                       {
+                                               retval = 0;
+                                       }
+                               }
+                               else
+                               {
+                                       TIZEN_LOGD("Error !!! getsockopt failed [%d] [%s]", errno, strerror(errno));
+                               }
+                       }
+                       break;
+               }
+       }
+       return retval;
+}
+
+int32 get_connection_status(SmartBondingData *SBData)
+{
+       struct timeval tv;
+       fd_set write_fds;
+
+       int32 sockFd = SBData->socket_fd;
+
+       int32 retval = -1;
+       int32 select_ret = 0;
+
+       tv.tv_sec = 1;
+       tv.tv_usec = 0;
+
+       FD_ZERO(&write_fds);
+       FD_SET(sockFd, &write_fds);
+
+       TIZEN_LOGD("SBData[%p] Check Connection Status ", SBData);
+
+       select_ret = select(sockFd + 1, NULL, &write_fds, NULL, &tv);
+       if(select_ret == 0)
+       {
+               SBData->con_status = CONNECTION_WAIT;
+               TIZEN_LOGD("Time out on select with socket [%d] SBData[%p]",sockFd, SBData);
+       }
+       else if(select_ret == -1)
+       {
+               SBData->con_status = CONNECTION_FAIL;
+               TIZEN_LOGD("Error !!! select failed [%d] [%s] SBData[%p]", errno, strerror(errno), SBData);
+       }
+       else if(select_ret == 1)
+       {
+               int so_error;
+               socklen_t slen = sizeof (so_error);
+               if(getsockopt(sockFd, SOL_SOCKET, SO_ERROR, &so_error, &slen) == 0)
+               {
+                       if(so_error)
+                       {
+                               SBData->con_status = CONNECTION_FAIL;
+                               TIZEN_LOGD("Error !!! getsockopt failed, so_error is true [%d] [%s] SBData[%p]", errno, strerror(errno), SBData);
+                       }
+                       else
+                       {
+                               SBData->con_status = CONNECTION_SUCCESS;
+                               TIZEN_LOGD("Connection Success");
+                               retval = 0;
+                       }
+               }
+               else
+               {
+                       SBData->con_status = CONNECTION_FAIL;
+                       TIZEN_LOGD("Error !!! getsockopt failed [%d] [%s] SBData[%p]", errno, strerror(errno), SBData);
+               }
+       }
+       return retval;
+}
+
+int32 connServer (int32 sockFd, struct sockaddr_in *remote_addr,struct sockaddr_in6 *remote_addr_ip6, uint32 timeout,
+  SmartBondingData *SBData)
+{
+       int32 retval = 0;
+       int32 select_ret = 0;
+       uint32 connTimeOut = 0;
+       uint64 connect_start = 0;
+       int8 tmp_ip_addr[INET_ADDRSTRLENG];
+       int32 connect_status = -1;
+
+       if((0 != timeout))
+       {
+               connTimeOut = MIN(timeout, 60);
+       }
+       else
+       {
+               connTimeOut = 60;
+       }
+
+       if(SBData->conn.ip_family)
+       {
+               SECURE_DB_INFO("SBData[%p] destIPv6 address [%s] timeout [%d]", SBData, inet_ntop(AF_INET6,&(remote_addr_ip6->sin6_addr),tmp_ip_addr,INET6_ADDRSTRLEN), connTimeOut);
+       }
+       else
+       {
+               SECURE_DB_INFO("SBData[%p] destIPv4 address [%s] timeout [%d]", SBData, inet_ntoa(remote_addr->sin_addr), connTimeOut);
+       }
+
+       if(-1 == fcntl(sockFd, F_SETFL, O_NONBLOCK))
+       {
+               TIZEN_LOGD("SBData[%p] Error !!! connection FCNTL failed [%d] [%s]", SBData, errno, strerror(errno));
+               return -1;
+       }
+       if(SBData->conn.ip_family)
+       {
+               connect_status = connect(sockFd, (struct sockaddr *)remote_addr_ip6, sizeof(struct sockaddr_in6));
+       }
+       else
+       {
+               connect_status = connect(sockFd, (struct sockaddr *)remote_addr, sizeof(struct sockaddr_in6));
+       }
+       if(connect_status == -1)
+       {
+               if(errno != EINPROGRESS)
+               {
+                       SBData->con_status = CONNECTION_FAIL;
+                       TIZEN_LOGD("SBData[%p] Error !!! connection failure [%d] [%d] [%s]", SBData, sockFd, errno, strerror(errno));
+                       return -1;
+               }
+               retval = -1;
+               SBData->con_status = CONNECTION_FAIL;
+               struct timeval tv;
+               fd_set write_fds;
+
+               connect_start = get_time_in_sec();
+               while(((get_time_in_sec() - connect_start) < connTimeOut) && (SBData->cancel != 1))
+               {
+                       tv.tv_sec = 0;
+                       tv.tv_usec = 500000; /* half sec */
+                       FD_ZERO(&write_fds);
+                       FD_SET(sockFd, &write_fds);
+                       select_ret = select(sockFd + 1, NULL, &write_fds, NULL, &tv);
+                       if(select_ret == 0)
+                       {
+                               SBData->con_status = CONNECTION_WAIT;
+                               TIZEN_LOGD("SBData[%p] Time out on select with socket [%d]",SBData, sockFd);
+                               continue;
+                       }
+                       else if(select_ret == -1)
+                       {
+                               SBData->con_status = CONNECTION_FAIL;
+                               TIZEN_LOGD("SBData[%p] Error !!! select failed [%d] [%s]", SBData, errno, strerror(errno));
+                               retval = -1;
+                       }
+                       else if(select_ret == 1)
+                       {
+                               int so_error;
+                               socklen_t slen = sizeof (so_error);
+                               if(getsockopt(sockFd, SOL_SOCKET, SO_ERROR, &so_error, &slen) == 0)
+                               {
+                                       if(so_error)
+                                       {
+                                               SBData->con_status = CONNECTION_FAIL;
+                                               TIZEN_LOGD("SBData[%p] Error !!! getsockopt failed, so_error is true [%d] [%s]",SBData, errno, strerror(errno));
+                                       }
+                                       else
+                                       {
+                                               struct sockaddr sockname;
+                                               unsigned int len = sizeof(sockname);
+                                               unsigned short port = 0;
+                                               memset(&sockname, 0, len);
+                                               if(getsockname(sockFd, &sockname, &len) != -1)
+                                               {
+                                                       port = ntohs(((struct sockaddr_in*)(&sockname))->sin_port);
+                                               }
+                                               else
+                                               {
+                                                       TIZEN_LOGD("SBData[%p] Error !!! getsockname failed [%d] [%s]",SBData, errno, strerror(errno));
+                                               }
+                                               SBData->con_status = CONNECTION_SUCCESS;
+                                               
+                                               SECURE_DB_INFO("SBData[%p] Conection Success source_port=%hu",SBData, port);
+                                               retval = 0;
+                                       }
+                               }
+                               else
+                               {
+                                       SBData->con_status = CONNECTION_FAIL;
+                                       TIZEN_LOGD("SBData[%p] Error !!! getsockopt failed [%d] [%s]",SBData, errno, strerror(errno));
+                               }
+                       }
+                       break;
+               }
+       }
+       else
+               SBData->con_status = CONNECTION_SUCCESS;
+       return retval;
+}
+
+void file_thread_connect_server(fileThread *fThread)
+{
+       int32 socketId = -1;
+       uint32 index = 0;
+       uint32 bindCount = 0;
+       struct hostent *h;
+       struct sockaddr_in remote_addr;
+       struct sockaddr_in6 remote_addr_ip6;
+
+       connection *conn = fThread->conn ;
+
+       index = fThread->interface_index;
+
+       TIZEN_LOGD("Connect Server");
+
+       h = gethostbyname(conn->ifaceInfo[index].server_ip);
+
+       SECURE_DB_INFO("Server IP %s For %d interface", conn->ifaceInfo[index].server_ip, index);
+
+       //      memset(&remote_addr, 0, sizeof(struct sockaddr_in));
+
+       if(conn->ip_family)
+       {
+               memset(&remote_addr_ip6, 0, sizeof(struct sockaddr_in6));
+               remote_addr_ip6.sin6_family = h->h_addrtype;
+               memcpy((char *) &remote_addr_ip6.sin6_addr.s6_addr, h->h_addr_list[0], h->h_length);
+               remote_addr_ip6.sin6_port = htons(conn->ifaceInfo[index].server_port);
+       }
+       else
+       {
+               memset(&remote_addr, 0, sizeof(struct sockaddr_in));
+               remote_addr.sin_family = h->h_addrtype;
+               memcpy((char *) &remote_addr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
+               remote_addr.sin_port = htons(conn->ifaceInfo[index].server_port);
+       }
+
+       while (*fThread->compRspRcvdFlag)
+       {
+               if(bindCount> 3)
+               {
+                       TIZEN_LOGD("thread ID Tried Connect More Times File Thread");
+                       socketId = -1;
+                       break;
+               }
+
+               socketId = conn_get_socket_bind(conn->ifaceInfo[index].ip,index,conn->ip_family);
+               if(socketId < 0)
+               {
+                       socketId = -1;
+                       usleep(100000);
+                       bindCount++;
+                       continue;
+               }
+
+               TIZEN_LOGD("Socket ID [%d]",socketId);
+
+               if(-1 == file_thread_connServer(socketId, &remote_addr,&remote_addr_ip6, fThread->SBData->timeout, fThread->SBData))
+               {
+                       CLOSE_SOCKET(socketId);
+                       socketId = -1;
+               }
+               break;
+       }
+       if (((*fThread->compRspRcvdFlag)== 0) && (socketId >= 0))
+       {
+               TIZEN_LOGD("socket compRspRcvdFlag 0 and socket thread id [%d]", socketId);
+               CLOSE_SOCKET(socketId);
+               socketId = -1;
+       }
+       fThread->socketId = socketId;
+       return;
+}
+
+void connect_server(RangeRequestThread *rrthread)
+{
+       int32 socketId = -1;
+       uint32 index = 0;
+       uint32 bindCount = 0;
+       int8 *default_iname = DEFAULT_INTERFACE;
+       struct hostent *h;
+       struct sockaddr_in remote_addr;
+       struct sockaddr_in6 remote_addr_ip6;
+       connection *conn = rrthread->conn ;
+
+       index = rrthread->threadId;
+
+       if (0 == strncasecmp(default_iname, LTE, strlen(LTE)))
+       {
+               index = (index +1) % 2;
+       }/* End of if */
+
+       h = gethostbyname(conn->ifaceInfo[index].server_ip);
+
+       SECURE_DB_INFO("Server IP [%s] For [%d] interface", conn->ifaceInfo[index].server_ip, index);
+
+       //      memset(&remote_addr, 0, sizeof(struct sockaddr_in));
+
+       if(conn->ip_family)
+       {
+               memset(&remote_addr_ip6, 0, sizeof(struct sockaddr_in6));
+               remote_addr_ip6.sin6_family = h->h_addrtype;
+               memcpy((char *) &remote_addr_ip6.sin6_addr.s6_addr, h->h_addr_list[0], h->h_length);
+               remote_addr_ip6.sin6_port = htons(conn->ifaceInfo[index].server_port);
+       }
+       else
+       {
+               memset(&remote_addr, 0, sizeof(struct sockaddr_in));
+               remote_addr.sin_family = h->h_addrtype;
+               memcpy((char *) &remote_addr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
+               remote_addr.sin_port = htons(conn->ifaceInfo[index].server_port);
+       }
+
+       while (*rrthread->compRspRcvdFlag)
+       {
+               if(bindCount> 3)
+               {
+                       TIZEN_LOGD("thread ID [%d] Tried Connect More Times",rrthread->threadId);
+                       socketId = -1;
+                       break;
+               }
+
+               socketId = conn_get_socket_bind(conn->ifaceInfo[index].ip,index,conn->ip_family);
+               if(socketId < 0)
+               {
+                       socketId = -1;
+                       usleep(100000);
+                       bindCount++;
+                       continue;
+               }
+
+               TIZEN_LOGD("Socket ID [%d]",socketId);
+
+               if(-1 == connServer(socketId, &remote_addr,&remote_addr_ip6,rrthread->SBData->timeout, rrthread->SBData))
+               {
+                       CLOSE_SOCKET(socketId);
+                       socketId = -1;
+               }
+               break;
+       }
+       if (((*rrthread->compRspRcvdFlag)== 0) && (socketId >= 0))
+       {
+               TIZEN_LOGD("socket compRspRcvdFlag 0 and socket thread id [%d]", socketId);
+               CLOSE_SOCKET(socketId);
+               socketId = -1;
+       }
+       conn->sockId[rrthread->threadId] = socketId;
+       rrthread->socketId = socketId;
+       return;
+}
+
+uint32 is_interface_up(int8* ifacename, interfaceInfo *ifaceinfo,int iptype)
+{
+       int32 status = 0 ;
+       int8 ip[INET_ADDRSTRLEN] = {0};
+       struct ifreq ifreq;
+
+       memset(&ifreq,0,sizeof(struct ifreq));
+       status = connection_interface_status(&ifreq, ifacename);
+       if (status!= -1)
+       {
+               if(iptype)
+               {
+                       struct sockaddr_in6 *address_ip6 = (struct sockaddr_in6 *) &ifreq.ifr_addr;
+                       if (!inet_ntop(AF_INET6, &address_ip6->sin6_addr, ip, sizeof(ip)))
+                       {
+                               TIZEN_LOGD("socket error");
+                               return B_FALSE;
+                       }
+               }
+               else
+               {
+                       struct sockaddr_in *address = (struct sockaddr_in *) &ifreq.ifr_addr;
+                       if (!inet_ntop(AF_INET, &address->sin_addr, ip, sizeof(ip)))
+                       {
+                               TIZEN_LOGD("socket error");
+                               return B_FALSE;
+                       }
+               }
+
+
+               if (!strncmp(ifacename, LTE_IFACE_NAME ,  strlen(ifacename)))
+               {
+                       memset(ifaceinfo[LTE_INTERFACE].ip , 0 , INET_ADDRSTRLENG);
+                       strcpy(ifaceinfo[LTE_INTERFACE].interface_name, ifreq.ifr_name);
+                       strcpy(ifaceinfo[LTE_INTERFACE].ip,ip);
+                       SECURE_DB_INFO("IP address of LTE [%s]",ip);
+                       return B_TRUE;
+               }
+               else if (!strncmp(ifacename, WIFI_IFACE_NAME , strlen(ifacename)))
+               {
+                       int32 is_on = VCONFKEY_MOBILE_HOTSPOT_MODE_NONE;
+                       memset(ifaceinfo[WIFI_INTERFACE].ip , 0 , INET_ADDRSTRLENG);
+                       strcpy(ifaceinfo[WIFI_INTERFACE].interface_name, ifreq.ifr_name);
+                       strcpy(ifaceinfo[WIFI_INTERFACE].ip,ip);
+                       SECURE_DB_INFO("IP address of WiFi [%s]", ip);
+
+                       vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &is_on);
+                       if(is_on != VCONFKEY_MOBILE_HOTSPOT_MODE_NONE)
+                       {
+                               TIZEN_LOGD("Wi-Fi is Not in Normal Wi-Fi Mode");
+                               return B_FALSE;
+                       }
+                       return B_TRUE;
+               }
+       }
+       TIZEN_LOGD ("Interface name [%s] is not found", ifacename);
+       return B_FALSE;
+}
+
+uint32 is_both_interface_avail(interfaceInfo *ifaceInfo,int iptype)
+{
+       uint32 lteFlag = 0;
+       uint32 wifiFlag = 0;
+
+       lteFlag = is_interface_up(LTE_IFACE_NAME, ifaceInfo,iptype);
+       TIZEN_LOGD ("MultiRat Main Thread lte [%u]", lteFlag);
+
+       wifiFlag = is_interface_up(WIFI_IFACE_NAME, ifaceInfo,iptype);
+       TIZEN_LOGD ("MultiRat Main Thread wifi [%u]", wifiFlag);
+
+       return (lteFlag && wifiFlag);
+}
+
+int32 conn_get_socket_bind(int8 *ip, int ifaceidx, int iptype)
+{
+       int32 socket_fd = -1;
+       int32 bind_ret = -1;
+       struct sockaddr_in sa_loc;
+       struct sockaddr_in6 sa_loc6;
+
+       memset(&sa_loc6, 0, sizeof(struct sockaddr_in6));
+       memset(&sa_loc, 0, sizeof(struct sockaddr_in));
+
+       if(iptype)
+       {
+               socket_fd = socket(AF_INET6, SOCK_STREAM, 0);
+               if (socket_fd < 0)
+               {
+                       TIZEN_LOGD("Error !!! socket creation failed [%d] [%s]", errno, strerror(errno));
+                       return -1;
+               }
+               sa_loc6.sin6_family = AF_INET6;
+               sa_loc6.sin6_port = htons(0);
+               inet_pton(AF_INET6,ip,&(sa_loc6.sin6_addr));
+       }
+       else
+       {
+               socket_fd = socket(AF_INET, SOCK_STREAM, 0);
+               if (socket_fd < 0)
+               {
+                       TIZEN_LOGD("Error !!! socket creation failed [%d] [%s]", errno, strerror(errno));
+                       return -1;
+               }
+               sa_loc.sin_family = AF_INET;
+               sa_loc.sin_port = htons(0);
+               sa_loc.sin_addr.s_addr = inet_addr(ip);
+       }
+
+       if(iptype == 0)
+       {
+               bind_ret = bind(socket_fd,(struct sockaddr *)&sa_loc, sizeof(struct sockaddr));
+       }
+       else
+       {
+               bind_ret = bind(socket_fd,(struct sockaddr *)&sa_loc6, sizeof(struct sockaddr_in6));
+       }
+
+       SECURE_DB_INFO("Binding [%d] on IP Address [%s]",socket_fd,ip);
+       if(bind_ret == -1)
+       {
+               TIZEN_LOGD("Error !!! bind failed [%d] [%s]", errno, strerror(errno));
+               CLOSE_SOCKET(socket_fd);
+               return -1;
+       }
+       SECURE_DB_INFO("Binding to the IP address[%s] Successful",ip);
+       return socket_fd;
+}
+
+int32 conn_poll(int32 socketId, uint32 timeout)
+{
+       struct pollfd rcvfd;
+       memset(&rcvfd, 0, sizeof(struct pollfd));
+       rcvfd.fd = socketId;
+       rcvfd.events = POLLIN;
+
+       return poll(&rcvfd, 1, timeout);
+}
+
+int32 file_thread_conn_poll(int32 socket, SmartBondingData *SBData)
+{
+       int32 pollret = 0;
+       uint32 pollStartTime = get_time_in_sec();
+       while((SBData->fStream->compRspRcvdFlag) && (((SBData->status == MAIN_START) || (SBData->file_status == NO_REDIVISION)) && ((get_time_in_sec() - pollStartTime) < 30)))
+       {
+               pollret = 0;
+               pollret = conn_poll(socket, 200);
+               if (pollret < 0)
+               {
+                       TIZEN_LOGD("Error !!! watchdog thread pollfd failed");
+                       break;
+               }
+               else if(pollret == 0)
+               {
+                       TIZEN_D_LOGD("Timeout on File Thread Poll");
+                       continue;
+               }
+               else
+               {
+                       TIZEN_D_LOGD("File Thread Response");
+                       break;
+               }
+       }
+       return pollret;
+}
+
+
+int32 watchdog_conn_poll(int32 socket, SmartBondingData *SBData)
+{
+       int32 pollret = 0;
+       uint32 pollStartTime = get_time_in_sec();
+       while((SBData->cthread->threadStatus != THREAD_FINISH) && ((get_time_in_sec() - pollStartTime) < 30))
+       {
+               pollret = 0;
+               pollret = conn_poll(socket, 2000);
+               if (pollret < 0)
+               {
+                       TIZEN_LOGD("Error !!! watchdog thread pollfd failed");
+                       break;
+               }
+               else if(pollret == 0)
+               {
+                       TIZEN_D_LOGD("Timeout on Watch Dog Poll");
+                       continue;
+               }
+               else
+               {
+                       TIZEN_D_LOGD("WatchDog Received Response");
+                       break;
+               }
+       }
+       return pollret;
+}
+
+void PollThread_poll(int32 socket, SmartBondingData *SBData, uint32 timeout_check)
+{
+       int32 pollret = 0;
+       uint32 pollStartTime = get_time_in_sec();
+    while((SBData->PollThrd->threadStatus != THREAD_FINISH) && ((get_time_in_sec() - pollStartTime) < 30))
+    {
+        pollret = 0;
+               pollret = conn_poll(socket, timeout_check);
+               if (pollret < 0)
+               {
+                       TIZEN_LOGD("Error !!! Poll Thread pollfd failed");
+                       break;
+               }
+               else if(pollret == 0)
+               {
+                       TIZEN_D_LOGD("Timeout on Pollthread Poll");
+                       continue;
+               }
+               else
+               {
+                       TIZEN_D_LOGD("Poll Thread Received Data");
+                       break;
+               }
+       }
+       return ;
+}
+
+void lib_conn_poll(int32 socket, SmartBondingData *SBData)
+{
+       int32 pollret = 0;
+       while((SBData->cancel != 1))
+       {
+               pollret = 0;
+               pollret = conn_poll(socket, 1000);
+               if (pollret < 0)
+               {
+                       TIZEN_LOGD("Error !!! Libapi pollfd failed");
+                       break;
+               }
+               else if(pollret == 0)
+               {
+                       TIZEN_D_LOGD("Timeout on Libapi Poll");
+                       continue;
+               }
+               else
+               {
+                       TIZEN_D_LOGD("App Read Received Data to Read");
+                       break;
+               }
+       }
+       return;
+}
+
+int32 read_conn_poll(int32 socket, SmartBondingData *SBData)
+{
+       int32 pollret = 0;
+       uint32 pollStartTime = get_time_in_sec();
+       while((SBData->cancel != 1) && ((get_time_in_sec() - pollStartTime) < SBData->timeout))
+       {
+               pollret = 0;
+               pollret = conn_poll(socket, 200);
+               if (pollret < 0)
+               {
+                       TIZEN_LOGD("Error !!! Read pollfd failed");
+                       break;
+               }
+               else if(pollret == 0)
+               {
+                       TIZEN_D_LOGD("Timeout on Read Poll");
+                       continue;
+               }
+               else
+               {
+                       TIZEN_D_LOGD("Received Data to Read");
+                       break;
+               }
+       }
+       return pollret;
+}
+
diff --git a/src/multirat_data_buffer.c b/src/multirat_data_buffer.c
new file mode 100644 (file)
index 0000000..f1761a1
--- /dev/null
@@ -0,0 +1,197 @@
+#include "multirat_process.h"
+#include "multirat_data_buffer.h"
+
+void data_buffer_init(DataBuffer *dbuffer, uint32 noOfChunks, uint64 cthread)
+{
+       uint32 i = 0;
+       DataBuffer *buff = NULL;
+
+       for (i = 0; i< noOfChunks ;i++)
+       {
+               buff = dbuffer + i;
+               buff->appReadLen = 0;
+               buff->data = NULL;
+               buff->offset = 0;
+               buff->threadId = -1;
+               buff->totalLen = 0;
+               buff->estSpeed = 0;
+               buff->socketId = 0;
+               buff->state = STATE_NOT_READ;
+               buff->cthread = cthread;
+               memset(buff->filePath,0,200);
+               pthread_mutex_init(&(buff->mut), NULL);
+       }
+}/* End of DataBuffer() */
+
+void data_buffer_init_chunk(int32 threadId, uint32 size, int32 socketId, DataBuffer *dbuffer, int64 *chunkInfo)
+{
+#if 0
+       dbuffer->data = (char*)malloc(size);
+       if (NULL == dbuffer->data)
+       {
+               TIZEN_LOGD("Error !!! while allocating memory for dbuffer->data");
+               return;
+       }
+       memset(dbuffer->data, 0, size);
+       memset(dbuffer->filePath,0,200);
+#endif
+       sprintf(dbuffer->filePath,"%s%llu%s%llu%s%llu%s%llu","/opt/usr/media/",get_time_in_microsec(),"-",dbuffer->cthread,"-",chunkInfo[0],"-",chunkInfo[1]);
+
+       TIZEN_LOGD("Created File %s", dbuffer->filePath);
+
+       dbuffer->writeFp = fopen(dbuffer->filePath,"w");
+
+       if(dbuffer->writeFp == NULL)
+       {
+               TIZEN_LOGD("unable to open(write) file");
+       }
+
+       dbuffer->readFp = fopen(dbuffer->filePath,"r");
+       if(dbuffer->readFp == NULL)
+       {
+               TIZEN_LOGD("unable to open(read) file");
+       }
+
+       dbuffer->totalLen = size;
+       dbuffer->threadId = threadId;
+       dbuffer->socketId = socketId;
+       dbuffer->state = STATE_OCCUPIED;
+}/* End of initChunk() */
+
+void data_buffer_reinit_chunk(int32 threadId, int32 socketId, DataBuffer *dbuffer)
+{
+       dbuffer->threadId = threadId;
+       dbuffer->socketId = socketId;
+       dbuffer->state = STATE_READING;
+}/* End of reInitChunk() */
+
+void data_buffer_add(uint32 size, int32 threadId, int8 *buff, DataBuffer *dbuffer)
+{
+       if (dbuffer->threadId != threadId)
+       {
+               return;
+       }
+
+       if ((size > 0) && (dbuffer->offset < dbuffer->totalLen))
+       {
+               pthread_mutex_lock(&(dbuffer->mut));
+               if (dbuffer->offset == 0)
+               {
+                       dbuffer->state = STATE_READING;
+               }/* End of if */
+               fwrite(buff, size, 1, dbuffer->writeFp);
+               fflush(dbuffer->writeFp);
+               dbuffer->offset = dbuffer->offset + size;
+
+               if (dbuffer->offset == dbuffer->totalLen)
+               {
+                       dbuffer->state = STATE_FULL_READ;
+               }/* End of if */
+
+               pthread_mutex_unlock(&(dbuffer->mut));
+       }/* End of if */
+       return;
+}/* End of add() */
+
+void data_buffer_freeBuffer(DataBuffer *dbuffer)
+{
+       int32 status = 0;
+       dbuffer->state = STATE_CLEARED;
+#if 0
+       if (NULL != dbuffer->data)
+       {
+               free(dbuffer->data);
+       }/* End of if */
+       dbuffer->data = NULL;
+#endif
+       if(dbuffer->readFp != NULL)
+       {
+               fclose(dbuffer->readFp);
+               dbuffer->readFp = NULL;
+       }
+       if(dbuffer->writeFp != NULL)
+       {
+               fclose(dbuffer->writeFp);
+               dbuffer->writeFp = NULL;
+       }
+       if(strlen(dbuffer->filePath) != 0)
+       {
+               status = remove(dbuffer->filePath);
+               if(status == 0)
+               {
+                       TIZEN_LOGD("File %s Deleted Successfully", dbuffer->filePath);
+               }
+               else
+               {
+                       TIZEN_LOGD("Unable to delete the file %s Error Number [%d] [%s]", dbuffer->filePath, errno, strerror(errno));
+               }
+               memset(dbuffer->filePath,0,200);
+       }
+}/* End of freeBuffer() */
+
+void data_buffer_read_portion(int8 *buff, uint32 size, DataBuffer *dbuffer)
+{
+       uint32 minLen = 0;
+       uint32 freadLen = 0;
+       uint32 bytesCanBeRead  = 0;
+       bytesCanBeRead  = dbuffer->offset - dbuffer->appReadLen;
+       if (bytesCanBeRead > 0)
+       {
+               pthread_mutex_lock(&(dbuffer->mut));
+               minLen = MIN(bytesCanBeRead, size);
+               TIZEN_D_LOGD("Reading from File %s", dbuffer->filePath);
+               freadLen = fread(buff, 1, minLen, dbuffer->readFp);
+               dbuffer->appReadLen = dbuffer->appReadLen + freadLen;
+               pthread_mutex_unlock(&(dbuffer->mut));
+       }
+       return;
+}
+
+void data_buffer_switch_socket(int32 threadId, uint32 otherSpeed, DataBuffer *dbuffer)
+{
+       dbuffer->threadId = threadId;
+       dbuffer->estSpeed = otherSpeed;
+       dbuffer->state = STATE_BLOCKED;
+
+       /* closing current socket */
+       close(dbuffer->socketId);
+}
+
+void data_buffer_exit(DataBuffer *dbuffer)
+{
+       int32 status = 0;
+#if 0
+       if (NULL != dbuffer->data)
+       {
+               free(dbuffer->data);
+       }/* End of if */
+       dbuffer->data = NULL;
+#endif
+
+       if(dbuffer->readFp != NULL)
+       {
+               fclose(dbuffer->readFp);
+               dbuffer->readFp = NULL;
+       }
+       if(dbuffer->writeFp != NULL)
+       {
+               fclose(dbuffer->writeFp);
+               dbuffer->writeFp = NULL;
+       }
+       if(strlen(dbuffer->filePath) != 0)
+       {
+               status = remove(dbuffer->filePath);
+               if(status == 0)
+               {
+                       TIZEN_LOGD("File %s Deleted Successfully", dbuffer->filePath);
+               }
+               else
+               {
+                       TIZEN_LOGD("Unable to delete the file %s Error Number [%d] [%s]", dbuffer->filePath, errno, strerror(errno));
+               }
+               memset(dbuffer->filePath,0,200);
+       }
+       pthread_mutex_destroy(&(dbuffer->mut));
+}
+
+
diff --git a/src/multirat_decode_http.c b/src/multirat_decode_http.c
new file mode 100644 (file)
index 0000000..0a4dcfe
--- /dev/null
@@ -0,0 +1,545 @@
+#include "multirat_decode_http.h"
+
+void decode_http_rsp_init(int8 *rspHeaders, uint32 len, httpResp *dhrsp)
+{
+       memcpy(dhrsp->resp_buff, rspHeaders, len);
+       dhrsp->resp_buff[len] = '\0';
+       dhrsp->http  = NULL;
+       dhrsp->rspcode  = NULL;
+       dhrsp->connection  = NULL;
+       dhrsp->contLen  = NULL;
+       dhrsp->contRange  = NULL;
+       dhrsp->accept_range  = NULL;
+}
+
+int32 decode_http_getvalue(int8 *pBuffer, int8 **pHeaderVal, uint32 offset)
+{
+       int32 pos = 0;
+       int8 *tempVal = NULL;
+
+       pos = decode_http_find_str(pBuffer, END_OF_LINE);
+       if (pos == -1)
+       {
+               return -1;
+       }
+
+       MEM_ALLOC(tempVal, (pos -offset + 1));
+       memcpy(tempVal, pBuffer + offset, pos -offset);
+       tempVal[pos -offset] = '\0';
+       decode_http_trim(tempVal, pHeaderVal);
+
+       free(tempVal);
+       tempVal = NULL;
+       return (pos + 2);
+}/* End of getValue() */
+
+void decode_http_trim(int8 *pBuffer, int8 **pHeaderVal)
+{
+       uint32 i = 0;
+       uint32 leftSpace = 0;
+       uint32 rightSpace = 0;
+       uint32 actualLen = 0;
+       uint32 buffLen = strlen(pBuffer);
+       int8 *tempBuf = NULL;
+
+       for (i = 0; i < buffLen ; i++)
+       {
+               if (pBuffer[i] == ' ')
+               {
+                       leftSpace++;
+               }
+               else
+               {
+                       break;
+               }
+       }
+       for( i = (buffLen -1); i > 0; i--)
+       {
+               if (pBuffer[i] == ' ')
+               {
+                       rightSpace++;
+               }
+               else
+               {
+                       break;
+               }
+       }
+
+       actualLen = buffLen -leftSpace -rightSpace;
+       MEM_ALLOC_RET(*pHeaderVal, (actualLen + 1));
+       tempBuf = *pHeaderVal;
+       memcpy(tempBuf, pBuffer + leftSpace, actualLen);
+       tempBuf[actualLen]  = '\0';
+
+       return;
+}/* End of trim() */
+
+int32 decode_http_find_str(int8 *buff, const char *str)
+{
+       const char *pTemp = NULL;
+
+       if (buff && str )
+       {
+               pTemp = strstr((const char*)buff, (const char*)str);
+               if (pTemp)
+               {
+                       return (int)(pTemp - buff);
+               }
+       }
+       return -1;
+}
+
+
+uint64 decode_http_rsp_get_cont_rnglen(int8 *contRange)
+{
+       int32 pos = 0;
+       uint64 retval = 0;
+       int8 tempVal[MAX_CONT_LEN] = {0};
+
+       pos = decode_http_find_str(contRange, "/");
+       if ((-1 != pos) && (NULL != strstr(contRange, "bytes")))
+       {
+               strncpy(tempVal, (contRange + (pos + 1)),strlen(contRange) -pos);
+               retval = atol(tempVal);
+       }
+       return retval;
+}/* End of getContRngLen() */
+
+int32 process_http_rsp(httpResp *resp)
+{
+       int32 len = 0;
+       int32 retval = HTTP_RSP_DECODING_ERROR;
+       int8 *tempBuff = resp->resp_buff;
+
+       if ( (-1 != decode_http_find_str(tempBuff, "HTTP")))
+               /* to check whether the http version is HTTP 1.1*/
+       {
+               MEM_ALLOC(resp->http, 9);
+               strncpy(resp->http, tempBuff, 8);
+               tempBuff = tempBuff + 9;
+               len = decode_http_find_str(tempBuff, "\r\n");
+               if (-1 != len)
+               {
+                       MEM_ALLOC(resp->rspcode, (len + 1));
+                       memcpy(resp->rspcode, tempBuff, len);
+                       resp->rspcode[len] = '\0';
+                       tempBuff = tempBuff + len + 2;
+                       TIZEN_D_LOGD("resp code [%s]",resp->rspcode);
+               }
+       }
+       else
+       {
+               return retval;
+       }
+
+       while (1)
+       {
+               len = 0;
+               if ((strlen(tempBuff) == LEN_OF_CRLF) && strncmp(tempBuff, END_OF_LINE, LEN_OF_CRLF) == 0)
+               {
+                       retval = HTTP_RSP_DECODING_SUCCESS;
+                       break;
+               }
+               if (strncmp(CONNECTION_RSP_HEADER, tempBuff,LEN_CONNECTION_RSP_HEADER) == 0)
+               {
+                       if ((len = decode_http_getvalue(tempBuff,&(resp->connection),
+                                       LEN_CONNECTION_RSP_HEADER)) == -1)
+                       {
+                               TIZEN_LOGD("Error !!! in decoding connection header");
+                               break;
+                       }
+                       tempBuff = tempBuff + len;
+               }
+               else if (strncmp(CONTRANGE_RSP_HEADER, tempBuff, LEN_CONTRANGE_RSP_HEADER) == 0)
+               {
+                       if ((len = decode_http_getvalue(tempBuff,&resp->contRange,LEN_CONTRANGE_RSP_HEADER)) == -1)
+                       {
+                               TIZEN_LOGD("Error !!! in decoding Content len header");
+                               break;
+                       }
+                       tempBuff = tempBuff + len;
+               }
+               else if (strncmp(LOCATION_RSP_HEADER, tempBuff,  LEN_LOCATION_RSP_HEADER) == 0)
+               {
+                       if ((len = decode_http_getvalue(tempBuff, &resp->location, LEN_LOCATION_RSP_HEADER)) == -1)
+                       {
+                               TIZEN_LOGD("Error !!! in decoding Location Header");
+                               break;
+                       }
+
+                       tempBuff = tempBuff + len;
+               }
+
+               else if (strncmp(CONTLEN_RSP_HEADER, tempBuff,LEN_CONTLEN_RSP_HEADER) == 0)
+               {
+                       if ((len = decode_http_getvalue(tempBuff,&resp->contLen,LEN_CONTLEN_RSP_HEADER)) == -1)
+                       {
+                               TIZEN_LOGD("Error !!! in decoding Content len header");
+                               break;
+                       }
+                       resp->cLen = atol(resp->contLen);
+                       tempBuff = tempBuff + len;
+               }
+               else if (strncmp(ACCEPT_RANGE_REQ_HEADER, tempBuff, LEN_ACCEPT_RANGE_REQ_HEADER) == 0)
+               {
+                       if ((len = decode_http_getvalue(tempBuff,&resp->accept_range,LEN_ACCEPT_RANGE_REQ_HEADER)) == -1)
+                       {
+                               TIZEN_LOGD("Error !!! in decoding Accept Range header");
+                               break;
+                       }
+                       if((resp->accept_range != NULL) && (0 == strcasecmp(resp->accept_range,"none")))
+                       {
+                               resp->acceptFlag = 0;
+                       }
+                       else
+                       {
+                               resp->acceptFlag = 1;
+                       }
+                       tempBuff = tempBuff + len;
+               }
+               else
+               {
+                       len = decode_http_find_str(tempBuff, END_OF_LINE);
+                       if (len == -1)
+                       {
+                               TIZEN_LOGD("invalid header string length [%d] [%s]",strlen(tempBuff), tempBuff);
+                               break;
+                       }
+                       else
+                       {
+                               tempBuff = tempBuff + len+ 2;
+                       }
+               }
+       }
+       if(resp->accept_range == NULL)
+       {
+               /* If Accept Range Field is not present in HTTP Response It means Range is Supported */
+               /* Only When it is Present as Accept-Ranges: none then only it is not supported */
+               resp->acceptFlag = 1;
+       }
+       if (((0 == strncasecmp(resp->rspcode,"302",strlen("302"))) ||
+                       (0 == strncasecmp(resp->rspcode,"301",
+                                       strlen("301"))) ||
+                                       (0 == strncasecmp(resp->rspcode,"300",
+                                       strlen("300"))) ||
+                                       (0 == strncasecmp(resp->rspcode,"303",
+                                       strlen("303")))) && (retval == HTTP_RSP_DECODING_SUCCESS))
+       {
+               retval = HTTP_RSP_REDIRECT;
+       }/* End of else */
+       TIZEN_D_LOGD("return value process http [%d]", retval);
+       return retval;
+}/* End of process_http_rsp */
+
+int32 decode_req_line(httpReq *psHttpReq, int8 *req)
+{
+       int8 *pTempBuff = req;
+       int len_method = 0;
+       int len_version = 0;
+       int len = 0;
+       /* Type of Method */
+       if ((len_method = decode_http_find_str(pTempBuff, "GET")) != -1)
+       {
+               psHttpReq->method = HTTP_GET;
+               pTempBuff = pTempBuff + 4;
+               len_method = len_method + 4;
+       }
+       else if ((len_method = decode_http_find_str(pTempBuff, "POST")) != -1)
+       {
+               psHttpReq->method = HTTP_POST;
+               pTempBuff = pTempBuff + 5;
+               len_method = len_method + 5;
+       }
+       else if ((len_method = decode_http_find_str(pTempBuff, "HEAD")) != -1)
+       {
+               psHttpReq->method = HTTP_HEAD;
+               pTempBuff = pTempBuff + 5;
+               len_method = len_method + 5;
+       }
+       else
+       {
+               TIZEN_LOGD("Error !!! HTTP method is unknown [%s]", psHttpReq->method);
+               return -1;
+       }
+       TIZEN_D_LOGD("Method Lenght [%d]", len_method);
+
+
+/*
+       // HTTP Version
+       if((len_version = decode_http_find_str(pTempBuff, "HTTP")) != -1)
+       {
+               psHttpReq->version = HTTP_VERSION_1_0;
+       }
+       else if((len_version = decode_http_find_str(pTempBuff, "HTTP")) != -1)
+       {
+               psHttpReq->version = HTTP_VERSION_1_1;
+       }
+       else
+       {
+               TIZEN_LOGD("Error !!! HTTP version is unknown [%s]", psHttpReq->version);
+               return -1;
+       }
+*/
+
+       len_version = decode_http_find_str(pTempBuff, "HTTP");
+
+       TIZEN_D_LOGD("Version Length [%d]",len_version);
+
+       pTempBuff = pTempBuff + len_version + 10;
+
+
+       /*PREVENT FIX */
+       if(len_version >= 0 )
+       {
+
+               len = len_version;
+
+               MEM_ALLOC(psHttpReq->url, len);
+               memcpy(psHttpReq->url, req + len_method, len - 1);
+
+               SECURE_DB_INFO("URL: [%s]", psHttpReq->url, len);
+       }
+
+       return (int)(pTempBuff - req);
+}/* End of decode_req_line() */
+
+int32 decode_headers(httpReq *psHttpReq, int8 *headReq)
+{
+       int8 *tempBuf = headReq;
+       int32 len = 0;
+       int32 retval;
+
+       while (1)
+       {
+               retval  = HTTP_RSP_DECODING_ERROR;
+               len = 0;
+               if ((strlen(tempBuf) == LEN_OF_CRLF) && strncmp(tempBuf, END_OF_LINE, LEN_OF_CRLF) == 0)
+               {
+                       retval = HTTP_RSP_DECODING_SUCCESS;
+                       break;
+               }
+
+               if (strncasecmp(CONNECTION_REQ_HEADER, tempBuf, LEN_CONNECTION_REQ_HEADER) == 0)
+               {
+                       if ((len = decode_http_getvalue(tempBuf,&psHttpReq->connection,
+                                       LEN_CONNECTION_REQ_HEADER)) == -1)
+                       {
+                               TIZEN_LOGD("Error !!! in decoding connection header");
+                               break;
+                       }
+                       tempBuf = tempBuf + len;
+               }
+               else if (strncasecmp(ACCEPT_RANGE_REQ_HEADER, tempBuf,LEN_ACCEPT_RANGE_REQ_HEADER) == 0)
+               {
+                       if ((len = decode_http_getvalue(tempBuf,&psHttpReq->accept_range,
+                                       LEN_ACCEPT_RANGE_REQ_HEADER)) == -1)
+                       {
+                               TIZEN_LOGD("Error !!! in decoding Accept header");
+                               break;
+                       }
+                       tempBuf = tempBuf + len;
+
+               }
+               else if (strncasecmp(CONTLEN_REQ_HEADER, tempBuf,LEN_CONTLEN_REQ_HEADER) == 0)
+               {
+                       if ((len = decode_http_getvalue(tempBuf, &psHttpReq->contLen,
+                                       LEN_CONTLEN_REQ_HEADER)) == -1)
+                       {
+                               TIZEN_LOGD("Error !!! in decoding Content len header");
+                               break;
+                       }
+                       tempBuf =  tempBuf + len;
+
+               }
+               else if (strncasecmp(RANGELEN_REQ_HEADER_CMP1, tempBuf, LEN_RANGELEN_REQ_HEADER_CMP1) == 0)
+               {
+                       if ((len = decode_http_getvalue(tempBuf, &psHttpReq->Rangeheader,
+                                       LEN_RANGELEN_REQ_HEADER)) == -1)
+                       {
+                               TIZEN_LOGD("Error !!! in decoding Range len header");
+                               break;
+                       }
+                       tempBuf = tempBuf + len;
+
+               }
+               else if(strncasecmp(RANGELEN_REQ_HEADER_CMP2, tempBuf, LEN_RANGELEN_REQ_HEADER_CMP2) == 0)
+               {
+                       if ((len = decode_http_getvalue(tempBuf, &psHttpReq->Rangeheader,
+                                       LEN_RANGELEN_REQ_HEADER)) == -1)
+                       {
+                               TIZEN_LOGD("Error !!! in decoding Range len header");
+                               break;
+                       }
+                       tempBuf = tempBuf + len;
+
+               }
+
+               else if (strncasecmp(CONTYPE_REQ_HEADER, tempBuf, LEN_CONTYPE_REQ_HEADER) == 0)
+               {
+                       if ((len = decode_http_getvalue(tempBuf, &psHttpReq->contType,
+                                       LEN_CONTYPE_REQ_HEADER)) == -1)
+                       {
+                               TIZEN_LOGD("Error in decoding Content type header");
+                               break;
+                       }
+                       tempBuf = tempBuf + len;
+                       TIZEN_LOGD("Content-Type: [%s]", psHttpReq->contType);
+               }
+
+               else if (strncasecmp(IF_RANGE, tempBuf, LEN_IF_RANGE) == 0)
+               {
+                       if ((len = decode_http_getvalue(tempBuf, &psHttpReq->ifRange,
+                                       LEN_IF_RANGE)) == -1)
+                       {
+                               TIZEN_LOGD("Error in decoding If Range Header");
+                               break;
+                       }
+                       tempBuf = tempBuf + len;
+                       TIZEN_LOGD("If-Range: [%s]", psHttpReq->ifRange);
+               }
+               else
+               {
+                       len = decode_http_find_str(tempBuf, END_OF_LINE);
+                       if (len == -1)
+                       {
+                               printf("invalid Header");
+                               break;
+                       }
+                       else
+                       {
+                               tempBuf = tempBuf + len + 2;
+                       }
+               }
+       }/* End of while */
+       return retval;
+}/* End of decode_headers() */
+
+int32 decode_http_req(httpReq *psHttpReq)
+{
+       int32 len = 0;
+       int32 retval = HTTP_RSP_DECODING_ERROR;
+       int8 *pTempBuff = psHttpReq->req_buff;
+       int8 *headReq = NULL;
+
+       len = decode_req_line(psHttpReq, pTempBuff);
+       if(len < 0)
+       {
+               TIZEN_LOGD("Error !!! Decoding Request Line failed");
+               return retval;;
+       }
+       pTempBuff = pTempBuff + len;
+
+       len = decode_http_find_str(pTempBuff,END_OF_HEADERS);
+       if(len > 0)
+       {
+               /* End of headers found */
+               MEM_ALLOC(headReq,(len+5));
+               memcpy(headReq,pTempBuff,len+4);
+               headReq[len+4]='\0';
+               retval = decode_headers(psHttpReq,headReq);
+               free(headReq);
+               headReq = NULL;
+               pTempBuff = pTempBuff + len + 4;
+       }/* End of if */
+       return retval;
+}/* End of decode_http_req */
+
+void delete_http_rsp(httpResp *dhrsp)
+{
+       if(NULL != dhrsp->connection)
+       {
+               free(dhrsp->connection);
+       }
+       if(NULL != dhrsp->contLen)
+       {
+               free(dhrsp->contLen);
+       }
+       if(NULL != dhrsp->rspcode)
+       {
+               free(dhrsp->rspcode);
+       }
+       if(NULL != dhrsp->contRange)
+       {
+               free(dhrsp->contRange);
+       }
+       if(NULL != dhrsp->location)
+       {
+               free(dhrsp->location);
+       }
+       if(NULL != dhrsp->http)
+       {
+               free(dhrsp->http);
+       }
+       if(NULL != dhrsp->accept_range)
+       {
+               free(dhrsp->accept_range);
+       }
+
+       dhrsp->connection = NULL;
+       dhrsp->contLen = NULL;
+       dhrsp->rspcode = NULL;
+       dhrsp->contRange =  NULL;
+       dhrsp->http = NULL;
+       dhrsp->location = NULL;
+       dhrsp->accept_range = NULL;
+}
+
+void delete_http_req(httpReq *req)
+{
+       if(req->url != NULL)
+       {
+               free(req->url);
+               req->url = NULL;
+       }
+       if(req->accept_range != NULL)
+       {
+               free(req->accept_range);
+               req->accept_range = NULL;
+       }
+       if(req->connection != NULL)
+       {
+               free(req->connection);
+               req->connection = NULL;
+       }
+       if(req->contLen != NULL)
+       {
+               free(req->contLen);
+               req->contLen = NULL;
+       }
+       if(req->Rangeheader != NULL)
+       {
+               free(req->Rangeheader);
+               req->Rangeheader =  NULL;
+       }
+       if(req->contType != NULL)
+       {
+               free(req->contType);
+               req->contType = NULL;
+       }
+       if(req->ifRange != NULL)
+       {
+               free(req->ifRange);
+               req->ifRange = NULL;
+       }
+       if(req->req_buff != NULL)
+       {
+               free(req->req_buff);
+               req->req_buff = NULL;
+       }
+       if(req->req_buff_wo_range != NULL)
+       {
+               free(req->req_buff_wo_range);
+               req->req_buff_wo_range = NULL;
+       }
+       if(req->request[0] != NULL)
+       {
+               free(req->request[0]);
+               req->request[0] =  NULL;
+       }
+       if(req->request[1] != NULL)
+       {
+               free(req->request[1]);
+               req->request[1] =  NULL;
+       }
+}
+
diff --git a/src/multirat_file_buffer.c b/src/multirat_file_buffer.c
new file mode 100644 (file)
index 0000000..a10c8e1
--- /dev/null
@@ -0,0 +1,307 @@
+#include "multirat_process.h"
+#include "multirat_file_buffer.h"
+#include "multirat_conf.h"
+
+
+void file_buffer_init(fileBuffer *fbuffer, uint32 brafMode)
+{
+       fbuffer->socketId = -1;
+       fbuffer->offset = 0;
+       fbuffer->startOffset = 0;
+       fbuffer->endOffset = 0;
+       fbuffer->totalLen = 0;
+       fbuffer->appReadLen = 0;
+       fbuffer->interface = 0;
+       fbuffer->readFp = NULL;
+       fbuffer->writeFp = NULL;
+       fbuffer->file_flush_offset = 0;
+       fbuffer->fThread_read = 0;
+       fbuffer->nodeType = FILE_NODE;
+       fbuffer->state = NODE_STATE_NOT_READ;
+       fbuffer->next = NULL;
+       fbuffer->bRafMode = brafMode;
+       pthread_mutex_init(&(fbuffer->mut), NULL);
+}
+
+void file_buffer_exit(fileBuffer *fbuffer)
+{
+       TIZEN_LOGD("File %p", fbuffer);
+       if(fbuffer->readFp != NULL)
+       {
+               fclose(fbuffer->readFp);
+               fbuffer->readFp = NULL;
+       }
+       if(fbuffer->writeFp != NULL)
+       {
+               if(!fbuffer->bRafMode)
+                       fclose(fbuffer->writeFp);
+               fbuffer->writeFp = NULL;
+       }
+       if(strlen(fbuffer->filePath) != 0)
+       {
+               int32 status = remove(fbuffer->filePath);
+               if(status == 0)
+               {
+                       TIZEN_LOGD("File [%s] Deleted Successfully", fbuffer->filePath);
+                       TIZEN_LOGD("Node [%s] Memory [%x] Type [%u] Start Offset [%llu] end Offset [%llu] total length [%llu]", fbuffer->filePath, fbuffer, fbuffer->nodeType, fbuffer->startOffset, fbuffer->endOffset, fbuffer->totalLen);
+               }
+               else
+               {
+                       TIZEN_LOGD("Unable to delete the file [%s] Error Number [%d] [%s]", fbuffer->filePath, errno, strerror(errno));
+               }
+               memset(fbuffer->filePath,0,200);
+       }
+       if(fbuffer->socketId >= 0)
+       {
+               CLOSE_SOCKET(fbuffer->socketId);
+               fbuffer->socketId = 0;
+       }
+       fbuffer->state = NODE_STATE_CLEARED;
+
+       pthread_mutex_destroy(&(fbuffer->mut));
+}
+
+void file_buffer_init_node(fileBuffer *fbuffer, int64 *chunkInfo, int32 socketId, uint32 nodeType, SmartBondingData *SBData, uint32 fThread_read)
+{
+       uint32 brafMode = SBData->bRafMode;
+       fbuffer->state = NODE_STATE_DOWNLOADING;
+
+       fbuffer->startOffset = chunkInfo[0];
+       fbuffer->endOffset = chunkInfo[1];
+
+       fbuffer->totalLen = chunkInfo[1] - chunkInfo[0] + 1;
+
+       fbuffer->socketId = socketId;
+       fbuffer->nodeType = nodeType;
+       fbuffer->bRafMode = brafMode;
+       if(!brafMode)
+       {
+               memset(fbuffer->filePath,0,200);
+               sprintf(fbuffer->filePath,"%s%d%s%lld%s%lld","/opt/usr/media/",getpid(),"-",chunkInfo[0],"-",chunkInfo[1]);
+               TIZEN_LOGD("Created File [%s]", fbuffer->filePath);
+
+               fbuffer->writeFp = fopen(fbuffer->filePath,"w");
+               if(fbuffer->writeFp == NULL)
+               {
+                       TIZEN_LOGD("unable to open(write) file");
+               }
+
+               fbuffer->readFp = fopen(fbuffer->filePath,"r");
+               if(fbuffer->readFp == NULL)
+               {
+                       TIZEN_LOGD("unable to open(read) file");
+               }
+               fbuffer->fThread_read = fThread_read;
+       }
+       else
+       {
+               fbuffer->readFp = NULL;
+               /*RAF mode file is already opening to same common file, so just align the file pointer */
+               fbuffer->writeFp = SBData->raFileMngr.writeFD2;
+               if(NULL == fbuffer->writeFp)
+               {
+                       TIZEN_LOGD("SBData[%p] ERROR SBData->raFileMngr.writeFD2 is NULL for [%s]", SBData, SBData->rafFileName);
+               }
+               else
+               {
+                       if( -1 == fseek(fbuffer->writeFp,chunkInfo[0],SEEK_SET))
+                       {
+                               TIZEN_LOGD("SBData[%p] ERROR [%s] fseek [%llu] failed", SBData, SBData->rafFileName, chunkInfo[0]);
+                       }
+               }
+       }
+       TIZEN_LOGD("Node Memory [%x] Type [%d] Start Offset [%llu] end Offset [%llu] total length [%llu]", fbuffer, fbuffer->nodeType, fbuffer->startOffset, fbuffer->endOffset, fbuffer->totalLen);
+}
+
+void file_buffer_reinit_node(fileBuffer *fbuffer, uint32 socket, uint32 nodeType)
+{
+       fbuffer->state = NODE_STATE_DOWNLOADING;
+       fbuffer->nodeType = nodeType;
+       if(fbuffer->socketId > 0)
+       {
+               CLOSE_SOCKET(fbuffer->socketId);
+       }
+       fbuffer->socketId = -1;
+       if(socket > 0)
+       {
+               fbuffer->socketId = socket;
+       }
+       TIZEN_LOGD("Node [%s] Memory [%x] Type [%u] Start Offset [%llu] end Offset [%llu] total length [%llu]", fbuffer->filePath, fbuffer, fbuffer->nodeType, fbuffer->startOffset, fbuffer->endOffset, fbuffer->totalLen);
+}
+
+
+
+void file_buffer_add(fileBuffer *fbuffer, int8 *buff, uint64 size, int64 *chunkInfo, uint64 rcvdRsp, SmartBondingData *SBData)
+{
+       pthread_mutex_lock(&(fbuffer->mut));
+       TIZEN_D_LOGD("Enter write Data into FILE [%llu]", size);
+
+       if(fbuffer->offset == 0)
+       {
+               TIZEN_LOGD("Started Writing into File Node [%x] Total Length [%llu]", fbuffer, file_buffer_getTotalLen(fbuffer));
+       }
+
+       if(fbuffer->offset == file_buffer_getTotalLen(fbuffer))
+       {
+               TIZEN_LOGD("File Node [%x] Total Length [%llu] is Completed",fbuffer, file_buffer_getTotalLen(fbuffer));
+               fbuffer->state = NODE_STATE_FULL_READ;
+       }
+       if(size != fwrite(buff,1,size, fbuffer->writeFp))
+       {
+               TIZEN_LOGD("Error: File Node [%x] Write size [%llu] failed ",fbuffer, size);
+       }
+
+       if(fbuffer->bRafMode)
+               fflush(fbuffer->writeFp);
+
+       fbuffer->offset = fbuffer->offset + size;
+
+       if(fbuffer->offset == file_buffer_getTotalLen(fbuffer))
+       {
+               TIZEN_LOGD("File Node [%x] Total Length [%llu] is Completed",fbuffer, file_buffer_getTotalLen(fbuffer));
+               fbuffer->state = NODE_STATE_FULL_READ;
+       }
+       pthread_mutex_unlock(&(fbuffer->mut));
+       TIZEN_D_LOGD("Exit write Data into FILE [%llu]", size);
+}
+
+void file_buffer_read_from_file(fileBuffer *fbuffer, int8 *buff, uint64 *size)
+{
+       uint32 bytesCanBeRead = 0;
+       uint32 minLen = 0;
+       uint32 freadLen = 0;
+       pthread_mutex_lock(&(fbuffer->mut));
+       TIZEN_D_LOGD("File Node [%x] size [%llu] read start", fbuffer, *size);
+
+       if(fbuffer->appReadLen == 0)
+       {
+               TIZEN_LOGD("Started Reading From File Node [%x] Total Length [%llu]", fbuffer, file_buffer_getTotalLen(fbuffer));
+       }
+       
+       bytesCanBeRead  = fbuffer->offset - fbuffer->appReadLen;
+       minLen = MIN(bytesCanBeRead, *size);
+
+       if(fbuffer->bRafMode)
+       {
+               if(bytesCanBeRead > 0xffffffff)
+               {
+                       bytesCanBeRead = 0xffffffff; /*as sb_read_data return in u32bit*/
+                       TIZEN_LOGD("File Node [%x] Total Length [%llu] bytesCanBeRead is greater than 0xffffffff", fbuffer, file_buffer_getTotalLen(fbuffer));
+               }
+               *size = bytesCanBeRead;
+               freadLen = bytesCanBeRead;
+       }
+       else
+       {
+               if(fbuffer->file_flush_offset < fbuffer->offset)
+               {
+                       fbuffer->file_flush_offset = fbuffer->offset;
+                       fflush(fbuffer->writeFp);
+                       TIZEN_LOGD("Flush File [%x]", fbuffer);
+               }
+               freadLen = fread(buff, 1, minLen, fbuffer->readFp);
+               *size = freadLen;
+       }
+
+       fbuffer->appReadLen = fbuffer->appReadLen + freadLen;
+
+       if(fbuffer->appReadLen == file_buffer_getTotalLen(fbuffer))
+       {
+               TIZEN_LOGD("File Node [%x] Total Length [%llu] is Completed", fbuffer, file_buffer_getTotalLen(fbuffer));
+               fbuffer->state = NODE_STATE_CLEARED;
+       }
+       pthread_mutex_unlock(&(fbuffer->mut));
+       TIZEN_D_LOGD("File Node [%x] size [%llu] is read done", fbuffer, *size);
+}
+
+void  file_buffer_read_from_socket(fileBuffer *fbuffer, uint32 size)
+{
+       pthread_mutex_lock(&(fbuffer->mut));
+
+       if(fbuffer->appReadLen == 0)
+       {
+               TIZEN_LOGD("Started Reading From Socket Node [%x] Total Length [%llu]", fbuffer, file_buffer_getTotalLen(fbuffer));
+       }
+
+       fbuffer->appReadLen = fbuffer->appReadLen + size;
+       fbuffer->offset = fbuffer->offset + size;
+       if(fbuffer->offset == file_buffer_getTotalLen(fbuffer))
+       {
+               TIZEN_LOGD("Socket Node [%x] Total Length [%llu] is Completed", fbuffer, file_buffer_getTotalLen(fbuffer));
+               fbuffer->state = NODE_STATE_CLEARED;
+       }
+       pthread_mutex_unlock(&(fbuffer->mut));
+}
+
+uint32 file_buffer_getState(fileBuffer *fbuffer)
+{
+       return fbuffer->state;
+}
+
+uint32 file_buffer_getType(fileBuffer *fbuffer)
+{
+       return fbuffer->nodeType;
+}
+
+uint64 file_buffer_noOfRspBytes(fileBuffer *fbuffer)
+{
+       return ((fbuffer->offset - fbuffer->appReadLen));
+}
+
+uint64 file_buffer_getTotalLen(fileBuffer *fbuffer)
+{
+       return fbuffer->totalLen;
+}
+
+uint64 file_buffer_getStrtOffset(fileBuffer *fbuffer)
+{
+       return fbuffer->startOffset;
+}
+
+uint64 file_buffer_getEndOffset(fileBuffer *fbuffer)
+{
+       return fbuffer->endOffset;
+}
+
+uint64 file_buffer_getOffset(fileBuffer *fbuffer)
+{
+       return fbuffer->offset;
+}
+
+uint32 file_buffer_getSocketId(fileBuffer *fbuffer)
+{
+       return fbuffer->socketId;
+}
+
+uint32 file_buffer_getNodeType(fileBuffer *fbuffer)
+{
+       return fbuffer->nodeType;
+}
+
+void file_buffer_setTotalLen(int newLen, fileBuffer *fbuffer)
+{
+       fbuffer->totalLen = newLen;
+       TIZEN_LOGD("Node [%s] Memory [%x] Type [%d] Start Offset [%llu] end Offset [%llu] total length [%llu]",
+               fbuffer->filePath, fbuffer, fbuffer->nodeType, fbuffer->startOffset, fbuffer->endOffset, fbuffer->totalLen);
+}
+
+uint64 file_buffer_getReadRspLen(fileBuffer *fbuffer)
+{
+       return fbuffer->appReadLen;
+}
+
+void check_set_filebuff_state(fileBuffer *tempBuff)
+{
+       if(tempBuff->offset == file_buffer_getTotalLen(tempBuff))
+       {
+               TIZEN_LOGD("File Node [%x] Total Length [%llu] is Already Written", tempBuff, file_buffer_getTotalLen(tempBuff));
+               tempBuff->state = NODE_STATE_FULL_READ;
+       }
+
+       if(tempBuff->appReadLen == file_buffer_getTotalLen(tempBuff))
+       {
+               TIZEN_LOGD("File Node [%x] Total Length [%llu] is Already Completed", tempBuff, file_buffer_getTotalLen(tempBuff));
+               tempBuff->state = NODE_STATE_CLEARED;
+       }
+}
+
diff --git a/src/multirat_file_manager.c b/src/multirat_file_manager.c
new file mode 100644 (file)
index 0000000..12f317b
--- /dev/null
@@ -0,0 +1,728 @@
+#include "multirat_file_buffer.h"
+#include "multirat_file_manager.h"
+#include "multirat_process.h"
+#include "multirat_conf.h"
+#include "multirat_process.h"
+#define MAX_TIMEFORALL_BY0 5
+#define MAX_TIMEFORALL_BY1 4
+
+#define SAME_INTERFACE_NO_DIVIDE 0
+#define CHANGE_INTERFACE_NO_DIVIDE 2
+#define DIVIDE 1
+
+void file_manager_init(fileStream *fStream, fileManager *fileMgr)
+{
+       fileMgr->ExpectedBytes = (fStream->mainSockExpBytes);
+       fileMgr->rspRead = fStream->mainSockRead;
+       fileMgr->totalLen = fStream->totalLen;
+       fileMgr->strtOffset = fStream->strtOffset;
+       fileMgr->fbuffer = &fStream->fileBuff;
+       fileMgr->thread_exception = B_FALSE;
+       pthread_mutex_init(&(fileMgr->mutex), NULL);
+}
+
+fileBuffer *file_manager_getNextChunkForFileThread(int64 *chunkInfo, SmartBondingData *SBData)
+{
+       fileManager *fileMgr = SBData->fStream->fileMgr;
+       fileStream *fStream = SBData->fStream;
+       fileThread *fThread = fStream->fThread;
+       fileBuffer *newfileBuf = NULL;
+
+       pthread_mutex_lock(&(fileMgr->mutex));
+       TIZEN_LOGD("Get Next Chunk For File Thread");
+
+       // This is First Chunk Alloted for the File Thread
+       if(*fileMgr->fbuffer == NULL)
+       {
+               TIZEN_LOGD("First Chunk");
+               chunkInfo[0] = *fileMgr->ExpectedBytes + fileMgr->strtOffset;
+               chunkInfo[1] =  fileMgr->totalLen - 1 + fileMgr->strtOffset;
+
+               newfileBuf = (fileBuffer *)malloc(sizeof(fileBuffer));
+               if(newfileBuf == NULL)
+               {
+                       TIZEN_LOGD("File Buffer Allocation Failed");
+                       pthread_mutex_unlock(&(fileMgr->mutex));
+                       return NULL;
+               }
+               memset(newfileBuf, 0, sizeof(fileBuffer));
+               file_buffer_init_node(newfileBuf, chunkInfo, -1, FILE_NODE, SBData, 0);
+               newfileBuf->next = NULL;
+               *fileMgr->fbuffer = newfileBuf;
+
+               TIZEN_LOGD("New Node Created [%x] and Total length [%llu] New Node [%x]", newfileBuf, file_buffer_getTotalLen(newfileBuf), fStream->fileBuff);
+       }
+       // This is For handling the case where File Thread just comes up and starts downloading but main is reading File Buffer ...
+       // In that it will continue to use File Buffer:
+       // IO Exception of Main Thread And IO exception of File Thread handled Similarly
+       if(SBData->status == MAIN_COMPLETE)
+       {
+               TIZEN_LOGD("Main Complete");
+               fThread->status = MAIN_COMPLETE;
+       }
+       // This is Handling Case When File Thread vitness IO Exception or Main Thread IO Exception
+       if(fThread->status == FILE_IO_EXCEPTION)
+       {
+               TIZEN_LOGD("File Io Exception");
+               newfileBuf = file_manager_get_next_chunk_handle_file_io_exception(fileMgr, chunkInfo);
+       }
+
+       // This is For Handling Case When Main Thread is Complete
+       else if(fThread->status == MAIN_COMPLETE)
+       {
+               TIZEN_LOGD("Main Thread Completed");
+               newfileBuf = file_manager_get_next_chunk_handle_main_complete(fileMgr, chunkInfo);
+       }
+
+       // This is For Handling Case When File Thread has Finished
+       else if(fThread->status == FILE_COMPLETE)
+       {
+               TIZEN_LOGD("File Thread Complete");
+               newfileBuf = file_manager_get_next_chunk_handle_file_complete(fileMgr, chunkInfo);
+       }
+
+       // Finally Setting main thread Status to Start
+       SBData->status = MAIN_START;
+       pthread_mutex_unlock(&(fileMgr->mutex));
+       return newfileBuf;
+}
+
+
+fileBuffer *file_manager_getReadingNode(fileManager *fileMgr)
+{
+       fileBuffer *tempBuff = *fileMgr->fbuffer;
+       uint32 state = 0;
+
+       while(tempBuff != NULL)
+       {
+               state = file_buffer_getState(tempBuff);
+               if(state == NODE_STATE_DOWNLOADING || state == NODE_STATE_BLOCKED || state == NODE_STATE_FULL_READ)
+               {
+                       break;
+               }
+               tempBuff = tempBuff->next;
+       }
+       return tempBuff;
+}
+
+
+fileBuffer *file_manager_getDownloadingNode(fileManager *fileMgr)
+{
+       fileBuffer *tempBuff = *fileMgr->fbuffer;
+       uint32 state = 0;
+
+       while(tempBuff != NULL)
+       {
+               state = file_buffer_getState(tempBuff);
+               if(state == NODE_STATE_DOWNLOADING || state == NODE_STATE_BLOCKED)
+               {
+                       break;
+               }
+               tempBuff = tempBuff->next;
+       }
+       return tempBuff;
+}
+
+fileBuffer *file_manager_getDownloadingFileNode(fileManager *fileMgr)
+{
+       fileBuffer *tempBuff = *fileMgr->fbuffer;
+       uint32 state = 0;
+       uint32 type = 0;
+       while(tempBuff != NULL)
+       {
+               state = file_buffer_getState(tempBuff);
+               type = file_buffer_getType(tempBuff);
+               if((state == NODE_STATE_DOWNLOADING || state == NODE_STATE_BLOCKED) && (type == FILE_NODE))
+               {
+                       break;
+               }
+               tempBuff = tempBuff->next;
+       }
+       TIZEN_LOGD("Download File Node [%x]",tempBuff);
+       return tempBuff;
+}
+
+uint32 file_manager_divideCont(uint64 remCont, int64 *contInfo, fileManager *fileMgr, uint32 nodeType)
+{
+       double temp2 = 0;
+       uint64 temp = 0;
+       SmartBondingData *SBData = fileMgr->SBData;
+       uint32 other_index = 0;
+
+       uint32 index_main = file_manager_get_main_thread_interface(fileMgr);
+       uint32 index_file = file_manager_get_file_thread_interface(fileMgr);
+
+       uint64 interfaceSpeed0 = 0;
+       uint64 interfaceSpeed1 = 0;
+
+       if(nodeType == FILE_NODE)
+       {
+               other_index = index_main;
+               interfaceSpeed0 = SBData->speed[index_file];
+               interfaceSpeed1 = SBData->speed[index_main];
+       }
+       else
+       {
+               other_index = index_file;
+               interfaceSpeed1 = SBData->speed[index_file];
+               interfaceSpeed0 = SBData->speed[index_main];
+       }
+
+       uint64 temp_cal = 0;
+       uint64 temp_time0 = 0;
+       double ratio = 0;
+       uint64 time0= 0;
+       uint64 time1= 0;
+       if(interfaceSpeed1)
+               ratio = MAX(0.1, MIN(10,(float)interfaceSpeed0/(float)interfaceSpeed1));
+       else
+       {
+               TIZEN_LOGD("ratio assigned 10 value as interfaceSpeed1 is 0");
+               ratio = 10;
+       }
+
+       TIZEN_LOGD("RemainContent [%llu] Interface0 Speed [%llu] Interface1 Speed [%llu] Ratio [%lf]", remCont, interfaceSpeed0, interfaceSpeed1, ratio);
+       temp2 = (float)(remCont)/(ratio + 1);
+       temp = abs(temp2);
+       time0 = (temp2 * 8 )/interfaceSpeed0;
+       time1 = (temp2 * 8 )/interfaceSpeed1;
+
+       TIZEN_LOGD("temp [%llu] temp2 [%lf] time0 [%llu] time1 [%llu]", temp, temp2,time0,time1);
+
+
+       temp_time0 = ((remCont - temp)*8)/interfaceSpeed0;
+       TIZEN_LOGD("temp_time0 [%llu]", temp_time0);
+
+       // 2 sec for slow start
+       if(time0 < 2)
+       {
+               TIZEN_LOGD("Time Less Than 2 Sec, same inter. no divide");
+               return SAME_INTERFACE_NO_DIVIDE;
+       }
+       else
+       {
+               TIZEN_LOGD("Dividing");
+               /* Stores the seconds for which we have initial bytes captured for this interface */
+               uint64 new_connection_slow_time = MIN(SBData->sStat.timeArray[other_index], MAX_HISTORY-1);
+               uint64 bytes_loss1 = 0;
+               uint64 bytes_loss0 = 0;
+
+               if(time1 < new_connection_slow_time)
+                       new_connection_slow_time = time1;
+
+               uint64 bytes_speed = 0; /* Bytes based on speed in specific time */
+               uint64 bytes_loss_slow_start = 0; /* Bytes loss as connection was in slow start initially */
+               /* Initial new_connection_slow_time seconds we get only below bytes in temp_cal */
+               temp_cal = SBData->sStat.dataArray[other_index][new_connection_slow_time];
+
+               /* As per the interfacespeed we should get this many bytes*/
+               bytes_speed = new_connection_slow_time * interfaceSpeed1/8;
+               if(bytes_speed > temp_cal)
+                       bytes_loss_slow_start = bytes_speed - temp_cal;
+
+               /* Now we should divide again this more load bytes_loss_slow_start on other_index
+               across two interfaces, so divide this in two parts based on speed ration and
+               now see  */
+               bytes_loss1 = (float)(bytes_loss_slow_start)/(ratio + 1);
+               bytes_loss0 = bytes_loss_slow_start - bytes_loss1;
+               if(temp > bytes_loss0)
+                       temp -= bytes_loss0;
+
+               TIZEN_LOGD("new_conn_slow [%llu] loss0 [%llu] loss1 [%llu] bytes_speed [%llu], temp_cal [%llu], bytes_loss_slow_start [%llu] temp [%llu]", new_connection_slow_time, bytes_loss0, bytes_loss1, bytes_speed,temp_cal, bytes_loss_slow_start, temp);
+
+               contInfo[1] = temp;
+               contInfo[0] = remCont - temp;
+       }
+       TIZEN_LOGD("First Part [%lld] Second part [%lld]", contInfo[0], contInfo[1]);
+       return DIVIDE;
+}
+
+uint32 file_manager_divideRemCont(uint64 remCont, fileManager *fileMgr, uint32 nodeType)
+{
+       TIZEN_LOGD("Divide remCont [%llu]", remCont);
+       SmartBondingData *SBData = fileMgr->SBData;
+       uint32 index_main = file_manager_get_main_thread_interface(fileMgr);
+       uint32 index_file = file_manager_get_file_thread_interface(fileMgr);
+       uint32 other_index = 0;
+       uint64 temp_data1 = 0;
+       if(SBData->division_count++ > 5)
+       {
+               TIZEN_LOGD("MAX DIVISION COUNT REACHED...  No more division ");
+               return SAME_INTERFACE_NO_DIVIDE;
+       }
+       TIZEN_LOGD("DIVISION COUNT is [%d]",SBData->division_count);
+
+       if(remCont > (MAX_BLOCK_SIZE* 4))
+       {
+               double interfaceTime0 = 0;
+               double interfaceTime1 = 0;
+               uint64 interfaceSpeed0 = 0;
+               uint64 interfaceSpeed1 = 0;
+
+               if(nodeType == FILE_NODE)
+               {
+                       other_index = index_main;
+                       if((SBData->speed[index_file] == 0))
+                       {
+                               TIZEN_LOGD("idx main [%d] file [%d] speed file index 0, CHANGE_INTERFACE_NO_DIVIDE", index_main, index_file);
+                               return CHANGE_INTERFACE_NO_DIVIDE;
+                       }
+                       if((SBData->speed[index_main] == 0))
+                       {
+                               TIZEN_LOGD("idx main [%d] file [%d] speed main index 0, SAME_INTERFACE_NO_DIVIDE", index_main, index_file);
+                               return SAME_INTERFACE_NO_DIVIDE;
+                       }
+                       interfaceSpeed0 = SBData->speed[index_file];
+                       interfaceSpeed1 = SBData->speed[index_main];
+                       interfaceTime0 = (float)(remCont*8)/ (float)interfaceSpeed0;
+                       interfaceTime1 = (float)(remCont*8)/ (float)interfaceSpeed1;
+               }
+               else
+               {
+                       other_index = index_file;
+                       if((SBData->speed[index_main] == 0))
+                       {
+                               TIZEN_LOGD("Skt idx main [%d] file [%d] speed main index 0, CHANGE_INTERFACE_NO_DIVIDE", index_main, index_file);
+                               return CHANGE_INTERFACE_NO_DIVIDE;
+                       }
+                       if((SBData->speed[index_file] == 0))
+                       {
+                               TIZEN_LOGD("Skt idx main [%d] file [%d] speed file index 0, SAME_INTERFACE_NO_DIVIDE", index_main, index_file);
+                               return SAME_INTERFACE_NO_DIVIDE;
+                       }
+                       interfaceSpeed1 = SBData->speed[index_file];
+                       interfaceSpeed0 = SBData->speed[index_main];
+                       interfaceTime1 = (float)(remCont*8)/ (float)interfaceSpeed1;
+                       interfaceTime0 = (float)(remCont*8)/ (float)interfaceSpeed0;
+               }
+
+               TIZEN_LOGD("Interface0 Speed [%llu] Interface1 Speed [%llu]", interfaceSpeed0, interfaceSpeed1);
+               TIZEN_LOGD("Interface0 Time [%lf] Interface1 time [%lf]", interfaceTime0, interfaceTime1);
+               TIZEN_LOGD("Time Array Other Interface Index [%llu]", SBData->sStat.timeArray[other_index]);
+               if(SBData->sStat.timeArray[other_index] < MAX_TIMEFORALL_BY1)
+               {
+
+                       temp_data1 = SBData->sStat.dataArray[other_index][SBData->sStat.timeArray[other_index]] + (interfaceSpeed1 *
+                       (MAX_TIMEFORALL_BY1 - SBData->sStat.timeArray[other_index]))/8;
+               }
+               else
+               {
+                       temp_data1 = SBData->sStat.dataArray[other_index][MAX_TIMEFORALL_BY1];
+               }
+
+               TIZEN_LOGD("tmpdata1 Data in 4 secs [%llu]", temp_data1);
+               if(interfaceTime0 < MAX_TIMEFORALL_BY0)
+               {
+                       TIZEN_LOGD("The Current interface Time Less Than 5");
+                       return SAME_INTERFACE_NO_DIVIDE;
+               }
+               else if((interfaceTime1 < MAX_TIMEFORALL_BY1) && (remCont <= temp_data1))
+               {
+                       TIZEN_LOGD("Other interface Time Less Than 4");
+                       return CHANGE_INTERFACE_NO_DIVIDE;
+               }
+               else if(interfaceSpeed1 < 2000)
+               {
+                       TIZEN_LOGD("Speed of other Interface is less");
+                       return SAME_INTERFACE_NO_DIVIDE;
+               }
+               else if(interfaceSpeed0 < 2000)
+               {
+                       TIZEN_LOGD("Speed of This Interface is less");
+                       return CHANGE_INTERFACE_NO_DIVIDE;
+               }
+               return DIVIDE;
+       }
+       else
+       {
+               TIZEN_LOGD("Remaing Content is Less");
+               return SAME_INTERFACE_NO_DIVIDE;
+       }
+}
+
+void file_manager_setSpeed(uint32 index, uint32 speed, SmartBondingData *SBData)
+{
+       SBData->speed[index] = speed;
+}
+
+void file_manager_exit(fileManager *fileMgr)
+{
+       pthread_mutex_destroy(&(fileMgr->mutex));
+}
+
+uint32 file_manager_get_file_thread_interface(fileManager *fileMgr)
+{
+       return  fileMgr->interface[FILE_THREAD];
+}
+uint32 file_manager_get_main_thread_interface(fileManager *fileMgr)
+{
+       return fileMgr->interface[MAIN_THREAD];
+}
+
+uint32 file_manager_check_main_thread_status(fileManager *fileMgr)
+{
+       return fileMgr->SBData->status;
+}
+
+fileBuffer * file_manager_get_next_chunk_handle_file_io_exception(fileManager *fileMgr, int64 *chunkInfo)
+{
+       fileBuffer *tempBuff = file_manager_getDownloadingFileNode(fileMgr);
+       fileBuffer *newfileBuf = NULL;
+       if(tempBuff != NULL)
+       {
+               pthread_mutex_lock(&(tempBuff->mut));
+               uint64 socketOffset = file_buffer_getOffset(tempBuff);
+               TIZEN_LOGD("Data in File Node is [%llu]", socketOffset);
+               newfileBuf = tempBuff;
+               chunkInfo[0] = tempBuff->startOffset + socketOffset;
+               chunkInfo[1] = tempBuff->endOffset;
+               file_buffer_reinit_node(newfileBuf, -1, FILE_NODE);
+               pthread_mutex_unlock(&(tempBuff->mut));
+       }
+       return newfileBuf;
+}
+
+fileBuffer * file_manager_get_next_chunk_handle_main_complete(fileManager *fileMgr, int64 *chunkInfo)
+{
+       fileBuffer *newfileBuf = NULL;
+       fileBuffer *tempBuff = file_manager_getDownloadingFileNode(fileMgr);
+       uint64 remContent = 0;
+       uint32 divide = B_FALSE;
+       int64 contInfo[2] = {0};
+
+       if(tempBuff != NULL)
+       {
+               pthread_mutex_lock(&(tempBuff->mut));
+               TIZEN_LOGD("Offset of Downloading File Buffer [%llu]", file_buffer_getOffset(tempBuff));
+               uint64 socketOffset = file_buffer_getOffset(tempBuff);
+
+               if(socketOffset == 0)
+               {
+                       TIZEN_LOGD("Data in File Node is Zero Making as Socket Node");
+                       file_manager_SwitchSocketNoData(tempBuff, fileMgr);
+                       pthread_mutex_unlock(&(tempBuff->mut));
+                       return NULL;
+               }
+
+               remContent = file_buffer_getTotalLen(tempBuff) - socketOffset;
+               TIZEN_LOGD("Remaining Content [%llu] offset [%llu]", remContent, socketOffset);
+
+               divide =  file_manager_divideRemCont(remContent, fileMgr, FILE_NODE);
+               //divide = 1;
+               if(!divide)
+               {
+                       TIZEN_LOGD("Make This File Node as Socket Node and Continue Downloading");
+                       TIZEN_LOGD("Data in File Node is Not Zero Creating New Socket Node and Use Same Interface");
+                       newfileBuf = file_manager_SwitchSocketData(tempBuff, fileMgr, chunkInfo, 0);
+               }
+               else
+               {       //divide = 2;
+                       if(divide == CHANGE_INTERFACE_NO_DIVIDE)
+                       {
+                               TIZEN_LOGD("Data in File Node is Not Zero Creating New Socket Node and Use Diff Interface");
+                               newfileBuf = file_manager_SwitchSocketData(tempBuff, fileMgr, chunkInfo, 1);
+                       }
+                       else
+                       {
+                               TIZEN_LOGD("Division According to Speed");
+                               divide = file_manager_divideCont(remContent, contInfo, fileMgr, FILE_NODE);
+                               TIZEN_LOGD("Divide [%d]",divide);
+                               //divide = 1;
+                               if(!divide)
+                               {
+                                       TIZEN_LOGD("Data in File is not Zero, Creating new Socket Node and Use Same Interface");
+                                       newfileBuf = file_manager_SwitchSocketData(tempBuff, fileMgr, chunkInfo, 0);
+                               }
+                               else
+                               {
+                                       TIZEN_LOGD("Need to Divide File Node");
+                                       fileBuffer *newfileBuftemp =  NULL;
+                                       TIZEN_LOGD("Data in File is not Zero, Make 3 Nodes");
+                                       file_buffer_setTotalLen(socketOffset, tempBuff);
+                                       TIZEN_LOGD("Set the Total Lenght to offset [%llu]", socketOffset);
+
+                                       check_set_filebuff_state(tempBuff);
+
+                                       newfileBuf = (fileBuffer *)malloc(sizeof(fileBuffer));
+                                       memset(newfileBuf, 0, sizeof(fileBuffer));
+                                       chunkInfo[0] = file_buffer_getStrtOffset(tempBuff) + file_buffer_getTotalLen(tempBuff);
+                                       chunkInfo[1] = chunkInfo[0] + contInfo[0] - 1;
+                                       TIZEN_LOGD("Start Offset [%llu] Total length [%llu]", file_buffer_getStrtOffset(tempBuff), file_buffer_getTotalLen(tempBuff));
+                                       TIZEN_LOGD("Chunk 0 [%lld] Chunk 1 [%lld] cont [%lld]", chunkInfo[0], chunkInfo[1], contInfo[0]);
+                                       //TIZEN_LOGD("ichunk 0 %lld ichunk 1 %lld cont %lld", chunkInfo[0], chunkInfo[1], contInfo[0]);
+                                       file_buffer_init_node(newfileBuf, chunkInfo, tempBuff->socketId, SOCKET_NODE, fileMgr->SBData, 0);
+                                       fileMgr->interface[MAIN_THREAD] = (fileMgr->interface[MAIN_THREAD] + 1) % 2;
+                                       fileMgr->interface[FILE_THREAD] = (fileMgr->interface[FILE_THREAD] + 1) % 2;
+                                       fileMgr->SBData->interface_index = fileMgr->interface[MAIN_THREAD];
+                                       newfileBuf->next = tempBuff->next;
+                                       tempBuff->next = newfileBuf;
+
+                                       TIZEN_LOGD("New Node Created [%x] and Total length [%llu]", newfileBuf, file_buffer_getTotalLen(newfileBuf));
+                                       newfileBuftemp = (fileBuffer *)malloc(sizeof(fileBuffer));
+                                       memset(newfileBuftemp, 0, sizeof(fileBuffer));
+
+                                       chunkInfo[0] = chunkInfo[1] + 1;
+                                       chunkInfo[1] = tempBuff->endOffset;
+
+                                       tempBuff->endOffset = file_buffer_getStrtOffset(tempBuff) + file_buffer_getTotalLen(tempBuff) - 1;
+
+                                       file_buffer_init_node(newfileBuftemp, chunkInfo, -1, FILE_NODE, fileMgr->SBData, 0);
+                                       newfileBuftemp->next = newfileBuf->next;
+                                       newfileBuf->next = newfileBuftemp;
+                                       newfileBuf = newfileBuftemp;
+                                       TIZEN_LOGD("New Node Created [%x] and Total length [%llu]", newfileBuf, file_buffer_getTotalLen(newfileBuf));
+                               }
+                       }
+               }
+               pthread_mutex_unlock(&(tempBuff->mut));
+       }
+       return newfileBuf;
+}
+
+fileBuffer * file_manager_get_next_chunk_handle_file_complete(fileManager *fileMgr, int64 *chunkInfo)
+{
+       fileBuffer *newfileBuf = NULL;
+       uint64 remContent = 0;
+       uint32 divide = B_FALSE;
+       int64 contInfo[2] = {0};
+
+       if(*fileMgr->rspRead < *fileMgr->ExpectedBytes)
+       {
+               remContent = *fileMgr->ExpectedBytes - *fileMgr->rspRead;
+               TIZEN_LOGD("File Thread Finished File Node ... Checking Dividing Expected Bytes [%llu] Remaing Content [%llu]", *fileMgr->ExpectedBytes, remContent);
+               divide =  file_manager_divideRemCont(remContent, fileMgr, SOCKET_NODE);
+               if(divide)
+               {
+                       if(divide == CHANGE_INTERFACE_NO_DIVIDE)
+                       {
+                               TIZEN_LOGD("No Need to Divide Main Socket Just Change Interface");
+                               if(fileMgr->SBData->node_exception == 0) // Only if Main Socket is not going for exception Close this
+                               {
+                                       CLOSE_SOCKET(fileMgr->SBData->socket_fd);
+                               }
+                       }
+                       else
+                       {
+                               TIZEN_LOGD("Division According to Speed");
+                               if(file_manager_divideCont(remContent, contInfo, fileMgr, SOCKET_NODE))
+                               {
+                                       newfileBuf = (fileBuffer *)malloc(sizeof(fileBuffer));
+                                       if(newfileBuf != NULL)
+                                       {
+                                               memset(newfileBuf, 0, sizeof(fileBuffer));
+                                               chunkInfo[1] = *fileMgr->ExpectedBytes - 1 + fileMgr->strtOffset;
+                                               *fileMgr->ExpectedBytes = *fileMgr->rspRead + contInfo[0];
+                                               chunkInfo[0] = *fileMgr->ExpectedBytes + fileMgr->strtOffset;
+                                               file_buffer_init_node(newfileBuf, chunkInfo, -1, FILE_NODE, fileMgr->SBData, 0);
+                                               /* Attach to head head */
+                                               newfileBuf->next = *fileMgr->fbuffer;
+                                               *fileMgr->fbuffer = newfileBuf;
+
+                                               TIZEN_LOGD("New Node Created [%x] and Total length [%llu] Reduce Expected Bytes [%llu]", newfileBuf, file_buffer_getTotalLen(newfileBuf), *fileMgr->ExpectedBytes);
+                                       }
+                               }
+                       }
+               }
+       }
+       else
+       {
+               TIZEN_LOGD("File Thread Dividing Socket Node");
+               fileBuffer *tempBuff = file_manager_getDownloadingNode(fileMgr);
+               if(tempBuff != NULL)
+               {
+                       pthread_mutex_lock(&(tempBuff->mut));
+                       uint64 socketOffset = file_buffer_getOffset(tempBuff);
+                       remContent = file_buffer_getTotalLen(tempBuff) - socketOffset;
+                       TIZEN_LOGD("Rem Con [%llu] offset [%llu]",remContent, socketOffset);
+                       divide =  file_manager_divideRemCont(remContent, fileMgr, SOCKET_NODE);
+                       if(divide)
+                       {
+                               if(divide == CHANGE_INTERFACE_NO_DIVIDE)
+                               {
+                                       TIZEN_LOGD("No Need to Divide Socket Node Just Change Interface");
+
+                                       if(fileMgr->SBData->node_exception == 0) // Only if Main Socket is not going for exception Close this
+                                       {
+                                               CLOSE_SOCKET(tempBuff->socketId);
+                                       }
+                                       //tempBuff->socketId = 0;
+                               }
+                               else
+                               {
+                                       TIZEN_LOGD("Division According to Speed");
+                                       if(file_manager_divideCont(remContent, contInfo, fileMgr, SOCKET_NODE))
+                                       {
+                                               newfileBuf = (fileBuffer *)malloc(sizeof(fileBuffer));
+                                               if(newfileBuf != NULL)
+                                               {
+                                                       memset(newfileBuf, 0, sizeof(fileBuffer));
+                                                       file_buffer_setTotalLen(socketOffset + contInfo[0], tempBuff);
+
+                                                       check_set_filebuff_state(tempBuff);
+
+                                                       chunkInfo[0] = file_buffer_getStrtOffset(tempBuff) + file_buffer_getTotalLen(tempBuff);
+                                                       chunkInfo[1] =  tempBuff->endOffset;
+
+                                                       tempBuff->endOffset = chunkInfo[0] - 1;
+
+                                                       TIZEN_LOGD("End Offset Node [%x] [%llu] Total length [%llu]", tempBuff, tempBuff->endOffset, file_buffer_getTotalLen(tempBuff));
+                                                       file_buffer_init_node(newfileBuf, chunkInfo, -1, FILE_NODE, fileMgr->SBData, 0);
+                                                       /* Attach new node after current node */
+                                                       newfileBuf->next = tempBuff->next;
+                                                       tempBuff->next = newfileBuf;
+                                                       TIZEN_LOGD("New Node Created [%x] and Total length [%llu]", newfileBuf, file_buffer_getTotalLen(newfileBuf));
+                                               }
+                                       }
+                               }
+                       }
+                       pthread_mutex_unlock(&(tempBuff->mut));
+               }
+       }
+       return newfileBuf;
+}
+
+void file_manager_update_socket_node(uint64 offset, SmartBondingData *SBData)
+{
+       fileBuffer *tempBuff = file_manager_getDownloadingNode(SBData->fStream->fileMgr);
+       TIZEN_LOGD("Socket Node [%x] setting offset [%llu] Socket [%d]", tempBuff, offset, SBData->socket_fd);
+       tempBuff->offset = tempBuff->offset + offset;
+       tempBuff->appReadLen = tempBuff->appReadLen + offset;
+       tempBuff->socketId = SBData->socket_fd;
+}
+
+void file_manager_SwitchSocketNoData(fileBuffer *tempBuff, fileManager *fileMgr)
+{
+       if(tempBuff->fThread_read)
+       {
+               TIZEN_LOGD("Created During File Thread socket Read");
+               tempBuff->fThread_read = 0;
+               fileMgr->interface[MAIN_THREAD] = (fileMgr->interface[MAIN_THREAD] + 1) % 2;
+               fileMgr->interface[FILE_THREAD] = (fileMgr->interface[FILE_THREAD] + 1) % 2;
+               fileMgr->SBData->interface_index = fileMgr->interface[MAIN_THREAD];
+       }
+
+       CLOSE_SOCKET(tempBuff->socketId);
+       tempBuff->socketId = -1;
+       file_buffer_reinit_node(tempBuff, -1, SOCKET_NODE);
+}
+
+fileBuffer *file_manager_SwitchSocketData(fileBuffer *tempBuff, fileManager *fileMgr, int64 *chunkInfo, int ifacechange)
+{
+       fileBuffer *newfileBuf = (fileBuffer *)malloc(sizeof(fileBuffer));
+       uint32 newfilebuf_null = 0;
+       uint64 socketOffset = file_buffer_getOffset(tempBuff);
+       if(newfileBuf != NULL)
+       {
+               memset(newfileBuf, 0, sizeof(fileBuffer));
+               file_buffer_setTotalLen(socketOffset, tempBuff);
+               check_set_filebuff_state(tempBuff);
+               chunkInfo[0] = file_buffer_getStrtOffset(tempBuff) + file_buffer_getTotalLen(tempBuff);
+               chunkInfo[1] =  tempBuff->endOffset;
+               if(ifacechange == 0)
+               {
+                       TIZEN_LOGD("No Need to Change Interface");
+                       if((tempBuff->bRafMode) || (tempBuff->fThread_read) || (socketOffset < MIN_FILE_NODE_SIZE))
+                       {
+                               file_buffer_init_node(newfileBuf, chunkInfo, tempBuff->socketId, SOCKET_NODE, fileMgr->SBData, 0);
+                               fileMgr->interface[MAIN_THREAD] = (fileMgr->interface[MAIN_THREAD] + 1) % 2;
+                               fileMgr->interface[FILE_THREAD] = (fileMgr->interface[FILE_THREAD] + 1) % 2;
+                               fileMgr->SBData->interface_index = fileMgr->interface[MAIN_THREAD];
+                               newfilebuf_null = 1;
+                       }
+                       else
+                       {
+                               TIZEN_LOGD("Raf Mode OFF making File Thread Read From Socket");
+                               file_buffer_init_node(newfileBuf, chunkInfo, tempBuff->socketId, FILE_NODE, fileMgr->SBData, FILE_THREAD_SOCK_READ);
+                       }
+               }
+               else
+               {
+                       TIZEN_LOGD("Change The Interface");
+                       if((tempBuff->bRafMode) || (tempBuff->fThread_read) || (socketOffset < MIN_FILE_NODE_SIZE))
+                       {
+                               file_buffer_init_node(newfileBuf, chunkInfo, -1, SOCKET_NODE, fileMgr->SBData, 0);
+                               newfilebuf_null = 1;
+                       }
+                       else
+                       {
+                               TIZEN_LOGD("Raf Mode OFF Making File Thread Read From Socket");
+                               file_buffer_init_node(newfileBuf, chunkInfo, -1, FILE_NODE, fileMgr->SBData, FILE_THREAD_SOCK_CREATE);
+                               fileMgr->interface[MAIN_THREAD] = (fileMgr->interface[MAIN_THREAD] + 1) % 2;
+                               fileMgr->interface[FILE_THREAD] = (fileMgr->interface[FILE_THREAD] + 1) % 2;
+                               fileMgr->SBData->interface_index = fileMgr->interface[MAIN_THREAD];
+                       }
+               }
+               /* Attach new node after current node */
+               newfileBuf->next = tempBuff->next;
+               tempBuff->next = newfileBuf;
+               TIZEN_LOGD("New Node Created [%x] and Total length [%llu]", newfileBuf, file_buffer_getTotalLen(newfileBuf));
+               if(newfilebuf_null)
+               {
+                       newfileBuf = NULL;
+                       tempBuff->fThread_read = 0;
+               }
+       }
+       return newfileBuf;
+}
+
+uint32 file_manager_file_node_block_handle(SmartBondingData *SBData)
+{
+       fileManager *fileMgr = SBData->fStream->fileMgr;
+       fileBuffer *tempBuff = NULL;
+       uint64 socketOffset = 0;
+       uint32 retval = B_FALSE;
+       pthread_mutex_lock(&(fileMgr->mutex));
+       SBData->fStream->fThread->status = FILE_COMPLETE;
+       tempBuff = file_manager_getDownloadingNode(fileMgr);
+       if(tempBuff == NULL)
+       {
+               pthread_mutex_unlock(&(fileMgr->mutex));
+               return B_TRUE;
+       }
+       pthread_mutex_lock(&(tempBuff->mut));
+       if(tempBuff->state !=  NODE_STATE_BLOCKED)
+       {
+               retval =  B_TRUE;
+       }
+       else
+       {
+               TIZEN_LOGD("File Node in Blocked State");
+               socketOffset = file_buffer_getOffset(tempBuff);
+               if(socketOffset == 0)
+               {
+                       TIZEN_LOGD("Data in File Node is Zero Making as Socket Node");
+                       file_manager_SwitchSocketNoData(tempBuff, fileMgr);
+                       retval = B_TRUE;
+               }
+               else
+               {
+                       int64 contInfo[2] = {0};
+                       fileBuffer *newfileBuf = (fileBuffer *)malloc(sizeof(fileBuffer));
+                       if(newfileBuf != NULL)
+                       {
+                               memset(newfileBuf, 0, sizeof(fileBuffer));
+                               file_buffer_setTotalLen(socketOffset, tempBuff);
+
+                               check_set_filebuff_state(tempBuff);
+
+                               contInfo[0] = file_buffer_getStrtOffset(tempBuff) + file_buffer_getTotalLen(tempBuff);
+                               contInfo[1] =  tempBuff->endOffset;
+                               file_buffer_init_node(newfileBuf, contInfo, -1, SOCKET_NODE, SBData, 0);
+                               /* Attach new node after current node */
+                               newfileBuf->next = tempBuff->next;
+                               tempBuff->next = newfileBuf;
+                               TIZEN_LOGD("New Node Created [%x] and Total length [%llu]", newfileBuf, file_buffer_getTotalLen(newfileBuf));
+                               retval = B_TRUE;
+                       }
+                       else
+                       {
+                               retval = B_FALSE;
+                       }
+               }
+       }
+       pthread_mutex_unlock(&(tempBuff->mut));
+       pthread_mutex_unlock(&(fileMgr->mutex));
+
+       return retval;
+}
+
diff --git a/src/multirat_file_stream.c b/src/multirat_file_stream.c
new file mode 100644 (file)
index 0000000..bfb8d06
--- /dev/null
@@ -0,0 +1,379 @@
+#include "multirat_libapi.h"
+#include "multirat_file_stream.h"
+#include "multirat_file_manager.h"
+#include "multirat_file_buffer.h"
+#include "multirat_range_request_thread.h"
+#include "multirat_file_thread.h"
+#include "multirat_process.h"
+#include "multirat_watch_dog_thread.h"
+#include "multirat_watchthread.h"
+
+void file_stream_init(SmartBondingData *SBData)
+{
+       fileStream *fStream = malloc(sizeof(fileStream));
+       fileManager *fileMgr = NULL;
+
+       if(fStream == NULL)
+       {
+               TIZEN_LOGD("Error malloc fileStream failed");
+               return;
+       }
+
+       memset(fStream, 0, sizeof(fileStream));
+
+       SBData->fStream = fStream;
+       fStream->SBData = SBData;
+
+       fStream->mainSockExpBytes = &(SBData->expectedbytes);
+       fStream->totalLen = (SBData->resp.cLen);
+       fStream->mainSockRead = &(SBData->response_body_read);
+       fStream->strtOffset = SBData->req.rangeStart;
+
+       fileMgr = (fileManager *)malloc(sizeof(fileManager));
+       if(fileMgr == NULL)
+       {
+               TIZEN_LOGD("fileManager Allocation Error");
+               return;
+       }
+       memset(fileMgr, 0, sizeof(fileManager));
+
+       fStream->fileMgr = fileMgr;
+       file_manager_init(fStream, fileMgr);
+       fileMgr->SBData = SBData;
+       fileMgr->interface[MAIN_THREAD] = SBData->interface_index;
+       fileMgr->interface[FILE_THREAD] = (SBData->interface_index + 1) % 2;
+
+       fStream->fThread = NULL;
+       fStream->compRspRcvdFlag = 1;
+}
+
+uint32 file_stream_start(SmartBondingData *SBData)
+{
+       TIZEN_D_LOGD("File Stream _start");
+       fileStream *fStream = SBData->fStream;
+       fileThread *fThread = malloc(sizeof (fileThread));
+       if(fThread == NULL)
+               return 0;
+       memset(fThread, 0, sizeof (fileThread));
+       fStream->fThread = fThread;
+       file_thread_init(fThread, SBData, fStream);
+       return file_thread_start(fThread);
+}
+
+int32 file_stream_read_from_socket(int32 socket, int8 *buff, uint64 toBeRead, int32 *tempLen, SmartBondingData *SBData, uint32 index)
+{
+       SBData->sStat.prev_read = MAIN_THREAD ;
+
+       if((index == 1) && (socket == -1))
+       {
+               SBData->node_exception = SOCKET_NODE_FORCE_EXCEPTION;
+               TIZEN_LOGD("Socket is Negative, Go for Main Socket Exception");
+               SBData->fStreamFileBufferReady =  B_FALSE;
+               SBData->fileThreadStarted = B_FALSE;
+               SBData->enableMultiRat = B_FALSE;
+               return SB_ERR;
+       }
+       *tempLen = recv(socket, buff, toBeRead, 0);
+       if(*tempLen > 0)
+       {
+               return SB_OK;
+       }
+       else
+       {
+               if((errno == EAGAIN) || (errno == EWOULDBLOCK))
+               {
+                       if(SBData->curl)
+                               return SB_WOULD_BLOCK;
+                       else if(SBData->sync)
+                       {
+                               int retval = 0;
+                               retval = read_conn_poll(socket, SBData);
+                               if(retval <= 0)
+                               {
+                                       TIZEN_LOGD("Error !!! Main socket time out");
+                                       return SB_ERR;
+                               }
+                               else
+                               {
+                                       *tempLen = recv(socket, buff, toBeRead, 0);
+                                       if(*tempLen <= 0)
+                                       {
+                                               TIZEN_LOGD("Error !!! Main socket error in recv [%s] ",strerror (errno));
+                                               return SB_ERR;
+                                       }
+                                       return SB_OK;
+                               }
+                       }
+                       else
+                               return SB_ERR;
+               }
+               else
+               {
+                       if((index == 0))
+                       {
+                               TIZEN_LOGD("Normal Socket Exception");
+                               SBData->node_exception = SOCKET_NORMAL_EXCEPTION;
+                               return SB_ERR;
+                       }
+                       SBData->node_exception = SOCKET_NODE_NORMAL_EXCEPTION;
+                       TIZEN_LOGD("Reading from socket node failed [%s] erro No [%d]", strerror(errno), errno);
+                       TIZEN_LOGD("Go for Main Socket Exception");
+                       SBData->fStreamFileBufferReady =  B_FALSE;
+                       SBData->fileThreadStarted = B_FALSE;
+                       SBData->enableMultiRat = B_FALSE;
+                       return SB_ERR;
+               }
+       }
+}
+
+int32 file_stream_read(int8 *buff, int32 maxAppLen, SmartBondingData *SBData, int32 *my_nread)
+{
+       int32 retval = SB_ERR;
+       uint64 toBeRead = 0;
+       int32 tempLen = -1;
+       fileBuffer *fbuff = NULL;
+
+       fileManager *fMgr = SBData->fStream->fileMgr;
+       fileBuffer *fileBuff = SBData->fStream->fileBuff;
+       if(fileBuff != NULL)
+       {
+               fbuff = file_manager_getReadingNode(fMgr);
+               if(NULL == fbuff)
+               {
+                       return SB_ERR;
+               }
+               tempLen = 0;
+               while(tempLen <= maxAppLen)
+               {
+                       TIZEN_D_LOGD("Reading File Buffer ... [%x] total length  ... [%llu] read length ... [%llu]", fbuff, file_buffer_getTotalLen(fbuff), file_buffer_getReadRspLen(fbuff));
+                       if(file_buffer_getTotalLen(fbuff) == file_buffer_getReadRspLen(fbuff))
+                       {
+                               TIZEN_D_LOGD("completed reading from node [%p] len [%llu]", fbuff, file_buffer_getTotalLen(fbuff));
+                               if(file_buffer_getNodeType(fbuff) == SOCKET_NODE)
+                               SBData->status = MAIN_COMPLETE;
+
+                               fbuff = file_manager_getReadingNode(fMgr);
+                               if(NULL == fbuff)
+                               {
+                                       if(tempLen > 0)
+                                       {
+                                               break;
+                                       }
+                                       return SB_ERR;
+                               }
+                       }
+
+                       if(tempLen> 0)
+                       {
+                               /* already read some bytes */
+                               break;
+                       }
+
+                       if(file_buffer_getNodeType(fbuff) == SOCKET_NODE)
+                       {
+                               TIZEN_D_LOGD("completed reading from socket node [%x] total lenght [%llu]  read length [%llu]", fbuff, file_buffer_getTotalLen(fbuff), file_buffer_getReadRspLen(fbuff));
+                               toBeRead = MIN(maxAppLen,(file_buffer_getTotalLen(fbuff) - file_buffer_getReadRspLen(fbuff)));
+                               retval = file_stream_read_from_socket(file_buffer_getSocketId(fbuff), buff, toBeRead, &tempLen, SBData, 1);
+                               if(tempLen > 0)
+                               {
+                                       file_buffer_read_from_socket(fbuff, tempLen);
+                                       *my_nread = tempLen;
+                                       TIZEN_D_LOGD("completed reading from socket node [%x] total lenght [%llu]  read length [%llu] ...", fbuff, file_buffer_getTotalLen(fbuff), file_buffer_getReadRspLen(fbuff));
+                                       if(file_buffer_getTotalLen(fbuff) == file_buffer_getReadRspLen(fbuff))
+                                       {
+                                               TIZEN_LOGD("completed reading from Socket node [%x]", fbuff);
+                                               SBData->status = MAIN_COMPLETE;
+                                       }
+                                       return SB_OK;
+                               }
+                               else
+                               {
+                                       if(retval == SB_ERR)
+                                               TIZEN_LOGD("SBData[%p] Sending Error", SBData);
+                                       return retval;
+                               }
+                       }
+                       TIZEN_D_LOGD("Reading File Buffer [%x] total length [%llu] read length [%llu]", fbuff, file_buffer_getTotalLen(fbuff), file_buffer_getReadRspLen(fbuff));
+                       if(file_buffer_noOfRspBytes(fbuff)== 0)
+                       {
+                               if(fbuff->state == NODE_STATE_BLOCKED)
+                               {
+                                       TIZEN_LOGD("Looks like File Node is Blocked");
+                                       if(!file_manager_file_node_block_handle(SBData))
+                                               return SB_ERR;
+                               }
+                               return SB_WOULD_BLOCK;
+                       }
+                       toBeRead = MIN((maxAppLen-tempLen),file_buffer_noOfRspBytes(fbuff));
+
+                       file_buffer_read_from_file(fbuff, buff+tempLen, &toBeRead);
+                       tempLen = tempLen + toBeRead;
+                       TIZEN_D_LOGD("Completed Reading File Buffer [%x] total length [%llu] read length [%llu] ... ", fbuff, file_buffer_getTotalLen(fbuff), file_buffer_getReadRspLen(fbuff));
+               }
+       }
+       else
+       {
+               TIZEN_LOGD("File buffer not created failed");
+               return SB_ERR;
+       }
+       *my_nread = tempLen;
+       return SB_OK;
+}
+
+void is_file_stream_read(SmartBondingData *SBData)
+{
+       fileThread *fThread = SBData->fStream->fThread;
+       if (SBData->response_body_read >= SBData->expectedbytes)
+       {
+               TIZEN_LOGD("Expected Bytes more");
+               if(fThread->firstRngStatus == FIRST_RSP_STATUS_SUCCESS)
+               {
+                       TIZEN_LOGD("Read Expected Bytes from Main thread");
+                       SBData->status = MAIN_COMPLETE;
+                       SBData->fStreamFileBufferReady = B_TRUE;
+                       CLOSE_SOCKET(SBData->socket_fd);
+                       SBData->socket_fd = -1;
+                       TIZEN_LOGD("FirstRangeRequest Success is_multirat_read");
+               }
+               else
+               {
+                       SBData->fStreamFileBufferReady =  B_FALSE;
+                       SBData->fileThreadStarted = B_FALSE;
+                       SBData->enableMultiRat = B_FALSE;
+                       TIZEN_LOGD("FirstRangeRequest FAILED");
+                       file_stream_exit(SBData->fStream);
+                       SBData->fStream =  NULL;
+               }
+       }
+}
+
+void submit_ratio_history(SmartBondingData *SBData)
+{
+       FILE *fp = fopen("/opt/usr/media/Ratiostat", "w");
+       if(fp == NULL)
+       {
+               TIZEN_LOGD("Opening File /opt/usr/media/Ratiostat Failed");
+               return ;
+       }
+       fprintf(fp,"%u %u",SBData->speed[1],SBData->speed[0]);
+       TIZEN_LOGD("Ratiostat Write Success spd[1] [%u] spd[0] [%u]", SBData->speed[1],SBData->speed[0]);
+       fclose(fp);
+}
+
+void file_stream_exit(fileStream *fStream)
+{
+       fileBuffer *fileBuff =  NULL;
+       fileBuffer *tempBuff =  NULL;
+       TIZEN_LOGD("file stream exit [%p]", fStream);
+       fStream->compRspRcvdFlag = 0;
+       submit_ratio_history(fStream->SBData);
+
+       if(fStream->SBData->cthread != NULL)
+       {
+               cthread_exit(fStream->SBData->cthread);
+               fStream->SBData->cthread =  NULL;
+       }
+
+       file_thread_exit(fStream->fThread);
+       fStream->fThread = NULL;
+
+       TIZEN_LOGD("file stream exit file Mgr [%p]", fStream->fileMgr);
+       if(NULL != fStream->fileMgr)
+       {
+               file_manager_exit(fStream->fileMgr);
+               free(fStream->fileMgr);
+               TIZEN_LOGD("File Manager Freed");
+       }
+       fStream->fileMgr = NULL;
+
+       fileBuff = fStream->fileBuff ;
+
+       while(fileBuff != NULL)
+       {
+               tempBuff = fileBuff;
+               fileBuff = tempBuff->next;
+               file_buffer_exit(tempBuff);
+       }
+       fileBuff = NULL;
+       free(fStream);
+       fStream = NULL;
+
+       TIZEN_LOGD("File Stream _exit finished");
+}
+
+void PollThread_poll_buffer(SmartBondingData *SBData)
+{
+       fileManager *fMgr = SBData->fStream->fileMgr;
+       fileBuffer *fileBuff = SBData->fStream->fileBuff;
+       fileBuffer *fbuff =  NULL;
+       uint64 startTime = 0;
+
+       if(fileBuff != NULL)
+       {
+               fbuff = file_manager_getReadingNode(fMgr);
+               if(NULL == fbuff)
+               {
+                       return;
+               }
+               if(file_buffer_getTotalLen(fbuff) == file_buffer_getReadRspLen(fbuff))
+               {
+                       return;
+               }
+               if(file_buffer_getNodeType(fbuff) == SOCKET_NODE)
+               {
+                       TIZEN_D_LOGD("Socket Node ... [%x]", fbuff);
+                       if(fbuff->socketId == -1)
+                       {
+                               TIZEN_LOGD("SBData[%p] Socket Node Socket -1", SBData);
+                               return;
+                       }
+                       PollThread_poll(fbuff->socketId, SBData, 10);
+                       return;
+               }
+               else
+               {
+                       startTime = get_time_in_sec();
+                       while(SBData->PollThrd->threadStatus != THREAD_FINISH)
+                       {
+                               fbuff = file_manager_getReadingNode(fMgr);
+                               TIZEN_D_LOGD("SBData[%p] File Node ... [%x]", SBData, fbuff);
+                               if(NULL == fbuff)
+                               {
+                                       return;
+                               }
+                               if(file_buffer_getTotalLen(fbuff) == file_buffer_getReadRspLen(fbuff))
+                               {
+                                       TIZEN_LOGD("Node Completed");
+                                       return;
+                               }
+                               if(file_buffer_getNodeType(fbuff) != FILE_NODE)
+                               {
+                                       return;
+                               }
+                               if(file_buffer_noOfRspBytes(fbuff)== 0)
+                               {
+                                       if(fbuff->fThread_read != 0)
+                                       {
+                                               TIZEN_LOGD("Making File Thread Exit");
+                                               SBData->status = MAIN_COMPLETE;
+                                       }
+                                       if(((fbuff->state == NODE_STATE_BLOCKED) && ((get_time_in_sec() - startTime) >= 2)))
+                                       {
+                                               TIZEN_LOGD("SBData[%p] Node State is BLOCK ...", SBData);
+                                               return;
+                                       }
+                                       else
+                                       {
+                                                       TIZEN_D_LOGD("SBData[%p] Node State BLOCK sleep", SBData);
+                                       }
+                                       usleep(10000);
+                                       continue;
+                               }
+                               else
+                               {
+                                       return;
+                               }
+                       }
+               }
+       }
+}
diff --git a/src/multirat_file_thread.c b/src/multirat_file_thread.c
new file mode 100644 (file)
index 0000000..6a663bc
--- /dev/null
@@ -0,0 +1,672 @@
+#include "multirat_conf.h"
+#include "multirat_process.h"
+#include "multirat_libapi.h"
+#include "multirat_range_request_thread.h"
+#include "multirat_connection.h"
+#include "multirat_file_manager.h"
+#include "multirat_file_buffer.h"
+#include "multirat_decode_http.h"
+#include "multirat_file_thread.h"
+#include "multirat_watch_dog_thread.h"
+
+#include <sys/time.h>
+
+void file_thread_init(fileThread *fThread, SmartBondingData *SBData, fileStream *fStream)
+{
+       TIZEN_LOGD("File Thread Init");
+       fThread->pthreadId = 0;
+       fThread->compRspRcvdFlag = &(fStream->compRspRcvdFlag);
+       fThread->compRspLen = SBData->resp.cLen ;
+       fThread->contRngLen = SBData->resp.instanceSize;
+       fThread->SBData = SBData;
+       fThread->conn = &SBData->conn;
+       fThread->socketId = -1;
+       fThread->fileMgr = fStream->fileMgr;
+       fThread->firstRngStatus = FIRST_RSP_STATUS_PENDING;
+}
+
+uint32 file_thread_start(fileThread *fThread)
+{
+       uint32 multiThreadStarted = B_TRUE;
+       if(0 != pthread_create(&fThread->pthreadId, NULL, &FileThreadCallBack, fThread))
+       {
+               TIZEN_LOGD("File thread failed");
+               multiThreadStarted = B_FALSE;
+       }
+       return multiThreadStarted;
+}
+
+void *FileThreadCallBack(void *ptr)
+{
+       fileThread *fileReq = (fileThread*)ptr;
+       file_thread_run(fileReq);
+       return NULL;
+}
+
+void file_thread_run(fileThread *fThread)
+{
+       int8 *newRequest = NULL;
+       int8 tempBuff[2*MAX_BLOCK_SIZE] = {0};
+       int8 rcvBuff[MAX_HEADER_SIZE + 1] = {0};
+       int32 headerRcvd = B_FALSE;
+       int32 IOException = B_TRUE;
+       int32 FIRST_TIME = B_TRUE;
+       int64 chunkInfo[CHUNK_INFO_SIZE] ={0};
+       uint32 reqLen = 0;
+       uint32 minBlockLen = MIN_BLOCK_SIZE;
+       uint32 ifCount = 0;
+       uint32 connClose = 0;
+       uint32 ifaceidx = fThread->interface_index;
+       uint64 currChunkLen = 0;
+       uint64 rcvdLen = 0;
+       uint64 blockOffset = 0;
+       uint32 status = 0;
+       uint64 blockLen = 0;
+       int32 lengthRcvd = 0;
+       fileBuffer *fbuffer = NULL;
+       fThread->status = FILE_START;
+       SmartBondingData *SBData = NULL;
+       fileManager *fileMgr = fThread->fileMgr;
+       SBData = fThread->SBData;
+       TIZEN_LOGD("File Thread Main");
+
+       while(*fThread->compRspRcvdFlag)
+       {
+               int32 return_val = 0;
+
+               fThread->interface_index =  file_manager_get_file_thread_interface(fileMgr);
+               ifaceidx = fThread->interface_index;
+               TIZEN_LOGD("Interface Index [%d]", fThread->interface_index );
+
+               if (IOException == B_TRUE)
+               {
+                       int32 retval = 0;
+
+                       retval = file_thread_handleIOExp(fThread,&ifCount,SBData->conn.ip_family);
+
+                       if(THREAD_EXIT == retval)
+                       {
+                               break;
+                       }
+                       else if (THREAD_CONTINUE == retval)
+                       {
+                               sleep(1);
+                               continue;
+                       }
+               }
+
+               fbuffer = file_manager_getNextChunkForFileThread(chunkInfo, SBData);
+
+               if(NULL == fbuffer)
+               {
+                       break;
+               }
+
+               fThread->status = FILE_START;
+               fThread->interface_index =  file_manager_get_file_thread_interface(fileMgr);
+       
+               if(fbuffer->fThread_read != FILE_THREAD_SOCK_READ)
+               {
+                       if(ifaceidx != fThread->interface_index)
+                       {
+                               int32 retval = 0;
+
+                               retval = file_thread_handleIOExp(fThread,&ifCount,SBData->conn.ip_family);
+
+                               if(THREAD_EXIT == retval)
+                               {
+                                       break;
+                               }
+                               else if (THREAD_CONTINUE == retval)
+                               {
+                                       sleep(1);
+                                       continue;
+                               }
+                       }
+                       ifaceidx = fThread->interface_index ;
+
+                       if((FIRST_TIME != B_TRUE))
+                       {
+                               return_val = file_thread_connet_server_interface(fThread);
+                               if(THREAD_EXIT == return_val)
+                               {
+                                       break;
+                               }
+                               else if (THREAD_CONTINUE == return_val)
+                               {
+                                       sleep(1);
+                                       continue;
+                               }
+
+                               fThread->req = SBData->req.request[ifaceidx] ;
+                               fThread->headerLen = strlen(SBData->req.request[ifaceidx]);
+
+                               if(newRequest != NULL)
+                                       free(newRequest);
+
+                               newRequest = (int8 *)malloc(fThread->headerLen + MAX_RANGE_FIELD_LEN);
+                               if(NULL == newRequest)
+                               {
+                                       return;
+                               }
+
+                               memset(newRequest,0,(fThread->headerLen + MAX_RANGE_FIELD_LEN));
+                               reqLen = file_thread_rebuildReq(newRequest, chunkInfo, fThread);
+
+                               SECURE_DB_INFO("In file thread New Request [%s]",newRequest) ;
+
+                               if(-1 == send(fThread->socketId,newRequest,reqLen,0))
+                               {
+                                       TIZEN_LOGD("Sending of HTTP Req from File Thread Failed");
+                                       break;
+                               }
+                               headerRcvd = B_FALSE;
+                       }
+                       else
+                       {
+                               int32 result = -1;
+                               TIZEN_LOGD("First Time File Thread Connection");
+                               result = file_thread_FirstConnection(fThread->SBData, fThread, chunkInfo, rcvBuff, &lengthRcvd);
+                               return_val = file_thread_connect_server_interface_first(result, fThread);
+                               if(THREAD_EXIT == return_val)
+                               {
+                                       break;
+                               }
+                               else if (THREAD_CONTINUE == return_val)
+                               {
+                                       sleep(1);
+                                       continue;
+                               }
+                               headerRcvd = B_FALSE;
+                       }
+                       fbuffer->socketId = fThread->socketId ;
+               }
+               else
+               {
+                       fThread->socketId = fbuffer->socketId;
+                       headerRcvd = B_TRUE;
+               }
+               currChunkLen = chunkInfo[1] - chunkInfo[0] + 1;
+               TIZEN_LOGD("File Thread Interface Index [%d]",fThread->interface_index);
+               TIZEN_LOGD("currChunkLen [%llu]",currChunkLen);
+               IOException = B_FALSE;
+               minBlockLen = MIN_BLOCK_SIZE;
+               rcvdLen = 0;
+
+               while(rcvdLen < currChunkLen && *fThread->compRspRcvdFlag)
+               {
+                       blockOffset = 0;
+                       status = 0;
+                       blockLen = MIN(minBlockLen, currChunkLen - rcvdLen);
+                       minBlockLen = MIN((2*MAX_BLOCK_SIZE),(minBlockLen << 2));
+                       memset(tempBuff,0,2*MAX_BLOCK_SIZE);
+
+                       /*If  Main thread Read stops for more than 2 sec , file thread stops reading */
+                       if(SBData->read_state_check == MAIN_SOCK_READ_INACTIVE)
+                       {
+                               usleep(10000);
+                               continue;
+                       }
+
+                       TIZEN_LOGD("File Thread Total Len [%llu] received [%llu] Block Len [%llu]",file_buffer_getTotalLen(fbuffer), rcvdLen, blockLen);
+                       status = file_manager_check_main_thread_status(fileMgr);
+                       if((status == MAIN_IO_EXCEPTION) && (SBData->file_status != NO_REDIVISION))
+                       {
+                               TIZEN_LOGD("IO Exception of Main Socket");
+                               fThread->status = FILE_IO_EXCEPTION;
+                               fbuffer->state = NODE_STATE_BLOCKED;
+                               IOException = B_TRUE;
+                               break;
+                       }
+                       else if((status == MAIN_COMPLETE)&& (SBData->file_status != NO_REDIVISION))
+                       {
+                               TIZEN_LOGD("Main Thread is Completed");
+                               fThread->status = MAIN_COMPLETE;
+                               fbuffer->state = NODE_STATE_BLOCKED;
+                               IOException = B_TRUE;
+                               break;
+                       }
+                       if(B_FALSE == headerRcvd)
+                       {
+                               int32 retval = HTTP_RSP_DECODING_ERROR;
+                               if(FIRST_TIME == B_TRUE)
+                               {
+                                       retval = file_thread_range_request_recv_rng_rsp_headers_first_req(&blockOffset, tempBuff, currChunkLen, &connClose, fThread, rcvBuff, lengthRcvd);
+                                       FIRST_TIME = B_FALSE;
+                               }
+                               else
+                                       retval = file_thread_range_request_recv_rng_rsp_headers(&blockOffset, tempBuff, currChunkLen, &connClose, fThread);
+                               if(HTTP_RSP_DECODING_SUCCESS != retval)
+                               {
+                                       if((fThread->firstRngStatus == FIRST_RSP_STATUS_PENDING)
+                                                       && (retval == HTTP_RSP_DECODING_ERROR))
+                                       {
+                                               TIZEN_LOGD("First Response failed");
+                                               *fThread->compRspRcvdFlag = 0;
+                                               fThread->firstRngStatus = FIRST_RSP_STATUS_FAILED;
+                                       }
+                                       else
+                                       {
+                                               IOException = B_TRUE;
+                                               TIZEN_LOGD("File Thread got Exception during recv headers");
+                                       }
+                                       break;
+                               }
+                               else
+                               {
+                                       headerRcvd = B_TRUE;
+                                       if(fThread->firstRngStatus == FIRST_RSP_STATUS_PENDING)
+                                       {
+                                               fThread->firstRngStatus = FIRST_RSP_STATUS_SUCCESS;
+                                               TIZEN_LOGD("First Response Success");
+                                       }
+                                       if(blockOffset > 0)
+                                       {
+                                               uint64 temp_history = 0;
+                                               uint64 temp_data = 0;
+                                               speedStat *sStat = &(SBData->sStat);
+                                               file_buffer_add(fbuffer, tempBuff, blockOffset, chunkInfo, rcvdLen, SBData);
+                                               if(SBData->bRafMode)
+                                               {
+                                                       sprintf(SBData->FileData,"%lld-%llu",chunkInfo[0],file_buffer_getOffset(fbuffer));
+                                               }
+                                               rcvdLen = rcvdLen + blockOffset;
+
+                                               temp_data = sStat->recv_length[fThread->interface_index];
+                                               sStat->recv_length[fThread->interface_index] = sStat->recv_length[fThread->interface_index] + blockOffset;
+                                               if(sStat->start_recv_time[fThread->interface_index] == 0)
+                                                       sStat->start_recv_time[fThread->interface_index] = get_time_in_microsec();
+                                               sStat->prev_recv_time[fThread->interface_index] = get_time_in_microsec();
+                                               temp_history = (sStat->prev_recv_time[fThread->interface_index] - sStat->start_recv_time[fThread->interface_index])/1000000;
+                                               if((sStat->timeArray[fThread->interface_index] < (MAX_HISTORY)) && (temp_history < MAX_HISTORY) && (temp_history > sStat->timeArray[fThread->interface_index]))
+                                               {
+                                                       int i = 0;
+                                                       sStat->dataArray[fThread->interface_index][temp_history] = sStat->recv_length[fThread->interface_index];
+                                                       for( i = sStat->timeArray[fThread->interface_index] + 1 ;  i < temp_history; i++)
+                                                       {
+                                                               sStat->dataArray[fThread->interface_index][i] = temp_data;
+                                                       }
+                                                       sStat->timeArray[fThread->interface_index] = temp_history;
+                                                       TIZEN_LOGD("Data History Time [%llu] Data [%llu]", temp_history, sStat->dataArray[fThread->interface_index][temp_history]);
+                                                       TIZEN_LOGD("temp_hist [%llu] tdata [%llu] Data [%llu]", temp_history, temp_data, sStat->dataArray[fThread->interface_index][temp_history]);
+                                               }
+                                               TIZEN_LOGD("File Thread Total Len [%llu] received [%llu] Block Len [%llu]",file_buffer_getTotalLen(fbuffer), rcvdLen, blockLen);
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               int32 lenRcvd = 0;
+                               while(blockOffset != blockLen)
+                               {
+                                       if (file_thread_conn_poll(fThread->socketId, SBData) <= 0)
+                                       {
+                                               TIZEN_LOGD("File Thread Fail Polling");
+                                               IOException = B_TRUE;
+                                               break;
+                                       }
+                                       //sleep(1);
+                                       lenRcvd = recv(fThread->socketId, tempBuff+blockOffset, blockLen-blockOffset,0);
+                                       if((lenRcvd == -1) || (lenRcvd == 0))
+                                       {
+                                               break;
+                                       }
+                                       else if(lenRcvd > 0)
+                                       {
+                                               blockOffset = blockOffset + lenRcvd;
+                                               uint64 temp_history = 0;
+                                               uint64 temp_data = 0;
+                                               speedStat *sStat = &(SBData->sStat);
+                                               temp_data = sStat->recv_length[fThread->interface_index];
+
+                                               sStat->recv_length[fThread->interface_index] = sStat->recv_length[fThread->interface_index] + lenRcvd;
+
+                                               if(sStat->start_recv_time[fThread->interface_index] == 0)
+                                                       sStat->start_recv_time[fThread->interface_index] = get_time_in_microsec();
+
+                                               sStat->prev_recv_time[fThread->interface_index] = get_time_in_microsec();
+
+                                               temp_history = (sStat->prev_recv_time[fThread->interface_index] - sStat->start_recv_time[fThread->interface_index])/1000000;
+                                               if((sStat->timeArray[fThread->interface_index] < (MAX_HISTORY)) && (temp_history < MAX_HISTORY) && (temp_history > sStat->timeArray[fThread->interface_index]))
+                                               {
+                                                       int i = 0;
+                                                       sStat->dataArray[fThread->interface_index][temp_history] = sStat->recv_length[fThread->interface_index];
+                                                       for( i = sStat->timeArray[fThread->interface_index] + 1 ;  i < temp_history; i++)
+                                                       {
+                                                               sStat->dataArray[fThread->interface_index][i] = temp_data;
+                                                       }
+                                                       sStat->timeArray[fThread->interface_index] = temp_history;
+                                                       TIZEN_LOGD("idx [%d] Data History Time [%llu] Data [%llu]", fThread->interface_index, temp_history, sStat->dataArray[fThread->interface_index][temp_history]);
+                                               }
+                                       }
+                               }
+                               if(blockOffset != blockLen)
+                               {
+                                       /* IO Exception */
+                                       TIZEN_LOGD("File Thread  IOException during read");
+                                       IOException = B_TRUE;
+                                       break;
+                               }
+                               else
+                               {
+                                       TIZEN_LOGD("File Buffer Write [%x]", fbuffer);
+                                       //file_buffer_add(fbuffer, tempBuff, blockOffset);
+                                       file_buffer_add(fbuffer, tempBuff, blockOffset,chunkInfo,rcvdLen,SBData);
+
+                                       if(SBData->bRafMode)
+                                       {
+                                               sprintf(SBData->FileData,"%lld-%llu",chunkInfo[0],file_buffer_getOffset(fbuffer));
+                                       }
+                                       rcvdLen = rcvdLen + blockOffset;
+                                       TIZEN_D_LOGD("File Thread Total Len [%llu] received [%llu] Block Len [%llu]", file_buffer_getTotalLen(fbuffer), rcvdLen, blockLen);
+                               }
+                       }
+               }
+               if((IOException == B_TRUE) && (file_buffer_getTotalLen(fbuffer) != rcvdLen))
+               {
+                       fbuffer->state = NODE_STATE_BLOCKED;
+                       IOException = B_TRUE;
+                       if(SBData->file_status == NO_REDIVISION)
+                       {
+                               TIZEN_LOGD("Close Socket ID As Exception and No Redivision");
+                               fThread->status = FILE_IO_EXCEPTION;
+                               CLOSE_SOCKET(fbuffer->socketId);
+                               fbuffer->socketId = 0;
+                               fThread->socketId = 0;
+                       }
+                       else if((fThread->SBData->status == MAIN_COMPLETE))
+                       {
+                               TIZEN_LOGD("Dont Close Socket ID As Main Complete");
+                               if(blockOffset > 0)
+                               {
+                                       TIZEN_LOGD("File Buffer Write [%x] Data Length [%llu]", fbuffer, blockOffset);
+                                       file_buffer_add(fbuffer, tempBuff, blockOffset,chunkInfo,rcvdLen,SBData);
+                                       if(SBData->bRafMode)
+                                       {
+                                               sprintf(SBData->FileData,"%lld-%llu",chunkInfo[0],file_buffer_getOffset(fbuffer));
+                                       }
+                               }
+                               fThread->status = MAIN_COMPLETE;
+                       }
+                       else
+                       {
+                               TIZEN_LOGD("Close Socket ID As Exception and Main is not Complete");
+                               fThread->status = FILE_IO_EXCEPTION;
+                               CLOSE_SOCKET(fbuffer->socketId);
+                               fbuffer->socketId = -1;
+                               fThread->socketId = -1;
+                       }
+
+                       TIZEN_LOGD("File Thread Interupted Download FILE NODE [%x] Total length [%llu] Received [%llu]", fbuffer, file_buffer_getTotalLen(fbuffer), file_buffer_getOffset(fbuffer));
+               }
+               else
+               {
+                       fThread->status = FILE_COMPLETE; // Means here it is complete
+                       TIZEN_LOGD("File Thread Finished Downloading FILE NODE [%x] Total length [%llu] Received [%llu]", fbuffer, file_buffer_getTotalLen(fbuffer), file_buffer_getOffset(fbuffer));
+
+                       if(fThread->SBData->file_status == NO_REDIVISION)
+                               *fThread->compRspRcvdFlag = 0;
+
+                       if(NULL == fbuffer->next)
+                       {
+                               TIZEN_LOGD("Close Socket ID as No Available Buffer");
+                               CLOSE_SOCKET(fbuffer->socketId);
+                               fbuffer->socketId = -1;
+                               fThread->socketId = -1;
+                               fThread->status = FILE_COMPLETE;
+                               IOException = B_TRUE;
+                       }
+                       if(NULL != fbuffer->next && fThread->socketId != file_buffer_getSocketId(fbuffer->next))
+                       {
+                               TIZEN_LOGD("Close Socket ID as Next Avalaible Buffer Socket is Not Same");
+                               CLOSE_SOCKET(fbuffer->socketId);
+                               fbuffer->socketId = -1;
+                               fThread->socketId = -1;
+                               fThread->status = FILE_COMPLETE;
+                               IOException = B_TRUE;
+                       }
+               }
+       }
+       TIZEN_LOGD("Exiting FILE THREAD");
+       if(NULL != newRequest)
+       {
+               free(newRequest);
+               newRequest = NULL;
+       }
+       TIZEN_LOGD("Exiting FILE THREAD ...");
+}
+
+
+int file_thread_handleIOExp(fileThread *fThread, uint32 *ifCount,int iptype)
+{
+       /* Check if interface is available */
+       if (!connection_is_ifaceup(fThread->interface_index, fThread->conn->ifaceInfo,iptype))
+       {
+               if((fThread->firstRngStatus == FIRST_RSP_STATUS_PENDING) && (*ifCount++ > 2))
+               {
+                       fThread->firstRngStatus = FIRST_RSP_STATUS_FAILED;
+                       *(fThread->compRspRcvdFlag) = 0;
+                       TIZEN_LOGD("First Response Failed for File ThreadId");
+                       return THREAD_EXIT;
+               }
+               else
+               {
+                       return THREAD_CONTINUE;
+               }
+       }
+       /* IOException case */
+       return 0;
+}
+
+
+int file_thread_connect_server_interface_first(int32 result, fileThread *fThread)
+{
+       fThread->socketId = result;
+       TIZEN_LOGD("File Thread socketId [%d]", fThread->socketId);
+    if ((-1 == fThread->socketId) || (!(*(fThread->compRspRcvdFlag))))
+    {
+        if (fThread->firstRngStatus == FIRST_RSP_STATUS_PENDING)
+        {
+            fThread->firstRngStatus = FIRST_RSP_STATUS_FAILED;
+            TIZEN_LOGD("First Response failed");;
+            /* server doest support Range Request */
+            /* Exit all threads */
+            *(fThread->compRspRcvdFlag) = 0;
+            TIZEN_LOGD("First Response Failed for File ThreadId");
+            return THREAD_EXIT;
+        }
+        else
+        {
+            if(fThread->SBData->file_status == NO_REDIVISION)
+            {
+                fThread->status = FILE_IO_EXCEPTION;
+            }
+            else if(fThread->SBData->status == MAIN_COMPLETE)
+            {
+                fThread->status = MAIN_COMPLETE;
+            }
+            else
+            {
+                fThread->status = FILE_IO_EXCEPTION;
+            }
+            return THREAD_CONTINUE;
+        }
+    }
+    return 0;
+}
+
+int file_thread_connet_server_interface(fileThread *fThread)
+{
+       file_thread_connect_server(fThread);
+       TIZEN_LOGD("File Thread socketId [%d]", fThread->socketId);
+
+       if ((0 > fThread->socketId) || (!(*(fThread->compRspRcvdFlag))))
+       {
+               if (fThread->firstRngStatus == FIRST_RSP_STATUS_PENDING)
+               {
+                       fThread->firstRngStatus = FIRST_RSP_STATUS_FAILED;
+                       TIZEN_LOGD("First Response failed");;
+                       /* server doest support Range Request */
+                       /* Exit all threads */
+                       *(fThread->compRspRcvdFlag) = 0;
+                       TIZEN_LOGD("First Response Failed for File ThreadId");
+                       return THREAD_EXIT;
+               }
+               else
+               {
+                       if(fThread->SBData->file_status == NO_REDIVISION)
+                       {
+                               fThread->status = FILE_IO_EXCEPTION;
+                       }
+                       else if(fThread->SBData->status == MAIN_COMPLETE)
+                       {
+                               fThread->status = MAIN_COMPLETE;
+                       }
+                       else
+                       {
+                               fThread->status = FILE_IO_EXCEPTION;
+                       }
+                       return THREAD_CONTINUE;
+               }
+       }
+       return 0;
+}
+
+
+
+int32 file_thread_range_request_recv_rng_rsp_headers_first_req(uint64 *bodyLen, char *blockSize, uint64 currChunkLen, uint32 *connClose, fileThread *fThread, int8 *rcvBuff, int32 lengthRcvd)
+{
+       uint32 offset = lengthRcvd;
+       int32 retval = -1;
+       int32 len = 0;
+       int8 rspPrint[MAX_HEADERS_SIZE] = {0};
+       httpResp httpRsp ;
+       uint64 instanceSize =  fThread->contRngLen;
+       uint64 respLen = fThread->compRspLen;
+       len = decode_http_find_str(rcvBuff, END_OF_HEADERS);
+       uint32 headerLen = (len+4);
+       *bodyLen = (uint64)(offset - headerLen);
+       memcpy(rspPrint, rcvBuff, headerLen);
+       SECURE_DB_INFO("Response [%s]", rspPrint);
+       TIZEN_LOGD("Total Data Received [%d]", lengthRcvd);
+       memset(&httpRsp, 0, sizeof(httpResp));
+       decode_http_rsp_init(rcvBuff, headerLen, &httpRsp);
+       retval = process_http_rsp(&httpRsp);
+       if(HTTP_RSP_DECODING_SUCCESS == retval)
+       {
+               TIZEN_LOGD("File Thread Response Decode Success");
+               retval = range_request_validate_rsp(instanceSize, &httpRsp, currChunkLen, respLen, connClose);
+               if((retval == HTTP_RSP_DECODING_SUCCESS) && (*bodyLen > 0))
+               {
+                       memcpy(blockSize,rcvBuff+headerLen,*bodyLen);
+               }
+       }
+       delete_http_rsp(&httpRsp);
+       TIZEN_LOGD("File Thread Response Decode Success ...");
+       return retval;
+}
+
+int32 file_thread_range_request_recv_rng_rsp_headers(uint64 *bodyLen, char *blockSize, uint64 currChunkLen, uint32 *connClose, fileThread *fThread)
+{
+       int32 rcvdLen = 0;
+       uint32 offset = 0;
+       int32 retval = -1;
+       int32 len = 0;
+       int8 rspSize[MAX_HEADERS_SIZE] = {0};
+       int8 rspPrint[MAX_HEADERS_SIZE] = {0};
+       httpResp httpRsp ;
+       uint64 instanceSize =  fThread->contRngLen;
+       uint64 respLen = fThread->compRspLen;
+       while(1)
+       {
+               TIZEN_LOGD("Recv Response");
+               if (file_thread_conn_poll(fThread->socketId, fThread->SBData) <= 0)
+               {
+                       TIZEN_LOGD("File Thread Fail Polling");
+                       return HTTP_RSP_SOCKET_ERROR;
+               }
+               TIZEN_LOGD("Recved Response");
+               rcvdLen = recv(fThread->socketId,rspSize+offset,MAX_HEADERS_SIZE-offset,0);
+               if(rcvdLen > 0)
+               {
+                       rspSize[offset + rcvdLen +1] = '\0';
+                       len = decode_http_find_str(rspSize,END_OF_HEADERS);
+                       if(-1 != len)
+                       {
+                               uint32 headerLen = len+4;
+                               offset  = offset + rcvdLen;
+                               *bodyLen = offset-headerLen;
+                               memcpy(rspPrint, rspSize, headerLen);
+                               SECURE_DB_INFO("Response [%s]", rspPrint);
+                               memset(&httpRsp, 0, sizeof(httpResp));
+                               decode_http_rsp_init(rspSize, headerLen, &httpRsp);
+                               retval = process_http_rsp(&httpRsp);
+                               if(HTTP_RSP_DECODING_SUCCESS == retval)
+                               {
+                                       TIZEN_LOGD("File Thread Response Decode Success");
+                                       retval = range_request_validate_rsp(instanceSize,
+                                                       &httpRsp, currChunkLen, respLen, connClose);
+                                       if((retval == HTTP_RSP_DECODING_SUCCESS) && (*bodyLen > 0))
+                                       {
+                                               memcpy(blockSize,rspSize+headerLen,*bodyLen);
+                                       }
+                               }
+                               delete_http_rsp(&httpRsp);
+                               TIZEN_LOGD("File Thread Response Decode Success ...");
+                               return retval;
+                       }
+                       else
+                       {
+                               offset  = offset + rcvdLen;
+                               if (offset == MAX_HEADERS_SIZE)
+                               {
+                                       /* Rsp header too large */
+                                       retval = HTTP_RSP_DECODING_ERROR;
+                                       break;
+                               }
+                       }
+               }
+               else
+               {
+                       retval = HTTP_RSP_SOCKET_ERROR;
+                       break;
+               }
+       }
+       return retval;
+}
+
+int32 file_thread_rebuildReq(char *newRequest, int64 *chunkInfo, fileThread *fThread)
+{
+       int32 rangeLen = 0;
+       int8 rangeField[MAX_RANGE_FIELD_LEN] = {0};
+       rangeLen = sprintf(rangeField,"%s%llu%s%llu%s","Range: bytes=",chunkInfo[0],"-",chunkInfo[1],"\r\n\r\n");
+       memcpy(newRequest, fThread->req, fThread->headerLen - 2);
+       memcpy(newRequest + fThread->headerLen -2, rangeField, rangeLen);
+       return (rangeLen+fThread->headerLen);
+}
+
+void file_thread_exit(fileThread *fThread)
+{
+       TIZEN_LOGD("File_Thread_Exit [%p]", fThread);
+
+       if (0 < fThread->socketId)
+       {
+               shutdown(fThread->socketId, 1);
+       }
+
+       if (0 != fThread->pthreadId)
+       {
+               pthread_join(fThread->pthreadId,NULL);
+               TIZEN_LOGD("File Thread Closed");
+               fThread->pthreadId = 0;
+       }
+       if (0 < fThread->socketId)
+       {
+               CLOSE_SOCKET(fThread->socketId);
+               fThread->socketId = -1;
+       }
+       free(fThread);
+       fThread = NULL;
+       TIZEN_LOGD("File Thread Exit Sucess [%p]", fThread);
+}
+
diff --git a/src/multirat_libapi.c b/src/multirat_libapi.c
new file mode 100644 (file)
index 0000000..4f9128b
--- /dev/null
@@ -0,0 +1,1511 @@
+#include "multirat_SB_http.h"
+#include "multirat_process.h"
+#include "multirat_decode_http.h"
+#include "multirat_libapi.h"
+#include "multirat_data_buffer.h"
+#include "multirat_conf.h"
+#include "multirat_watch_dog_thread.h"
+#include "multirat_watchthread.h"
+#include "multirat_poll_thread.h"
+#include "multirat_multisocket.h"
+#include "multirat_file_stream.h"
+#include "multirat_file_manager.h"
+
+#define TIME_ELAPSED_SINCE_LAST_TEMP_READ_IN_SECS 3
+
+uint32 sb_get_cached_chunk(struct SmartBondingHandler *SBHandler, int8* buffer, uint32 len)
+{
+       if((buffer == NULL) || (!len))
+       {
+               TIZEN_LOGD("SBHandler[%p] Buffer Null", SBHandler);
+               return SB_ERR;
+       }
+       if(SBHandler != NULL)
+       {
+               if(SBHandler->SBData != NULL)
+               {
+                       buffer = memcpy(buffer, SBHandler->SBData->FileData, len);
+                       TIZEN_LOGD("SBHandler[%p] FileData [%s]", SBHandler, buffer);
+                       return SB_OK;
+               }
+       }
+       return SB_ERR;
+}
+
+void sb_set_direct_write_mode(struct SmartBondingHandler *SBHandler)
+{
+       if(SBHandler != NULL )
+       {
+               if(SBHandler->SBData != NULL)
+               {
+                       TIZEN_LOGD("SBHandler[%p] Setting RAF Mode", SBHandler);
+                       SBHandler->SBData->bRafMode = B_TRUE;
+               }
+       }
+       return;
+}
+
+uint32 sb_set_direct_filename(struct SmartBondingHandler *SBHandler, int8 *buffer, uint32 len)
+{
+       TIZEN_LOGD("SBHandler[%p] Setting Direct Write File Name", SBHandler);
+       if(SBHandler == NULL)
+       {
+               return SB_ERR;
+       }
+       if((buffer != NULL))
+       {
+               if(pthread_mutex_trylock(SBHandler->lock)!= 0)
+               {
+                       TIZEN_LOGD("SBHandler[%p] Error !!! trylock failed, session closed by another thread [%d] [%s]",
+                                                       SBHandler, errno, strerror(errno));
+                       return SB_ERR;
+               }
+
+               if(SBHandler->SBData != NULL)
+               {
+                       SmartBondingData *SBData = SBHandler->SBData;
+                       randomFileManager *raFileMngr = &(SBData->raFileMngr);
+                       httpReq *req = &(SBData->req);
+                       httpResp *resp = &(SBData->resp);
+                       if(!SBData->bRafMode)
+                       {
+                               TIZEN_LOGD("SBHandler[%p] RAF Mode Not Set", SBHandler);
+                               pthread_mutex_unlock(SBHandler->lock);
+                               return SB_ERR;
+                       }
+                       memcpy(SBData->rafFileName,buffer,len);
+
+                       // Random Access File Creation
+                       if((SBData->req.ifRange != NULL))
+                       {
+                               raFileMngr->writeFD1= fopen(SBData->rafFileName,"r+");
+                       }
+                       else
+                       {
+                               raFileMngr->writeFD1= fopen(SBData->rafFileName,"wb");
+                       }
+                       if(raFileMngr->writeFD1 == NULL)
+                       {
+                               TIZEN_LOGD("SBHandler[%p] Unable to open RAF File:writeFD1 file [%s] Failed", SBHandler, SBData->rafFileName);
+                               pthread_mutex_unlock(SBHandler->lock);
+                               return SB_ERR;
+                       }
+
+                       // Random Access File Creation
+                       if((req->ifRange != NULL))
+                       {
+                               raFileMngr->writeFD2= fopen(SBData->rafFileName,"r+");
+                       }
+                       else
+                       {
+                               raFileMngr->writeFD2= fopen(SBData->rafFileName,"wb");
+                       }
+                       if(raFileMngr->writeFD2 == NULL)
+                       {
+                               TIZEN_LOGD("SBHandler[%p] Unable to open RAF File:writeFD2 file [%s] Failed", SBHandler, SBData->rafFileName);
+                               fclose(raFileMngr->writeFD1);
+                               raFileMngr->writeFD1 = NULL;
+                               pthread_mutex_unlock(SBHandler->lock);
+                               return SB_ERR;
+                       }
+
+                       TIZEN_LOGD("SBHandler[%p] Created RAF File [%s]", SBHandler, SBData->rafFileName);
+
+                       raFileMngr->rspRead = SBData->startOffset;
+
+                       TIZEN_D_LOGD("SBHandler[%p] Random File:Seeking to this position:[%llu]", SBHandler, raFileMngr->rspRead);
+                       if(-1 == fseek(raFileMngr->writeFD1,raFileMngr->rspRead,SEEK_SET))
+                       {
+                               TIZEN_LOGD("SBHandler[%p] [%s] fseek [%llu] failed", SBHandler, SBData->rafFileName, raFileMngr->rspRead);
+                       }
+                       fwrite((void*)(resp->resp_buff_body + resp->resp_header_length),SBData->response_body_read, 1, raFileMngr->writeFD1);
+                       fflush(raFileMngr->writeFD1);
+                       raFileMngr->rspRead = raFileMngr->rspRead + SBData->response_body_read;
+                       TIZEN_LOGD("SBHandler[%p] random file:totoal bytes read [%llu], response_body_read [%llu]", SBHandler, raFileMngr->rspRead, SBData->response_body_read);
+
+                       if((SBData->enableMultiRat) && (NULL == SBData->cthread))
+                       {
+                               /*watchdog cthread is being created */
+                               SBData->cthread = cthread_init();
+                               /*watchdog cthread is initialised */
+                               cthread_start_thread(SBData);
+                               TIZEN_D_LOGD ("SBHandler[%p] MultiRat enabled, waiting for to start multi socket", SBHandler);
+                       }
+                       pthread_mutex_unlock(SBHandler->lock);
+                       return SB_OK;
+               }
+               pthread_mutex_unlock(SBHandler->lock);
+       }
+       return SB_ERR;
+}
+
+/* Smart Bonding Handler Initialisation */
+struct SmartBondingHandler *smart_bonding_handler_init(void)
+{
+       SmartBondingData *SBData = NULL;
+
+       struct SmartBondingHandler *SBHandler = malloc(sizeof(struct SmartBondingHandler));
+       if(SBHandler == NULL)
+       {
+               TIZEN_LOGD("Error !!! SBHandler malloc failed [%d] [%s]", errno, strerror(errno));
+               return NULL;
+       }
+       memset(SBHandler, 0, sizeof(struct SmartBondingHandler));
+
+       pthread_mutex_t *lock = malloc(sizeof(pthread_mutex_t));
+       if(lock == NULL)
+       {
+               TIZEN_LOGD("Error !!! Mutex Lock malloc failed [%d] [%s]", errno, strerror(errno));
+               free(SBHandler);
+               return NULL;
+       }
+       memset(lock, 0, sizeof(pthread_mutex_t));
+       SBHandler->lock = lock;
+
+       if (pthread_mutex_init(SBHandler->lock, NULL) != 0)
+       {
+               TIZEN_LOGD("Error !!! mutex init failed [%d] [%s]", errno, strerror(errno));
+               free(SBHandler->lock);
+               free(SBHandler);
+               return NULL;
+       }
+
+       SBData = (SmartBondingData *)malloc(sizeof(SmartBondingData));
+
+       if(SBData == NULL)
+       {
+               pthread_mutex_destroy(SBHandler->lock);
+               free(SBHandler->lock);
+               free(SBHandler);
+               TIZEN_LOGD("Error !!! SBData allocation failure [%d] [%s]", errno, strerror(errno));
+               return NULL;
+       }
+
+       memset(SBData, 0, sizeof(SmartBondingData));
+       SBHandler->SBData = SBData;
+       SBData->socket_fd = -1;
+
+       #ifdef TWO_CHUNK
+       SBData->twoChunk = 1;
+       TIZEN_LOGD("SBHandler[%p] SBData[%p] Two --Chunk", SBHandler, SBData);
+       #endif
+
+       if (pthread_mutex_init(&SBData->tempLock, NULL) != 0)
+       {
+               TIZEN_LOGD("Error !!! mutex init failed [%d] [%s]", errno, strerror(errno));
+               pthread_mutex_destroy(SBHandler->lock);
+               free(SBHandler->lock);
+               free(SBData);
+               free(SBHandler);
+               return NULL;
+       }
+
+       if(SBData->twoChunk == 1)
+       {
+               if (pipe(SBData->trigger_pipefd) < 0)
+               {
+                       TIZEN_LOGD("Error !!! pipe failed [%d] [%s]", errno, strerror(errno));
+                       pthread_mutex_destroy(SBHandler->lock);
+                       free(SBHandler->lock);
+                       free(SBData);
+                       free(SBHandler);
+                       return NULL;
+               }
+
+               /* Setting Socket NON_BLOCKING */
+               if (fcntl(SBData->trigger_pipefd[0], F_SETFL, O_NONBLOCK) != 0)
+               {
+                       TIZEN_LOGD("Error !!! failed to set pipe fd [0] as NON-BLOCKING [%d] [%s]", errno, strerror(errno));
+
+                       CLOSE_SOCKET(SBData->trigger_pipefd[0]);
+                       CLOSE_SOCKET(SBData->trigger_pipefd[1]);
+
+                       pthread_mutex_destroy(SBHandler->lock);
+                       free(SBHandler->lock);
+                       free(SBData);
+                       free(SBHandler);
+                       return NULL;
+               }
+
+               if (fcntl(SBData->trigger_pipefd[1], F_SETFL, O_NONBLOCK) != 0)
+               {
+                       TIZEN_LOGD("Error !!! failed to set pipe fd [1] as NON-BLOCKING [%d] [%s]", errno, strerror(errno));
+
+                       CLOSE_SOCKET(SBData->trigger_pipefd[0]);
+                       CLOSE_SOCKET(SBData->trigger_pipefd[1]);
+
+                       pthread_mutex_destroy(SBHandler->lock);
+                       free(SBHandler->lock);
+                       free(SBData);
+                       free(SBHandler);
+                       return NULL;
+               }
+
+               TIZEN_LOGD("SBHandler[%p] Trigger PIPE Fd[0] [%d] Fd[1] [%d]", SBHandler, SBData->trigger_pipefd[0], SBData->trigger_pipefd[1]);
+
+               if (pipe(SBData->noti_pipefd) < 0)
+               {
+                       TIZEN_LOGD("Error !!! pipe failed [%d] [%s]", errno, strerror(errno));
+
+                       CLOSE_SOCKET(SBData->trigger_pipefd[0]);
+                       CLOSE_SOCKET(SBData->trigger_pipefd[1]);
+
+                       pthread_mutex_destroy(SBHandler->lock);
+                       free(SBHandler->lock);
+                       free(SBData);
+                       free(SBHandler);
+                       return NULL;
+               }
+
+               /* Setting Socket NON_BLOCKING */
+               if (fcntl(SBData->noti_pipefd[0], F_SETFL, O_NONBLOCK) != 0)
+               {
+                       TIZEN_LOGD("Error !!! failed to set pipe fd [0] as NON-BLOCKING [%d] [%s]", errno, strerror(errno));
+
+                       CLOSE_SOCKET(SBData->trigger_pipefd[0]);
+                       CLOSE_SOCKET(SBData->trigger_pipefd[1]);
+                       CLOSE_SOCKET(SBData->noti_pipefd[0]);
+                       CLOSE_SOCKET(SBData->noti_pipefd[1]);
+
+                       pthread_mutex_destroy(SBHandler->lock);
+                       free(SBHandler->lock);
+                       free(SBData);
+                       free(SBHandler);
+                       return NULL;
+               }
+
+               if (fcntl(SBData->noti_pipefd[1], F_SETFL, O_NONBLOCK) != 0)
+               {
+                       TIZEN_LOGD("Error !!! failed to set pipe fd [1] as NON-BLOCKING [%d] [%s]", errno, strerror(errno));
+
+                       CLOSE_SOCKET(SBData->trigger_pipefd[0]);
+                       CLOSE_SOCKET(SBData->trigger_pipefd[1]);
+                       CLOSE_SOCKET(SBData->noti_pipefd[0]);
+                       CLOSE_SOCKET(SBData->noti_pipefd[1]);
+
+                       pthread_mutex_destroy(SBHandler->lock);
+                       free(SBHandler->lock);
+                       free(SBData);
+                       free(SBHandler);
+                       return NULL;
+               }
+
+               TIZEN_LOGD("SBHandler[%p] Notification PIPE Fd[0] [%d] Fd[1] [%d]", SBHandler, SBData->noti_pipefd[0], SBData->noti_pipefd[1]);
+               SBData->Libfd = SBData->trigger_pipefd[0];
+       }
+
+       TIZEN_D_LOGD("Smart Bonding initialisation is done successfully Handler [%x]", SBHandler);
+       return SBHandler;
+}
+
+void smart_bonding_handler_exit(struct SmartBondingHandler *SBHandler)
+{
+       pthread_mutex_t *mutex_lock = NULL;
+
+       if(SBHandler != NULL)
+       {
+               mutex_lock = SBHandler->lock;
+               /* Mutex Lock */
+               pthread_mutex_lock(mutex_lock);
+               TIZEN_LOGD("SBHandler[%p] Mutex Locked in SmartBonding Handler Exit", SBHandler);
+
+               if(SBHandler->SBData != NULL)
+               {
+                       smart_bonding_exit(SBHandler->SBData);
+                       SBHandler->SBData = NULL;
+               }
+
+               free(SBHandler);
+               SBHandler =  NULL;
+               pthread_mutex_unlock(mutex_lock);
+               pthread_mutex_destroy(mutex_lock);
+               TIZEN_LOGD("Mutex Lock Released in SmartBonding Handler Exit");
+               free(mutex_lock);
+       }
+}
+
+struct SmartBondingHandler *sb_request_send(int8 *http_req, uint32 timeout, struct sockaddr_storage *remote_info,
+                                                                        void (*LibraryCallbackFunction)(void *), void *LibSessionIdentifier)
+{
+       struct SmartBondingHandler *SBHandler = NULL;
+       TIZEN_LOGD("FAILED as this API is not implemented");
+       return SBHandler;
+}
+
+struct SmartBondingHandler *sb_request_send_sync(int8 *http_req, uint32 timeout, struct sockaddr_storage *remote_info)
+{
+       SmartBondingData *SBData = NULL;
+       struct SmartBondingHandler *SBHandler = NULL;
+
+       SBHandler = send_request(http_req, timeout, remote_info);
+
+       if(SBHandler != NULL)
+       {
+               SBData =  (SmartBondingData *)(SBHandler->SBData);
+               if(SBData != NULL)
+               {
+                       SBData->sync = 1;
+               }
+       }
+       TIZEN_LOGD("SBHandler[%p] sb_request_send exit", SBHandler);
+       return SBHandler;
+}
+
+struct SmartBondingHandler *sb_request_send_curl(int8 *http_req, uint32 timeout, struct sockaddr_storage *remote_info)
+{
+       /* Code Removed */
+       struct SmartBondingHandler *SBHandler = NULL;
+       return SBHandler;
+}
+
+int32 sb_get_connection_status(struct SmartBondingHandler *SBHandler)
+{
+       TIZEN_LOGD("SBHandler[%p] Check Connection Status", SBHandler);
+       if(SBHandler == NULL)
+       {
+               return CONNECTION_FAIL;
+       }
+       int32 status = get_connection_status(SBHandler->SBData);
+       if(status == -1)
+       {
+               if(SBHandler->SBData->con_status == CONNECTION_WAIT)
+               {
+                       TIZEN_LOGD("SBHandler[%p] Connection WAIT",SBHandler);
+               }
+               else if (SBHandler->SBData->con_status == CONNECTION_FAIL)
+               {
+                       TIZEN_LOGD("SBHandler[%p] Connection Failed", SBHandler);
+               }
+       }
+       else
+       {
+               TIZEN_LOGD("SBHandler[%p] Connected Successfully", SBHandler);
+       }
+       return SBHandler->SBData->con_status;
+}
+
+struct SmartBondingHandler *sb_request_connect_only_curl(uint32 timeout, struct sockaddr_storage *remote_info)
+{
+       SmartBondingData *SBData = NULL;
+       struct SmartBondingHandler *SBHandler = NULL;
+
+       SBHandler = curl_connect_request(timeout, remote_info);
+
+       if(SBHandler != NULL)
+       {
+               TIZEN_LOGD("SBHandler[%p] Success", SBHandler);
+               SBData =  SBHandler->SBData;
+               if(SBData != NULL)
+               {
+                       SBData->curl = 1;
+               }
+       }
+       return SBHandler;
+}
+
+struct SmartBondingHandler *curl_connect_request(uint32 timeout, struct sockaddr_storage *remote_info)
+{
+       SmartBondingData *SBData = NULL;
+       struct sockaddr_in serv_addr;
+       struct sockaddr_in6 serv_addr_ip6;
+       connection *conn = NULL;
+       struct SmartBondingHandler *SBHandler = NULL;
+
+       /* Creating SmartBonding Handler */
+       SBHandler = smart_bonding_handler_init();
+       if (SBHandler == NULL)
+       {
+               TIZEN_LOGD("Smart Bonding Handler Creation Failed");
+               return NULL;
+       }
+
+       pthread_mutex_lock(SBHandler->lock);
+
+       SBData = SBHandler->SBData;
+       conn = &(SBData->conn);
+       if(SBData->twoChunk == 1)
+               SBData->status = MAIN_START;
+
+       smart_bonding_init_speed(SBData);
+
+       SBData->stat.startTime = get_time_in_microsec();
+
+       /* Get the IP address and Port number of Remote Server */
+       switch(remote_info->ss_family)
+       {
+               case AF_INET:
+               memset(&serv_addr, 0, sizeof(struct sockaddr_in));
+               memcpy(&serv_addr,(struct sockaddr_in *)remote_info,sizeof(struct sockaddr_in));
+
+               inet_ntop(AF_INET,&(serv_addr.sin_addr),(char*)conn->ip_addr,INET_ADDRSTRLENG);
+               conn->port = ntohs(serv_addr.sin_port);
+               conn->ip_family = 0;  /*Ipv4 */
+               break;
+
+               case AF_INET6:
+
+               memset(&serv_addr_ip6, 0, sizeof(struct sockaddr_in6));
+               memcpy(&serv_addr_ip6,(struct sockaddr_in6 *)remote_info,sizeof(struct sockaddr_in6));
+               inet_ntop(AF_INET6,&(serv_addr_ip6.sin6_addr),(char*)conn->ip_addr,INET_ADDRSTRLENG);
+               conn->port = ntohs(serv_addr_ip6.sin6_port);
+               conn->ip_family = 1;  /*Ipv6 */
+               break;
+
+               default:
+               strncpy(conn->ip_addr, "Unknown AF", INET_ADDRSTRLENG);
+               TIZEN_LOGD("SBHandler[%p] Error !!  Unknown Family name ..", SBHandler);
+               pthread_mutex_unlock(SBHandler->lock);
+               smart_bonding_handler_exit(SBHandler);
+               return NULL;
+       }
+
+       SECURE_DB_INFO("SBHandler[%p] destination IP address [%s:%d]",SBHandler, conn->ip_addr, conn->port);
+
+       memcpy(conn->ifaceInfo[SBData->interface_index].server_ip, conn->ip_addr, strlen(conn->ip_addr));
+       conn->ifaceInfo[SBData->interface_index].server_port = conn->port;
+       memcpy(conn->ifaceInfo[(SBData->interface_index + 1) % 2].server_ip, conn->ip_addr, strlen(conn->ip_addr));
+
+       get_client_socket(SBData, timeout, &serv_addr, &serv_addr_ip6);
+
+       if(SBData->socket_fd < 0)
+       {
+               TIZEN_LOGD("SBHandler[%p] Error !!! connect failed", SBHandler);
+               pthread_mutex_unlock(SBHandler->lock);
+               smart_bonding_handler_exit(SBHandler);
+               return NULL;
+       }
+
+       pthread_mutex_unlock(SBHandler->lock);
+       return SBHandler;
+}
+/* 0 if send error 1 if success */
+int32 sb_request_send_only_curl(struct SmartBondingHandler * SBHandler, int8 *http_req_in, uint32 len)
+{
+       SmartBondingData *SBData = NULL;
+       connection *conn = NULL;
+       uint32 nbytes = 0;
+       int8*  http_req = NULL;
+       uint32 err = B_FALSE;
+
+       if((http_req_in != NULL) && (len > 4))
+       {
+               http_req = malloc((sizeof (char)) * (len+1));
+               if(http_req)
+               {
+                       memset(http_req, 0, (len+1));
+                       memcpy(http_req, http_req_in, len);
+               }
+               else
+               {
+                       TIZEN_LOGD("SBHandler[%p] malloc failed", SBHandler);
+                       err = B_TRUE;
+               }
+       }
+       else
+               err = B_TRUE;
+       if(err == B_TRUE)
+       {
+               TIZEN_LOGD("SBHandler[%p] Invalid http_req_in or len<0 or malloc failed", SBHandler);
+               return B_FALSE;
+       }
+
+       pthread_mutex_lock(SBHandler->lock);
+
+       SBData = SBHandler->SBData;
+       conn = &(SBData->conn);
+       store_http_request(http_req, SBData);
+
+       /* check if proxy is present for main socket interface */
+       int32 len_header = -1;
+       len_header = decode_http_find_str(http_req,"http://");
+       if((len_header != -1) && (len_header <= 4))
+       {
+               TIZEN_LOGD("Main thread setting proxy Enable");
+
+               /* The Server IP and Port Number is of Proxy */
+               memcpy(conn->ifaceInfo[SBData->interface_index].proxy_addr, conn->ifaceInfo[SBData->interface_index].server_ip, strlen(conn->ip_addr));
+               conn->ifaceInfo[SBData->interface_index].proxy_port = conn->port;
+
+               conn->ifaceInfo[SBData->interface_index].proxyEnable = 1;
+       }
+
+       SBData->stat.main_thread_sendTime = get_time_in_sec();
+
+       if (send(SBData->socket_fd, http_req, len, 0) < 0)
+       {
+               TIZEN_LOGD("SBHandler[%p] Error !!! HTTP request send is failed [%d] [%s]", SBHandler, errno, strerror(errno));
+               pthread_mutex_unlock(SBHandler->lock);
+               CLOSE_SOCKET(SBData->socket_fd);
+               SBData->socket_fd = -1;
+               free(http_req);
+               return B_FALSE;
+       }
+       SECURE_DB_INFO("SBHandler[%p] HTTP request is sent successfully [%s]", SBHandler, http_req);
+
+       if(SBData->twoChunk == 1)
+       {
+               /* Create Thread */
+               SBData->PollThrd = PollThread_init();
+               if(SBData->PollThrd != NULL)
+               {
+                       PollThread_start(SBData);
+               }
+               else
+               {
+                       pthread_mutex_unlock(SBHandler->lock);
+                       free(http_req);
+                       return B_FALSE;
+               }
+               TIZEN_D_LOGD("SBHandler[%p] Write Data to Notification Pipe Fd [%s]", SBHandler, NOTI_TRIGGER);
+               nbytes = write(SBData->noti_pipefd[1], NOTI_TRIGGER, NOTI_TRIGGER_LENGTH);
+               nbytes = nbytes; /*warning removal */
+       }
+
+       pthread_mutex_unlock(SBHandler->lock);
+       free(http_req);
+       return B_TRUE;
+}
+
+struct SmartBondingHandler *send_request(int8 *http_req, uint32 timeout, struct sockaddr_storage *remote_info)
+{
+       SmartBondingData *SBData = NULL;
+       connection *conn = NULL;
+       struct sockaddr_in serv_addr;
+       struct sockaddr_in6 serv_addr_ip6;
+       struct SmartBondingHandler *SBHandler = NULL;
+       /* Creating SmartBonding Handler */
+       TIZEN_LOGD("Init");
+       SBHandler = smart_bonding_handler_init();
+       if (SBHandler == NULL)
+       {
+               TIZEN_LOGD("Smart Bonding Handler Creation Failed");
+               return NULL;
+       }
+
+       pthread_mutex_lock(SBHandler->lock);
+
+       SBData = SBHandler->SBData;
+       conn = &(SBData->conn);
+       SBData->stat.startTime = get_time_in_microsec();
+
+       /* Get the IP address and Port number of Remote Server */
+       switch(remote_info->ss_family)
+       {
+               case AF_INET:
+               memset(&serv_addr, 0, sizeof(struct sockaddr_in));
+               memcpy(&serv_addr,(struct sockaddr_in *)remote_info,sizeof(struct sockaddr_in));
+
+               inet_ntop(AF_INET,&(serv_addr.sin_addr),(char*)conn->ip_addr,INET_ADDRSTRLENG);
+               conn->port = ntohs(serv_addr.sin_port);
+               conn->ip_family = 0;  /*Ipv4 */
+               break;
+
+               case AF_INET6:
+
+               memset(&serv_addr_ip6, 0, sizeof(struct sockaddr_in6));
+               memcpy(&serv_addr_ip6,(struct sockaddr_in6 *)remote_info,sizeof(struct sockaddr_in6));
+               inet_ntop(AF_INET6,&(serv_addr_ip6.sin6_addr),(char*)conn->ip_addr,INET_ADDRSTRLENG);
+               conn->port = ntohs(serv_addr_ip6.sin6_port);
+               conn->ip_family = 1;  /*Ipv6 */
+               break;
+
+               default:
+               strncpy(SBData->conn.ip_addr, "Unknown AF", INET_ADDRSTRLENG);
+               TIZEN_LOGD("SBHandler[%p] Error-Unknown Family name", SBHandler);
+               break;
+       }
+
+       SECURE_DB_INFO("SBHandler[%p] destination IP address [%s:%d]",SBHandler, conn->ip_addr, conn->port);
+       memcpy(conn->ifaceInfo[SBData->interface_index].server_ip, conn->ip_addr, strlen(conn->ip_addr));
+       conn->ifaceInfo[SBData->interface_index].server_port = conn->port;
+       memcpy(conn->ifaceInfo[(SBData->interface_index + 1) % 2].server_ip, conn->ip_addr, strlen(conn->ip_addr));
+
+       /* Storing of HTTP Request */
+       store_http_request(http_req, SBData);
+       get_client_socket(SBData, timeout, &serv_addr,&serv_addr_ip6);
+       if(SBData->socket_fd < 0)
+       {
+               TIZEN_LOGD("SBHandler[%p] Error !!! connect failed", SBHandler);
+               pthread_mutex_unlock(SBHandler->lock);
+               //CLOSE_SOCKET(SBData->socket_fd);
+               smart_bonding_handler_exit(SBHandler);
+               return NULL;
+       }
+
+       SBData->stat.main_thread_sendTime = get_time_in_sec();
+
+       /* check if proxy is present for main socket interface */
+       int32 len_header = -1;
+       len_header = decode_http_find_str(http_req,"http://");
+       if((len_header != -1) && (len_header <= 4))
+       {
+               TIZEN_LOGD("Main thread setting proxy Enable");
+               /* The Server IP and Port Number is of Proxy */
+               memcpy(conn->ifaceInfo[SBData->interface_index].proxy_addr, conn->ifaceInfo[SBData->interface_index].server_ip, strlen(conn->ip_addr));
+               conn->ifaceInfo[SBData->interface_index].proxy_port = conn->port ;
+
+               conn->ifaceInfo[SBData->interface_index].proxyEnable = 1;
+       }
+
+       if (send(SBData->socket_fd, http_req, strlen(http_req), 0) < 0)
+       {
+               TIZEN_LOGD("SBHandler[%p] Error-HTTP request send is failed [%d] [%s]", SBHandler, errno, strerror(errno));
+               pthread_mutex_unlock(SBHandler->lock);
+               CLOSE_SOCKET(SBData->socket_fd);
+               SBData->socket_fd = -1;
+               smart_bonding_handler_exit(SBHandler);
+               return NULL;
+       }
+       SECURE_DB_INFO("SBHandler[%p] HTTP request is sent to server successfully [%s]", SBHandler, http_req);
+
+       pthread_mutex_unlock(SBHandler->lock);
+       return SBHandler;
+}
+
+void get_client_socket(SmartBondingData *SBData, uint32 timeout, struct sockaddr_in *serv_addr,struct sockaddr_in6 *serv_addr_ip6)
+{
+       int32 socket_fd = -1;
+       int32 interface_index = -1;
+       uint64 connect_start = 0;
+       connection *conn = &(SBData->conn);
+       connect_start = get_time_in_sec();
+
+       while((get_time_in_sec() - connect_start) < timeout && (!SBData->cancel))
+       {
+               /* Creating a  Client Socket */
+               if(is_both_interface_avail(conn->ifaceInfo, conn->ip_family))
+               {
+                       if(-1 == interface_index)
+                       {
+                               interface_index = MAIN_SOCKET_DEFAULT;
+                       }
+                       SECURE_DB_INFO("SBData[%p] source IP address [%s]", SBData, conn->ifaceInfo[interface_index].ip);
+                       socket_fd = conn_get_socket_bind(conn->ifaceInfo[interface_index].ip,interface_index, conn->ip_family);
+                       if(socket_fd < 0)
+                       {
+                               TIZEN_LOGD("SBData[%p] Error !!! while creating socket", SBData);
+                               usleep(5000);
+                               interface_index = (interface_index + 1) % 2;
+                               continue;
+                       }
+               }
+               else
+               {
+                       if(strlen(conn->ifaceInfo[1].ip) != 0)
+                       {
+                               TIZEN_LOGD("SBData[%p] Avilable Interface is LTE for Main Socket Connection", SBData);
+                               interface_index = 1;
+                       }
+                       else
+                       {
+                               TIZEN_LOGD("SBData[%p] Avilable Interface is Wi-Fi for Main Socket Connection", SBData);
+                               interface_index = 0;
+                       }
+
+
+                       if(SBData->conn.ip_family)
+                       {
+                               socket_fd = socket(AF_INET6, SOCK_STREAM, 0);
+                       }
+                       else
+                       {
+                               socket_fd = socket(AF_INET, SOCK_STREAM, 0);
+                       }
+                       if (socket_fd < 0)
+                       {
+                               TIZEN_LOGD("SBData[%p] Error !!! client socket creation failed", SBData);
+                               continue;
+                       }
+               }
+
+               SBData->interface_index = interface_index;
+               if(-1 == connServer(socket_fd, serv_addr, serv_addr_ip6,timeout, SBData)) // Disabled COnnectivity Feature
+               {
+                       if(SBData->con_status == CONNECTION_FAIL)
+                       {
+                               TIZEN_LOGD("SBData[%p] Error !!! connect to server failed", SBData);
+                               CLOSE_SOCKET(socket_fd);
+                               socket_fd = -1;
+                               continue;
+                       }
+                       else if(SBData->con_status == CONNECTION_WAIT)
+                       {
+                               TIZEN_LOGD("SBData[%p] Connect in WAIT STATE", SBData);
+                               SBData->socket_fd = socket_fd;
+                               break;
+                       }
+               }
+               else
+               {
+                       SBData->socket_fd = socket_fd;
+                       TIZEN_LOGD("SBData[%p] connection is done successfully [%d]", SBData, SBData->socket_fd);
+               }
+               break;
+       }
+       SBData->timeout =  30;
+       return;
+}
+
+int32 sb_read_data(struct SmartBondingHandler *SBHandler, int8 *buffer, uint32 size, int32 *nread)
+{
+       int32 retval = SB_OK;
+       uint64 temp_endTime = 0;
+       SmartBondingData *SBData = NULL;
+       StatDetails *stat = NULL;
+       randomFileManager *raFileMngr = NULL;
+       char readbuffer[NOTI_TRIGGER_LENGTH + 1] = "";
+       uint32 nbytes = 0;
+       httpResp *resp = NULL;
+       if (SBHandler ==  NULL)
+       {
+               TIZEN_LOGD("SBHandler is NULL");
+               return SB_ERR;
+       }
+
+       SBData = SBHandler->SBData;
+       if (SBData == NULL)
+       {
+               TIZEN_LOGD("SBHandler[%p] SBData is NULL", SBHandler);
+               return SB_ERR;
+       }
+
+       stat = &(SBData->stat);
+       resp = &(SBData->resp);
+       raFileMngr = &(SBData->raFileMngr);
+       speedStat *sStat = &(SBData->sStat);
+
+       if(pthread_mutex_trylock(SBHandler->lock)!= 0)
+       {
+               TIZEN_LOGD("SBHandler[%p] Error !!! trylock failed, session closed by another thread [%d] [%s]",
+                       SBHandler, errno, strerror(errno));
+               return SB_ERR;
+       }
+
+       TIZEN_D_LOGD("SBHandler[%p] Mutex Locked sb_read_data", SBHandler);
+
+       /* Read the Data from the Trigger Pipe Fd */
+       nbytes = read(SBData->trigger_pipefd[0], readbuffer, NOTI_TRIGGER_LENGTH);
+       TIZEN_D_LOGD("SBHandler[%p] Read Data from Trigger Pipe Fd [%s] Length [%d]", SBHandler, readbuffer, nbytes);
+
+       /* Setting Flag for main sock read active state */
+       stat->read_start_time = (get_time_in_microsec());
+       SBData->read_state_check = MAIN_SOCK_READ_ACTIVE;
+
+       /* Checking For Session Cancel Flag */
+       if(SBData->cancel)
+       {
+               TIZEN_LOGD("SBHandler[%p] Error !!! cancel_session command is recieved", SBHandler);
+               pthread_mutex_unlock(SBHandler->lock);
+               return SB_ERR;
+       }
+
+       if(stat->tempTime == 0)
+       {
+               stat->tempTime = get_time_in_sec();
+               temp_endTime = stat->tempTime;
+       }
+       else
+       {
+               temp_endTime = get_time_in_sec();
+       }
+
+       if((temp_endTime - stat->tempTime) > TIME_ELAPSED_SINCE_LAST_TEMP_READ_IN_SECS )
+       {
+               TIZEN_D_LOGD("SBHandler[%p] Main Thread GET TEMP", SBHandler);
+               getTempLevel(SBData);
+               stat->tempTime = temp_endTime;
+       }
+       if(SBData->twoChunk == 1)
+       {
+               if((SBData->bRafMode) && (!(SBData->response_check)))
+               {
+                       size = size - SBData->response_check_length - DIRECT_WRITE_HEADER_LENGTH;
+                       TIZEN_LOGD("SBHandler[%p] Reducing the Size of Read Buffer to [%d]", SBHandler, size);
+               }
+               if((SBData->bRafMode) && (!(strlen(SBData->rafFileName))) && (SBData->response_check))
+               {
+                       TIZEN_LOGD("SBHandler[%p] Response is Completed ... File Name Not set ... Sending Error", SBHandler);
+                       pthread_mutex_unlock(SBHandler->lock);
+                       return SB_ERR;
+               }
+               if(SBData->fStreamFileBufferReady)
+               {
+                       retval = file_stream_read(buffer, size, SBData, nread);
+                       if(SBData->sStat.prev_read == MAIN_THREAD)
+                       {
+                               if((SB_ERR == retval) && ((SBData->response_check != 0) ||
+                                               ((SBData->response_check == 0) && (SBData->response_body_read == 0))))
+                               {
+                                       TIZEN_LOGD("SBHandler[%p] Main Socket Exception", SBHandler);
+                                       retval = handleMainSocExp(SBData, buffer, size, nread);
+                                       SBData->poll_thread_noti_exception= 1;
+                               }
+                       }
+               }
+               else
+               {
+                       retval = twoChunk_read_from_socket(SBData,buffer,size,nread);
+               }
+       }
+       else
+       {
+               if(SBData->mSocketDataBufferReady)
+               {
+                       retval = read_from_buffer(SBData,buffer,size,nread);
+               }
+               else
+               {
+                       retval = read_from_socket(SBData,buffer,size,nread);
+               }
+       }
+       if (*nread > 0)
+       {
+               SBData->response_body_read = SBData->response_body_read + *nread;
+
+               SBData->stat.offsetForSpeed = SBData->stat.offsetForSpeed + *nread;
+               TIZEN_D_LOGD("SBHandler[%p] Read Data [%llu]",SBHandler, SBData->response_body_read);
+
+               if(SBData->response_check == 0)
+               {
+                       start_watchdog(SBData, buffer, *nread);
+               }
+               if((!SBData->resp_complete)&& (SBData->twoChunk) && (SBData->bRafMode))
+               {
+                       if(SBData->response_check == 0)
+                       {
+                               *nread = 0;
+                               TIZEN_LOGD("SBHandler[%p] Complete Response is not Received", SBHandler);
+                               pthread_mutex_unlock(SBHandler->lock);
+                               return SB_OK;
+                       }
+                       else if((SBData->response_check == 1) && (!SBData->enableMultiRat))
+                       {
+                               TIZEN_LOGD("SBHandler[%p] No Need to go for RAF", SBHandler);
+                               /* We Dont Need to Change the Header */
+                               SBData->bRafMode = B_FALSE;
+                               memcpy(buffer, resp->resp_buff_body, SBData->response_check_length);
+                               *nread = SBData->response_check_length;
+                               SBData->resp_complete = B_TRUE;
+                       }
+                       else if((SBData->response_check == 1) && (SBData->enableMultiRat))
+                       {
+                               TIZEN_LOGD("SBHandler[%p] We Need to Continue with RAF", SBHandler);
+                               /* We Need to Change the Header*/
+                               memcpy(buffer, resp->resp_buff, resp->resp_header_length);
+                               sprintf(buffer + resp->resp_header_length - 4, "%s%s%s", "\r\n",DIRECT_WRITE_HEADER, "\r\n\r\n");
+                               *nread = resp->resp_header_length + DIRECT_WRITE_HEADER_LENGTH ;
+                               SBData->resp_complete = B_TRUE;
+                               SECURE_DB_INFO("SBHandler[%p] Response Sent [%s]", SBHandler, buffer);
+                       }
+               }
+               if(SBData->twoChunk != 1)
+               {
+                       if(!SBData->mSocketDataBufferReady)
+                       {
+                               sb_calc_speed(SBData);
+                       }
+               }
+               else
+               {
+                       if(sStat->prev_read == MAIN_THREAD)
+                       {
+                               if(SBHandler->SBData->bRafMode)
+                               {
+                                       if(raFileMngr->rspHeaderCheck == 1)
+                                       {
+                                               if(raFileMngr->writeFD1 == NULL)
+                                               {
+                                                       TIZEN_LOGD("SBHandler[%p] FD1 null for [%s]", SBHandler, SBData->rafFileName);
+                                                       pthread_mutex_unlock(SBHandler->lock);
+                                                       return SB_ERR;
+                                               }
+
+                                               if(!sStat->prev_sock_read)
+                                               {
+                                                       TIZEN_D_LOGD("SBHandler[%p] Random File:Seeking to this position:[%llu]", SBHandler, raFileMngr->rspRead);
+                                                       if(-1 == fseek(raFileMngr->writeFD1, raFileMngr->rspRead,SEEK_SET))
+                                                       {
+                                                               TIZEN_LOGD("SBHandler[%p] fseek [%llu] failed", SBHandler, raFileMngr->rspRead);
+                                                       }
+                                                       sStat->prev_sock_read = B_TRUE;
+                                               }
+
+                                               fwrite(buffer, *nread, 1, raFileMngr->writeFD1);
+                                               fflush(raFileMngr->writeFD1);
+                                               raFileMngr->rspRead = raFileMngr->rspRead + *nread ;
+                                               TIZEN_D_LOGD("SBHandler[%p] Random file:Total bytes read [%llu], *nread is [%d]", SBHandler, raFileMngr->rspRead , *nread);
+                                       }
+
+                                       if(raFileMngr->rspHeaderCheck == 0)
+                                       {
+                                               if(SBData->response_check == 1)
+                                                       raFileMngr->rspHeaderCheck = 1;
+                                       }
+                               }
+                               uint64 temp_history = 0;
+                               uint64 temp_data = 0;
+                               temp_data = sStat->recv_length[SBData->interface_index];
+                               sStat->recv_length[SBData->interface_index] = sStat->recv_length[SBData->interface_index] + *nread;
+                               if(sStat->start_recv_time[SBData->interface_index] == 0)
+                                       sStat->start_recv_time[SBData->interface_index] = get_time_in_microsec();
+                               sStat->prev_recv_time[SBData->interface_index] = get_time_in_microsec();
+                               temp_history = (sStat->prev_recv_time[SBData->interface_index] - sStat->start_recv_time[SBData->interface_index])/1000000;
+                               if((sStat->timeArray[SBData->interface_index] < (MAX_HISTORY)) && (temp_history < MAX_HISTORY) && (temp_history > sStat->timeArray[SBData->interface_index]))
+                               {
+                                       int i = 0;
+                                       TIZEN_LOGD("SBHandler[%p] Infidx [%d] Array Index [%llu] Data [%llu]", SBHandler, SBData->interface_index, sStat->timeArray[SBData->interface_index], sStat->dataArray[SBData->interface_index][sStat->timeArray[SBData->interface_index]]);
+                                       sStat->dataArray[SBData->interface_index][temp_history] = sStat->recv_length[SBData->interface_index];
+                                       for( i = sStat->timeArray[SBData->interface_index] + 1 ;  i < temp_history; i++)
+                                       {
+                                               sStat->dataArray[SBData->interface_index][i] = temp_data;
+                                       }
+                                       sStat->timeArray[SBData->interface_index] = temp_history;
+                                       TIZEN_LOGD("SBHandler[%p] Infidx [%d] Data History Time [%llu] Data [%llu]", SBHandler, SBData->interface_index, temp_history, sStat->dataArray[SBData->interface_index][temp_history]);
+                               }
+                               sStat->prev_read = FILE_THREAD;
+
+                               TIZEN_D_LOGD("SBHandler[%p] Speed Calculated [%d] Interface Data [%llu]", SBHandler, SBData->interface_index, SBData->sStat.recv_length[SBData->interface_index]);
+                       }
+                       else
+                       {
+                               if(SBHandler->SBData->bRafMode)
+                               {
+                                       sStat->prev_sock_read = B_FALSE;
+                                       raFileMngr->rspRead = raFileMngr->rspRead + *nread ;
+                               }
+                       }
+               }
+       }
+       if(SBData->twoChunk == 1)
+       {
+               /* Write the Data to the Noti Pipe Fd */
+               if(SBData->poll_thread_noti_exception != 1)
+               {
+                       TIZEN_D_LOGD("SBHandler[%p] Write Data to Notification Pipe Fd [%s]", SBHandler, NOTI_TRIGGER);
+                       nbytes = write(SBData->noti_pipefd[1], NOTI_TRIGGER, NOTI_TRIGGER_LENGTH);
+                       nbytes = nbytes; /*warning removal */
+               }
+       }
+       pthread_mutex_unlock(SBHandler->lock);
+       TIZEN_D_LOGD("SBHandler[%p] Mutext Lock Released read from socket", SBHandler);
+       return retval;
+}
+
+int32 twoChunk_read_from_socket(SmartBondingData *SBData,int8 *buffer, int32 size, int32 *my_nread)
+{
+       int32 readSocketData = size;
+       int32 read_value = 0;
+       int32 retval = 0;
+       uint32 connClose = 0;
+       if(SBData->enableMultiRat)
+       {
+               if (SBData->fileThreadStarted)
+               {
+                       is_file_stream_read(SBData);
+                       if(SBData->fStreamFileBufferReady == B_TRUE)
+                       {
+                               read_value = file_stream_read(buffer, size, SBData, my_nread);
+                               if(read_value == SB_ERR)
+                                       TIZEN_LOGD("SBData[%p] Error", SBData);
+                               if(SBData->sStat.prev_read == MAIN_THREAD)
+                               {
+                                       if((SB_ERR == read_value) && ((SBData->response_check != 0) ||
+                                                       ((SBData->response_check == 0) && (SBData->response_body_read == 0))))
+                                       {
+                                               TIZEN_LOGD("SBData[%p] Main Socket Exception", SBData);
+                                               read_value = handleMainSocExp(SBData,buffer, readSocketData, my_nread);
+                                       }
+                               }
+                               return read_value;
+                       }
+                       else
+                       {
+                               if ((SBData->expectedbytes > 0) && (SBData->response_body_read < SBData->expectedbytes))
+                               {
+                                       readSocketData = MIN((SBData->expectedbytes - SBData->response_body_read), size );
+                                       TIZEN_D_LOGD("SBData[%p] size[%d]", SBData, readSocketData);
+                               }
+                       }
+               }
+       }
+
+       if(SBData->curlThrd != NULL)
+       {
+               if(SBData->curlThrd->threadStatus == THREAD_FINISH)
+               {
+                       curlThread_exit(SBData->curlThrd);
+                       SBData->curlThrd = NULL;
+                       TIZEN_LOGD("SBData[%p] Socket File [%d]", SBData, SBData->socket_fd);
+                       if(SBData->socket_fd < 0)
+                       {
+                               TIZEN_LOGD("SBData[%p] ERROR !!! Time out in Curl", SBData);
+                               SBData->cancel = 1;
+                               return SB_ERR;
+                       }
+                       else
+                       {
+                               //newly added to curl main socket exception
+                               uint64 currChunkLen = SBData->resp.cLen - SBData->response_body_read ;
+                               retval = range_request_recv_rng_rsp_headers(SBData->socket_fd,
+                                               size, (SBData->timeout * 1000), SBData->resp.instanceSize,
+                                               currChunkLen, my_nread, buffer, SBData->resp.cLen, &connClose);
+                               if (HTTP_RSP_DECODING_SUCCESS != retval)
+                               {
+                                       return SB_ERR;
+                               }
+                               SBData->mainSockExp = 0;
+                               reset_stats(&(SBData->stat));
+                               TIZEN_LOGD("SBData[%p] New Socket for Curl [%d]", SBData, SBData->socket_fd);
+                               if(*my_nread != 0)
+                               {
+                                       if((SBData->node_exception == SOCKET_NODE_FORCE_EXCEPTION) || (SBData->node_exception == SOCKET_NODE_NORMAL_EXCEPTION))
+                                               // This Can be Due to Normal Exception or Forced Exception
+                                       {
+                                               TIZEN_LOGD("SBData[%p] Need to update the Socket Node about New Socket and Offset [%d]",SBData, *my_nread);
+                                               file_manager_update_socket_node((uint64)*my_nread, SBData);
+                                               SBData->fStreamFileBufferReady =  B_TRUE;
+                                               SBData->fileThreadStarted = B_TRUE;
+                                               SBData->enableMultiRat = B_TRUE;
+                                               SBData->node_exception = 0;
+                                       }
+                                       else if(SBData->node_exception ==  SOCKET_NORMAL_EXCEPTION)
+                                       {
+                                               SBData->node_exception = 0;
+                                       }
+                                       return SB_OK;
+                               }
+                       }
+               }
+               else
+               {
+                       TIZEN_D_LOGD("SBData[%p] curl trying to connect", SBData);
+                       return SB_WOULD_BLOCK;
+               }
+       }
+       read_value = file_stream_read_from_socket(SBData->socket_fd, buffer, readSocketData, my_nread, SBData, 0);
+       TIZEN_D_LOGD("SBData[%p] Read Value [%d] and Size [%d] Socket [%d]", SBData, read_value, *my_nread, SBData->socket_fd);
+
+       if((SB_ERR == read_value) && ((SBData->response_check != 0) ||
+               ((SBData->response_check == 0) && (SBData->response_body_read == 0))))
+       {
+               read_value = handleMainSocExp(SBData,buffer, readSocketData, my_nread);
+               SBData->poll_thread_noti_exception = 1;
+       }
+
+       return read_value;
+}
+
+int32 read_from_socket(SmartBondingData *SBData,int8 *buffer, int32 size, int32 *my_nread)
+{
+       int32 read_value = 0;
+       int32 readSocketData = size;
+
+       if(SBData->enableMultiRat)
+       {
+               if (SBData->multiSocketThreadStarted)
+               {
+                       uint32 retval = is_multirat_read(SBData);
+                       if(retval)
+                       {
+                               if(SBData->curl)
+                               {
+                                       if(retval == CURL_TIMEOUT_MULTIRAT_READ)
+                                               return SB_ERR;
+                                       else if(retval == CURL_BLOCK_MULTIRAT_READ)
+                                               return SB_WOULD_BLOCK;
+                               }
+                       }
+                       if(SBData->mSocketDataBufferReady == B_TRUE)
+                       {
+                               return read_from_buffer(SBData,buffer,readSocketData, my_nread);
+                       }
+                       else
+                       {
+                               if ((SBData->totalExpectedBytes > 0) && (SBData->response_body_read < SBData->totalExpectedBytes))
+                               {
+                                       readSocketData = MIN((SBData->totalExpectedBytes - SBData->response_body_read), size );
+                                       TIZEN_D_LOGD("SBData[%p] size[%d]", SBData, readSocketData);
+                               }
+                       }
+               }
+       }
+       if(SBData->curl == 1)
+       {
+               TIZEN_D_LOGD("SBData[%p] Read the Data from Socket Curl [%d]", SBData, SBData->socket_fd);
+               read_value = read_from_socket_curl(buffer, readSocketData, my_nread, SBData);
+
+               if(read_value == SB_WOULD_BLOCK)
+               {
+                       if(SBData->CurlStartTime == 0)
+                               SBData->CurlStartTime = get_time_in_sec();
+
+                       if((get_time_in_sec() - SBData->CurlStartTime) > SBData->timeout)
+                       {
+                               TIZEN_LOGD("SBData[%p] Curl Socket Read Timeout", SBData);
+                               return SB_ERR;
+                       }
+               }
+
+               if((read_value == SB_ERR) && (SBData->cancel == 1))
+               {
+                       /* Return error if error is due to timeout */
+                       return SB_ERR;
+               }
+
+               if(read_value == SB_OK)
+                       SBData->CurlStartTime = 0;
+       }
+       else if(SBData->sync == 1)
+       {
+               TIZEN_D_LOGD("SBData[%p] Read the Data from Socket SYNC", SBData);
+               read_value = read_from_socket_sync(buffer, readSocketData, my_nread, SBData);
+       }
+
+       if((SB_ERR == read_value) && ((SBData->response_check != 0) ||
+                       ((SBData->response_check == 0) && (SBData->response_body_read == 0))))
+       {
+               read_value = handleMainSocExp(SBData,buffer, readSocketData, my_nread);
+       }
+       return read_value;
+}
+
+int32 handleMainSocExp(SmartBondingData *SBData, int8 *buffer, uint32 size, int32 *my_nread)
+{
+       int32 retval = 0;
+       TIZEN_LOGD("SBData[%p] Main Socket Handle Exception", SBData);
+
+       // We Can Support Exception only after Other Interface Proxy and DNS are updated Properly in watch Dog code
+       if(SBData->twoChunk == 1)
+       {
+               if(SBData->watch_dog_complete == B_FALSE)
+               return SB_ERR;
+       }
+
+       // We Can Support Exception as We are doing Polling on Separate Thread
+       if(0 < SBData->socket_fd)
+       {
+               CLOSE_SOCKET(SBData->socket_fd);
+               SBData->socket_fd = -1;
+       }
+       if(SBData->resp.acceptFlag == 0)
+       {
+               TIZEN_LOGD("SBData[%p] Main Socket Exception Server Does not Support Range Request", SBData);
+               return SB_ERR;
+       }
+
+       SBData->mainSockExp = 1 ;
+
+       if(SBData->sync == 1)
+       {
+               retval =  checkinterface_connect(SBData);;
+               if(retval == 0)
+               {
+                       if(SBData->socket_fd > 0)
+                       {
+                               CLOSE_SOCKET(SBData->socket_fd);
+                               SBData->socket_fd = -1;
+                       }
+                       retval = SB_ERR;
+               }
+               else
+               {
+                       retval = read_from_socket_sync(buffer, size, my_nread, SBData);
+               }
+       }
+       else if(SBData->curl == 1)
+       {
+               SBData->curlThrd = curlThread_init();
+               if(SBData->curlThrd != NULL)
+               {
+                       curlThread_start(SBData);
+                       retval = SB_WOULD_BLOCK;
+               }
+               else
+                       retval = SB_ERR;
+
+       }
+       return retval;
+}
+
+int32 read_from_socket_sync(int8 *buffer, uint32 size , int32 *my_nread, SmartBondingData *SBData)
+{
+       int32 retval = 0;
+       uint32 connClose = 0;
+
+       if(SBData->mainSockExp == 1)
+       {
+               uint64 currChunkLen = SBData->resp.cLen - SBData->response_body_read ;
+               retval = range_request_recv_rng_rsp_headers(SBData->socket_fd, size, (SBData->timeout * 1000),
+                               SBData->resp.instanceSize, currChunkLen, my_nread, buffer, SBData->resp.cLen, &connClose);
+               if (HTTP_RSP_DECODING_SUCCESS != retval)
+               {
+                       return SB_ERR;
+               }
+               reset_stats(&(SBData->stat));
+               SBData->mainSockExp = 0;
+               if(*my_nread != 0)
+                       return SB_OK;
+       }
+       retval = recv(SBData->socket_fd,buffer,size,0);
+       if(retval <= 0)
+       {
+               if((errno == EAGAIN) || (errno == EWOULDBLOCK))
+               {
+                       retval = conn_poll(SBData->socket_fd, SBData->timeout * 1000);
+                       if(retval <= 0)
+                       {
+                               TIZEN_LOGD("SBData[%p] Error !!! Main socket time out", SBData);
+                               return SB_ERR;
+                       }
+                       else
+                       {
+                               retval = recv(SBData->socket_fd, buffer, size, 0);
+                               if(retval <= 0)
+                               {
+                                       TIZEN_LOGD("SBData[%p] Error !!! Main socket error in recv [%s] ",SBData,  strerror (errno));
+                                       return SB_ERR;
+                               }
+                               *my_nread = retval;
+                               return SB_OK;
+                       }
+               }
+               else
+               {
+                       TIZEN_LOGD("SBData[%p] Error !!! Main socket error [%s] ",SBData, strerror (errno));
+                       return SB_ERR;
+               }
+       }
+       else
+       {
+               *my_nread = retval;
+               return SB_OK;
+       }
+}
+
+int32 read_from_socket_curl(int8 *buffer, uint32 size , int32 *my_nread, SmartBondingData *SBData)
+{
+       int32 retval = 0;
+       uint32 connClose = 0;
+       if(SBData->curlThrd != NULL)
+       {
+               if(SBData->curlThrd->threadStatus == THREAD_FINISH)
+               {
+                       curlThread_exit(SBData->curlThrd);
+                       SBData->curlThrd = NULL;
+                       if(SBData->socket_fd < 0)
+                       {
+                               TIZEN_LOGD("SBData[%p] ERROR !!! Time out in Curl", SBData);
+                               SBData->cancel = 1;
+                               return SB_ERR;
+                       }
+                       else
+                       {
+                               //newly added to curl main socket exception
+                               uint64 currChunkLen = SBData->resp.cLen - SBData->response_body_read ;
+                               retval = range_request_recv_rng_rsp_headers(SBData->socket_fd,
+                                               size, (SBData->timeout * 1000), SBData->resp.instanceSize,
+                                               currChunkLen, my_nread, buffer, SBData->resp.cLen, &connClose);
+                               if (HTTP_RSP_DECODING_SUCCESS != retval)
+                               {
+                                       return SB_ERR;
+                               }
+                               SBData->mainSockExp = 0;
+                               reset_stats(&(SBData->stat));
+                               TIZEN_LOGD("SBData[%p] New Socket for Curl [%d]", SBData, SBData->socket_fd);
+                               if(*my_nread != 0)
+                                       return SB_OK;
+                       }
+               }
+               else
+               {
+                       TIZEN_D_LOGD("SBData[%p] curl trying to connect", SBData);
+                       return SB_WOULD_BLOCK;
+               }
+       }
+       retval = recv(SBData->socket_fd, buffer, size,0);
+       if(retval <= 0)
+       {
+               if((errno == EAGAIN) || (errno == EWOULDBLOCK))
+               {
+                       return SB_WOULD_BLOCK;
+               }
+               else
+               {
+                       TIZEN_LOGD("SBData[%p] Error !!! Main socket error [%d] [%s] returning SB_ERR", SBData, errno, strerror (errno));
+                       return SB_ERR;
+               }
+       }
+       *my_nread = retval;
+       return SB_OK;
+}
+
+int32 sb_session_close(struct SmartBondingHandler *SBHandler)
+{
+       SmartBondingData *SBData = NULL;
+       if(SBHandler == NULL)
+       {
+               TIZEN_LOGD("SBHandler is NULL");
+               return B_FALSE;
+       }
+       SBData = (SmartBondingData *)SBHandler->SBData;
+       if (SBData != NULL)
+       {
+               TIZEN_LOGD("SBHandler[%p] SBData[%p] Smart Bonding Session Close RAF[%d] RespBodyRead [%llu] contetlen [%llu]",
+                       SBHandler, SBData, SBData->bRafMode, SBData->response_body_read, SBData->content_length);
+               SBData->cancel = 1;
+       }
+
+       smart_bonding_handler_exit(SBHandler);
+       return 1;
+}
+
+int32 checkinterface_connect(SmartBondingData *SBData)
+{
+       int32 socket = -1;
+       int32 status = 0;
+       uint32 length = 0;
+       uint32 interface_index = 0;
+       uint64 startTime = 0;
+       int8 *newReq = NULL;
+       connection *conn = &(SBData->conn);
+
+       startTime = get_time_in_sec();
+       if(SBData->twoChunk == 1)
+       {
+               if(SBData->node_exception == SOCKET_NODE_FORCE_EXCEPTION)
+                       interface_index = (SBData->interface_index + 1) % 2;
+               else
+                       interface_index = SBData->interface_index;
+       }
+       else
+               interface_index = SBData->interface_index;
+       while((get_time_in_sec() - startTime) < SBData->timeout && (!SBData->cancel))
+       {
+               if(interface_index == 1)
+               {
+                       if(!is_interface_up(WIFI_IFACE_NAME, conn->ifaceInfo, conn->ip_family))
+                       {
+                               if(!is_interface_up(LTE_IFACE_NAME, conn->ifaceInfo, conn->ip_family))
+                               {
+                                       usleep(100000);
+                                       continue;
+                               }
+                               else
+                               {
+                                       interface_index = 1;
+                               }
+                       }
+                       else
+                       {
+                               interface_index = 0;
+                       }
+               }
+               else
+               {
+                       if(!is_interface_up(LTE_IFACE_NAME, conn->ifaceInfo, conn->ip_family))
+                       {
+                               if(!is_interface_up(WIFI_IFACE_NAME, conn->ifaceInfo, conn->ip_family))
+                               {
+                                       usleep(100000);
+                                       continue;
+                               }
+                               else
+                               {
+                                       interface_index = 0;
+                               }
+                       }
+                       else
+                       {
+                               interface_index = 1;
+                       }
+               }
+
+               socket = conn_get_socket_bind(conn->ifaceInfo[interface_index].ip, interface_index, conn->ip_family);
+               if(socket < 0)
+               {
+                       return B_FALSE;
+               }
+
+               if(SBData->twoChunk == 1)
+               {
+                       if((SBData->file_status != NO_REDIVISION) && (SBData->fStream != NULL) && (SBData->fStream->fileMgr != NULL))
+                       {
+                               SBData->fStream->fileMgr->interface[MAIN_THREAD] = interface_index;
+                               SBData->fStream->fileMgr->interface[FILE_THREAD] = (interface_index + 1) % 2;
+                       }
+                       SBData->status = MAIN_IO_EXCEPTION;
+               }
+
+               SBData->socket_fd = socket;
+               SBData->interface_index = interface_index;
+               TIZEN_LOGD("SBData[%p] Check Interface Fd [%d]", SBData, SBData->socket_fd);
+               if(SBData->watch_dog_complete)
+               {
+                       TIZEN_LOGD("SBData[%p] Watch Dog is Completed Lets Take Watch Dog DNS", SBData);
+
+                       if(SBData->req.Rangeheader != NULL)
+                       {
+                               newReq = get_new_req(SBData->req.request[interface_index], SBData->req.rangeStart,
+                                               SBData->response_body_read, 0, &length, strlen(SBData->req.request[interface_index]), SBData->conn.ifaceInfo[interface_index].proxyEnable);
+                       }
+                       else
+                       {
+                               newReq = get_new_req(SBData->req.request[interface_index], 0, SBData->response_body_read, 0,
+                                               &length, strlen(SBData->req.request[interface_index]), SBData->conn.ifaceInfo[interface_index].proxyEnable);
+                       }
+               }
+               else
+               {
+                       if(SBData->req.Rangeheader != NULL)
+                       {
+                               newReq = get_new_req(SBData->req.req_buff_wo_range,
+                                               SBData->req.rangeStart,
+                                               SBData->response_body_read, 0, &length, SBData->req.req_wo_len, SBData->conn.ifaceInfo[interface_index].proxyEnable);
+                       }
+                       else
+                       {
+                               newReq = get_new_req(SBData->req.req_buff, 0,
+                                               SBData->response_body_read, 0, &length, SBData->req.reqLen, SBData->conn.ifaceInfo[interface_index].proxyEnable);
+                       }
+               }
+               if(newReq == NULL)
+               {
+                       CLOSE_SOCKET(socket);
+                       SBData->socket_fd = -1;
+                       break;
+               }
+
+               status = send_req(newReq, length, socket, interface_index, SBData);
+
+               if(status == 0)
+               {
+                       CLOSE_SOCKET(socket);
+                       SBData->socket_fd = -1;
+                       free(newReq);
+                       newReq = NULL;
+                       continue;
+               }
+               else
+                       break;
+       }
+
+       if(NULL != newReq)
+       {
+               free(newReq);
+               newReq = NULL;
+       }
+       if(SBData->twoChunk == 1)
+       {
+               /* Write the Data to the Noti Pipe Fd */
+
+               if(SBData->poll_thread_noti_exception != 0)
+               {
+                       uint32 nbytes = 0;
+                       TIZEN_D_LOGD("SBData[%p] Write Data to Notification Pipe Fd [%s]", SBData, NOTI_TRIGGER);
+                       nbytes = write(SBData->noti_pipefd[1], NOTI_TRIGGER, NOTI_TRIGGER_LENGTH);
+                       nbytes = nbytes; /*warning removal */
+                       SBData->poll_thread_noti_exception = 0;
+               }
+       }
+       return status;
+}
diff --git a/src/multirat_multisocket.c b/src/multirat_multisocket.c
new file mode 100644 (file)
index 0000000..f6d953f
--- /dev/null
@@ -0,0 +1,448 @@
+#include "multirat_libapi.h"
+#include "multirat_multisocket.h"
+#include "multirat_block_manager.h"
+#include "multirat_data_buffer.h"
+#include "multirat_range_request_thread.h"
+#include "multirat_process.h"
+#include "multirat_watch_dog_thread.h"
+#include "multirat_watchthread.h"
+void multisocket_init(MultiSockInput *mSockInput, SmartBondingData *SBData)
+{
+       MultiSocket *mSocket = NULL;
+       DataBuffer *commbuffer = NULL;
+       BlockManager *bmanager = NULL;
+
+       mSocket = malloc(sizeof(MultiSocket));
+       if (mSocket == NULL)
+               return;
+
+       memset(mSocket, 0, sizeof(MultiSocket));
+
+       mSocket->rspOffset = mSockInput->rspOffset;
+       mSocket->noOfChunks = mSockInput->noOfChunks;
+       mSocket->strtOffset =  SBData->req.rangeStart;
+       mSocket->compRspLen = SBData->resp.cLen ;
+
+       mSocket->appReadLen = 0;
+       mSocket->compRspRcvdFlag = 1;
+       mSocket->currentChunkId = 0;
+       mSocket->conn = mSockInput->conn;
+
+       commbuffer = (DataBuffer *)malloc(mSocket->noOfChunks * sizeof(DataBuffer));
+       if(commbuffer == NULL)
+       {
+               TIZEN_LOGD("Error !!! commbuffer allocation failure");
+               free(mSocket);
+               return ;
+       }
+       memset(commbuffer, 0, mSocket->noOfChunks * sizeof(DataBuffer));
+
+       mSocket->commBuffer = commbuffer;
+       SBData->msocket = mSocket;
+
+       data_buffer_init(commbuffer, mSocket->noOfChunks, SBData->cthread->threadId);
+
+       /* Initialize and Sending Block data to Block Manager */
+       bmanager = (BlockManager *)malloc(sizeof(BlockManager));
+       if(bmanager == NULL)
+       {
+               TIZEN_LOGD("Error !!! blockMgr allocation failure");
+               free(commbuffer);
+               free(mSocket);
+               return ;
+       }
+       memset(bmanager, 0, sizeof(BlockManager));
+       mSocket->blockMgr = bmanager;
+
+       block_manager_init(mSocket, bmanager,mSockInput);
+       mSocket->SBData =  SBData;
+       bmanager->SBData = SBData;
+
+}/* End of MultiSocket() */
+
+uint32 multisocket_start(SmartBondingData *SBData)
+{
+       uint32 i = 0;
+       uint32 multiThreadStarted[MAX_INTERFACES] = {0};
+       MultiSocket *msocket = SBData->msocket;
+
+       TIZEN_D_LOGD("multisocket_start");
+
+       for (i = 0; i < MAX_INTERFACES; i++ )
+       {
+               msocket->reqThread[i] = (RangeRequestThread *)malloc(sizeof (RangeRequestThread));
+               if(msocket->reqThread[i] == NULL)
+               {
+                       TIZEN_LOGD("Error !!! msocket->reqThread[%d] allocation failure\n", i);
+                       return 0;
+               }
+               memset(msocket->reqThread[i], 0, sizeof (RangeRequestThread));
+               msocket->reqThread[i]->threadId = i;
+               range_request_thread_init(msocket->reqThread[i], SBData);
+               multiThreadStarted[i] = range_request_thread_start(msocket->reqThread[i]);
+       }
+       return (multiThreadStarted[0] && multiThreadStarted[1]);
+}/* End of start() */
+
+int32 multisocket_get_firstrange_status(MultiSocket *msocket)
+{
+       int32 retval = FIRST_RSP_STATUS_PENDING;
+
+       if (RANGE_REQUEST_THREAD_GET_FIRST_RANGE_STATUS(msocket->reqThread[0]) == FIRST_RSP_STATUS_FAILED ||
+                       RANGE_REQUEST_THREAD_GET_FIRST_RANGE_STATUS(msocket->reqThread[1]) == FIRST_RSP_STATUS_FAILED)
+               retval = FIRST_RSP_STATUS_FAILED;
+
+       else if (RANGE_REQUEST_THREAD_GET_FIRST_RANGE_STATUS(msocket->reqThread[0]) == FIRST_RSP_STATUS_PENDING ||
+                       RANGE_REQUEST_THREAD_GET_FIRST_RANGE_STATUS(msocket->reqThread[1]) == FIRST_RSP_STATUS_PENDING)
+               retval = FIRST_RSP_STATUS_PENDING;
+
+       else if (RANGE_REQUEST_THREAD_GET_FIRST_RANGE_STATUS(msocket->reqThread[0]) == FIRST_RSP_STATUS_SUCCESS &&
+                       RANGE_REQUEST_THREAD_GET_FIRST_RANGE_STATUS(msocket->reqThread[1]) == FIRST_RSP_STATUS_SUCCESS)
+               retval = FIRST_RSP_STATUS_SUCCESS;
+
+       return retval;
+}/* End of getFirstRangeStatus() */
+
+int32 multisocket_read(int8 *appBuff, uint32 maxAppLen, SmartBondingData *SBData)
+{
+       uint32 tempLen = 0;
+       uint32 toBeRead = 0;
+       DataBuffer *currChunk = NULL;
+       MultiSocket *msocket = SBData->msocket;
+
+       TIZEN_D_LOGD("multisocket_read current chunk %d\n", msocket->currentChunkId);
+       if(msocket->currentChunkId >= msocket->noOfChunks)
+       {
+               return -1;
+       }
+
+       currChunk = msocket->commBuffer + msocket->currentChunkId;
+       while (tempLen != maxAppLen)
+       {
+               if (DATA_BUFFER_GET_TOTAL_LEN(currChunk) == 0)
+               {
+                       /* Block not yet assigned to thread */
+                       if(currChunk->isContinueChunk == 1)
+                       {
+                               if(tempLen > 0)
+                               {
+                                       break;
+                               }
+                               SBData->interface_index = (currChunk->threadId + 1) % 2;
+                               TIZEN_LOGD("End of multisocket as continue Chunk is present total lenght 0");
+                               return -2;
+                       }
+                       return 0;
+               }
+
+               if (DATA_BUFFER_GET_TOTAL_LEN(currChunk) ==
+                               DATA_BUFFER_GET_READ_RES_LEN(currChunk))
+               {
+                       data_buffer_freeBuffer(currChunk);
+                       msocket->currentChunkId++;
+                       if (msocket->currentChunkId >= msocket->noOfChunks)
+                       {
+                               msocket->compRspRcvdFlag = 0;
+                               break;
+                       }
+                       currChunk = msocket->commBuffer + msocket->currentChunkId;
+                       TIZEN_LOGD("started reading block = %d", msocket->currentChunkId);
+               }
+
+               if (DATA_BUFFER_GET_RES_BYTES(currChunk)== 0)
+               {
+                       if(currChunk->isContinueChunk == 1)
+                       {
+                               if(tempLen > 0)
+                               {
+                                       break;
+                               }
+                               SBData->interface_index = (currChunk->threadId + 1) % 2;
+                               TIZEN_LOGD("End of multisocket as continue Chunk is present");
+                               return -2;
+                       }
+                       if(DATA_BUFFER_GET_TOTAL_LEN(currChunk) ==
+                                       DATA_BUFFER_GET_READ_RES_LEN(currChunk))
+                       {
+                               /* This is for Continued chunk */
+                               continue;
+                       }
+                       break;
+               }/* End of if */
+
+               toBeRead = MIN((maxAppLen - tempLen), DATA_BUFFER_GET_RES_BYTES(currChunk));
+               data_buffer_read_portion(appBuff + tempLen, toBeRead, currChunk);
+               tempLen = tempLen + toBeRead;
+       }/* End of while */
+
+       msocket->appReadLen = msocket->appReadLen + tempLen;
+       TIZEN_D_LOGD("multisocket_read Application read length %d calculated  %d total lenght %d,tempLen %d\n", msocket->appReadLen,
+                       (msocket->appReadLen + msocket->rspOffset), msocket->compRspLen,tempLen);
+       if((msocket->appReadLen + msocket->rspOffset) == msocket->compRspLen)
+       {
+               /* Complete response read by application */
+               TIZEN_LOGD ("Complete response read by application\n");;
+               msocket->compRspRcvdFlag = 0;
+       }
+       return tempLen;
+
+}/* End of read() */
+
+int32 multisocket_read_sync(int8 *appBuff, uint32 maxAppLen, SmartBondingData *SBData)
+{
+       uint32 tempLen = 0;
+       uint32 toBeRead = 0;
+       uint32 rspPresent = 0;
+       uint64 startTime = 0;
+       DataBuffer *currChunk = NULL;
+       MultiSocket *msocket = SBData->msocket;
+
+       TIZEN_D_LOGD("multisocket_read current chunk %d\n", msocket->currentChunkId);
+
+       if(msocket->currentChunkId >= msocket->noOfChunks)
+       {
+               return -1;
+       }
+
+       currChunk = msocket->commBuffer + msocket->currentChunkId;
+       while (tempLen != maxAppLen)
+       {
+               if (DATA_BUFFER_GET_TOTAL_LEN(currChunk) == 0)
+               {
+                       if(currChunk->isContinueChunk == 1)
+                       {
+                               if(tempLen > 0)
+                               {
+                                       break;
+                               }
+                               SBData->interface_index = (currChunk->threadId + 1) % 2;
+                               TIZEN_LOGD("End of multisocket as continue Chunk is present total lenght 0");
+                               return -2;
+                       }
+                       /* Block not yet assigned to thread */
+                       usleep(1000);
+                       continue;
+               }
+
+               if (DATA_BUFFER_GET_TOTAL_LEN(currChunk) ==
+                               DATA_BUFFER_GET_READ_RES_LEN(currChunk))
+               {
+                       data_buffer_freeBuffer(currChunk);
+                       msocket->currentChunkId++;
+                       if (msocket->currentChunkId >= msocket->noOfChunks)
+                       {
+                               msocket->compRspRcvdFlag = 0;
+                               if(tempLen > 0)
+                                       break;
+                       }
+                       currChunk = msocket->commBuffer + msocket->currentChunkId;
+                       TIZEN_LOGD("started reading block = %d", msocket->currentChunkId);
+               }
+
+               startTime = get_time_in_sec();
+               rspPresent = 0;
+               while (DATA_BUFFER_GET_RES_BYTES(currChunk) == 0)
+               {
+                       if(currChunk->isContinueChunk == 1)
+                       {
+                               if(tempLen > 0)
+                               {
+                                       rspPresent = 1;
+                                       break;
+                               }
+                               SBData->interface_index = (currChunk->threadId + 1) % 2;
+                               TIZEN_LOGD("End of multisocket as continue Chunk is present");
+                               return -2;
+                       }
+
+                       if (DATA_BUFFER_GET_TOTAL_LEN(currChunk) ==
+                                       DATA_BUFFER_GET_READ_RES_LEN(currChunk))
+                       {
+                               /* This is for Continued chunk */
+                               rspPresent = 2;
+                               break;
+                       }
+                       else if(tempLen > 0)
+                       {
+                               rspPresent = 1;
+                               break;
+                       }
+                       else if (((get_time_in_sec() - startTime) > SBData->timeout)|| (SBData->cancel == 1))
+                       {
+                               TIZEN_LOGD("No Interface available Exiting multiSocket or Cancel Session" );
+                               rspPresent = 1;
+                               break;
+                       }
+                       usleep(5000);
+               }
+
+               if(2 == rspPresent)
+               {
+                       continue;
+               }
+               if(1 == rspPresent)
+               {
+                       break;
+               }
+
+               toBeRead = MIN((maxAppLen -tempLen), (DATA_BUFFER_GET_RES_BYTES(currChunk)));
+               data_buffer_read_portion(appBuff + tempLen, toBeRead, currChunk);
+               tempLen = tempLen + toBeRead;
+       }/* End of while */
+
+       msocket->appReadLen = msocket->appReadLen + tempLen;
+       TIZEN_D_LOGD("multisocket_read Application read length %d calculated  %d total lenght %d\n",
+                       msocket->appReadLen,(msocket->appReadLen + msocket->rspOffset), msocket->compRspLen);
+       if((msocket->appReadLen + msocket->rspOffset) == msocket->compRspLen)
+       {
+               /* Complete response read by application */
+               TIZEN_LOGD ("Complete response read by application\n");;
+               msocket->compRspRcvdFlag = 0;
+       }
+       return tempLen;
+}/* End of read() */
+
+void multisocket_exit(MultiSocket *msocket)
+{
+       uint32 i = 0;
+       TIZEN_LOGD("multisocket_exit %p", msocket);
+       msocket->compRspRcvdFlag = 0;
+
+       for (i = 0; i < MAX_INTERFACES; i++)
+       {
+               TIZEN_LOGD("multisocket_exit reqThread[%d] %p", i, msocket->reqThread[i]);
+               if (NULL != msocket->reqThread[i])
+               {
+                       range_request_thread_exit (msocket->reqThread[i]);
+                       msocket->reqThread[i] = NULL;
+               }
+       }
+
+       TIZEN_LOGD("multisocket_exit blockMgr %p", msocket->blockMgr);
+       if(NULL != msocket->blockMgr)
+       {
+               block_manager_exit(msocket->blockMgr);
+               free(msocket->blockMgr);
+               TIZEN_LOGD("Block Manager Freed");
+       }
+       msocket->blockMgr = NULL;
+
+       for (i = 0; i < msocket->noOfChunks; i++)
+       {
+               TIZEN_LOGD("multisocket_exit commBuffer[%d] %p", i, msocket->commBuffer + i);
+               if (NULL != msocket->commBuffer + i)
+               {
+                       data_buffer_exit(msocket->commBuffer + i);
+               }
+       }
+
+       TIZEN_LOGD("multisocket_exit commBuffer %p", msocket->commBuffer);
+       if(msocket->commBuffer != NULL)
+       {
+               free(msocket->commBuffer);
+       }
+       msocket->commBuffer = NULL;
+       free(msocket);
+       msocket = NULL;
+       TIZEN_LOGD("multisocket_exit finished\n");
+}/* End of ~MultiSocket() */
+
+uint32 is_multirat_read(SmartBondingData *SBData)
+{
+       /* Read First range request */
+       if (NULL != SBData->cthread)
+       {
+               /*multiSocketThreadStarted*/
+               TIZEN_D_LOGD ("about to exit cthread");
+               cthread_exit(SBData->cthread);
+               SBData->cthread = NULL;
+       }
+       if (SBData->response_body_read >= SBData->totalExpectedBytes)
+       {
+               if((SBData->sync))
+               {
+                       uint64 start_time = get_time_in_sec();
+                       while(multisocket_get_firstrange_status(SBData->msocket) == FIRST_RSP_STATUS_PENDING)
+                       {
+                               if(((get_time_in_sec() - start_time) > SBData->timeout)||(SBData->cancel == 1))
+                               {
+                                       TIZEN_LOGD("Cancel Session or timeout in is_multirat_read");
+                                       break;
+                               }
+                               usleep(10000); // sleep for 10 ms
+                       }
+               }
+               else if(SBData->curl)
+               {
+                       if(multisocket_get_firstrange_status(SBData->msocket) == FIRST_RSP_STATUS_PENDING)
+                       {
+                               if(SBData->CurlStartTime == 0)
+                                       SBData->CurlStartTime = get_time_in_sec();
+
+                               if((get_time_in_sec() - SBData->CurlStartTime) > SBData->timeout)
+                               {
+                                       TIZEN_LOGD("Curl Taken More than TImeout For Buffer Preperation");
+                                       return CURL_TIMEOUT_MULTIRAT_READ;
+                               }
+
+                               return CURL_BLOCK_MULTIRAT_READ;
+                       }
+               }
+               if(multisocket_get_firstrange_status(SBData->msocket) == FIRST_RSP_STATUS_SUCCESS)
+               {
+                       SBData->mSocketDataBufferReady = B_TRUE;
+                       close(SBData->socket_fd);
+                       SBData->socket_fd = 0;
+                       TIZEN_LOGD("FirstRangeRequest Success Is Multirat Read\n");
+               }
+               else
+               {
+                       SBData->mSocketDataBufferReady =  B_FALSE;
+                       SBData->multiSocketThreadStarted = B_FALSE;
+                       SBData->enableMultiRat = B_FALSE;
+                       TIZEN_LOGD("FirstRangeRequest FAILED");
+                       multisocket_exit(SBData->msocket);
+                       SBData->msocket = NULL;
+               }
+       }
+       return 0;
+}
+
+int32 read_from_buffer(SmartBondingData *SBData,int8 *buffer, uint32 size, int32 *my_nread)
+{
+       if(SBData->sync)
+       {
+               *my_nread = multisocket_read_sync(buffer, size, SBData);
+               if(*my_nread == 0)
+                       return SB_ERR;
+       }
+       else
+       {
+               *my_nread = multisocket_read(buffer,size, SBData);
+               if(*my_nread == 0)
+               {
+                       if(SBData->CurlStartTime == 0)
+                               SBData->CurlStartTime = get_time_in_sec();
+
+                       if((get_time_in_sec() - SBData->CurlStartTime) > SBData->timeout)
+                       {
+                               TIZEN_LOGD("Timeout on Reading from Buffer in Curl");
+                               return SB_ERR;
+                       }
+                       return SB_WOULD_BLOCK;
+               }
+       }
+       if (*my_nread == -2)
+       {
+               SBData->multiSocketThreadStarted = B_FALSE;
+               SBData->mSocketDataBufferReady = B_FALSE;
+               SBData->enableMultiRat = B_FALSE;
+               SBData->socket_fd = 0;
+               return handleMainSocExp (SBData,buffer, size, my_nread);
+       }
+
+       if(0 != SBData->curl)
+               SBData->CurlStartTime = 0;
+       return SB_OK;
+}
+
diff --git a/src/multirat_poll_thread.c b/src/multirat_poll_thread.c
new file mode 100644 (file)
index 0000000..5a56c53
--- /dev/null
@@ -0,0 +1,115 @@
+#include "multirat_SB_http.h"
+#include "multirat_poll_thread.h"
+#include "multirat_process.h"
+#include "multirat_conf.h"
+#include "multirat_watch_dog_thread.h"
+#include "multirat_libapi.h"
+#include "multirat_file_manager.h"
+#include "multirat_file_stream.h"
+
+PollThread* PollThread_init()
+{
+       PollThread *PollThrd = malloc(sizeof(PollThread));
+       if(PollThrd == NULL)
+       {
+               TIZEN_LOGD("Error !!! curl thread allocation failed [%d] [%s]", errno, strerror(errno));
+               return NULL;
+       }
+       memset(PollThrd,0,sizeof(PollThread));
+       return PollThrd;
+}
+
+void PollThread_start(SmartBondingData *SBData)
+{
+       int32 ECode = 0;
+       pthread_t thread = 0;
+
+       if ((ECode = pthread_create(&thread, NULL, PollThread_entry_function,(void *)SBData)) != 0)
+       {
+               TIZEN_LOGD("Error !!! creating pthread [%d] [%s]", errno, strerror(errno));
+               PollThread_exit(SBData->PollThrd);
+               SBData->PollThrd = NULL;
+       }
+       else
+       {
+               TIZEN_LOGD("SBData [%p] Poll Thread Started", SBData);
+               SBData->PollThrd->threadStatus = THREAD_INIT;
+               SBData->PollThrd->threadId = thread;
+       }
+}
+
+void *PollThread_entry_function(void *pArg)
+{
+       SmartBondingData *SBData = (SmartBondingData *)pArg;
+       if(SBData)
+       {
+               PollThread_run_thread(SBData);
+       }
+       return NULL;
+}
+
+void PollThread_exit(PollThread *PollThrd)
+{
+       TIZEN_LOGD("Poll Thread Exit called");
+       if(PollThrd != NULL)
+       {
+               if(PollThrd->threadStatus == THREAD_INIT)
+                       usleep(100000);
+               PollThrd->threadStatus = THREAD_FINISH;
+
+               if(0 != PollThrd->threadId)
+                       pthread_join(PollThrd->threadId,NULL);
+               PollThrd->threadId = 0;
+               free(PollThrd);
+               PollThrd = NULL;
+       }
+       TIZEN_LOGD("Poll Thread Exit done");
+}
+
+void PollThread_run_thread(SmartBondingData *SBData)
+{
+       uint32 nbytes = 0;
+       PollThread *PollThrd = SBData->PollThrd;
+       char readbuffer[NOTI_TRIGGER_LENGTH + 1] = "\0";
+
+       TIZEN_LOGD("SBData[%p] Poll Thread Run", SBData);
+       PollThrd->threadStatus = THREAD_RUNNING;
+       /* Poll for the Data on Noti Pipe Fd */
+       while(PollThrd->threadStatus != THREAD_FINISH)
+       {
+               TIZEN_D_LOGD("SBData[%p] Waiting For Data on Notification Pipe Fd", SBData);
+
+               PollThread_poll(SBData->noti_pipefd[0], SBData, 1000);
+
+               if(PollThrd->threadStatus == THREAD_FINISH)
+               {
+                       TIZEN_LOGD("SBData[%p] Exiting Poll Thread",SBData);
+                       return;
+               }
+
+       /* Read the Data from the Noti Pipe Fd */
+               nbytes = read(SBData->noti_pipefd[0], readbuffer, NOTI_TRIGGER_LENGTH);
+               nbytes = nbytes; /* Just to remove warnings */
+               TIZEN_D_LOGD("SBData[%p] Read Data from Notification Pipe Fd [%s] Length [%d]",SBData, readbuffer, nbytes);
+
+               /* Wait on Socket or PIPE fd */
+
+               if(((SBData->response_body_read < SBData->expectedbytes) || (SBData->expectedbytes == 0) || (SBData->fStreamFileBufferReady == 0)))
+               {
+                       TIZEN_D_LOGD("SBData[%p] Waiting For Data on Socket", SBData);
+                       PollThread_poll(SBData->socket_fd, SBData, 10);
+                       /* Write Into Trigger Pipe Fd */
+                       TIZEN_D_LOGD("SBData [%p] Write Data to Trigger Pipe Fd [%s]", SBData, NOTI_TRIGGER);
+                       nbytes = write(SBData->trigger_pipefd[1], NOTI_TRIGGER, NOTI_TRIGGER_LENGTH);
+               }
+               else
+               {
+                       TIZEN_D_LOGD("SBData[%p] Waiting For Data on Node", SBData);
+                       PollThread_poll_buffer(SBData);
+                       /* Write Into Trigger Pipe Fd */
+                       TIZEN_D_LOGD("SBData[%p] Write Data to Trigger Pipe Fd [%s]", SBData, NOTI_TRIGGER);
+                       nbytes = write(SBData->trigger_pipefd[1], NOTI_TRIGGER, NOTI_TRIGGER_LENGTH);
+               }
+       }
+       PollThrd->threadStatus = THREAD_FINISH;
+}
diff --git a/src/multirat_process.c b/src/multirat_process.c
new file mode 100644 (file)
index 0000000..c891a4e
--- /dev/null
@@ -0,0 +1,1054 @@
+#include "multirat_conf.h"
+#include "multirat_process.h"
+#include "multirat_watch_dog_thread.h"
+#include "multirat_multisocket.h"
+#include "multirat_libapi.h"
+#include "multirat_watchthread.h"
+#include "multirat_poll_thread.h"
+#ifdef TIZEN_UX_SUPPORT
+#include "smartbonding-client.h"
+#endif
+#include "multirat_file_stream.h"
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <ares.h>
+#include <wifi.h>
+#include <net_connection.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#define _E(fmt, args...)   SLOGE(fmt, ##args)
+
+#define BUS_NAME               "org.tizen.system.deviced"
+#define PATH_NAME              "/Org/Tizen/System/DeviceD/Process"
+#define INTERFACE_NAME         "org.tizen.system.deviced.Process"
+#define METHOD_NAME            "GetSiopLevel"
+
+#define DEVICED_DBUS_TIMEOUT   (120 * 1000)
+
+#define VCONF_SMART_BONDING_POLICY "file/private/wifi/network_bonding"
+#define SMART_BONDING_WIFI_ONLY 0x00
+
+#define DNS_NUM 2
+
+static void state_cb(void *data, int s, int read, int write)
+{
+       TIZEN_D_LOGD("Change state fd [%d] read:[%d] write:[%d]", s, read, write);
+}
+
+
+static void callback(void *arg, int status, int timeouts, struct hostent *host)
+{
+       TIZEN_D_LOGD("Call Back");
+       SmartBondingData *SBData = (SmartBondingData *)arg;
+       connection *conn = &(SBData->conn);
+       if(!host || status != ARES_SUCCESS)
+       {
+               TIZEN_LOGD("Failed to lookup [%s]", ares_strerror(status));
+               return;
+       }
+
+       TIZEN_D_LOGD("Found address name [%s]", host->h_name);
+
+       char ip[INET_ADDRSTRLENG];
+
+       inet_ntop(host->h_addrtype, host->h_addr_list[0], ip, sizeof(ip));
+       SBData->dns = 1;
+       memset(conn->ifaceInfo[SBData->dns_iface].server_ip, 0, INET_ADDRSTRLENG);
+       memcpy(conn->ifaceInfo[SBData->dns_iface].server_ip, ip, INET_ADDRSTRLENG);
+}
+
+static void wait_ares(ares_channel channel, SmartBondingData *SBData)
+{
+       fileStream *fStream = SBData->fStream;
+       while(fStream->compRspRcvdFlag)
+       {
+               struct timeval *tvp, tv;
+               fd_set read_fds, write_fds;
+               int nfds;
+               int select_return = 0;
+
+               FD_ZERO(&read_fds);
+               FD_ZERO(&write_fds);
+               TIZEN_D_LOGD("Before Select Ares Wait");
+               nfds = ares_fds(channel, &read_fds, &write_fds);
+               if(nfds == 0)
+               {
+                       break;
+               }
+               tv.tv_sec = 0; tv.tv_usec = 500000;
+               tvp = ares_timeout(channel, &tv, &tv);
+               select_return = select(nfds, &read_fds, &write_fds, NULL, tvp);
+               if(select_return == -1)
+               {
+                       TIZEN_LOGD("Select Failed");
+                       break;
+               }
+               else if(select_return == 0)
+               {
+                       TIZEN_D_LOGD("Time out in Select Ares DNS Call");
+                       continue;
+               }
+               else
+               {
+                       TIZEN_D_LOGD("After Select Ares Wait");
+                       ares_process(channel, &read_fds, &write_fds);
+               }
+       }
+}
+
+
+static DBusMessage *method_call(const char *dest, const char *path,
+const char *interface, const char *method);
+
+void get_object_size(httpResp *resp)
+{
+       int32 len = 0;
+
+       len = decode_http_find_str(resp->contRange, "/");
+       if (len != -1)
+       {
+               len=len + 1;
+               resp->instanceSize = atol(resp->contRange + len);
+               return;
+       }
+       else
+       {
+               resp->instanceSize = 0;
+       }
+       return;
+}
+
+void store_check_http_response(SmartBondingData *SBData)
+{
+       httpResp *resp = &(SBData->resp);
+
+       /*For filling request structure members */
+       if (HTTP_RSP_DECODING_SUCCESS != process_http_rsp(resp))
+       {
+               TIZEN_LOGD("Error !!! decoding response failed");
+               delete_http_rsp(resp);
+               return;
+       }
+
+       /*
+        *response_body_read gets incrementd when data is read_from_network.
+        *We need to subtract headers from this to get the actual body lenght
+        */
+       if (resp->contRange != NULL)
+       {
+               get_object_size(resp);
+       }
+
+       if (SBData->multiRatCheckDone != B_TRUE)
+       {
+               TIZEN_D_LOGD("about to enable multirat");
+               SBData->enableMultiRat = should_enable_multirat(SBData);
+               if ((SBData->enableMultiRat) && (NULL == SBData->cthread) && (!SBData->bRafMode))
+               {
+                       TIZEN_LOGD("MultiRAT is enabled as content length [%llu] body read so far [%llu]",
+                                       resp->cLen, SBData->response_body_read);
+                       /*watchdog cthread is being created */
+                       SBData->cthread = cthread_init();
+                       /*  watchdog cthread is initialised */
+                       cthread_start_thread(SBData);
+                       TIZEN_D_LOGD ("MultiRat enabled, waiting for to start multi socket");
+               }
+               SECURE_DB_INFO("Response [%s]", resp->resp_buff);
+               TIZEN_LOGD("Enable MultiRat ?? [%d]", SBData->enableMultiRat);
+               SBData->multiRatCheckDone = B_TRUE;
+       }
+}
+
+void store_http_request(int8 *req, SmartBondingData *SBData)
+{
+       int32 len = 0;
+       httpReq *dupReq = &(SBData->req);
+
+       len = decode_http_find_str(req, "\r\n\r\n");
+
+       if (len != -1)
+       {
+               len = len + 5;
+
+               dupReq->req_buff = (int8 *)malloc(len);
+               if(dupReq->req_buff == NULL)
+               {
+                       TIZEN_LOGD("Error !!! SBData->req->req_buff allocation failed [%d] [%s]", errno, strerror(errno));
+                       return;
+               }
+               memset(dupReq->req_buff, 0, len);
+               memcpy(dupReq->req_buff, req, len-1);
+               dupReq->reqLen = len-1;
+
+               TIZEN_D_LOGD("HTTP request is [%s]", dupReq->req_buff);
+
+               if (HTTP_RSP_DECODING_SUCCESS != decode_http_req(dupReq))
+               {
+                       TIZEN_LOGD("Error !!! HTTP req decode is failed ");
+                       delete_http_req(dupReq);
+                       return;
+               }
+
+               if (dupReq->Rangeheader != NULL)
+               {
+                       dupReq->req_buff_wo_range = (int8 *)malloc(len);
+                       if(NULL != dupReq->req_buff_wo_range)
+                       {
+                               memset(dupReq->req_buff_wo_range, 0, len);
+                               dupReq->req_wo_len = get_req_without_range(dupReq->req_buff,
+                                               dupReq->req_buff_wo_range, dupReq->Rangeheader, &dupReq->rangeStart);
+                               SBData->startOffset = (dupReq->rangeStart);
+                       }
+               }
+       }
+       return;
+}
+
+uint32 should_enable_multirat(SmartBondingData *SBData)
+{
+       uint32 method_get = 0;
+       uint32 bUseMultiRat = 0;
+       httpReq *req = &(SBData->req);
+       httpResp *resp = &(SBData->resp);
+       int32 smartbonding_value = 0;
+
+       TIZEN_LOGD("multirat process should_enable_multirat Threshold [%d]",get_multirat_threshold());
+
+       vconf_get_int(VCONF_SMART_BONDING_POLICY, &smartbonding_value);
+
+       if (smartbonding_value == SMART_BONDING_WIFI_ONLY)
+       {
+               TIZEN_LOGD("Smart bonding policy is OFF");
+       }
+
+       if (req->method == HTTP_GET) {
+               TIZEN_D_LOGD("HTTP method is GET");
+               method_get = 1;
+       }
+
+       if (resp->rspcode != NULL && resp->contLen != NULL)
+       {
+               SBData->content_length = resp->cLen;
+
+               bUseMultiRat = ((method_get)  &&
+                               (!(strncasecmp(resp->rspcode,"200",3))  ||
+                                               !(strncasecmp(resp->rspcode , "206",
+                                                               3))) && (resp->acceptFlag) &&
+                                                               (resp->cLen > get_multirat_threshold()) && (!SBData->interface_index) && (smartbonding_value));
+               SBData->multiRatCheckDone = B_TRUE;
+       }
+       if(bUseMultiRat)
+       {
+               return !(getTempLevel(SBData));
+       }
+
+       TIZEN_D_LOGD("can we start MultiRat? [%d]", bUseMultiRat);
+       return bUseMultiRat;
+}
+
+void start_watchdog(SmartBondingData *SBData, int8 *buffer, int32 my_nread)
+{
+       int32 len = 0;
+       uint32 length_check = 0;
+       uint32 write_len = 0;
+       uint64 endTime = 0;
+       httpResp *resp = &(SBData->resp);
+       StatDetails *stat = &(SBData->stat);
+
+       TIZEN_D_LOGD("checking for response response_check_length[%d] my_nread[%d]", SBData->response_check_length, my_nread);
+       length_check = SBData->response_check_length + my_nread;
+
+       if(length_check > (MAX_HEADER_SIZE - DIRECT_WRITE_HEADER_LENGTH))
+               length_check = (MAX_HEADER_SIZE - DIRECT_WRITE_HEADER_LENGTH) - SBData->response_check_length;
+       else
+               length_check = my_nread;
+
+       memcpy(resp->resp_buff + SBData->response_check_length, buffer, length_check);
+       SBData->response_check_length = SBData->response_check_length + my_nread;
+       TIZEN_LOGD("checking for response response_check_length[%d] my_nread[%d]", SBData->response_check_length, my_nread);
+       len = decode_http_find_str(resp->resp_buff,END_OF_HEADER);
+
+       if (len != -1)
+       {
+               len = len + 4;
+               TIZEN_LOGD("Response Header Length [%d]", len);
+
+               endTime = get_time_in_microsec();
+               stat->dataStrtTime = endTime;
+               stat->dataOffsetTime = endTime;
+
+               resp->resp_header_length = len;
+               write_len = (SBData->response_check_length > (MAX_HEADER_SIZE - DIRECT_WRITE_HEADER_LENGTH)) ? (MAX_HEADER_SIZE - DIRECT_WRITE_HEADER_LENGTH): SBData->response_check_length;
+               memcpy(resp->resp_buff_body, resp->resp_buff, write_len);
+               memset((resp->resp_buff+len),0,MAX_HEADER_SIZE-len);
+               store_check_http_response(SBData);
+               SBData->response_body_read = SBData->response_body_read - len;
+               stat->timeT1 = (endTime - stat->startTime)/1000;
+               SBData->response_check = 1;
+       }
+       else
+       {
+               if(SBData->response_check_length > (MAX_HEADER_SIZE - DIRECT_WRITE_HEADER_LENGTH))
+               {
+                       SBData->response_check = 1;
+                       TIZEN_LOGD("Invalid Header Not passing through SB");
+               }
+       }
+}
+
+int8 *get_new_req(int8 *req, uint64 rangeStart, uint64 bytesRead, uint64 rangeEnd, uint32 *length, uint32 len, int32 proxy)
+{
+       int32 rangeLen = 0;
+       int8 *newRequest = NULL;
+       int8 rangeField[MAX_RANGE_FIELD_LEN] = { 0 };
+
+       newRequest = (int8*)malloc(len + MAX_RANGE_FIELD_LEN);
+
+       if (newRequest == NULL)
+       {
+               TIZEN_LOGD("NewRequest allocation failed\n");
+               return NULL;
+       }
+       memset(newRequest, 0, len + MAX_RANGE_FIELD_LEN);
+
+       if (rangeEnd)
+       {
+               rangeLen = sprintf(rangeField, "%s%llu%s%llu%s", "Range: bytes=", rangeStart + bytesRead, "-", rangeEnd, "\r\n\r\n");
+       }
+       else
+       {
+               rangeLen = sprintf(rangeField, "%s%llu%s%s", "Range: bytes=", rangeStart + bytesRead, "-", "\r\n\r\n");
+       }
+
+       TIZEN_LOGD("RebuildReq rangeLen %d", rangeLen);
+       SECURE_DB_INFO("Req without change %s\n", req);
+
+       int32 offset = 0;
+
+       if (proxy)
+       {
+               if (0 != strncmp(req + 4, "http://", 7))
+               {
+                       /* Request is of type GET /lkkk.gif  */
+                       char *hostName = NULL;
+                       getHost(&hostName, req);
+                       if (NULL != hostName)
+                       {
+                               char reqLine[20] = { 0 };
+                               strcpy(reqLine, "GET http://");
+
+                               if (req[4] != '/')
+                               {
+                                       offset = sprintf(newRequest, "%s%s%s", reqLine, hostName, "/");
+                               }/* End of if */
+                               else
+                               {
+                                       offset = sprintf(newRequest, "%s%s", reqLine, hostName);
+                               }/* End of else */
+                               TIZEN_LOGD("Proxy offset %d\n", offset);
+                       }/* End of if */
+                       else
+                       {
+                               SECURE_DB_INFO("Invalid relative request without host name, %s", req);
+                       }
+                       SECURE_DB_INFO("Proxy Rereq without range [%s]", newRequest);
+                       memcpy(newRequest + offset, req + 4, len - 6);
+                       offset = offset + len - 6;
+                       SECURE_DB_INFO("Proxy RebuildReq without range [%s]", newRequest);
+               }
+               else
+               {
+                       memcpy(newRequest, req, len - 2);
+                       offset = len - 2;
+               }
+       }/* End of if */
+       else
+       {
+               int http_len = strlen("http://");
+               if (0 == strncmp(req + 4, "http://", http_len))
+               {
+                       /* Destination Interface not proxied and request is absolute*/
+                       char *pHost = req + 4 + http_len; /* Move past GET http:// */
+                       char *pUrl = strchr(pHost, '/');
+                       if (NULL == pUrl)
+                       {
+                               SECURE_DB_INFO("pUrl null phost [%s]", pHost);
+                               pUrl = pHost; /* Just to avoid crash as null return of newRequest is not handled*/
+                       }
+
+                       memcpy(newRequest, req, 4);
+                       memcpy(newRequest + 4, pUrl, len - ((pUrl - req) + 2)); /* Copy whole url except \r\n*/
+                       offset = 4 + len - ((pUrl - req) + 2);
+               }
+               else
+               {
+                       memcpy(newRequest, req, len);
+                       offset = len - 2;
+               }
+       }
+       SECURE_DB_INFO("RebuildReq without range [%s]", newRequest);
+       memcpy(newRequest + offset, rangeField, rangeLen);
+       *length = offset + rangeLen;
+       newRequest[*length] = '\0';
+       return newRequest;
+}
+int32 send_req(int8 *req, uint32 reqLen,int32 socket,uint32 index, SmartBondingData *SBData)
+{
+       int32 retval = 0;
+       uint32 timeout = SBData->timeout;
+       int8 temp[1] = {0};
+       struct hostent *h = NULL;
+       struct sockaddr_in remote_addr;
+       struct sockaddr_in6 remote_addr_ip6;
+       connection *conn = &(SBData->conn);
+
+       if(SBData->watch_dog_complete == 1)
+               h = gethostbyname(conn->ifaceInfo[index].server_ip);
+       else
+               h = gethostbyname(conn->ip_addr);
+
+       if(SBData->conn.ip_family)
+       {
+               memset(&remote_addr_ip6, 0, sizeof(struct sockaddr_in6));
+               remote_addr_ip6.sin6_family = h->h_addrtype;
+               memcpy((int8 *) &remote_addr_ip6.sin6_addr.s6_addr, h->h_addr_list[0], h->h_length);
+               remote_addr_ip6.sin6_port = htons(conn->port);
+
+       }
+       else
+       {
+               memset(&remote_addr, 0, sizeof(struct sockaddr_in));
+               remote_addr.sin_family = h->h_addrtype;
+               memcpy((int8 *) &remote_addr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
+               remote_addr.sin_port = htons(conn->port);
+       }
+
+       if(-1 == connServer(socket, &remote_addr, &remote_addr_ip6,(timeout/2),SBData))
+       {
+               TIZEN_LOGD("connection is Failed");
+               return 0;
+       }
+       else
+       {
+               TIZEN_LOGD("connection is done successfully");
+       }
+
+       if (-1 == send(socket, req, reqLen, 0))
+       {
+               TIZEN_LOGD("Main Socket Exception got Exception during send [%s]", strerror (errno));
+       }
+       else
+       {
+               TIZEN_LOGD("Main Socket Exception Send HTTP Request Success");
+               retval = read_conn_poll(socket, SBData);
+               if(retval == -1)
+               {
+                       TIZEN_LOGD("Main Socket Exception Data Poll Error");
+                       retval = 0;
+               }
+               else if(retval == 0)
+               {
+                       TIZEN_LOGD("Main Socket Exception Data Poll Timeout");
+               }
+               else
+               {
+                       retval = recv(socket, temp, 1, MSG_PEEK);
+                       if(retval < 0)
+                               retval = 0;
+               }
+       }
+
+       TIZEN_LOGD("RETURN VALUE IN MAIN SOCKET EXPCETION [%d]",retval);
+       return retval;
+}
+
+void smart_bonding_exit(SmartBondingData *SBData)
+{
+       int32 nbytes = 0;
+       if(SBData != NULL)
+       {
+               TIZEN_LOGD("SBData[%p] smart_bonding_exit", SBData);
+               if (SBData->socket_fd > 0)
+               {
+                       CLOSE_SOCKET(SBData->socket_fd);
+                       SBData->socket_fd = -1;
+               }
+
+               if(SBData->PollThrd != NULL)
+               {
+                       if(SBData->PollThrd->threadStatus == THREAD_INIT)
+                               usleep(100000);
+
+                       SBData->PollThrd->threadStatus = THREAD_FINISH;
+                       TIZEN_D_LOGD("Write Data to Noti Pipe Fd [%s]", NOTI_TRIGGER);
+                       nbytes = write(SBData->noti_pipefd[1], NOTI_TRIGGER, NOTI_TRIGGER_LENGTH);
+                       nbytes = nbytes; /*Warning remove */
+                       PollThread_exit(SBData->PollThrd);
+                       SBData->PollThrd =  NULL;
+               }
+
+               TIZEN_LOGD("Poll thread Closed Successfully");
+
+               if(SBData->cthread != NULL)
+               {
+                       TIZEN_LOGD("sb_exit watchdog thread [%p]", SBData->cthread);
+                       cthread_exit(SBData->cthread);
+                       SBData->cthread =  NULL;
+               }
+
+               if(SBData->curlThrd != NULL)
+               {
+                       TIZEN_LOGD("sb_exit curlThrd thread [%p]", SBData->curlThrd);
+                       curlThread_exit(SBData->curlThrd);
+                       SBData->curlThrd =  NULL;
+               }
+
+               if(SBData->msocket != NULL)
+               {
+                       TIZEN_LOGD("sb_exit SBData_msocket [%p]", SBData->msocket);
+                       multisocket_exit(SBData->msocket);
+                       TIZEN_LOGD("Multisocket freed");
+                       SBData->msocket = NULL;
+               }
+
+               if(SBData->fStream != NULL)
+               {
+                       file_stream_exit(SBData->fStream);
+                       TIZEN_LOGD("File Stream Exit");
+                       SBData->fStream = NULL;
+               }
+
+               delete_http_req(&(SBData->req));
+
+               delete_http_rsp(&(SBData->resp));
+
+#ifdef TIZEN_UX_SUPPORT
+               if(lib_init_success() == 1)
+               {
+                       if(SBData->user_option != 0)
+                       {
+                               TIZEN_LOGD("Remove POP UP");
+                               smart_bonding_stop((void *)SBData);
+                       }
+               }
+#endif
+
+               pthread_mutex_destroy(&SBData->tempLock);
+               if(SBData->raFileMngr.writeFD1 != NULL)
+               {
+                       fclose(SBData->raFileMngr.writeFD1);
+                       SBData->raFileMngr.writeFD1 = NULL;
+               }
+               if(SBData->raFileMngr.writeFD2 !=NULL)
+               {
+                       fclose(SBData->raFileMngr.writeFD2);
+                       SBData->raFileMngr.writeFD2 = NULL;
+               }
+
+               CLOSE_SOCKET(SBData->noti_pipefd[0]);
+               CLOSE_SOCKET(SBData->noti_pipefd[1]);
+               CLOSE_SOCKET(SBData->trigger_pipefd[0]);
+               CLOSE_SOCKET(SBData->trigger_pipefd[1]);
+
+               TIZEN_LOGD("All PIPE/File FD are close");
+
+               free(SBData);
+               SBData = NULL;
+               TIZEN_LOGD("Multisocket Exit new sb_exit finished");
+       }
+       else
+       {
+               TIZEN_LOGD("SBdata null sb_exit finished");
+       }
+}
+
+static DBusMessage *method_call(const char *dest, const char *path,
+const char *interface, const char *method)
+{
+       DBusMessageIter iter;
+       DBusError err;
+       DBusMessage *msg = NULL;
+       DBusMessage *reply = NULL;
+       DBusConnection *conn = NULL;
+
+       conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+       if (!conn)
+       {
+               _E("dbus_bus_get error");
+               return NULL;
+       }
+
+       msg = dbus_message_new_method_call(dest, path, interface, method);
+       if (!msg) {
+               _E("dbus_message_new_method_call(%s:%s-%s)", path, interface, method);
+               return NULL;
+       }
+
+       dbus_message_iter_init_append(msg, &iter);
+
+       dbus_error_init(&err);
+
+       reply = dbus_connection_send_with_reply_and_block(conn, msg,
+                       DEVICED_DBUS_TIMEOUT, &err);
+       if (!reply)
+       {
+               _E("dbus_connection_send error(No reply)");
+       }
+
+       if (dbus_error_is_set(&err))
+       {
+               _E("dbus_connection_send error(%s:%s)", err.name, err.message);
+               dbus_error_free(&err);
+               reply = NULL;
+       }
+
+       dbus_message_unref(msg);
+       return reply;
+}
+
+int get_siop_level(void)
+{
+       DBusError err;
+       DBusMessage *msg;
+       int32 ret, level;
+
+       msg = method_call(BUS_NAME, PATH_NAME, INTERFACE_NAME, METHOD_NAME);
+       if (!msg)
+               return -1;
+
+       dbus_error_init(&err);
+
+       ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &level,
+                       DBUS_TYPE_INVALID);
+       if (!ret) {
+               _E("no message : [%s:%s]", err.name, err.message);
+               level = -1;
+       }
+       dbus_message_unref(msg);
+       dbus_error_free(&err);
+
+       return level;
+}
+
+int32 getTempLevel(SmartBondingData *SBData)
+{
+#if 0
+       int32 level = 0;
+       TIZEN_LOGD("Get Temperature");
+       pthread_mutex_lock(&SBData->tempLock);
+       level = get_siop_level();
+       pthread_mutex_unlock(&SBData->tempLock);
+       TIZEN_LOGD("Temperature Level is %d",level);
+       if(level == -1)
+       {
+               TIZEN_LOGD("Temperature Not Fetched Properly");
+       }
+       else if(level > get_multirat_temp_threshold())
+       {
+               TIZEN_LOGD("Temperature Is above threshold");
+               return B_TRUE;
+       }
+#endif
+       return B_FALSE;
+}
+
+uint64 get_time_in_microsec()
+{
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       return ((tv.tv_sec * 1000000) + tv.tv_usec);
+}
+
+uint64 get_time_in_sec()
+{
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       return tv.tv_sec;
+}
+
+void reset_stats(StatDetails *stat)
+{
+       stat->dataStrtTime = get_time_in_microsec();
+       stat->dataOffsetTime = stat->dataStrtTime;
+       stat->offsetForSpeed = 0;
+       stat->dataOffset = 0;
+       stat->mainSockSpeed = 0;
+       memset(stat->dataArr,0,(100*sizeof(uint32)));
+       memset(stat->timeArr,0,(100*sizeof(uint64)));
+       stat->speedIndex = 0;
+}
+
+void getHost(char **host, char *reqHeaders)
+{
+       int len = 0;
+       char *tempBuff = reqHeaders;
+
+       len = decode_http_find_str(tempBuff,"\r\n");
+       if(len == -1)
+       {
+               return;
+       }/* End of if */
+       tempBuff = tempBuff+len+2;
+       while(strlen(tempBuff) > 0)
+       {
+               len = decode_http_find_str(tempBuff,"\r\n");
+               if(len != 1)
+               {
+                       if(0 == strncasecmp(tempBuff,"Host:",5))
+                       {
+                               *host = (char*)malloc(len + 1);
+                               memset(*host,0,len + 1);
+                               memcpy(*host,tempBuff+6,len-6);
+                               break;
+                       }/* End of if */
+                       tempBuff = tempBuff + len + 2;
+               }/* End of if */
+               else
+               {
+                       break;
+               }/* End of else */
+       }/* End of while */
+       return;
+}/*  */
+
+uint32 get_wifi_dns_ip(int8 *dns_ip)
+{
+       int32 ret = WIFI_ERROR_NONE;
+       int8 *dns_ip_temp = NULL;
+       wifi_ap_h ap_h;
+       ret = wifi_initialize();
+       if(ret != WIFI_ERROR_NONE)
+               return B_FALSE;
+       ret = wifi_get_connected_ap(&ap_h);
+       if(ret != WIFI_ERROR_NONE)
+               return B_FALSE;
+       wifi_ap_get_dns_address(ap_h, 1, WIFI_ADDRESS_FAMILY_IPV4, &dns_ip_temp);
+       SECURE_DB_INFO("WiFi DNS Server IP [%s]", dns_ip);
+       memcpy(dns_ip, dns_ip_temp, strlen(dns_ip_temp));
+       free(dns_ip_temp);
+       return B_TRUE;
+}
+
+uint32 get_lte_dns_ip(int8 *dns_ip)
+{
+       int32 ret = CONNECTION_ERROR_NONE;
+       int8 *dns_ip_temp = NULL;
+       int32 service_type;
+       connection_profile_h profile = NULL;
+       connection_h connection = NULL;
+       ret = connection_create(&connection);
+       if(ret != CONNECTION_ERROR_NONE)
+               return B_FALSE;
+       service_type = CONNECTION_CELLULAR_SERVICE_TYPE_INTERNET;
+       ret = connection_get_default_cellular_service_profile(connection, service_type, &profile);
+       if(ret != CONNECTION_ERROR_NONE)
+               return B_FALSE;
+       connection_profile_get_dns_address(profile, 1, CONNECTION_ADDRESS_FAMILY_IPV4, &dns_ip_temp);
+       SECURE_DB_INFO("LTE DNS Server IP [%s]", dns_ip_temp);
+       memcpy(dns_ip, dns_ip_temp, strlen(dns_ip_temp));
+       free(dns_ip_temp);
+       return B_TRUE;
+}
+
+int getDNSInfo(char *host, int iface, SmartBondingData *SBData)
+{
+       int retval = 0;
+       int8 *server_ip = NULL;
+       int8 *interface_ip = SBData->conn.ifaceInfo[iface].ip;
+       ares_channel channel;
+       int status;
+       connection *conn = &(SBData->conn);
+       struct ares_options options;
+       int optmask = 0;
+       struct in_addr a4;
+       uint32 ret = B_FALSE;
+       char dns_ip[INET_ADDRSTRLENG] = {0};
+       int i = 0;
+       memset(dns_ip, 0 ,INET_ADDRSTRLENG);
+
+       for(i = 1; i <= DNS_NUM; i++)
+       {
+               retval = 0;
+               if(i == 1)
+               {
+                       if(strcmp(conn->ifaceInfo[iface].dns_1, "") == 0)
+                       {
+                               TIZEN_LOGD("SBData[%p] First DNS IP Not Present", SBData);
+                               continue;
+                       }
+                       else
+                               strncpy(dns_ip, conn->ifaceInfo[iface].dns_1, strlen(conn->ifaceInfo[iface].dns_1));
+               }
+               else
+               {
+                       if(strcmp(conn->ifaceInfo[iface].dns_2, "") == 0)
+                       {
+                               TIZEN_LOGD("No DNS IP from LTE Profile");
+                               ret = get_lte_dns_ip(dns_ip);
+                               if(ret!= B_TRUE)
+                               {
+                                       TIZEN_LOGD("SBData[%p] Unable to fetch DNS Server IP", SBData);
+                                       return retval;
+                               }
+                       }
+                       else
+                               strncpy(dns_ip, conn->ifaceInfo[iface].dns_2, strlen(conn->ifaceInfo[iface].dns_2));
+               }
+
+               server_ip = SBData->conn.ifaceInfo[iface].server_ip;
+
+               SECURE_DB_INFO("Server IP [%s] Interface IP [%s] DNS Server [%s]",
+                       server_ip, interface_ip, dns_ip);
+               a4.s_addr = inet_addr(interface_ip);
+
+               status = ares_library_init(ARES_LIB_INIT_ALL);
+               if (status != ARES_SUCCESS)
+               {
+                       TIZEN_LOGD("ares_library_init: [%s]", ares_strerror(status));
+                       continue;
+               }
+
+               options.sock_state_cb = state_cb;
+               optmask |= ARES_OPT_SOCK_STATE_CB;
+
+               options.timeout = 100000000;
+               optmask |= ARES_OPT_TIMEOUTMS;
+
+               status = ares_init_options(&channel, &options, optmask);
+               if(status != ARES_SUCCESS)
+               {
+                       TIZEN_LOGD("ares_init_options: [%s]", ares_strerror(status));
+                       continue;
+               }
+               TIZEN_D_LOGD("Ares Init Success");
+
+               ares_set_servers_csv(channel, dns_ip);
+
+               TIZEN_D_LOGD("DNS Server Set PASS");
+
+               ares_set_local_ip4(channel, ntohl(a4.s_addr));
+
+               TIZEN_D_LOGD("Set Local IP Address PASS");
+
+               SBData->dns = 0;
+               SBData->dns_iface = iface;
+               ares_gethostbyname(channel, host, AF_INET, callback, SBData);
+               TIZEN_D_LOGD("After Get host by name");
+
+               wait_ares(channel,SBData);
+               ares_destroy(channel);
+               ares_library_cleanup();
+
+               if(SBData->dns == 1)
+               {
+                       retval = 1;
+                       SECURE_DB_INFO("SBData[%p] New IP Address [%s]",SBData, conn->ifaceInfo[iface].server_ip);
+                       return retval;
+               }
+               else
+               {       
+                       TIZEN_LOGD("SBData[%p] Resolution Failure", SBData);
+               }
+       }
+       return retval;
+}/* End of getDNSInfo */
+
+int handleRedirection(char *location,  uint32 iface, char **reqHeaders, uint32 *headerLen, SmartBondingData *SBData)
+{
+       int retval = HTTP_RSP_DECODING_ERROR;
+       char *tempLoc = location;
+       char *host = NULL;
+       char *url = NULL;
+       char *newReq = NULL;
+
+       /* Decode the location */
+       decodeLocation(tempLoc,&host,&url);
+       newReq = getNewRedirectReq(host,url,*reqHeaders);
+       if((NULL != newReq) && (getDNSInfo(host,iface,SBData)))
+       {
+               free(*reqHeaders);
+               *reqHeaders = NULL;
+               *reqHeaders =  newReq;
+               *headerLen = strlen(newReq);
+               SECURE_DB_INFO("New Requset after Redirect [%s]", newReq);
+               retval =  HTTP_RSP_DECODING_SUCCESS;
+       }/* End of if */
+       else if (NULL != newReq)
+       {
+               free(newReq);
+               newReq = NULL;
+       }
+       if(NULL != host)
+       {
+               free(host);
+       }/* End of if */
+
+       if(NULL != url)
+       {
+               free(url);
+       }/* End of if */
+
+       host = NULL;
+       url = NULL;
+       return retval;
+}/* End of handleRedirection() */
+
+/*
+* FUNCTION     : decodeLocation
+* PARAMETERS   : *loc = location to be decoded
+*                **host = host from loction
+*                **url = url from loction
+* DESCRIPTION  : This function will decode the location headers from 3XX response
+                                and extract the host and url
+* RETURN VALUE : void
+*/
+void decodeLocation(char *loc,char **host,char **url)
+{
+       int ret = 0;
+       int offset = 0;
+       int len = strlen(loc);
+
+       if(0 == strncmp(loc,"http://",7))
+       {
+               offset = offset + 7;
+       }/* End of if */
+       ret = decode_http_find_str(loc+offset,"/");
+       if(ret != -1)
+       {
+               *host = (char*)malloc(ret+1);
+               memset(*host,0,ret+1);
+               memcpy(*host,loc+offset,ret);
+               *url = (char*)malloc(len-(offset+ret)+1);
+               memset(*url,0,(len-(offset+ret)+1));
+               memcpy(*url,loc+offset+ret,len-(offset+ret));
+       }/* End of if */
+       else
+       {
+               /* host and url are same */
+               int tempLen = len-offset;
+               *host = (char*)malloc(tempLen+1);
+               memset(*host,0,tempLen+1);
+               memcpy(*host,loc+offset,tempLen);
+               *url = (char*)malloc(tempLen+1);
+               memset(*url,0,tempLen+1);
+               memcpy(*url,loc+offset+ret,tempLen);
+       }/* End of else */
+       SECURE_DB_INFO("Decode Loaction URL [%s] Host [%s]", *url , *host);
+}/* End of decodeLocation() */
+
+/*
+* FUNCTION     : getNewRedirectReq
+* PARAMETERS   : *host = host from loction header
+*                *url = url from loction header
+* DESCRIPTION  : This function will build the new HTTP
+*                request after redirection response is received
+* RETURN VALUE : void
+*/
+char *getNewRedirectReq(char *host,char *url, char *reqHeaders)
+{
+       int len = 0;
+       int index = 0;
+       int offset = 0;
+       int totalLen = 0;
+       int headerLen = 0;
+       int numOfhead = 0;
+       int reqLineLen = 0;
+       char *headers[20] = {0};
+       char *newReq = NULL;
+       char *tempBuff = reqHeaders;
+
+       len = decode_http_find_str(tempBuff,"\r\n");
+       if(len == -1)
+       {
+               return NULL;
+       }/*      End of if */
+
+       tempBuff = tempBuff+len+2;
+       while((strlen(tempBuff) > 0) && (numOfhead < 20))
+       {
+               len = decode_http_find_str(tempBuff,"\r\n");
+               if(len != 1)
+               {
+                       if(0 != strncasecmp(tempBuff,"Host:",5))
+                       {
+                               headers[numOfhead] = (char*)malloc(len + 3);
+                               memset(headers[numOfhead],0,len + 3);
+                               memcpy(headers[numOfhead],tempBuff,len+2);
+                               headerLen = headerLen + len + 2;
+                               numOfhead++;
+                       }/* End of if */
+                       tempBuff = tempBuff + len + 2;
+               }/* End of if */
+               else
+               {
+                       break;
+               }/* End of else */
+       }/* End of if */
+       totalLen = strlen(host)+strlen(url)+headerLen+(2 * MAX_RANGE_FIELD_LEN);
+       newReq = (char*)malloc(totalLen);
+       if(NULL == newReq)
+       {
+               return NULL;
+       }/* End of if */
+
+       memset(newReq,0,totalLen);
+       reqLineLen = sprintf(newReq,"%s%s%s%s","GET ",url," HTTP/1.1",END_OF_LINE);
+       offset = reqLineLen + sprintf(newReq+reqLineLen,"%s%s%s","Host: ",host,END_OF_LINE);
+       for(index = 0; index < numOfhead; index++)
+       {
+               headerLen = strlen(headers[index]);
+               memcpy(newReq+offset,headers[index],headerLen);
+               offset = offset+headerLen;
+               free(headers[index]);
+               headers[index] = NULL;
+       }/* End of if */
+       return newReq;
+}/* End of getNewRedirectReq() */
+
+uint32 store_interface_ip_request(char *newReq, SmartBondingData *SBData, uint32 interface_index)
+{
+       char *temp_req1 = NULL;
+       char *temp_req2 = NULL;
+       char *temp;
+       int retval = -1;
+       int len = -1;
+       int len1 = 0;
+       httpReq *req = &(SBData->req);
+       len = decode_http_find_str(newReq, RANGELEN_REQ_HEADER);
+       if(len != -1)
+       {
+               temp_req1 = malloc(strlen(newReq)+ 1);
+               memset(temp_req1, 0, strlen(newReq)+ 1);
+               memcpy(temp_req1,newReq,len);
+               len1 = len ;
+               temp = newReq + len;
+               len = decode_http_find_str(temp,END_OF_LINE);
+               temp = temp + len;
+               memcpy(temp_req1+len1,"\r\n",2);
+               req->request[interface_index] = temp_req1;
+       }
+       else
+       {
+               return retval;
+       }
+
+       if(SBData->req.Rangeheader == NULL)
+       {
+               len  = strlen(req->req_buff);
+               temp_req2 = malloc(len + 1);
+               memset(temp_req2, 0, len + 1);
+               memcpy(temp_req2, req->req_buff, len);
+       }
+       else
+       {
+               len  = strlen(req->req_buff_wo_range);
+               temp_req2 = malloc(len + 1);
+               memset(temp_req2, 0, len + 1);
+               memcpy(temp_req2, req->req_buff_wo_range, len);
+       }
+
+       req->request[(interface_index+1) % 2] = temp_req2;
+       retval = 0;
+       return retval;
+}
diff --git a/src/multirat_range_request_thread.c b/src/multirat_range_request_thread.c
new file mode 100644 (file)
index 0000000..0eaba75
--- /dev/null
@@ -0,0 +1,652 @@
+#include "multirat_conf.h"
+#include "multirat_process.h"
+#include "multirat_libapi.h"
+#include "multirat_range_request_thread.h"
+#include "multirat_connection.h"
+#include "multirat_block_manager.h"
+#include "multirat_data_buffer.h"
+#include "multirat_decode_http.h"
+#include <sys/time.h>
+
+
+void range_request_thread_init(RangeRequestThread *rrthread, SmartBondingData *SBData)
+{
+       MultiSocket *mSocket = SBData->msocket;
+       int8 *default_iname = DEFAULT_INTERFACE;
+       uint32 ifaceidx = rrthread->threadId;
+
+       rrthread->pThreadId = 0;
+       rrthread->socketId = 0;
+       rrthread->minBlockSize = MIN_BLOCK_SIZE;
+       rrthread->maxBlockSize = MAX_BLOCK_SIZE;
+       rrthread->speedTimeOut = SPEED_TIMEOUT;
+       rrthread->blockForSpeed = BLOCK_SIZE_SPEED;
+       rrthread->minDataForSpeed =  MIN_DATA_FOR_SPEED;
+       rrthread->compRspLen = mSocket->compRspLen;
+       rrthread->contRngLen = SBData->resp.instanceSize;
+       rrthread->commBuffer = mSocket->commBuffer;
+       rrthread->conn = mSocket->conn;
+       rrthread->blockMgr = mSocket->blockMgr;
+       rrthread->compRspRcvdFlag = &mSocket->compRspRcvdFlag;
+       rrthread->firstRngStatus = FIRST_RSP_STATUS_PENDING;
+
+       if (0 == strncasecmp(default_iname, LTE, strlen(LTE)))
+       {
+               /*
+               * thread  0 should get interface LTE (1)
+               * and thread 1 should get interface WIFI(0)
+               */
+               ifaceidx = (ifaceidx + 1) % 2;
+       }
+
+       rrthread->reqHeaders = SBData->req.request[ifaceidx] ;
+       rrthread->headerLen = strlen(SBData->req.request[ifaceidx]);
+
+       #if 0
+       if(SBData->req.req_buff_wo_range != NULL)
+       {
+               rrthread->reqHeaders = SBData->req.req_buff_wo_range;
+               rrthread->headerLen = SBData->req.req_wo_len;
+       }
+       else
+       {
+               rrthread->reqHeaders = SBData->req.req_buff;
+               rrthread->headerLen =  SBData->req.reqLen;
+       }
+       #endif
+       rrthread->SBData = SBData;
+
+}/* End of RangeRequestThread() */
+
+uint32 range_request_thread_start(RangeRequestThread *rrthread)
+{
+       if(0 != pthread_create(&rrthread->pThreadId, NULL,
+       range_request_thread_rngreq_thread_callback, (void *)rrthread))
+       {
+               TIZEN_LOGD("Error !!! while creating range thread");
+               range_request_thread_exit(rrthread);
+               rrthread = NULL;
+               return B_FALSE;
+       }
+       TIZEN_LOGD("thread ID %d Rangethread started", rrthread->threadId);
+       return B_TRUE;
+}
+
+void *range_request_thread_rngreq_thread_callback(void *pArg)
+{
+       RangeRequestThread *rngReq = ((RangeRequestThread*)pArg);
+       range_request_thread_run(rngReq);
+       return NULL;
+}
+
+
+int range_request_thread_handleIOExp(RangeRequestThread *rrthread, uint32 *ifCount , int iptype)
+{
+       /* Check if interface is available */
+       if (!connection_is_ifaceup(rrthread->threadId, rrthread->conn->ifaceInfo,iptype))
+       {
+               if((rrthread->firstRngStatus == FIRST_RSP_STATUS_PENDING) && (*ifCount++ > 2))
+               {
+                       rrthread->firstRngStatus = FIRST_RSP_STATUS_FAILED;
+                       *(rrthread->compRspRcvdFlag) = 0;
+                       TIZEN_LOGD("First Response Failed for ThreadId %d\n",rrthread->threadId);
+                       return THREAD_EXIT;
+               }
+               uint32 otherId = GET_OTHER_THREAD_ID(rrthread->threadId);
+               if((rrthread->blockMgr->threadState[otherId] == STATE_THREAD_STOPPED) &&
+                               (connection_is_ifaceup(otherId, rrthread->conn->ifaceInfo,iptype)))
+               {
+                       TIZEN_LOGD("Swapping thread as other thread is stopped \n");
+                       rrthread->blockMgr->threadState[rrthread->threadId] = STATE_THREAD_STOPPED;
+                       rrthread->threadId = otherId;
+                       rrthread->blockMgr->threadState[otherId] = STATE_THREAD_RUNNING;
+                       rrthread->blockMgr->noOfIOExp[otherId] = 0;
+               }
+               else
+               {
+                       return THREAD_CONTINUE;
+               }
+       }
+       /* IOException case */
+       connect_server(rrthread);
+       TIZEN_LOGD("thread ID %d rrthread->socketId %d\n",rrthread->threadId,rrthread->socketId);
+       if ((0 == rrthread->socketId) || (!(*(rrthread->compRspRcvdFlag))))
+       {
+               if (rrthread->firstRngStatus == FIRST_RSP_STATUS_PENDING)
+               {
+                       rrthread->firstRngStatus = FIRST_RSP_STATUS_FAILED;
+                       TIZEN_LOGD("First Response failed\n");;
+                       /* server doest support Range Request */
+                       /* Exit all threads */
+                       *(rrthread->compRspRcvdFlag) = 0;
+                       TIZEN_LOGD("First Response Failed for ThreadId %d\n",rrthread->threadId);
+                       return THREAD_EXIT;
+               }
+               else
+               {
+                       return THREAD_CONTINUE;
+               }
+       }
+       return 0;
+}
+
+void range_request_thread_handleSendFailCase(RangeRequestThread *rrthread, int32 chunkId)
+{
+       TIZEN_LOGD("Thread with %d got Exception during send",rrthread->threadId);
+
+       if (rrthread->firstRngStatus == FIRST_RSP_STATUS_PENDING)
+       {
+               rrthread->firstRngStatus = FIRST_RSP_STATUS_FAILED;
+               TIZEN_LOGD("First Response failed\n");;
+               /* server doest support Range Request */
+               /* Exit all threads */
+               *(rrthread->compRspRcvdFlag) = 0;
+       }
+
+       if (rrthread->socketId != 0)
+       {
+               close(rrthread->socketId);
+               rrthread->socketId = 0;
+       }
+       if ((chunkId != -1) && (DATA_BUFFER_GET_THREAD_ID(rrthread->commBuffer + chunkId) == rrthread->threadId))
+       {
+               /* IO Exception inform Block manager */
+               block_manager_io_exception(rrthread->threadId, chunkId, rrthread->blockMgr);
+               DATA_BUFFER_SET_STATE(STATE_BLOCKED, (rrthread->commBuffer + chunkId));
+       }
+}
+
+void range_request_thread_run(RangeRequestThread *rrthread)
+{
+       int32 retval = 0;
+       int32 chunkId = -1;
+       int32 blockOffset = 0;
+       int32 headerRcvd = B_FALSE;
+       int32 IOException = B_TRUE;
+       uint32 reqLen = 0;
+       uint32 ifCount = 0;
+       uint32 blockLen = 0;
+       uint32 rngRspLen = 0;
+       uint32 connClose = 0;
+       uint32 waitThread = B_FALSE;
+       uint32 iface_check_count = 0;
+       uint32 minBlockLen = rrthread->minBlockSize;
+       uint64 endTime = 0;
+       uint64 startTime = 0;
+       uint64 currChunkLen = 0;
+       uint64 chunkStrTime = 0;
+       uint64 temp_startTime = 0;
+       int64 chunkInfo[CHUNK_INFO_SIZE] = {0};
+       int8 *newRequest = NULL;
+       //int8 *chunkBuff = NULL;
+       int8 tempBuff[MAX_BLOCK_SIZE] = {0};
+       DataBuffer *currChunk =  NULL;
+
+       newRequest = (char*)malloc(rrthread->headerLen + MAX_RANGE_FIELD_LEN);
+       if(NULL == newRequest)
+       {
+               return;
+       }/* End of if */
+       while (*(rrthread->compRspRcvdFlag))
+       {
+               /* Check the current state of thread */
+               if(rrthread->blockMgr->threadState[rrthread->threadId] == STATE_THREAD_STOPPED)
+               {
+                       TIZEN_LOGD("Thread %d stopped state exiting\n",rrthread->threadId);
+                       break;
+               }
+
+               /* Get the status of commonBuffer (memory availability) */
+               if (1 == block_manager_check_buffer_status(rrthread->blockMgr))
+               {
+                       usleep(30000);
+                       continue;
+               }/* End of if */
+
+               if(waitThread == B_TRUE)
+               {
+                       retval =  block_manager_checkAllBufferStatus(rrthread->blockMgr,rrthread->threadId);
+                       if(THREAD_WAIT == retval)
+                       {
+                               /* Other thread is downloading this thread has to wait */
+                               usleep(1000000);
+                               continue;
+                       }
+                       else if (THREAD_EXIT == retval)
+                       {
+                               /* Wait thread should exit as other thread has completed */
+                               TIZEN_LOGD("Download Complete by other thread Exiting Thread Id %d",rrthread->threadId);
+                               break;
+                       }
+                       else if(THREAD_CONTINUE == retval)
+                       {
+                               /* Other thread has chunk is blocked */
+                               TIZEN_LOGD("waiting thread need to download chunk", rrthread->threadId);
+                               waitThread = B_FALSE;
+                       }
+               }
+
+               if (IOException == B_TRUE)
+               {
+                       retval = 0;
+                       if(iface_check_count > rrthread->SBData->timeout)
+                       {
+                               rrthread->blockMgr->threadState[rrthread->threadId] = STATE_THREAD_STOPPED;
+                               TIZEN_LOGD("Stopping Thread %d as Interaface is Down For Long Time");
+                               break;
+                       }
+                       retval = range_request_thread_handleIOExp(rrthread,&ifCount,rrthread->SBData->conn.ip_family);
+                       if(THREAD_EXIT == retval)
+                       {
+                               break;
+                       }
+                       else if (THREAD_CONTINUE == retval)
+                       {
+                               iface_check_count++;
+                               sleep(1);
+                               continue;
+                       }
+                       iface_check_count = 0;
+                       IOException = B_FALSE;
+               }
+               memset(chunkInfo,0,CHUNK_INFO_SIZE*sizeof(int64));
+
+               /* Block Manager for next block */
+               block_manager_get_next_chunk(chunkInfo, rrthread->threadId,
+                                                                               rrthread->socketId, rrthread->blockMgr);
+
+               currChunkLen = chunkInfo[1] - chunkInfo[0] + 1;
+               chunkId = chunkInfo[2];
+               TIZEN_LOGD("Chunk Id %d Thread Id %d RANGE START %dRANGE END %d\n",
+               chunkId, rrthread->threadId, chunkInfo[0] ,chunkInfo[1]);
+
+               if (chunkId < 0)
+               {
+                       /* This condition is for keep-alive case */
+                       waitThread = B_TRUE;
+                       continue;
+               }
+
+               currChunk = rrthread->commBuffer + chunkId;
+               memset(newRequest,0,(rrthread->headerLen + MAX_RANGE_FIELD_LEN));
+               reqLen = range_request_thread_rebuild_req(newRequest, chunkInfo, rrthread);
+
+               startTime = get_time_in_microsec();
+
+               if (-1 == send(rrthread->socketId, newRequest, reqLen, 0))
+               {
+                       range_request_thread_handleSendFailCase(rrthread,chunkId);
+                       IOException = B_TRUE;
+                       continue;
+               }/* End of if */
+
+               rngRspLen = 0;
+               headerRcvd = B_FALSE;
+               connClose = 0;
+               //chunkBuff = DATA_BUFFER_GET_BUFFER(currChunk);
+
+               while (rngRspLen != currChunkLen)
+               {
+                       blockLen =  MIN(minBlockLen, (currChunkLen-rngRspLen));
+                       minBlockLen = MIN(rrthread->maxBlockSize, (minBlockLen<<1));
+                       blockOffset = 0;
+                       memset(tempBuff,0,MAX_BLOCK_SIZE);
+                       if (0 == headerRcvd)
+                       {
+                               retval = range_request_recv_rng_rsp_headers(rrthread->socketId, blockLen, TIME_OUT_MILLISEC,
+                               rrthread->contRngLen, currChunkLen, &blockOffset, tempBuff, rrthread->compRspLen, &connClose);
+                               if (HTTP_RSP_DECODING_SUCCESS != retval)
+                               {
+                                       if (rrthread->firstRngStatus == FIRST_RSP_STATUS_PENDING)
+                                       {
+                                               TIZEN_LOGD("First Response failed\n");;
+                                               /* server doest support Range Request */
+                                               /* Exit all threads */
+                                               *(rrthread->compRspRcvdFlag) = 0;
+                                               rrthread->firstRngStatus = FIRST_RSP_STATUS_FAILED;
+                                       }/* End of else */
+                                       else
+                                       {
+                                               /* IO Exception */
+                                               IOException = B_TRUE;
+                                               TIZEN_LOGD("Thread %d got Exception during recv headers",rrthread->threadId);
+                                       }
+                                       break;
+                               }
+                               else
+                               {
+                                       endTime = get_time_in_microsec();
+                                       temp_startTime = endTime;
+                                       chunkStrTime = endTime;
+                                       uint64 headSpeed = (endTime-startTime)/1000;
+
+                                       TIZEN_D_LOGD("Thread %d Header speed %d\n",rrthread->threadId,headSpeed);
+                                       SET_HEAD_SPEED(rrthread->threadId,headSpeed,rrthread->blockMgr);
+                                       headerRcvd = B_TRUE;
+
+                                       /* Success response received from server */
+                                       if (rrthread->firstRngStatus == FIRST_RSP_STATUS_PENDING)
+                                       {
+                                               rrthread->firstRngStatus = FIRST_RSP_STATUS_SUCCESS;
+                                               TIZEN_LOGD("First Response Success\n");
+                                       }
+                                       if (blockOffset > 0)
+                                       {
+                                               data_buffer_add(blockOffset, rrthread->threadId, tempBuff, currChunk);
+                                               rngRspLen = rngRspLen + blockOffset;
+                                       }/* End of if */
+                               }/* End of else */
+                       }/* End of if */
+                       else
+                       {
+                               int32 lenRcvd = 0;
+                               uint32 currOffset = 0;
+                               uint32 prevOffset = 0;
+                               uint32 diffOffset = 0;
+                               uint32 temp_check = 0;
+                               uint64 speed = 0;
+                               uint64 avgTime = 0;
+                               uint64 currTime = 0;
+                               uint64 prevTime = 0;
+                               uint64 diffTime = 0;
+                               uint64 blockStrtTime = 0;
+                               uint64 blockEndTime = 0;
+                               int8 *block = tempBuff;
+
+                               prevTime = get_time_in_microsec();
+                               blockStrtTime = prevTime;
+                               while (blockOffset != blockLen)
+                               {
+                                       if (conn_poll(rrthread->socketId, TIME_OUT_MILLISEC) <= 0)
+                                       {
+                                               TIZEN_LOGD("Thread %d pollfd <=0\n",rrthread->threadId);
+                                               break;
+                                       }
+
+                                       lenRcvd = recv(rrthread->socketId,block + blockOffset,blockLen-blockOffset, 0);
+                                       if ((lenRcvd == -1) || (lenRcvd == 0))
+                                       {
+                                               TIZEN_LOGD("Thread %d pollfd recv faill \n",rrthread->threadId);
+                                               break;
+                                       }
+                                       else if (lenRcvd > 0)
+                                       {
+                                               currOffset = currOffset + lenRcvd;
+                                               blockOffset = blockOffset + lenRcvd;
+                                               currTime = get_time_in_microsec();
+                                               blockEndTime = currTime;
+                                               diffTime = (currTime-prevTime) /1000;
+                                               diffOffset = currOffset-prevOffset;
+                                               if((rngRspLen > rrthread->minDataForSpeed) &&
+                                                               ((diffOffset >= rrthread->blockForSpeed) || (diffTime >= rrthread->speedTimeOut)))
+                                               {
+                                                       prevTime = currTime;
+                                                       prevOffset = currOffset;
+                                                       avgTime = (currTime - chunkStrTime)/1000;
+                                                       if(avgTime > 0)
+                                                       {
+                                                               speed = ((rngRspLen + blockOffset) * 8)/avgTime;
+                                                       }/* End of if */
+                                                       SET_SPEED(rrthread->threadId,speed, rrthread->blockMgr);
+                                               }
+                                               if((blockEndTime-blockStrtTime) >= BLOCK_TIME_OUT)
+                                               {
+                                                       blockLen = blockOffset;
+                                               }
+                                       }
+                               }
+                               if (blockOffset != blockLen)
+                               {
+                                       /* IO Exception */
+                                       TIZEN_LOGD("Thread %d IOException during read\n",rrthread->threadId);
+                                       IOException = B_TRUE;
+                                       break;
+                               }
+                               else
+                               {
+                                       temp_check = 0;
+                                       data_buffer_add(blockOffset, rrthread->threadId, tempBuff, currChunk);
+                                       rngRspLen = rngRspLen + blockOffset;
+
+                                       TIZEN_D_LOGD("Thread %d completed block of len\n",blockLen);
+                                       /* check the other thread status */
+                                       if((currTime - temp_startTime) > TEMP_TIME_OUT)
+                                       {
+                                               TIZEN_D_LOGD("Go For Temperature Checking");
+                                               temp_startTime = currTime;
+                                               temp_check = 1;
+                                       }
+                                       if(block_manager_checkOtherThread(rrthread->threadId,chunkId,rrthread->blockMgr,temp_check))
+                                       {
+                                               TIZEN_LOGD("Thread %d IOException as other thread is blocked read\n",rrthread->threadId);
+                                               IOException = B_TRUE;
+                                               break;
+                                       }
+                               }
+                       }
+               }/* End of while */
+               if (IOException == B_TRUE)
+               {
+                       if ((chunkId != -1) && (DATA_BUFFER_GET_THREAD_ID(rrthread->commBuffer + chunkId) ==
+                       rrthread->threadId))
+                       {
+                               /* close the current fd */
+                               if (rrthread->socketId != 0)
+                               {
+                                       close(rrthread->socketId);
+                                       rrthread->socketId = 0;
+                               }
+                               /* IO Exception inform Block manager */
+                               block_manager_io_exception(rrthread->threadId,chunkId, rrthread->blockMgr);
+                               DATA_BUFFER_SET_STATE(STATE_BLOCKED, (rrthread->commBuffer + chunkId));
+                               if(blockOffset != blockLen)
+                               {
+                                       /* Consider only IO Expection due to socket */
+                                       rrthread->blockMgr->noOfIOExp[rrthread->threadId]++;
+                               }
+                       }
+                       else
+                       {
+                               /* Current thread is slow Need to check buffer status */
+                               if (block_manager_chunk_present(rrthread->blockMgr) <= 0)
+                               {
+                                       waitThread = B_TRUE;
+                                       TIZEN_LOGD("Slow Thread %d is in wait state \n",rrthread->threadId);
+                               }
+                               rrthread->socketId = 0;
+                       }
+               }
+               else
+               {
+                       TIZEN_LOGD("Thread %d  Completed chunk %d \n",rrthread->threadId, chunkId);
+               }
+               if ((IOException == B_FALSE) && (1 == connClose))
+               {
+                       IOException = B_TRUE;
+                       if (block_manager_chunk_present(rrthread->blockMgr) <= 0)
+                       {
+                               waitThread = B_TRUE;
+                               TIZEN_LOGD("Thread %d is in wait state \n",rrthread->threadId);
+                       }
+                       if (rrthread->socketId != 0)
+                       {
+                               close(rrthread->socketId);
+                               rrthread->socketId = 0;
+                       }
+               }/* End of if */
+       }/* End of while */
+
+       rrthread->blockMgr->threadState[rrthread->threadId] = STATE_THREAD_STOPPED;
+
+       if (rrthread->socketId != 0)
+       {
+               close(rrthread->socketId);
+               rrthread->socketId = 0;
+       }
+
+       if(NULL != newRequest)
+       {
+               free(newRequest);
+               newRequest = NULL;
+       }/* End of if */
+
+}/* End of run() */
+
+uint32 range_request_thread_rebuild_req(int8 *newRequest, int64 *chunkInfo,RangeRequestThread *rrthread)
+{
+       int8 rangeField[50] = {0};
+       uint32 rangeLen = 0;
+
+       rangeLen = sprintf(rangeField,"%s%lld%s%lld%s","Range: bytes=", chunkInfo[0], "-",
+       chunkInfo[1], "\r\n\r\n");
+
+       memcpy(newRequest, rrthread->reqHeaders, rrthread->headerLen);
+       newRequest[rrthread->headerLen] = '\0';
+
+
+       memcpy(newRequest + (rrthread->headerLen - 2), rangeField, rangeLen);
+       newRequest[rangeLen + rrthread->headerLen-2] = '\0';
+       TIZEN_LOGD("thread ID %d range_request_thread_rebuild_req new req with range =%s\n",
+       rrthread->threadId, newRequest);
+       return (rangeLen + rrthread->headerLen -2);
+}
+
+void range_request_thread_exit(RangeRequestThread *rrthread)
+{
+       TIZEN_LOGD("range_request_thread_exit %p", rrthread);
+
+       if (0 != rrthread->socketId)
+       {
+               close(rrthread->socketId);
+               rrthread->socketId = 0;
+       }
+
+       if (0 != rrthread->pThreadId)
+       {
+               pthread_join(rrthread->pThreadId,NULL);
+               rrthread->pThreadId = 0;
+       }
+
+       free(rrthread);
+       rrthread = NULL;
+       TIZEN_LOGD("range_request_thread_exit Sucess %p", rrthread);
+}
+
+int range_request_recv_rng_rsp_headers(int32 socket_fd, uint32 size, uint32 timeout, uint64 instanceSize,
+                                                               uint64 currChunkLen, int32 *bodyLen, int8 *blockSize, uint64 respLen, uint32 *connClose)
+{
+       int32 len = 0;
+       int32 rcvdLen = 0;
+       int32 retval = -1;
+       uint32 offset = 0;
+       uint32 headerLen;
+       int8 rspSize[MAX_HEADERS_SIZE + 1] = {0};
+       int8 rspPrint[MAX_HEADERS_SIZE] = {0};
+       httpResp httprsp;
+
+       memset(rspSize, 0, MAX_HEADERS_SIZE + 1);
+       memset(rspPrint, 0, MAX_HEADERS_SIZE);
+
+       while (1)
+       {
+               if(conn_poll(socket_fd, timeout) <= 0)
+               {
+                       TIZEN_LOGD("Poll Error in recv headers");
+                       return HTTP_RSP_SOCKET_ERROR;
+               }/* End of if */
+               uint32 min_size = MIN(size, (MAX_HEADERS_SIZE - offset));
+               rcvdLen = recv(socket_fd, rspSize + offset,     min_size, 0);
+               TIZEN_D_LOGD("thread ID recvd lenght %d\n", rcvdLen);
+               if (rcvdLen > 0)
+               {
+                       rspSize[offset + rcvdLen +1] = '\0';
+                       len = decode_http_find_str(rspSize, END_OF_HEADERS);
+                       if (-1 != len)
+                       {
+                               headerLen = len+4;
+                               offset  = offset + rcvdLen;
+                               *bodyLen = offset - headerLen;
+
+                               memcpy(rspPrint, rspSize, headerLen);
+                               TIZEN_LOGD("Response %s\n", rspPrint);
+                               /* Decode Response headers */
+                               memset(&httprsp, 0, sizeof(httpResp));
+                               decode_http_rsp_init(rspSize, headerLen, &httprsp);
+
+                               retval = process_http_rsp(&httprsp);
+                               if (HTTP_RSP_DECODING_SUCCESS == retval)
+                               {
+                                       retval = range_request_validate_rsp(instanceSize,
+                                                               &httprsp, currChunkLen, respLen, connClose);
+
+                                       if((retval == HTTP_RSP_DECODING_SUCCESS) && (*bodyLen > 0))
+                                       {
+                                               /* Copy initial Response to block */
+                                               memcpy(blockSize,rspSize + headerLen,*bodyLen);
+                                       }
+                               }
+                               delete_http_rsp(&httprsp);
+                               return retval;
+                       }/* End of if */
+                       else
+                       {
+                               offset  = offset + rcvdLen;
+                               if (offset == MAX_HEADERS_SIZE)
+                               {
+                                       /* Rsp header too large */
+                                       retval = HTTP_RSP_DECODING_ERROR;
+                                       break;
+                               }
+                       }
+               }
+               else
+               {
+                       TIZEN_LOGD("recv Error in recv headers");
+                       retval = HTTP_RSP_SOCKET_ERROR;
+                       break;
+               }
+       }
+       return retval;
+}/* End of recvRngRspHeaders() */
+
+int range_request_validate_rsp(uint64 instanceSize, httpResp *httpRsp,
+                                                               uint64 currChunkLen, uint64 respLen, uint32 *connClose)
+{
+       int32 retval = HTTP_RSP_DECODING_ERROR;
+       int8 *rspCode = DECODE_HTTP_RSP_GET_RSP_CODE(httpRsp);
+       int8 *contLen =  DECODE_HTTP_RSP_GET_CONT_LEN(httpRsp);
+       int8 *conn = DECODE_HTTP_RSP_GET_CONNECTION(httpRsp);
+
+       if(conn != NULL)
+       {
+               if(0 == strncasecmp(conn,"close",strlen("close")))
+               {
+                       *connClose = 1;
+               }/* End of if */
+       }
+
+       if ((rspCode != NULL) && (contLen != NULL))
+       {
+               if ((0 == strncasecmp(rspCode, "200 OK", strlen("200 OK")))
+                               || (0 == strncasecmp(rspCode, "206 Partial Content",strlen("206 Partial Content"))))
+               {
+                       uint64 rcvdContLen = atol(contLen);
+                       TIZEN_LOGD("rcvdContLen %llu Expected %llu",rcvdContLen,currChunkLen);
+                       if (rcvdContLen == currChunkLen)
+                       {
+                               uint64 rcvdContRngLen = decode_http_rsp_get_cont_rnglen(httpRsp->contRange);
+                               TIZEN_LOGD("rcvdContRngLen %llu contRngLen %llu compRspLen %s",
+                               rcvdContRngLen, instanceSize, contLen);
+                               if ((instanceSize != 0) && (instanceSize == rcvdContRngLen))
+                               {
+                                       retval = HTTP_RSP_DECODING_SUCCESS;
+                               }
+                               else if (rcvdContRngLen == respLen)
+                               {
+                                       retval = HTTP_RSP_DECODING_SUCCESS;
+                               }
+                       }
+               }
+       }
+       return retval;
+}
diff --git a/src/multirat_watch_dog_thread.c b/src/multirat_watch_dog_thread.c
new file mode 100644 (file)
index 0000000..f4a215d
--- /dev/null
@@ -0,0 +1,994 @@
+#include "multirat_conf.h"
+#include "multirat_process.h"
+#include "multirat_libapi.h"
+#include "multirat_watch_dog_thread.h"
+#include "multirat_multisocket.h"
+#include "multirat_decode_http.h"
+#include "multirat_range_request_thread.h"
+#include <vconf.h>
+#include <vconf-keys.h>
+#include "multirat_file_stream.h"
+#include "multirat_file_manager.h"
+#include "multirat_file_buffer.h"
+#include "multirat_watchthread.h"
+
+#ifdef TIZEN_UX_SUPPORT
+#include "smartbonding-client.h"
+#endif
+
+void get_proxy_info(SmartBondingData *SBData, int interface_index)
+{
+       connection *conn =  &(SBData->conn);
+       get_proxy_ip_port(conn->ifaceInfo[interface_index].proxy_addr, &(conn->ifaceInfo[interface_index].proxy_port));
+       if(strlen(conn->ifaceInfo[interface_index].proxy_addr) != 0)
+       {
+               memset(SBData->conn.ifaceInfo[interface_index].server_ip,0,INET_ADDRSTRLEN);
+               memcpy(conn->ifaceInfo[interface_index].server_ip, conn->ifaceInfo[interface_index].proxy_addr, strlen(conn->ifaceInfo[interface_index].proxy_addr));
+               conn->ifaceInfo[interface_index].server_port = conn->ifaceInfo[interface_index].proxy_port;
+               conn->ifaceInfo[interface_index].proxyEnable = B_TRUE;
+       }
+       else
+       {
+               conn->ifaceInfo[interface_index].server_port = 80;
+       }
+       get_dns_ip(conn->ifaceInfo[interface_index].dns_1, conn->ifaceInfo[interface_index].dns_2);
+
+       SECURE_DB_INFO("Server/Proxy IP Address [%s]", conn->ifaceInfo[interface_index].server_ip);
+       SECURE_DB_INFO("Server/Proxy Port [%d]", conn->ifaceInfo[interface_index].server_port);
+       SECURE_DB_INFO("DNS 1 [%s]", conn->ifaceInfo[interface_index].dns_1);
+       SECURE_DB_INFO("DNS 2 [%s]", conn->ifaceInfo[interface_index].dns_2);
+}
+
+int32 file_thread_FirstConnection(SmartBondingData *SBData, fileThread *fThread, int64 *chunkInfo, int8 *recv_buf, int32 *lengthRcvd)
+{
+       int8 *host = NULL;
+       int32 socket = -1;
+       uint32 redirect = 0;
+       uint32 length = 0;
+       uint32 retval_watch_dog = 1;
+       int retval = -1;
+       uint32 interface_index = 0;
+       int8 *newReq = NULL;
+       httpReq *req = &(SBData->req);
+       struct hostent *h = NULL;
+       struct sockaddr_in remote_addr;
+       struct sockaddr_in6 remote_addr_ip6;
+       httpResp httprsp;
+       connection *conn =  &(SBData->conn);
+       memset(&httprsp, 0, sizeof(httpResp));
+       interface_index = (fThread->interface_index);
+
+       SECURE_DB_INFO("Server IP Address [%s]", conn->ifaceInfo[SBData->interface_index].server_ip);
+       get_proxy_info(SBData, interface_index);
+       if(req->Rangeheader != NULL)
+       {
+               newReq = get_new_req(req->req_buff_wo_range, 0, chunkInfo[0], chunkInfo[1], &length, req->req_wo_len, conn->ifaceInfo[interface_index].proxyEnable);
+       }
+       else
+       {
+               newReq = get_new_req(req->req_buff, 0, chunkInfo[0], chunkInfo[1], &length, req->reqLen, conn->ifaceInfo[interface_index].proxyEnable);
+       }
+
+       SECURE_DB_INFO("HTTP New Req [%s]",newReq);
+
+       if(!SBData->conn.ifaceInfo[interface_index].proxyEnable)
+       {
+               getHost(&host, newReq);
+               if(NULL != host)
+               {
+                       SECURE_DB_INFO("DNS Resolution for Proxy Case Host [%s]", host);
+                       if(!getDNSInfo(host, interface_index, SBData))
+                       {
+                               TIZEN_LOGD("DNS Resolution Failed for Interface [%d]", interface_index);
+                               free(host);
+                               if(newReq != NULL)
+                                       free(newReq);
+                               return retval;
+                       }
+               }
+               else
+               {
+                       if(newReq != NULL)
+                               free(newReq);
+                       return retval;
+               }
+       }
+
+       while(*fThread->compRspRcvdFlag)
+       {
+               retval_watch_dog = 1;
+               memset(recv_buf, 0, MAX_HEADERS_SIZE + 1);
+
+               socket = conn_get_socket_bind(conn->ifaceInfo[interface_index].ip,interface_index,conn->ip_family);
+
+               if(socket < 0)
+               {
+                       if(NULL != host)
+                               free(host);
+                       if(newReq != NULL)
+                               free(newReq);
+                       return retval;
+               }
+
+               TIZEN_LOGD("File Thread Socket [%d]",socket);
+
+               redirect ++;
+
+               if(redirect > 3)
+               {
+                       TIZEN_LOGD("No Of Redirections Exceeded");
+                       CLOSE_SOCKET(socket);
+                       if(NULL != host)
+                               free(host);
+                       if(newReq != NULL)
+                               free(newReq);
+                       return retval;
+               }
+
+               h = gethostbyname(conn->ifaceInfo[interface_index].server_ip);
+
+               if(SBData->conn.ip_family)
+               {
+                       memset(&remote_addr_ip6, 0, sizeof(struct sockaddr_in6));
+                       remote_addr_ip6.sin6_family = h->h_addrtype;
+                       memcpy((char *) &remote_addr_ip6.sin6_addr.s6_addr, h->h_addr_list[0], h->h_length);
+                       remote_addr_ip6.sin6_port = htons(conn->port);
+               }
+               else
+               {
+                       memset(&remote_addr, 0, sizeof(struct sockaddr_in));
+                       remote_addr.sin_family = h->h_addrtype;
+                       memcpy((char *) &remote_addr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
+                       remote_addr.sin_port = htons(conn->port);
+               }
+
+               if(-1 == file_thread_connServer(socket, &remote_addr, &remote_addr_ip6, SBData->timeout, SBData))
+               {
+                       CLOSE_SOCKET(socket);
+                       if(NULL != host)
+                               free(host);
+                       if(newReq != NULL)
+                               free(newReq);
+                       return retval;
+               }
+
+               TIZEN_LOGD("Connect Success in File Thread");
+
+               if (-1 == send(socket, newReq, length, 0))
+               {
+                       TIZEN_LOGD("File Thread got Exception during send [%s]", strerror (errno));
+               }
+               else
+               {
+                       TIZEN_LOGD("Send HTTP Request Success in File Thread");
+                       memset(recv_buf, 0, MAX_HEADERS_SIZE + 1);
+                       while (*fThread->compRspRcvdFlag)
+                       {
+                               int32 len = 0;
+                               int32 offset = 0;
+                               int32 rcvdLen = 0;
+                               int32 headerLen = 0;
+
+                               if(file_thread_conn_poll(socket, SBData) <= 0)
+                               {
+                                       TIZEN_LOGD("Error !!! File Thread pollfd failed Timeout or Fail or Exit");
+                                       break;
+                               }
+
+                               rcvdLen = recv(socket, recv_buf + offset, MAX_HEADERS_SIZE - offset, 0);
+                               TIZEN_LOGD("Recvd length [%d]",rcvdLen);
+
+                               if (rcvdLen > 0)
+                               {
+                                       len = decode_http_find_str(recv_buf, END_OF_HEADERS);
+                                       if (-1 != len)
+                                       {
+                                               headerLen = len + 4;
+                                               TIZEN_LOGD("Header length [%d]", headerLen);
+                                               memset(&httprsp, 0, sizeof(httpResp));
+                                               decode_http_rsp_init(recv_buf, headerLen, &httprsp);
+                                               SECURE_DB_INFO("File Thread Response [%s]", httprsp.resp_buff);
+
+                                               retval = process_http_rsp(&httprsp);
+                                               if ((HTTP_RSP_REDIRECT  == retval) && (httprsp.location != NULL))
+                                               {
+                                                       TIZEN_LOGD("Redirection Happening and New Location [%s]", httprsp.location);
+
+                                                       if(handleRedirection(httprsp.location, interface_index, &newReq, &length, SBData) == HTTP_RSP_DECODING_SUCCESS)
+                                                       {
+                                                               retval_watch_dog = 0;
+                                                               CLOSE_SOCKET(socket);
+                                                               socket = -1;
+                                                               retval = -1;
+                                                               break;
+                                                       }
+                                                       else
+                                                       {
+                                                               retval = -1;
+                                                               break;
+                                                       }
+                                               }
+                                               else if(HTTP_RSP_DECODING_SUCCESS != retval)
+                                               {
+                                                       TIZEN_LOGD("HTTP Decoding Error");
+                                                       retval = -1;
+                                                       break;
+                                               }
+                                               retval = 0;
+                                               TIZEN_LOGD("HTTP Response in File Trhead is SUCCESS");
+                                               *lengthRcvd  = rcvdLen;
+                                               break;
+                                       }
+                                       offset = offset + rcvdLen;
+                                       if(offset >= MAX_HEADERS_SIZE)
+                                       {
+                                               retval = -1;
+                                               break;
+                                       }
+                               }
+                               else
+                               {
+                                       /* Socket error */
+                                       break;
+                               }
+                       }
+                       delete_http_rsp(&httprsp);
+                       if(retval_watch_dog == 1)
+                               break;
+               }
+       }
+
+       TIZEN_LOGD("RETURN VALUE [%d]",retval);
+
+       if(retval == -1)
+       {
+               if(socket > 0)
+               {
+                       CLOSE_SOCKET(socket);
+                       socket = -1;
+               }
+               if(NULL != host)
+                       free(host);
+               if(newReq != NULL)
+                       free(newReq);
+               return retval;
+       }
+       if((store_interface_ip_request(newReq, SBData, interface_index) == 0))
+       {
+               SBData->watch_dog_complete = 1;
+       }
+       if(NULL != host)
+               free(host);
+       if(newReq != NULL)
+               free(newReq);
+       return socket;
+}
+
+int32 watchdog_test_connection_type(SmartBondingData *SBData)
+{
+       int8 *host = NULL;
+       int32 socket = -1;
+       int32 retval = 0;
+       int32 connType = 0;
+       uint32 redirect = 0;
+       uint32 length = 0;
+       uint32 retval_dns = 0;
+       uint32 retval_watch_dog = 1;
+       uint32 timeT2 = 0;
+       uint32 resp_len  = 0;
+       uint32 resp_offset = 0;
+       uint32 interface_index = 0;
+       uint64 endTime = 0;
+       uint64 startTime = 0;
+       uint64 contLength = 0;
+       int8 recv_buf[MAX_HEADERS_SIZE + 1] = {0};
+       int8 *newReq = NULL;
+       httpReq *req = &(SBData->req);
+       struct hostent *h = NULL;
+       struct sockaddr_in remote_addr;
+       struct sockaddr_in6 remote_addr_ip6;
+       httpResp httprsp;
+       connection *conn =  &SBData->conn;
+       startTime = get_time_in_microsec();
+       memset(&httprsp, 0, sizeof(httpResp));
+       TIZEN_LOGD("WatchDog test");
+       interface_index = (SBData->interface_index + 1) % 2;
+       if(req->Rangeheader != NULL)
+       {
+               newReq = get_new_req(req->req_buff_wo_range, 0, 0, 1, &length, req->req_wo_len, conn->ifaceInfo[interface_index].proxyEnable);
+       }
+       else
+       {
+               newReq = get_new_req(req->req_buff, 0, 0, 1, &length, req->reqLen, conn->ifaceInfo[interface_index].proxyEnable);
+       }
+       TIZEN_LOGD("UID [%d]", getuid());
+       memcpy(conn->ifaceInfo[SBData->interface_index].server_ip, conn->ip_addr, strlen(conn->ip_addr));
+       memcpy(conn->ifaceInfo[interface_index].server_ip, conn->ip_addr, strlen(conn->ip_addr));
+
+       SECURE_DB_INFO("Server IP Address [%s]", conn->ifaceInfo[SBData->interface_index].server_ip);
+
+       SECURE_DB_INFO("HTTP New Req [%s]",newReq);
+       getHost(&host, newReq);
+       if(NULL != host)
+       {
+               SECURE_DB_INFO("DNS Resolution for Proxy Case Host [%s]", host);
+               retval_dns = getDNSInfo(host, interface_index, SBData);
+               free(host);
+       }
+       if(0 == retval_dns)
+       {
+               TIZEN_LOGD("DNS Resolution Failed for Interface [%d]", interface_index);
+               free(newReq);
+               return -1;
+       }
+       while(SBData->cthread->threadStatus != THREAD_FINISH)
+       {
+               retval_watch_dog = 1;
+
+               socket = conn_get_socket_bind(conn->ifaceInfo[interface_index].ip,interface_index,conn->ip_family);
+
+               if(socket < 0)
+               {
+                       free(newReq);
+                       return -1;
+               }
+
+               TIZEN_LOGD("WatchDog Socket [%d]",socket);
+
+               redirect ++;
+               if(redirect > 3)
+               {
+                       TIZEN_LOGD("No Of Redirections Exceeded");
+                       CLOSE_SOCKET(socket);
+                       return -1;
+               }
+
+               h = gethostbyname(conn->ifaceInfo[interface_index].server_ip);
+
+               if(SBData->conn.ip_family)
+               {
+
+                       memset(&remote_addr_ip6, 0, sizeof(struct sockaddr_in6));
+                       remote_addr_ip6.sin6_family = h->h_addrtype;
+                       memcpy((char *) &remote_addr_ip6.sin6_addr.s6_addr, h->h_addr_list[0], h->h_length);
+                       remote_addr_ip6.sin6_port = htons(conn->port);
+               }
+               else
+               {
+                       memset(&remote_addr, 0, sizeof(struct sockaddr_in));
+                       remote_addr.sin_family = h->h_addrtype;
+                       memcpy((char *) &remote_addr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
+                       remote_addr.sin_port = htons(conn->port);
+               }
+
+               if(-1 == connServer(socket, &remote_addr,&remote_addr_ip6,SBData->timeout, SBData))
+               {
+                       free(newReq);
+                       CLOSE_SOCKET(socket);
+                       return -1;
+               }
+
+               TIZEN_LOGD("Connect Success in Watchdog");
+
+               if (-1 == send(socket, newReq, length, 0))
+               {
+                       TIZEN_LOGD("Watch Dog Thread got Exception during send [%s]", strerror (errno));
+               }
+               else
+               {
+                       TIZEN_LOGD("Send HTTP Request Success in Watchdog");
+                       memset(recv_buf, 0, MAX_HEADERS_SIZE + 1);
+                       while (SBData->cthread->threadStatus != THREAD_FINISH)
+                       {
+
+                               int32 len = 0;
+                               int32 offset = 0;
+                               int32 rcvdLen = 0;
+                               int32 headerLen = 0;
+                               int retval = -1;
+
+                               if(watchdog_conn_poll(socket, SBData) <= 0)
+                               {
+                                       TIZEN_LOGD("Error !!! watchdog thread pollfd failed Timeout or Fail or Exit");
+                                       break;
+                               }
+
+                               rcvdLen = recv(socket, recv_buf + offset, MAX_HEADERS_SIZE - offset, 0);
+                               TIZEN_LOGD("Recvd lenght [%d]",rcvdLen);
+
+                               if (rcvdLen > 0)
+                               {
+                                       TIZEN_D_LOGD("Watch1 Dog Thread Response [%s]",recv_buf);
+                                       len = decode_http_find_str(recv_buf, END_OF_HEADERS);
+                                       if (-1 != len)
+                                       {
+
+                                               headerLen = len + 4;
+                                               TIZEN_LOGD("Watch Dog Thread Response [%s]",recv_buf);
+
+                                               memset(&httprsp, 0, sizeof(httpResp));
+
+                                               decode_http_rsp_init(recv_buf, headerLen, &httprsp);
+                                               retval = process_http_rsp(&httprsp);
+
+                                               if ((HTTP_RSP_REDIRECT  == retval) && (httprsp.location != NULL))
+                                               {
+                                                       TIZEN_LOGD("Redirection Happening and New Location [%s]", httprsp.location);
+
+                                                       if(handleRedirection(httprsp.location, interface_index, &newReq, &length, SBData) == HTTP_RSP_DECODING_SUCCESS)
+                                                       {
+                                                               retval_watch_dog = 0;
+                                                               CLOSE_SOCKET(socket);
+                                                               socket = -1;
+                                                               break;
+                                                       }
+                                                       else
+                                                       {
+                                                               break;
+                                                       }
+                                               }
+                                               else if(HTTP_RSP_DECODING_SUCCESS != retval)
+                                               {
+                                                       TIZEN_LOGD("HTTP Decoding Error");
+                                                       break;
+                                               }
+
+                                               TIZEN_LOGD("HTTP Response in Watch Dog is SUCCESS");
+                                               contLength = atol(httprsp.contLen);
+
+                                               if(httprsp.connection != NULL)
+                                                       connType = strncmp(httprsp.connection, "close", strlen("close"));
+
+                                               if(connType != 0)
+                                               {
+                                                       TIZEN_LOGD("Connection Type is Not CLOSE");
+                                                       connType = 1;
+                                               }
+                                               endTime = get_time_in_microsec();
+                                               timeT2 = (endTime-startTime)/1000;
+
+                                               resp_offset = offset + rcvdLen;
+                                               resp_len = len + 4;
+                                               TIZEN_LOGD("Response Lenght in Watch dog [%d] and Data Read till Now [%d]",resp_len, resp_offset);
+                                               break;
+                                       }
+                                       offset = offset + rcvdLen;
+                                       if(offset >= MAX_HEADERS_SIZE)
+                                               break;
+                               }
+                               else
+                               {
+                                       /* Socket error */
+                                       break;
+                               }
+                       }
+                       delete_http_rsp(&httprsp);
+                       if(retval_watch_dog == 1)
+                               break;
+               }
+       }
+       if(endTime == 0)
+       {
+               TIZEN_LOGD("End Time is Zero");
+               /* Error condtion abort multisocket(This interface is not stable) */
+               retval = -1;
+       }
+       else
+       {
+               /* Compair the time between two interfaces */
+               retval = check_speed(SBData, timeT2, resp_offset, resp_len, recv_buf, socket, contLength);
+
+               if(retval == 0)
+               {
+                       retval = connType;
+               }
+       }
+
+       CLOSE_SOCKET(socket);
+
+       if((store_interface_ip_request(newReq, SBData, interface_index) == 0))
+       {
+               SBData->watch_dog_complete = 1;
+       }
+
+       free(newReq);
+
+       TIZEN_LOGD("RETURN VALUE [%d]",retval);
+       return retval;
+}
+
+int32 check_speed(SmartBondingData *SBData, uint32 timeT2, uint32 resp_offset,
+                                                                               uint32 resp_len, int8 *recv_buf, int32 socket, uint64 contLength)
+{
+       int32 retval = 0;
+       StatDetails *stat = &(SBData->stat);
+
+       if(stat->timeT1 > (5 * timeT2))
+       {
+               /* Watch Dog Socket Becomes Main Socket */
+               TIZEN_LOGD("Interface 2 Much Faster Than Interaface 1");
+               //CLOSE_SOCKET(SBData->socket_fd);
+               //SBData->socket_fd = 0;
+               //retval = -1;
+       }
+       else if(timeT2 > (5 * stat->timeT1))
+       {
+               TIZEN_LOGD("IF 1 much faster than 2 abort \n");
+               /* Abort multi socket */
+               //retval = -1;
+       }
+       return retval;
+}
+
+int32 get_bytesof_range_request(uint64 *start, int8 *rangeHeader)
+{
+       int32 len = 0;
+       int8 *i1 = NULL;
+       int8 *i2 = NULL;
+       int8 *i3 = NULL;
+       int8 *i4 = NULL;
+       int8 temp1[100] = {0};
+
+       len = decode_http_find_str(rangeHeader, "bytes");
+       if (len != -1)
+       {
+               i1 = strchr(rangeHeader, '=');
+               i2 = strchr(rangeHeader, '-');
+               i3 = strrchr(rangeHeader, '-');
+               i4 = strchr(rangeHeader, ',');
+
+               if ((i1 == 0) || (i2 == 0) || ((i1+1) >= i2) || (i2 != i3) || (i4!=0))
+               {
+                       return B_FALSE;
+               }
+               else
+               {
+                       strncpy(temp1, rangeHeader + 6, ((i2 -i1)-1));
+                       *start = atol(temp1);
+                       return B_TRUE;
+               }
+       }
+       else
+       {
+               return B_FALSE;
+       }
+}
+
+int32 is_connection_header_keepalive(SmartBondingData *SBData)
+{
+       if (SBData->resp.connection != NULL)
+       {
+               if (strcmp(SBData->resp.connection, "Keep-Alive") == 0)
+                       return 1;
+       }
+       return 0;
+}
+
+CThread * cthread_init()
+{
+       CThread *cthread = malloc(sizeof(CThread));
+       if(cthread == NULL)
+       {
+               TIZEN_LOGD("Error !!! cthread allocation failed [%d] [%s]", errno, strerror(errno));
+               return NULL;
+       }
+       memset(cthread,0,sizeof(CThread));
+       cthread->threadId = 0;
+       return cthread;
+}
+
+void cthread_start_thread(SmartBondingData *SBData)
+{
+       int32 ECode = 0;
+       pthread_t thread = 0;
+       CThread *cthread = SBData->cthread;
+       TIZEN_D_LOGD("Starting Thread");
+       if ((ECode = pthread_create(&thread, NULL, cthread_entry_function, (void *)SBData)) != 0)
+       {
+               TIZEN_LOGD("Error !!! creating pthread [%d] [%s]", errno, strerror(errno));
+               cthread_exit(cthread);
+       }
+       else
+       {
+               TIZEN_D_LOGD("Init Watch Dog Thread ");
+               cthread->threadStatus = THREAD_INIT;
+               cthread->threadId = thread;
+       }
+}
+
+
+void * cthread_entry_function (void *pArg)
+{
+       if(pArg)
+       {
+               SmartBondingData *SBData = (SmartBondingData *)pArg;
+               if(SBData->twoChunk == 1)
+                       file_cthread_run_thread(SBData);
+               else
+                       cthread_run_thread(SBData);
+       }
+       else
+       {
+               cthread_exit((CThread *)pArg);
+       }
+       return 0;
+}
+
+int32 cthread_get_thread_status(CThread *cthread)
+{
+       return cthread->threadStatus;
+}
+
+void cthread_exit(CThread *cthread)
+{
+       TIZEN_LOGD("Cthread Exit\n");
+       if(cthread != NULL)
+       {
+               if(cthread->threadStatus == THREAD_INIT)
+                       usleep(100000);
+               cthread->threadStatus = THREAD_FINISH;
+               if(0 != cthread->threadId)
+                       pthread_join(cthread->threadId,NULL);
+               cthread->threadId = 0;
+               free(cthread);
+               cthread = NULL;
+       }
+}
+
+int32 get_req_without_range(int8 *oldReq, int8 *newReq, int8 *rangeHeader, uint64 *rangeStart)
+{
+       int32 len = 0;
+       int32 tempLen = 0;
+       int8 *temp = NULL;
+
+       if (get_bytesof_range_request(rangeStart, rangeHeader))
+       {
+               len = decode_http_find_str(oldReq, RANGELEN_REQ_HEADER_CMP1);
+               if(len == -1)
+                       len = decode_http_find_str(oldReq, RANGELEN_REQ_HEADER_CMP2);
+               tempLen = len;
+               memcpy(newReq, oldReq, len);
+               TIZEN_LOGD ("Before Range [%s] Range Header [%s]", newReq, rangeHeader);
+               temp = oldReq + len;
+               if(!(decode_http_find_str(temp, END_OF_LINE) == decode_http_find_str(temp, END_OF_HEADERS)))
+               {
+                       /*this will bring to point after Rnage header*/
+                       len = decode_http_find_str(temp, END_OF_LINE);
+                       temp = temp + len + 2;
+               }
+               else
+               {
+                       len = decode_http_find_str(temp, END_OF_HEADERS);
+                       temp = temp + len + 2;
+               }
+               memcpy(newReq + tempLen, temp, strlen(temp));
+               TIZEN_LOGD ("Successfully removed range header [%s]", newReq);
+               return strlen(newReq);
+       }
+       else
+       {
+               free(newReq);
+               newReq = NULL;
+               return 0;
+       }
+}
+
+
+#ifdef TIZEN_UX_SUPPORT
+static void _smart_bonding_start_cb(smbd_event_info_t event, void *user_data)
+{
+       TIZEN_LOGD("start bonding cb \n");
+       SmartBondingData *SBData = (SmartBondingData *)user_data;
+       switch (event.Event) {
+       case SMBD_EVENT_USER_OPTION_OK:
+               if(SBData != NULL)
+                       SBData->user_option = USER_OK;
+               break;
+       case SMBD_EVENT_USER_OPTION_CANCEL:
+               if(SBData != NULL)
+                       SBData->user_option = USER_CANCEL;
+               break;
+       default:
+               break;
+       }
+}
+
+int32 user_selection(SmartBondingData *SBData)
+{
+       int32 retval = B_FALSE;
+       int status = VCONFKEY_NETWORK_CELLULAR_NO_SERVICE;
+       CThread *cthread = SBData->cthread;
+       TIZEN_LOGD("Test For Tizen Ux Support");
+       if(!(smartbonding_client_init()))
+               return retval;
+
+       TIZEN_LOGD("INIT UX Library User Option");
+
+       while(SBData->response_check == 0 && cthread->threadStatus != THREAD_FINISH)
+       {
+               if(cthread->threadStatus != THREAD_FINISH)
+                       usleep(10000);
+               else
+                       return retval;
+       }
+
+       vconf_get_int(VCONFKEY_NETWORK_CELLULAR_STATE, &status);
+
+       TIZEN_LOGD("current LTE status [%d] and Expected LTE Status [%d]", status, VCONFKEY_NETWORK_CELLULAR_ON);
+
+       while(((status) != VCONFKEY_NETWORK_CELLULAR_ON) && (cthread->threadStatus != THREAD_FINISH))
+       {
+               TIZEN_D_LOGD("LTE Data pack Off");
+               usleep(100000);
+               status = VCONFKEY_NETWORK_CELLULAR_NO_SERVICE;
+               vconf_get_int(VCONFKEY_NETWORK_CELLULAR_STATE, &status);
+       }
+
+       TIZEN_LOGD("Data Pack On status [%d]", status);
+
+       if (smart_bonding_start(SBData->req.url, SBData->resp.cLen, _smart_bonding_start_cb, (void *)SBData) !=  SMBD_ERR_NONE)
+       {
+               TIZEN_LOGD("Start Bonding API failed");
+               return retval;
+       }
+
+       TIZEN_LOGD("Start Bonding API success");
+       SBData->user_option = USER_POP_UP;
+
+       while(SBData->user_option == USER_POP_UP && cthread->threadStatus != THREAD_FINISH)
+       {
+               if(cthread->threadStatus != THREAD_FINISH)
+                       usleep(10000);
+               else
+                       return retval;
+       }
+
+       if(SBData->user_option != USER_OK)
+       {
+               TIZEN_LOGD("User selected cancel");
+               return retval;
+       }
+
+       retval  = B_TRUE;
+       TIZEN_LOGD("User selected OK");
+       return retval;
+}
+#endif
+
+void file_cthread_run_thread(SmartBondingData *SBData)
+{
+       uint32 bIsUp = 0;
+       uint32 bFileStreamStarted = 0;
+       uint64 speed_time = get_time_in_sec();
+       connection *conn = &(SBData->conn);
+       CThread *cthread = SBData->cthread;
+       cthread->threadStatus = THREAD_RUNNING;
+       float ratio =  0; /* Ratio of Wifi/LTE speed */
+       uint32 wifiSpeed = 0;
+       uint32 lteSpeed = 0;
+       uint64 expected_bytes = 0;
+       FILE *fp = NULL;
+
+       if(SBData->interface_index == 1)
+       {
+               TIZEN_LOGD("Main Interface is LTE");
+               return;
+       }
+
+#ifdef TIZEN_UX_SUPPORT
+       if(!user_selection(SBData))
+               return;
+#endif
+
+       fp= fopen("/opt/usr/media/Ratiostat", "r");
+
+       if (fp != NULL)
+       {
+               int32 nitems = 0;
+               nitems = fscanf (fp, "%u %u",&lteSpeed,&wifiSpeed);
+               nitems = nitems;
+               TIZEN_LOGD("LTE SPEEED IS [%u] and WIFI SPEED IS [%u]",lteSpeed,wifiSpeed);
+               if( (lteSpeed != 0) && ( wifiSpeed != 0))
+               {
+                       ratio = (double)lteSpeed/(double)wifiSpeed;
+               }
+               TIZEN_LOGD("Ratio of Previous Download From History %f", ratio);
+       }
+       else
+       {
+               TIZEN_LOGD("Failed to Open History previous Download");
+       }
+
+       while ((cthread->threadStatus != THREAD_FINISH) && ((SBData->resp.cLen - SBData->response_body_read) > (MULTIRAT_LOWER_LIMIT_TWO_CHUNK * 2)))
+       {
+               if(ratio > 0)
+               {
+                       ratio = MAX(0.1, MIN(10,ratio));
+                       expected_bytes = ((SBData->resp.cLen - SBData->response_body_read)/(ratio + 1));
+               }
+               else
+                       expected_bytes  = (SBData->resp.cLen - SBData->response_body_read)/2;
+
+               expected_bytes += SBData->response_body_read;
+
+               bIsUp = is_both_interface_avail(conn->ifaceInfo,conn->ip_family);
+               if (bIsUp)
+               {
+                       SBData->expectedbytes  = expected_bytes;
+                       TIZEN_LOGD("Expected Bytes [%llu]", SBData->expectedbytes);
+
+                       file_stream_init(SBData);
+
+                       if((bFileStreamStarted = file_stream_start(SBData)))
+                       {
+                               SBData->fileThreadStarted = bFileStreamStarted;
+                               TIZEN_LOGD("File Stream Started [%d]",bFileStreamStarted);
+                               break;
+                       }
+               }
+               usleep(10000);
+       }
+
+       if(!(SBData->fileThreadStarted))
+               return;
+
+       while (cthread->threadStatus != THREAD_FINISH)
+       {
+               uint32 status = 0;
+
+               status = speed_calc_check_compare(&speed_time, SBData);
+
+               if(!status)
+                       break;
+
+               usleep(20000);
+       }
+
+       cthread->threadStatus = THREAD_FINISH;
+       return ;
+}
+
+void cthread_run_thread(SmartBondingData *SBData)
+{
+       uint32 bIsUp = 0;
+       uint32 chunk_div = 0;
+       uint32 min_chunk = 0;
+       uint32 max_chunk = 0;
+       uint32 bMultiSocketStarted = 0;
+       uint64 bytesForMultiSocket = 0;
+       int32 conn_type = 0;
+       connection *conn = &(SBData->conn);
+       MultiSockInput mSockInput;
+       CThread *cthread = SBData->cthread;
+       cthread->threadStatus = THREAD_RUNNING;
+       /* NOT USED FOR 2 chunk approach */
+
+       if(SBData->interface_index == 1)
+       {
+               TIZEN_LOGD("Main Interface is LTE");
+               return;
+       }
+
+#ifdef TIZEN_UX_SUPPORT
+       if(!user_selection(SBData))
+               return;
+#endif
+
+       bytesForMultiSocket = SBData->resp.cLen - SBData->response_body_read;
+
+       while ((cthread->threadStatus != THREAD_FINISH) && (bytesForMultiSocket > MULTIRAT_LOWER_LIMIT))
+       {
+               bIsUp = is_both_interface_avail(conn->ifaceInfo,conn->ip_family);
+               if (bIsUp)
+               {
+                       memset(&mSockInput, 0, sizeof(mSockInput));
+
+                       conn_type = watchdog_test_connection_type(SBData);
+                       if(conn_type == 1)
+                       {
+                               chunk_div = MULTIRAT_BLOCK_DIV;
+                               max_chunk = MAX_MULTIRAT_BLOCK_SIZE;
+                       }
+                       else if(conn_type == 0)
+                       {
+                               chunk_div = 2;
+                               max_chunk = MULTIRAT_CHUNK_SIZE;
+                       }
+                       else
+                       {
+                               TIZEN_LOGD("Aborting watch dog");
+                               break;
+                       }
+
+                       while(SBData->response_check == 0)
+                       {
+                               if(cthread->threadStatus != THREAD_FINISH)
+                                       usleep(10000);
+                               else
+                                       break;
+                       }
+
+                       min_chunk = MIN_MULTIRAT_BLOCK_SIZE;
+
+                       mSockInput.rspOffset = SBData->response_body_read + EXPECTED_BYTE;
+                       bytesForMultiSocket = SBData->resp.cLen - mSockInput.rspOffset;
+                       mSockInput.chunkSize = bytesForMultiSocket/chunk_div;
+                       mSockInput.conn = conn;
+
+                       if (mSockInput.chunkSize > max_chunk)
+                               mSockInput.chunkSize = max_chunk;
+                       else if (mSockInput.chunkSize < min_chunk)
+                               mSockInput.chunkSize =  min_chunk;
+
+
+                       if(bytesForMultiSocket > (mSockInput.chunkSize))
+                       {
+                               multirat_watchdogthread_calnochunks(mSockInput.chunkSize,
+                                               &mSockInput.noOfChunks, &mSockInput.lastChunk, bytesForMultiSocket);
+                       }
+                       else
+                       {
+                               TIZEN_LOGD("Size too small ignoring this content");
+                               break;
+                       }
+
+                       TIZEN_LOGD("No of Chunks = [%d],Chunk Size = [%d] bytesForMultiSocket = [%llu]",
+                                       mSockInput.noOfChunks, mSockInput.chunkSize, bytesForMultiSocket);
+
+                       multisocket_init(&mSockInput, SBData);
+                       if ((bMultiSocketStarted = multisocket_start(SBData)))
+                       {
+                               TIZEN_LOGD ("MultiSocket  started [%d]", bMultiSocketStarted);
+                               SBData->totalExpectedBytes = SBData->msocket->rspOffset;
+                               SBData->multiSocketThreadStarted = bMultiSocketStarted;
+                               break;
+                       }
+                       else
+                       {
+                               TIZEN_LOGD ("MultiSocket  failed");
+                               multisocket_exit(SBData->msocket);
+                               SBData->msocket = NULL;
+                               break;
+                       }
+               }
+               usleep(SLEEP_TIME);
+               if(SBData->response_check !=0)
+                       bytesForMultiSocket = SBData->resp.cLen - SBData->response_body_read;
+       }
+       cthread->threadStatus = THREAD_FINISH;
+       return ;
+}
+
+void multirat_watchdogthread_calnochunks(uint32 chunkSize, uint32 *noOfChunks, uint32 *lastChunk, uint64 totalSize)
+{
+       uint32 min = 0;
+       uint32 tempChunk = 0;
+       uint32 tempTotalChunks = 0;
+
+       TIZEN_LOGD("Multirat Watchdog Thread CalNoChunks");
+
+       tempChunk = (totalSize % chunkSize);
+       min = MIN((chunkSize/3), MIN_LAST_CHUNK);
+       if((0 != tempChunk) && (tempChunk < min))
+       {
+               tempTotalChunks = (totalSize/chunkSize);
+               tempChunk = chunkSize + tempChunk;
+               TIZEN_LOGD("Last Chunk Size Changed");
+       }
+       else
+       {
+               TIZEN_LOGD("Last Chunk Size not Chnaged");
+               if(0 == tempChunk)
+               {
+                       tempTotalChunks = (totalSize/chunkSize);
+               }
+               else
+               {
+                       tempTotalChunks = (totalSize/chunkSize) + 1;
+               }
+               tempChunk = 0;
+       }
+       *lastChunk = tempChunk;
+       *noOfChunks = tempTotalChunks;
+}
+
diff --git a/src/multirat_watchthread.c b/src/multirat_watchthread.c
new file mode 100644 (file)
index 0000000..fd4f1fa
--- /dev/null
@@ -0,0 +1,339 @@
+#include "multirat_SB_http.h"
+#include "multirat_watchthread.h"
+#include "multirat_process.h"
+#include "multirat_conf.h"
+#include "multirat_watch_dog_thread.h"
+#include "multirat_libapi.h"
+#include "multirat_file_manager.h"
+#include "smartbonding-client.h"
+
+#define MIN_TIME_TO_CHECK_STOP_SLOW  (6 * 1000 );
+#define MIN_TIME_TO_CHECK_STOP_SLOW_FOR_LOW_TH  (7 * 1000 )
+#define MIN_TIME_TO_CHECK_DATA_READ (2 * 1000 * 1000)
+#define MAX_TIME_TO_CHECK_DATA_READ (30 * 1000 * 1000)
+#define TIME_CHECK_SPEED ( 1 * 1000 * 1000)
+#define THRESHOLD_OF_SLOW_TH  (10 * 1024 * 1024 / 1000)
+#define OFFSET_TIME_TO_CHECK_STOP_SLOW  (3 * 1000)
+#define MIN_RATIO_FOR_ONLY_ONE_INF_0V1  (5)
+#define MIN_RATIO_FOR_ONLY_ONE_INF_1V0  (5)
+
+#define WLAN_INT 0
+#define LTE_INT 1
+
+void smart_bonding_init_speed(SmartBondingData *SBData)
+{
+       int i = 0;
+       int j = 0;
+       speedStat *sStat = &(SBData->sStat);
+       for(i = 0; i < MAX_INTERFACES; i++)
+       {
+               SBData->speed[i] = 0;
+               sStat->prev_recv_time[i] = 0;
+               sStat->slow_start_length[i] = 0;
+               sStat->slow_start_time[i] = 0;
+               sStat->recv_length[i] = 0;
+               sStat->start_recv_time[i] = 0;
+
+               /* Stores initial data to measure loss of bytes due to slowstart tcp phase */
+               sStat->timeArray[i] = 0;
+               for(j = 0; j<MAX_HISTORY; j++)
+               {
+                       sStat->dataArray[i][j] = 0;
+               }
+       }
+       TIZEN_LOGD("Init Success");
+}
+
+uint64  getSpeedWithOffset(int id, SmartBondingData *SBData)
+{
+       speedStat *sStat = &(SBData->sStat);
+       if((sStat->recv_length[id] == 0) || (sStat->slow_start_length[id] == 0))
+               return 0;
+       uint64 speed = 0;
+       uint64 data = (sStat->recv_length[id] - sStat->slow_start_length[id]);
+       uint64 time = ((sStat->prev_recv_time[id] - sStat->start_recv_time[id])/1000) - sStat->slow_start_time[id];
+       TIZEN_D_LOGD("Data [%llu] time [%llu]", data, time);
+       if(time <= 0 || data <= 0)
+       {
+               return 0;
+       }
+       else
+       {
+               speed = ((data/time)  * 8 * 1000);
+               TIZEN_D_LOGD("speed with offset [%llu]", speed);
+               return speed;
+       }
+}
+
+uint64  getSpeedWithoutOffset(int id, SmartBondingData *SBData)
+{
+       speedStat *sStat = &(SBData->sStat);
+       if((sStat->recv_length[id] == 0) || (sStat->slow_start_length[id] == 0))
+               return 0;
+       uint64 speed = 0;
+       uint64 data = (sStat->recv_length[id]);
+       uint64 time = ((sStat->prev_recv_time[id] - sStat->start_recv_time[id])/1000);
+       TIZEN_D_LOGD("Data [%llu] time [%llu]", data, time);
+       if(time <= 0 || data <= 0)
+       {
+               return 0;
+       }
+       else
+       {
+               speed = (((data)/time) * 8 * 1000);
+               TIZEN_D_LOGD("speed without offset [%llu]", speed);
+               return speed;
+       }
+}
+
+
+uint32 speed_calc_check_compare(uint64 *speed_time , SmartBondingData *SBData)
+{
+       uint64 current_time = (get_time_in_microsec());
+       uint64 difftime0 = 0;
+       uint64 difftime1 = 0;
+       speedStat *sStat = &(SBData->sStat);
+       uint32 id0 = SBData->interface_index;
+       uint32 id1 = (SBData->interface_index + 1) % 2;
+
+       if(sStat->start_recv_time[id0] != 0)
+               difftime0 = (current_time - sStat->start_recv_time[id0])/1000;
+
+       if(sStat->start_recv_time[id1] != 0)
+               difftime1 = (current_time - sStat->start_recv_time[id1])/1000;
+
+       if((current_time - *speed_time) < TIME_CHECK_SPEED)
+       {
+               usleep(20000);
+               return B_TRUE;
+       }
+
+       if((abs((get_time_in_microsec() - SBData->stat.read_start_time)) > (MIN_TIME_TO_CHECK_DATA_READ)) &&  (abs((get_time_in_microsec() - SBData->stat.read_start_time)) < (MAX_TIME_TO_CHECK_DATA_READ)))
+       {
+               SBData->read_state_check = MAIN_SOCK_READ_INACTIVE;
+               TIZEN_LOGD(" MAIN READ INACTIVE - >  FILE THREAD SUD STOP READ ");
+       }
+
+       else if((abs(get_time_in_microsec() - SBData->stat.read_start_time)) >= (MAX_TIME_TO_CHECK_DATA_READ))
+       {
+               TIZEN_LOGD("current time [%llu] read tme [%llu]", get_time_in_microsec(), SBData->stat.read_start_time);
+               TIZEN_LOGD("MAIN SOCK READ DOWN..   EXIT FILE THREAD");
+               SBData->fStream->compRspRcvdFlag = 0;
+               return B_FALSE;
+       }
+
+       TIZEN_D_LOGD("ID0 [%u] ID1 [%u]", id0, id1);
+       TIZEN_D_LOGD("start time [%llu] [%llu]", sStat->start_recv_time[id0], sStat->start_recv_time[id1]);
+       TIZEN_LOGD("Diff Times Zero [%llu] one [%llu] Recv length Zero [%llu] Receive length one [%llu]", difftime0, difftime1, sStat->recv_length[0], sStat->recv_length[1]);
+
+       sStat->start_speed_check_time = current_time;
+
+       *speed_time = (get_time_in_microsec());
+
+       if((sStat->slow_start_length[id0] == 0) &&  (difftime0 >= OFFSET_TIME_TO_CHECK_STOP_SLOW))
+       {
+               uint64 initSpeed0 = 0;
+               sStat->slow_start_length[id0] = sStat->recv_length[id0];
+               sStat->slow_start_time[id0] = difftime0;
+               initSpeed0 = sStat->slow_start_time[id0] == 0 ? 0 : (sStat->slow_start_length[id0] * 8 * 1000) / sStat->slow_start_time[id0];
+               if(initSpeed0 > THRESHOLD_OF_SLOW_TH)
+               {
+                       sStat->minTimeToCheckStopSlow[id0] = MIN_TIME_TO_CHECK_STOP_SLOW;
+               }
+               else
+               {
+                       sStat->minTimeToCheckStopSlow[id0] = MIN_TIME_TO_CHECK_STOP_SLOW_FOR_LOW_TH;
+               }
+               TIZEN_LOGD("Min Time [%llu] Slow Start for id0 [%d]", sStat->minTimeToCheckStopSlow[id0], id0);
+       }
+
+       if((SBData->sStat.slow_start_length[id1] == 0) &&  (difftime1 >= OFFSET_TIME_TO_CHECK_STOP_SLOW))
+       {
+               long initSpeed1 = 0;
+               sStat->slow_start_length[id1] = sStat->recv_length[id1];
+               sStat->slow_start_time[id1] = difftime1;
+               initSpeed1 = sStat->slow_start_time[id1] == 0 ? 0 : sStat->slow_start_length[id1] * 8 *1000 / sStat->slow_start_time[id1];
+               if(initSpeed1 > THRESHOLD_OF_SLOW_TH)
+               {
+                       sStat->minTimeToCheckStopSlow[id1] = MIN_TIME_TO_CHECK_STOP_SLOW;
+               }
+               else
+               {
+                       sStat->minTimeToCheckStopSlow[id1] = MIN_TIME_TO_CHECK_STOP_SLOW_FOR_LOW_TH;
+               }
+               TIZEN_LOGD("Min Time [%llu] Slow Start for id1 [%d]", sStat->minTimeToCheckStopSlow[id1], id1);
+       }
+
+       if((sStat->minTimeToCheckStopSlow[id0] > 0) && (difftime0 >= sStat->minTimeToCheckStopSlow[id0]))
+       {
+               uint64 sp0 = 0;
+               uint64 sp1 = 0;
+               uint64 spNoOffset1 = 0;
+               sp0 = getSpeedWithOffset(id0, SBData);
+               sp1 = getSpeedWithOffset(id1, SBData);
+               SBData->speed[id0] = sp0;
+               SBData->speed[id1] = sp1;
+               spNoOffset1 = getSpeedWithoutOffset(id1, SBData);
+
+               TIZEN_LOGD("Wifi Speed [%u] LTE Speed [%u] sp0 [%llu] sp1 [%llu]", SBData->speed[0], SBData->speed[1], sp0, sp1);
+               if((SBData->response_body_read < SBData->expectedbytes))
+               {
+                       if((sStat->minTimeToCheckStopSlow[id1] > 0) && (((difftime1 >= sStat->minTimeToCheckStopSlow[id1])
+                               && (sStat->slow_start_time[id1] != difftime1)
+                                       && (sp0 > MIN_RATIO_FOR_ONLY_ONE_INF_0V1 * sp1))
+                                               || ((spNoOffset1 <= 10) && (difftime1 >= sStat->minTimeToCheckStopSlow[id1]/ 2) && (sStat->recv_length[id1] > 0)
+                                                       && (SBData->sStat.slow_start_time[id1] != difftime1))))
+                       {
+                               SBData->enableMultiRat = 0;
+                               SBData->fStream->compRspRcvdFlag = 0;
+                               TIZEN_LOGD("Close The File Thread");
+                               if(id0 == WLAN_INT)
+                               {
+                                       TIZEN_LOGD("POP UP LTE SLOW");
+                                       smart_bonding_notify_interface_usage("download_booster_lte_slow");
+                               }
+                               else
+                               {
+                                       TIZEN_LOGD("POP UP WI-FI SLOW");
+                                       smart_bonding_notify_interface_usage("download_booster_wifi_slow");
+                               }
+                               return B_FALSE;
+                       }
+
+                       else if((sStat->minTimeToCheckStopSlow[id1] > 0) && (difftime1 >= sStat->minTimeToCheckStopSlow[id1]
+                                       && MIN_RATIO_FOR_ONLY_ONE_INF_1V0 >= 0 && sp1 > MIN_RATIO_FOR_ONLY_ONE_INF_1V0 * sp0 && sp0 > 0 && sp1 > 0))
+                       {
+                               SBData->file_status = NO_REDIVISION;
+                               TIZEN_LOGD("Close Main Socket and No Redivision in File");
+                               if(id0 == LTE_INT)
+                               {
+                                       TIZEN_LOGD("POP UP LTE SLOW");
+                                       smart_bonding_notify_interface_usage("download_booster_lte_slow");
+                               }
+                               else
+                               {
+                                       TIZEN_LOGD("POP UP WI-FI SLOW");
+                                       smart_bonding_notify_interface_usage("download_booster_wifi_slow");
+                               }
+                               CLOSE_SOCKET(SBData->socket_fd);
+                               return B_FALSE;
+                       }
+               }
+       }
+       TIZEN_D_LOGD("Curr time [%llu] Interface 0 time [%llu] Interface 1 time [%llu]", current_time, SBData->sStat.prev_recv_time[0], SBData->sStat.prev_recv_time[1]);
+       return B_TRUE;
+}
+
+void sb_calc_speed(SmartBondingData *SBData)
+{
+       uint64 diffTime = 0;
+       uint64 currTime = get_time_in_microsec();
+       StatDetails *stat = &(SBData->stat);
+
+       if(stat->dataOffsetTime != 0)
+       diffTime = (currTime - stat->dataOffsetTime)/ 1000;
+
+       if(diffTime > 50)
+       {
+               if(stat->speedIndex == 100)
+               {
+                       stat->speedIndex = 0;
+               }
+               stat->dataArr[stat->speedIndex] = stat->offsetForSpeed - stat->dataOffset;
+               stat->timeArr[stat->speedIndex] = diffTime;
+               stat->dataOffset = stat->offsetForSpeed;
+               stat->dataOffsetTime = currTime;
+               stat->speedIndex++;
+               if((stat->dataStrtTime != 0) && (currTime - stat->dataStrtTime) > 5000000)
+               {
+                       stat->mainSockSpeed = getAggSpeed(stat->dataArr,stat->timeArr);
+                       TIZEN_D_LOGD("Main socket Speed [%d]",stat->mainSockSpeed);
+               }
+       }
+}
+
+uint32 getAggSpeed(uint32 *dataArr,uint64 *timeArr)
+{
+       uint32 i = 0;
+       uint32 aggData = 0;
+       uint64 aggTime = 0;
+
+       for(i = 0; i < 100; i++)
+       {
+               aggData = aggData + dataArr[i];
+               aggTime = aggTime + timeArr[i];
+       }
+       return (uint32)((aggData * 8)/aggTime);
+}
+
+curlThread* curlThread_init()
+{
+       curlThread *curlThrd = malloc(sizeof(curlThread));
+       if(curlThrd == NULL)
+       {
+               TIZEN_LOGD("Error !!! curl thread allocation failed [%d] [%s]", errno, strerror(errno));
+               return NULL;
+       }
+       memset(curlThrd,0,sizeof(curlThread));
+       curlThrd->threadId = 0;
+       return curlThrd;
+}
+
+void curlThread_start(SmartBondingData *SBData)
+{
+       int32 ECode = 0;
+       pthread_t thread = 0;
+
+       if ((ECode = pthread_create(&thread, NULL, curlThread_entry_function,(void *)SBData)) != 0)
+       {
+               TIZEN_LOGD("SBData[%p] Error !!! creating pthread [%d] [%s]", SBData, errno, strerror(errno));
+               curlThread_exit(SBData->curlThrd);
+               SBData->curlThrd = NULL;
+       }
+       else
+       {
+               SBData->curlThrd->threadStatus = THREAD_INIT;
+               SBData->curlThrd->threadId = thread;
+       }
+}
+
+void *curlThread_entry_function(void *pArg)
+{
+       SmartBondingData *SBData = (SmartBondingData *)pArg;
+
+       if(SBData)
+       {
+               curlThread_run_thread(SBData);
+       }
+       return NULL;
+}
+
+void curlThread_exit(curlThread *curlThrd)
+{
+       TIZEN_LOGD("Curl Thread Exit");
+       if(curlThrd != NULL)
+       {
+               if(curlThrd->threadStatus == THREAD_INIT)
+                       usleep(100000);
+               curlThrd->threadStatus = THREAD_FINISH;
+               if(0 != curlThrd->threadId)
+                       pthread_join(curlThrd->threadId,NULL);
+               curlThrd->threadId = 0;
+               free(curlThrd);
+               curlThrd = NULL;
+       }
+}
+
+void curlThread_run_thread(SmartBondingData *SBData)
+{
+       int32 status = checkinterface_connect(SBData);
+       if(status == 0)
+       {
+               if(SBData->socket_fd > 0)
+               {
+                       CLOSE_SOCKET(SBData->socket_fd);
+                       SBData->socket_fd = -1;
+               }
+       }
+       SBData->curlThrd->threadStatus =  THREAD_FINISH;
+}