--- /dev/null
+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)
+
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+#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
--- /dev/null
+#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_ */
+
--- /dev/null
+#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
+
+
--- /dev/null
+#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
--- /dev/null
+#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
+
--- /dev/null
+#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_ */
+
--- /dev/null
+#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
+
--- /dev/null
+#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_ */
+
--- /dev/null
+#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_ */
--- /dev/null
+#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_ */
+
--- /dev/null
+#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
--- /dev/null
+#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_ */
+
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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_ */
+
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
--- /dev/null
+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
--- /dev/null
+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
+
--- /dev/null
+#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);
+}
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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));
+}
+
+
--- /dev/null
+#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;
+ }
+}
+
--- /dev/null
+#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;
+ }
+}
+
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+#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);
+}
+
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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",<eSpeed,&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;
+}
+
--- /dev/null
+#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;
+}