#define SIGNAL_NAME_DHCP_STATUS "dhcp_status"
#define SIGNAL_MSG_NOT_AVAIL_INTERFACE "Interface is not available"
+#define SIGNAL_MSG_TIMEOUT "There is no connection for a while"
#define DNSMASQ_LEASES_FILE "/var/lib/misc/dnsmasq.leases"
#define IP_USB_SUBNET "192.168.129"
#define DNSMASQ_DBUS_INTERFACE "uk.org.thekelleys.dnsmasq"
-#define PROC_NET_DEV "/proc/net/dev"
-#define MAX_TRANSFER_CHECK_COUNT 180 /* 30 minutes */
+#define PROC_NET_DEV "/proc/net/dev"
+#define TETHERING_CONN_TIMEOUT (1200000) /* 20 Mins */
#define CHECK_NET_STATE_RETRY_COUNT 5
#define PSK_ITERATION_COUNT 4096
int _remove_station_info_all(mobile_ap_type_e type);
int _get_station_info(gconstpointer data, GCompareFunc func,
mobile_ap_station_info_t **si);
-int _get_station_count(int *count);
+int _get_station_count(gconstpointer data, GCompareFunc func, int *count);
int _station_info_foreach(GFunc func, void *user_data);
int _add_data_usage_rule(const char *src, const char *dest);
int _del_data_usage_rule(const char *src, const char *dest);
#ifndef __MOBILEAP_HANDLER_H__
#define __MOBILEAP_HANDLER_H__
-
void _register_vconf_cb(void *user_data);
void _unregister_vconf_cb(void *user_data);
+void _init_timeout_cb(mobile_ap_type_e type, void *user_data);
+void _start_timeout_cb(mobile_ap_type_e type);
+void _stop_timeout_cb(mobile_ap_type_e type);
+void _deinit_timeout_cb(mobile_ap_type_e type);
#endif
#include "mobileap_common.h"
#include "mobileap_agent.h"
+#include "mobileap_handler.h"
static pid_t dnsmasq_pid = 0;
static pid_t hostapd_pid = 0;
char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
char *pbuf = NULL;
gsize read = 0;
+ int n_station = 0;
#if !GLIB_CHECK_VERSION(2, 31, 0)
int ret = 0;
DBG("Disconnected station MAC : %s\n", pbuf);
_remove_station_info(pbuf, _slist_find_station_by_mac);
+ _get_station_count((gconstpointer)MOBILE_AP_TYPE_WIFI,
+ _slist_find_station_by_interface, &n_station);
+ if (n_station == 0)
+ _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
+
return TRUE;
} else {
DBG("Event is not handled\n");
#include "mobileap_agent.h"
#include "mobileap_common.h"
#include "mobileap_bluetooth.h"
+#include "mobileap_handler.h"
typedef struct {
bt_device_info_s *info;
__bt_remote_device_s *remote;
bt_device_info_s *info;
int ret;
+ int n_station = 0;
DBG("Remote address : %s, Interface : %s, %s\n",
remote_address, interface_name,
connected ? "Connected" : "Disconnected");
+
if (connected) {
ret = bt_adapter_get_bonded_device_info(remote_address, &info);
if (ret != BT_ERROR_NONE) {
}
} else {
_remove_station_info(remote_address, _slist_find_station_by_mac);
- if (__del_bt_remote(remote_address) == FALSE)
+ if (__del_bt_remote(remote_address) == FALSE) {
ERR("__del_bt_remote is failed\n");
+ }
+
+ _get_station_count((gconstpointer)MOBILE_AP_TYPE_BT,
+ _slist_find_station_by_interface, &n_station);
+ if (n_station == 0)
+ _start_timeout_cb(MOBILE_AP_TYPE_BT);
}
return;
_remove_station_info_all(MOBILE_AP_TYPE_BT);
__del_bt_remote_all();
+ _deinit_timeout_cb(MOBILE_AP_TYPE_BT);
_deinit_tethering(obj);
_mobileap_clear_state(MOBILE_AP_STATE_BT);
goto FAIL;
}
+ _init_timeout_cb(MOBILE_AP_TYPE_BT, (void *)obj);
+ _start_timeout_cb(MOBILE_AP_TYPE_BT);
+
_emit_mobileap_dbus_signal(obj, E_SIGNAL_BT_TETHER_ON, NULL);
dbus_g_method_return(context, MOBILE_AP_ENABLE_BT_TETHERING_CFM, ret);
return TRUE;
extern DBusConnection *mobileap_conn;
-static GSList *station_list = NULL;;
+static GSList *station_list = NULL;
gint _slist_find_station_by_interface(gconstpointer a, gconstpointer b)
{
return MOBILE_AP_ERROR_NONE;
}
-int _get_station_count(int *count)
+int _get_station_count(gconstpointer data, GCompareFunc func, int *count)
{
if (count == NULL) {
ERR("Invalid param\n");
return MOBILE_AP_ERROR_INVALID_PARAM;
}
- *count = g_slist_length(station_list);
+ GSList *l = station_list;
+ int _count = 0;
+
+ for (_count = 0; l != NULL; _count++, l = g_slist_next(l)) {
+ l = g_slist_find_custom(l, data, func);
+ if (l == NULL)
+ break;
+ }
+
+ *count = _count;
+ DBG("Station count : %d\n", *count);
return MOBILE_AP_ERROR_NONE;
}
#include "mobileap_wifi.h"
#include "mobileap_usb.h"
+typedef struct {
+ guint src_id;
+ GSourceFunc func;
+ void *user_data;
+} sp_timeout_handler_t;
+
+static gboolean __wifi_timeout_cb(gpointer user_data);
+static gboolean __bt_timeout_cb(gpointer user_data);
+
+static sp_timeout_handler_t sp_timeout_handler[MOBILE_AP_TYPE_MAX] = {
+ {0, __wifi_timeout_cb, NULL},
+ {0, NULL, NULL},
+ {0, __bt_timeout_cb, NULL}};
static void __handle_flight_mode_changed_cb(keynode_t *key, void *data)
{
return;
}
+static gboolean __wifi_timeout_cb(gpointer data)
+{
+ DBG("+\n");
+ if (data == NULL) {
+ ERR("data is NULL\n");
+ return FALSE;
+ }
+
+ MobileAPObject *obj = (MobileAPObject *)data;
+
+ if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI) == FALSE) {
+ ERR("There is no conn. via Wi-Fi tethernig. But nothing to do\n");
+ return FALSE;
+ }
+
+ _disable_wifi_tethering(obj);
+ _emit_mobileap_dbus_signal(obj,
+ E_SIGNAL_WIFI_TETHER_OFF, SIGNAL_MSG_TIMEOUT);
+
+ DBG("-\n");
+ return FALSE;
+}
+
+static gboolean __bt_timeout_cb(gpointer data)
+{
+ DBG("+\n");
+ if (data == NULL) {
+ ERR("data is NULL\n");
+ return FALSE;
+ }
+
+ MobileAPObject *obj = (MobileAPObject *)data;
+
+ if (_mobileap_is_enabled(MOBILE_AP_STATE_BT) == FALSE) {
+ ERR("There is no conn. via BT tethering. But nothing to do\n");
+ return FALSE;
+ }
+
+ _disable_bt_tethering(obj);
+ _emit_mobileap_dbus_signal(obj,
+ E_SIGNAL_BT_TETHER_OFF, SIGNAL_MSG_TIMEOUT);
+
+ DBG("-\n");
+ return FALSE;
+}
+
+void _init_timeout_cb(mobile_ap_type_e type, void *user_data)
+{
+ DBG("+\n");
+ if (sp_timeout_handler[type].func == NULL) {
+ DBG("Not supported timeout : type[%d]\n", type);
+ return;
+ }
+
+ if (user_data == NULL) {
+ ERR("Invalid param\n");
+ return;
+ }
+
+ if (sp_timeout_handler[type].src_id > 0) {
+ DBG("There is already registered timeout source\n");
+ g_source_remove(sp_timeout_handler[type].src_id);
+ sp_timeout_handler[type].src_id = 0;
+ }
+
+ sp_timeout_handler[type].user_data = user_data;
+
+ DBG("-\n");
+ return;
+}
+
+void _start_timeout_cb(mobile_ap_type_e type)
+{
+ DBG("+\n");
+ if (sp_timeout_handler[type].func == NULL) {
+ DBG("Not supported timeout : type[%d]\n", type);
+ return;
+ }
+
+ if (sp_timeout_handler[type].src_id > 0) {
+ ERR("It is not registered or stopped\n");
+ return;
+ }
+
+ sp_timeout_handler[type].src_id = g_timeout_add(TETHERING_CONN_TIMEOUT,
+ sp_timeout_handler[type].func,
+ sp_timeout_handler[type].user_data);
+
+ DBG("-\n");
+ return;
+}
+
+void _stop_timeout_cb(mobile_ap_type_e type)
+{
+ DBG("+\n");
+ if (sp_timeout_handler[type].func == NULL) {
+ DBG("Not supported timeout : type[%d]\n", type);
+ return;
+ }
+
+ if (sp_timeout_handler[type].src_id == 0) {
+ ERR("It is not started yet\n");
+ return;
+ }
+
+ g_source_remove(sp_timeout_handler[type].src_id);
+ sp_timeout_handler[type].src_id = 0;
+
+ DBG("-\n");
+ return;
+}
+
+void _deinit_timeout_cb(mobile_ap_type_e type) {
+ DBG("+\n");
+ if (sp_timeout_handler[type].func == NULL) {
+ DBG("Not supported timeout : type[%d]\n", type);
+ return;
+ }
+
+ if (sp_timeout_handler[type].src_id > 0) {
+ g_source_remove(sp_timeout_handler[type].src_id);
+ sp_timeout_handler[type].src_id = 0;
+ }
+
+ sp_timeout_handler[type].user_data = NULL;
+
+ DBG("-\n");
+ return;
+}
return TRUE;
}
-
-static void __reset_interface(MobileAPObject *obj)
-{
- obj->rx_bytes = 0;
- obj->tx_bytes = 0;
- obj->transfer_check_count = 0;
-}
-
-
-static gboolean __check_data_transfer_cb(gpointer data)
-{
- MobileAPObject *obj = (MobileAPObject *)data;
- GIOChannel *io = NULL;
- gchar *line = NULL;
-
- char *if_name = NULL;
- gchar iface[IF_BUF_LEN] = {0, };
- unsigned long long rx_bytes = 0;
- unsigned long long tx_bytes = 0;
-
- if (_mobileap_is_disabled()) {
- ERR("Nothing is to be done.\n");
- return TRUE;
- }
-
- if (_get_network_interface_name(&if_name) == FALSE)
- return TRUE;
-
- io = g_io_channel_new_file(PROC_NET_DEV, "r", NULL);
- if (!io) {
- ERR("g_io_channel_new_file failed\n");
- return TRUE;
- }
-
- while (g_io_channel_read_line(io, &line, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) {
-
- line = g_strdelimit(line, ":", ' ');
- sscanf(line, "%29s %19lld %*s %*s %*s %*s %*s %*s %*s %19lld %*s %*s %*s %*s %*s",
- iface, &rx_bytes, &tx_bytes);
-
- g_free(line);
-
- if (g_ascii_strcasecmp(iface, if_name) == 0) {
- break;
- }
- }
-
- g_io_channel_unref(io);
- free(if_name);
-
- /*DBG("rx:%lld tx:%lld\n", rx_bytes, tx_bytes);*/
- if (obj->rx_bytes < rx_bytes || obj->tx_bytes < tx_bytes) {
- obj->rx_bytes = rx_bytes;
- obj->tx_bytes = tx_bytes;
- obj->transfer_check_count = 0;
- } else {
- obj->transfer_check_count++;
-
- /* 30 minutes */
- if (obj->transfer_check_count == MAX_TRANSFER_CHECK_COUNT) {
- _emit_mobileap_dbus_signal(obj,
- E_SIGNAL_NO_DATA_TIMEOUT, NULL);
- __reset_interface(obj);
- _disable_wifi_tethering(obj);
- }
- }
-
- return TRUE;
-}
-
-
static DBusHandlerResult __dnsmasq_signal_filter(DBusConnection *conn,
DBusMessage *msg, void *user_data)
{
mobile_ap_type_e type = MOBILE_AP_TYPE_MAX;
MobileAPObject *obj = (MobileAPObject *)user_data;
mobile_ap_station_info_t *info = NULL;
+ int n_station = 0;
dbus_error_init(&error);
if (dbus_message_is_signal(msg, DNSMASQ_DBUS_INTERFACE,
return DBUS_HANDLER_RESULT_HANDLED;
}
+ _get_station_count((gconstpointer)type,
+ _slist_find_station_by_interface, &n_station);
+ if (n_station == 1)
+ _stop_timeout_cb(type);
+
_send_dbus_station_info("DhcpConnected", info);
return DBUS_HANDLER_RESULT_HANDLED;
_register_wifi_station_handler();
_register_vconf_cb((void *)mobileap_obj);
- /* check tx/rx every 10 seconds */
- g_timeout_add(10000, __check_data_transfer_cb, mobileap_obj);
-
dbus_error_init(&dbus_error);
dbus_bus_add_match(mobileap_conn, rule, &dbus_error);
if (dbus_error_is_set(&dbus_error)) {
#include "mobileap_agent.h"
#include "mobileap_common.h"
#include "mobileap_wifi.h"
+#include "mobileap_handler.h"
static int __generate_initial_passphrase(char *passphrase_buf);
static mobile_ap_error_code_e __get_hide_mode(int *hide_mode);
static gboolean __send_station_event_cb(gpointer data)
{
int sig = GPOINTER_TO_INT(data);
+ int n_station = 0;
mobile_ap_station_info_t *si = NULL;
if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
return FALSE;
}
_remove_station_info(si->mac, _slist_find_station_by_mac);
+
+ _get_station_count((gconstpointer)MOBILE_AP_TYPE_WIFI,
+ _slist_find_station_by_interface, &n_station);
+ if (n_station == 0)
+ _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
}
return FALSE;
return ret;
}
+ _deinit_timeout_cb(MOBILE_AP_TYPE_WIFI);
+
if (_remove_station_info_all(MOBILE_AP_TYPE_WIFI) !=
MOBILE_AP_ERROR_NONE) {
ERR("_remove_station_info_all is failed. Ignore it.\n");
goto FAIL;
}
+ _init_timeout_cb(MOBILE_AP_TYPE_WIFI, (void *)obj);
+ _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
+
_emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_ON, NULL);
dbus_g_method_return(context, MOBILE_AP_ENABLE_WIFI_TETHERING_CFM, ret);