示例#1
0
文件: server.c 项目: luetzel/bluez
int server_unregister(struct btd_adapter *adapter, uint16_t id)
{
	struct network_adapter *na;
	struct network_server *ns;

	na = find_adapter(adapters, adapter);
	if (!na)
		return -EINVAL;

	ns = find_server(na->servers, id);
	if (!ns)
		return -EINVAL;

	na->servers = g_slist_remove(na->servers, ns);
	server_free(ns);

	if (g_slist_length(na->servers) > 0)
		return 0;

	g_dbus_unregister_interface(btd_get_dbus_connection(),
						adapter_get_path(adapter),
						NETWORK_SERVER_INTERFACE);

	return 0;
}
示例#2
0
int proxy_register(DBusConnection *conn, struct btd_adapter *btd_adapter)
{
    struct serial_adapter *adapter;
    const char *path;

    adapter = find_adapter(adapters, btd_adapter);
    if (adapter)
        return -EINVAL;

    adapter = g_new0(struct serial_adapter, 1);
    adapter->conn = dbus_connection_ref(conn);
    adapter->btd_adapter = btd_adapter_ref(btd_adapter);

    path = adapter_get_path(btd_adapter);

    if (!g_dbus_register_interface(conn, path,
                                   SERIAL_MANAGER_INTERFACE,
                                   manager_methods, manager_signals, NULL,
                                   adapter, manager_path_unregister)) {
        error("Failed to register %s interface to %s",
              SERIAL_MANAGER_INTERFACE, path);
        return -1;
    }

    register_stored(adapter);

    adapters = g_slist_append(adapters, adapter);

    debug("Registered interface %s on path %s",
          SERIAL_MANAGER_INTERFACE, path);

    return 0;
}
示例#3
0
static bool endpoint_properties_get(const char *uuid,
						struct btd_device *dev,
						DBusMessageIter *iter,
						void *user_data)
{
	struct media_adapter *adapter;
	DBusMessageIter dict;
	GSList *l;

	adapter = find_adapter(dev);
	if (adapter == NULL)
		return false;

	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
					DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
					DBUS_TYPE_STRING_AS_STRING
					DBUS_TYPE_VARIANT_AS_STRING
					DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
					&dict);

	for (l = adapter->endpoints; l; l = l->next) {
		struct media_endpoint *endpoint = l->data;

		if (strcasecmp(endpoint->uuid, uuid) != 0)
			continue;

		append_endpoint(endpoint, &dict);
	}

	dbus_message_iter_close_container(iter, &dict);

	return true;
}
示例#4
0
void proxy_unregister(struct btd_adapter *btd_adapter)
{
    struct serial_adapter *adapter;

    adapter = find_adapter(adapters, btd_adapter);
    if (!adapter)
        return;

    g_dbus_unregister_interface(adapter->conn,
                                adapter_get_path(btd_adapter),
                                SERIAL_MANAGER_INTERFACE);
}
示例#5
0
static void media_server_remove(struct btd_adapter *adapter)
{
	struct audio_adapter *adp;
	const gchar *path = adapter_get_path(adapter);

	DBG("path %s", path);

	adp = find_adapter(adapters, adapter);
	if (!adp)
		return;

	media_unregister(path);
	audio_adapter_unref(adp);
}
示例#6
0
文件: server.c 项目: luetzel/bluez
int server_register(struct btd_adapter *adapter, uint16_t id)
{
	struct network_adapter *na;
	struct network_server *ns;
	const char *path;

	na = find_adapter(adapters, adapter);
	if (!na) {
		na = create_adapter(adapter);
		if (!na)
			return -EINVAL;
		adapters = g_slist_append(adapters, na);
	}

	ns = find_server(na->servers, id);
	if (ns)
		return 0;

	ns = g_new0(struct network_server, 1);

	ns->name = g_strdup("Network service");

	path = adapter_get_path(adapter);

	if (g_slist_length(na->servers) > 0)
		goto done;

	if (!g_dbus_register_interface(btd_get_dbus_connection(), path,
						NETWORK_SERVER_INTERFACE,
						server_methods, NULL, NULL, na,
						path_unregister)) {
		error("D-Bus failed to register %s interface",
						NETWORK_SERVER_INTERFACE);
		server_free(ns);
		return -1;
	}

	DBG("Registered interface %s on path %s", NETWORK_SERVER_INTERFACE,
									path);

done:
	bacpy(&ns->src, btd_adapter_get_address(adapter));
	ns->id = id;
	ns->na = na;
	ns->record_id = 0;
	na->servers = g_slist_append(na->servers, ns);

	return 0;
}
示例#7
0
static bool endpoint_properties_exists(const char *uuid,
						struct btd_device *dev,
						void *user_data)
{
	struct media_adapter *adapter;

	adapter = find_adapter(dev);
	if (adapter == NULL)
		return false;

	if (media_adapter_find_endpoint(adapter, NULL, NULL, uuid) == NULL)
		return false;

	return true;
}
示例#8
0
static struct audio_adapter *audio_adapter_get(struct btd_adapter *adapter)
{
	struct audio_adapter *adp;

	adp = find_adapter(adapters, adapter);
	if (!adp) {
		adp = audio_adapter_create(adapter);
		if (!adp)
			return NULL;
		adapters = g_slist_append(adapters, adp);
	} else
		audio_adapter_ref(adp);

	return adp;
}
示例#9
0
static void a2dp_server_remove(struct btd_adapter *adapter)
{
	struct audio_adapter *adp;
	const gchar *path = adapter_get_path(adapter);
	bdaddr_t src;

	DBG("path %s", path);

	adp = find_adapter(adapters, adapter);
	if (!adp)
		return;

	adapter_get_address(adapter, &src);
	a2dp_unregister(&src);
	audio_adapter_unref(adp);
}
示例#10
0
文件: server.c 项目: sancane/BlueZ
int server_register(struct btd_adapter *adapter)
{
	struct network_adapter *na;
	struct network_server *ns;
	const char *path;

	na = find_adapter(adapters, adapter);
	if (!na) {
		na = create_adapter(adapter);
		if (!na)
			return -EINVAL;
		adapters = g_slist_append(adapters, na);
	}

	ns = find_server(na->servers, BNEP_SVC_NAP);
	if (ns)
		return 0;

	ns = g_new0(struct network_server, 1);

	ns->iface = g_strdup(NETWORK_SERVER_INTERFACE);
	ns->name = g_strdup("Network service");

	path = adapter_get_path(adapter);

	if (!g_dbus_register_interface(connection, path, ns->iface,
					server_methods, NULL, NULL,
					ns, path_unregister)) {
		error("D-Bus failed to register %s interface",
				ns->iface);
		server_free(ns);
		return -1;
	}

	adapter_get_address(adapter, &ns->src);
	ns->id = BNEP_SVC_NAP;
	ns->na = na;
	ns->record_id = 0;
	na->servers = g_slist_append(na->servers, ns);

	DBG("Registered interface %s on path %s", ns->iface, path);

	return 0;
}
示例#11
0
文件: server.c 项目: sancane/BlueZ
int server_unregister(struct btd_adapter *adapter)
{
	struct network_adapter *na;
	struct network_server *ns;
	uint16_t id = BNEP_SVC_NAP;

	na = find_adapter(adapters, adapter);
	if (!na)
		return -EINVAL;

	ns = find_server(na->servers, id);
	if (!ns)
		return -EINVAL;

	g_dbus_unregister_interface(connection, adapter_get_path(adapter),
					ns->iface);

	return 0;
}
示例#12
0
static void state_changed(struct btd_adapter *adapter, gboolean powered)
{
	struct audio_adapter *adp;
	static gboolean telephony = FALSE;
	GSList *l;

	DBG("%s powered %s", adapter_get_path(adapter),
						powered ? "on" : "off");

	/* ignore powered change, adapter is powering down */
	if (powered && adapter_powering_down(adapter))
		return;

	adp = find_adapter(adapters, adapter);
	if (!adp)
		return;

	adp->powered = powered;

	if (powered) {
		/* telephony driver already initialized*/
		if (telephony == TRUE)
			return;
		telephony_init();
		telephony = TRUE;
		return;
	}

	/* telephony not initialized just ignore power down */
	if (telephony == FALSE)
		return;

	for (l = adapters; l; l = l->next) {
		adp = l->data;

		if (adp->powered == TRUE)
			return;
	}

	telephony_exit();
	telephony = FALSE;
}
示例#13
0
static guint bluetooth_connect(const char *source, const char *destination,
				const char *service, uint16_t port,
				obc_transport_func func, void *user_data)
{
	struct bluetooth_session *session;
	static guint id = 0;

	DBG("");

	if (destination == NULL)
		return 0;

	session = g_try_malloc0(sizeof(*session));
	if (session == NULL)
		return 0;

	session->id = ++id;
	session->func = func;
	session->user_data = user_data;

	session->conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
	if (session->conn == NULL) {
		g_free(session);
		return 0;
	}

	session->service = g_strdup(service);
	str2ba(destination, &session->dst);

	if (find_adapter(session, source) < 0) {
		g_free(session);
		return 0;
	}

	sessions = g_slist_prepend(sessions, session);

	return session->id;
}
示例#14
0
static void gateway_server_remove(struct btd_adapter *adapter)
{
	struct audio_adapter *adp;
	const gchar *path = adapter_get_path(adapter);

	DBG("path %s", path);

	adp = find_adapter(adapters, adapter);
	if (!adp)
		return;

	if (adp->hfp_hs_record_id) {
		remove_record_from_server(adp->hfp_hs_record_id);
		adp->hfp_hs_record_id = 0;
	}

	if (adp->hfp_hs_server) {
		g_io_channel_unref(adp->hfp_hs_server);
		adp->hfp_hs_server = NULL;
	}

	audio_adapter_unref(adp);
}
示例#15
0
static void headset_server_remove(struct btd_adapter *adapter)
{
	struct audio_adapter *adp;
	const gchar *path = adapter_get_path(adapter);

	DBG("path %s", path);

	adp = find_adapter(adapters, adapter);
	if (!adp)
		return;

	if (adp->hsp_ag_record_id) {
		remove_record_from_server(adp->hsp_ag_record_id);
		adp->hsp_ag_record_id = 0;
	}

	if (adp->hsp_ag_server) {
		g_io_channel_shutdown(adp->hsp_ag_server, TRUE, NULL);
		g_io_channel_unref(adp->hsp_ag_server);
		adp->hsp_ag_server = NULL;
	}

	if (adp->hfp_ag_record_id) {
		remove_record_from_server(adp->hfp_ag_record_id);
		adp->hfp_ag_record_id = 0;
	}

	if (adp->hfp_ag_server) {
		g_io_channel_shutdown(adp->hfp_ag_server, TRUE, NULL);
		g_io_channel_unref(adp->hfp_ag_server);
		adp->hfp_ag_server = NULL;
	}

	btd_adapter_unregister_powered_callback(adapter, state_changed);

	audio_adapter_unref(adp);
}
示例#16
0
/**
 * Initialise WinPcap and return our MAC address.
 */
int pkt_eth_init (mac_address *mac_addr)
{
  struct {
    PACKET_OID_DATA oidData;
    char            descr[512];
  } oid;
  const ADAPTER *adapter = NULL;
  DWORD thread_id;
  BOOL  is_up;

  if (_watt_is_win9x)  /**< \todo Support Win-9x too */
  {
    (*_printf) (_LANG("Win-NT or later reqired.\n"));
    _pkt_errno = PDERR_GEN_FAIL;
    return (WERR_ILL_DOSX);
  }

  if (!_watt_no_config || _watt_user_config_fn)
     parse_config_pass_1();

  _pkt_inf = calloc (sizeof(*_pkt_inf), 1);
  if (!_pkt_inf)
  {
    (*_printf) (_LANG("Failed to allocate WinPcap DRIVER data.\n"));
    _pkt_errno = PDERR_GEN_FAIL;
    return (WERR_NO_MEM);
  }

  if (debug_on >= 2 && dump_fname[0])
     dump_file = fopen_excl (ExpandVarStr(dump_fname), "w+t");

  if (!PacketInitModule(TRUE, dump_file))
  {
    (*_printf) (_LANG("Failed to initialise WinPcap.\n"));
    pkt_release();
    _pkt_errno = PDERR_NO_DRIVER;
    return (WERR_PKT_ERROR);
  }

  if (!_pktdrvrname[0] &&
      !find_adapter(_pktdrvrname,sizeof(_pktdrvrname)))
  {
    (*_printf) (_LANG("No WinPcap driver found.\n"));
    _pkt_errno = PDERR_NO_DRIVER;
    return (WERR_NO_DRIVER);
  }

  TCP_CONSOLE_MSG (2, ("device %s\n", _pktdrvrname));

  adapter = PacketOpenAdapter (_pktdrvrname);
  if (!adapter)
  {
    if (debug_on > 0)
       (*_printf) (_LANG("PacketOpenAdapter (\"%s\") failed; %s\n"),
                   _pktdrvrname, win_strerror(GetLastError()));
    pkt_release();
    return (WERR_NO_DRIVER);
  }

  _pkt_inf->adapter = adapter;
#if defined(USE_DYN_PACKET)
  _pkt_inf->adapter_info = NULL;
#else
  _pkt_inf->adapter_info = PacketFindAdInfo (_pktdrvrname);
#endif

  /* Query the NIC driver for the adapter description
   */
  memset (&oid, 0, sizeof(oid));
  oid.oidData.Oid    = OID_GEN_VENDOR_DESCRIPTION;
  oid.oidData.Length = sizeof(oid.descr);

  if (PacketRequest (adapter, FALSE, &oid.oidData))
     StrLcpy (_pktdrvr_descr, (char*)oid.oidData.Data, sizeof(_pktdrvr_descr));
  else
  {
    (*_printf) (_LANG("PacketRequest() failed; %s\n"),
                win_strerror(GetLastError()));
    pkt_release();
    return (WERR_PKT_ERROR);
  }

  if (!get_interface_type(&_pktdevclass))
  {
    pkt_release();
    return (WERR_PKT_ERROR);
  }

  if (get_connected_status(&is_up) && !is_up)
     (*_printf) (_LANG("Warning: the adapter %s is down\n"), _pktdrvrname);

  switch (_pktdevclass)
  {
    case PDCLASS_TOKEN:
         _pkt_ip_ofs = sizeof(tok_Header);
         break;
    case PDCLASS_ETHER:
         _pkt_ip_ofs = sizeof(eth_Header);
         break;
    case PDCLASS_FDDI:
         _pkt_ip_ofs = sizeof(fddi_Header);
         break;
    case PDCLASS_ARCNET:
         _pkt_ip_ofs = ARC_HDRLEN;
         break;
    default:
         pkt_release();
         (*_printf) (_LANG("WinPcap-ERROR: Unsupported driver class %dh\n"),
                     _pktdevclass);
         _pkt_errno = PDERR_NO_CLASS;
         return (WERR_PKT_ERROR);
  }

  if (!pkt_get_addr(mac_addr))  /* get our MAC address */
  {
    pkt_release();
    return (WERR_PKT_ERROR);
  }

  pktq_init (&_pkt_inf->pkt_queue,
             sizeof(_pkt_inf->rx_buf[0]),   /* RX_SIZE */
             DIM(_pkt_inf->rx_buf),         /* RX_BUFS */
             (char*)&_pkt_inf->rx_buf);

  _pkt_inf->npf_buf_size = RX_SIZE * pkt_num_rx_bufs;
  _pkt_inf->npf_buf = malloc (_pkt_inf->npf_buf_size);
  if (!_pkt_inf->npf_buf)
  {
    (*_printf) (_LANG("Failed to allocate %d byte Rx buffer.\n"),
                _pkt_inf->npf_buf_size);
    pkt_release();
    _pkt_errno = PDERR_GEN_FAIL;
    return (WERR_NO_MEM);
  }

  PacketSetMode (adapter, PACKET_MODE_CAPT);
  PacketSetBuff (adapter, _pkt_inf->npf_buf_size);
  PacketSetMinToCopy (adapter, ETH_MIN);

  /* PacketReceivePacket() blocks until something is received
   */
  PacketSetReadTimeout ((ADAPTER*)adapter, 0);

  /* Set Rx-mode forced via config.
   */
  if (_pkt_forced_rxmode != -1)
  {
    _pkt_forced_rxmode &= 0xFFFF;     /* clear bits not set via ARG_ATOX_W */
    if (_pkt_forced_rxmode == 0 ||    /* check illegal bit-values */
        (_pkt_forced_rxmode & 0x10) ||
        (_pkt_forced_rxmode & 0x40) ||
        (_pkt_forced_rxmode > 0x80))
     {
       TCP_CONSOLE_MSG (0, ("Illegal Rx-mode (0x%02X) specified\n",
                        _pkt_forced_rxmode));
       _pkt_forced_rxmode = -1;
     }
  }

  if (pkt_get_rcv_mode())
     _pkt_rxmode0 = _pkt_rxmode;

  if (_pkt_forced_rxmode != -1)
       pkt_set_rcv_mode (_pkt_forced_rxmode);
  else pkt_set_rcv_mode (RXMODE_DEFAULT);

#if 1
  _pkt_inf->recv_thread = CreateThread (NULL, 2048, pkt_recv_thread,
                                        NULL, 0, &thread_id);
#else
  _pkt_inf->recv_thread = _beginthreadex (NULL, 2048, pkt_recv_thread,
                                          NULL, 0, &thread_id);
#endif

  if (!_pkt_inf->recv_thread)
  {
    (*_printf) (_LANG("Failed to create receiver thread; %s\n"),
                win_strerror(GetLastError()));
    pkt_release();
    _pkt_errno = PDERR_GEN_FAIL;
    return (WERR_PKT_ERROR);
  }

  if (thr_realtime)
     SetThreadPriority (_pkt_inf->recv_thread,
                        THREAD_PRIORITY_TIME_CRITICAL);

  TCP_CONSOLE_MSG (2, ("capture thread-id %lu\n", thread_id));

#if defined(USE_DEBUG)
  if (debug_on >= 2)
  {
    (*_printf) ("link-details:\n");
    show_link_details();
  }
#endif
  return (0);
}
示例#17
0
int bt_input(int argc, char *argv[])
{
	GError *error = NULL;
	GOptionContext *context;

	/* Query current locale */
	setlocale(LC_CTYPE, "");

	g_type_init();
	dbus_init();

	context = g_option_context_new("- a bluetooth input manager");
	g_option_context_add_main_entries(context, entries, NULL);
	g_option_context_set_summary(context, "Version "PACKAGE_VERSION);
	g_option_context_set_description(context,
			//"Report bugs to <"PACKAGE_BUGREPORT">."
			"Project home page <"PACKAGE_URL">."
			);

	if (!g_option_context_parse(context, &argc, &argv, &error)) {
		g_print("%s: %s\n", g_get_prgname(), error->message);
		g_print("Try `%s --help` for more information.\n", g_get_prgname());
		exit(EXIT_FAILURE);
	} else if ((!connect_arg || strlen(connect_arg) == 0) && (!disconnect_arg || strlen(disconnect_arg) == 0)) {
		g_print("%s", g_option_context_get_help(context, FALSE, NULL));
		exit(EXIT_FAILURE);
	}

	g_option_context_free(context);

	if (!dbus_system_connect(&error)) {
		g_printerr("Couldn't connect to DBus system bus: %s\n", error->message);
		exit(EXIT_FAILURE);
	}

	/* Check, that bluetooth daemon is running */
	if (!intf_supported(BLUEZ_DBUS_NAME, MANAGER_DBUS_PATH, MANAGER_DBUS_INTERFACE)) {
		g_printerr("%s: bluez service is not found\n", g_get_prgname());
		g_printerr("Did you forget to run bluetoothd?\n");
		exit(EXIT_FAILURE);
	}

	Adapter *adapter = find_adapter(adapter_arg, &error);
	exit_if_error(error);

	Device *device = find_device(adapter, connect_arg != NULL ? connect_arg : disconnect_arg, &error);
	exit_if_error(error);

	if (!intf_supported(BLUEZ_DBUS_NAME, device_get_dbus_object_path(device), INPUT_DBUS_INTERFACE)) {
		g_printerr("Input service is not supported by this device\n");
		exit(EXIT_FAILURE);
	}

	GMainLoop *mainloop = g_main_loop_new(NULL, FALSE);

	Input *input = g_object_new(INPUT_TYPE, "DBusObjectPath", device_get_dbus_object_path(device), NULL);
	g_signal_connect(input, "PropertyChanged", G_CALLBACK(input_property_changed), mainloop);

	if (connect_arg) {
		if (input_get_connected(input) == TRUE) {
			g_print("Input service is already connected\n");
		} else {
			input_connect(input, &error);
			exit_if_error(error);
			g_main_loop_run(mainloop);
		}
	} else if (disconnect_arg) {
		if (input_get_connected(input) == FALSE) {
			g_print("Input service is already disconnected\n");
		} else {
			input_disconnect(input, &error);
			exit_if_error(error);
			g_main_loop_run(mainloop);
		}
	}

	g_main_loop_unref(mainloop);
	g_object_unref(input);
	g_object_unref(device);
	g_object_unref(adapter);
	dbus_disconnect();

	exit(EXIT_SUCCESS);
}
示例#18
0
int bt_obex(int argc, char *argv[])
{
	GError *error = NULL;
	GOptionContext *context;

	/* Query current locale */
	setlocale(LC_CTYPE, "");

	g_type_init();
	dbus_init();

	context = g_option_context_new(" - a bluetooth OBEX client/server");
	g_option_context_add_main_entries(context, entries, NULL);
	g_option_context_set_summary(context, "Version "PACKAGE_VERSION);
	g_option_context_set_description(context,
			"Server Options:\n"
			"  -s, --server [<path>]\n"
			"  Register self at OBEX server and use given `path` as OPP save directory\n"
			"  If `path` does not specified - use current directory\n\n"
			"OPP Options:\n"
			"  -p, --opp <name|mac> <file>\n"
			"  Send `file` to remote device using Object Push Profile\n\n"
			//"Report bugs to <"PACKAGE_BUGREPORT">."
			"Project home page <"PACKAGE_URL">."
			);

	if (!g_option_context_parse(context, &argc, &argv, &error)) {
		g_print("%s: %s\n", g_get_prgname(), error->message);
		g_print("Try `%s --help` for more information.\n", g_get_prgname());
		exit(EXIT_FAILURE);
	} else if (!server_arg && !opp_arg && (!ftp_arg || strlen(ftp_arg) == 0)) {
		g_print("%s", g_option_context_get_help(context, FALSE, NULL));
		exit(EXIT_FAILURE);
	} else if (server_arg && argc != 1 && (argc != 2 || strlen(argv[1]) == 0)) {
		g_print("%s: Invalid arguments for --server\n", g_get_prgname());
		g_print("Try `%s --help` for more information.\n", g_get_prgname());
		exit(EXIT_FAILURE);
	} else if (opp_arg && (argc != 3 || strlen(argv[1]) == 0 || strlen(argv[2]) == 0)) {
		g_print("%s: Invalid arguments for --opp\n", g_get_prgname());
		g_print("Try `%s --help` for more information.\n", g_get_prgname());
		exit(EXIT_FAILURE);
	}

	g_option_context_free(context);

	if (!dbus_system_connect(&error)) {
		g_printerr("Couldn't connect to DBus system bus: %s\n", error->message);
		exit(EXIT_FAILURE);
	}

	if (!dbus_session_connect(&error)) {
		g_printerr("Couldn't connect to DBus session bus: %s\n", error->message);
		exit(EXIT_FAILURE);
	}

	/* Check, that bluetooth daemon is running */
	if (!intf_supported(BLUEZ_DBUS_NAME, MANAGER_DBUS_PATH, MANAGER_DBUS_INTERFACE)) {
		g_printerr("%s: bluez service is not found\n", g_get_prgname());
		g_printerr("Did you forget to run bluetoothd?\n");
		exit(EXIT_FAILURE);
	}

	/* Check, that obexd daemon is running */
	if (!intf_supported(OBEXS_DBUS_NAME, OBEXMANAGER_DBUS_PATH, OBEXMANAGER_DBUS_INTERFACE)) {
		g_printerr("%s: obex service is not found\n", g_get_prgname());
		g_printerr("Did you forget to run obexd?\n");
		exit(EXIT_FAILURE);
	}

	if (server_arg) {
		if (argc == 2) {
			server_path_arg = argv[1];
		}

		/* Check that `path` is valid */
		gchar *root_folder = server_path_arg == NULL ? g_get_current_dir() : g_strdup(server_path_arg);
		if (!is_dir(root_folder, &error)) {
			exit_if_error(error);
		}

		server_transfers = g_hash_table_new(g_str_hash, g_str_equal);

		OBEXManager *manager = g_object_new(OBEXMANAGER_TYPE, NULL);
		g_signal_connect(manager, "SessionCreated", G_CALLBACK(obexmanager_session_created), NULL);
		g_signal_connect(manager, "SessionRemoved", G_CALLBACK(obexmanager_session_removed), NULL);
		g_signal_connect(manager, "TransferStarted", G_CALLBACK(obexmanager_transfer_started), NULL);
		g_signal_connect(manager, "TransferCompleted", G_CALLBACK(obexmanager_transfer_completed), NULL);

		OBEXAgent *agent = g_object_new(OBEXAGENT_TYPE, "RootFolder", root_folder, NULL);

		g_free(root_folder);

		obexmanager_register_agent(manager, OBEXAGENT_DBUS_PATH, &error);
		exit_if_error(error);

		mainloop = g_main_loop_new(NULL, FALSE);

		/* Add SIGTERM && SIGINT handlers */
		struct sigaction sa;
		memset(&sa, 0, sizeof(sa));
		sa.sa_handler = sigterm_handler;
		sigaction(SIGTERM, &sa, NULL);
		sigaction(SIGINT, &sa, NULL);

		g_main_loop_run(mainloop);

		/* Waiting for connections... */

		g_main_loop_unref(mainloop);

		/* Stop active transfers */
		GHashTableIter iter;
		gpointer key, value;
		g_hash_table_iter_init(&iter, server_transfers);
		while (g_hash_table_iter_next(&iter, &key, &value)) {
			OBEXTransfer *t = OBEXTRANSFER(value);
			obextransfer_cancel(t, NULL); // skip errors
			g_object_unref(t);
			g_hash_table_iter_remove(&iter);
		}
		g_hash_table_unref(server_transfers);

		obexmanager_unregister_agent(manager, OBEXAGENT_DBUS_PATH, &error);
		g_object_unref(agent);
		g_object_unref(manager);
	} else if (opp_arg) {
		opp_device_arg = argv[1];
		opp_file_arg = argv[2];

		/* Check that `file` is valid */
		if (!is_file(opp_file_arg, &error)) {
			exit_if_error(error);
		}

		gchar * files_to_send[] = {NULL, NULL};
		files_to_send[0] = g_path_is_absolute(opp_file_arg) ? g_strdup(opp_file_arg) : get_absolute_path(opp_file_arg);

		/* Get source address (address of adapter) */
		Adapter *adapter = find_adapter(adapter_arg, &error);
		exit_if_error(error);
		gchar *src_address = g_strdup(adapter_get_address(adapter));

		/* Get destination address (address of remote device) */
		gchar *dst_address = NULL;
		if (g_regex_match_simple("^\\x{2}:\\x{2}:\\x{2}:\\x{2}:\\x{2}:\\x{2}$", opp_device_arg, 0, 0)) {
			dst_address = g_strdup(opp_device_arg);
		} else {
			Device *device = find_device(adapter, opp_device_arg, &error);
			exit_if_error(error);
			dst_address = g_strdup(device_get_address(device));
			g_object_unref(device);
		}

		g_object_unref(adapter);

		/* Build arguments */
		GHashTable *device_dict = g_hash_table_new(g_str_hash, g_str_equal);
		GValue src_v = {0};
		GValue dst_v = {0};
		g_value_init(&src_v, G_TYPE_STRING);
		g_value_init(&dst_v, G_TYPE_STRING);
		g_value_set_string(&src_v, src_address);
		g_value_set_string(&dst_v, dst_address);
		g_hash_table_insert(device_dict, "Source", &src_v);
		g_hash_table_insert(device_dict, "Destination", &dst_v);

		mainloop = g_main_loop_new(NULL, FALSE);

		OBEXClient *client = g_object_new(OBEXCLIENT_TYPE, NULL);

		OBEXAgent *agent = g_object_new(OBEXAGENT_TYPE, NULL);
		g_signal_connect(agent, "AgentReleased", G_CALLBACK(agent_released), mainloop);

		/* Sending file(s) */
		obexclient_send_files(client, device_dict, files_to_send, OBEXAGENT_DBUS_PATH, &error);
		exit_if_error(error);

		/* Add SIGTERM && SIGINT handlers */
		struct sigaction sa;
		memset(&sa, 0, sizeof(sa));
		sa.sa_handler = sigterm_handler;
		sigaction(SIGTERM, &sa, NULL);
		sigaction(SIGINT, &sa, NULL);

		g_main_loop_run(mainloop);

		/* Sending files process here ?? */

		g_main_loop_unref(mainloop);

		g_object_unref(agent);
		g_object_unref(client);

		g_value_unset(&src_v);
		g_value_unset(&dst_v);
		g_hash_table_unref(device_dict);

		g_free(src_address);
		g_free(dst_address);
		g_free(files_to_send[0]);
		files_to_send[0] = NULL;
	} else if (ftp_arg) {
		/* Get source address (address of adapter) */
		Adapter *adapter = find_adapter(adapter_arg, &error);
		exit_if_error(error);
		gchar *src_address = g_strdup(adapter_get_address(adapter));

		/* Get destination address (address of remote device) */
		Device *device = find_device(adapter, ftp_arg, &error);
		exit_if_error(error);
		gchar *dst_address = g_strdup(device == NULL ? ftp_arg : device_get_address(device));

		g_object_unref(device);
		g_object_unref(adapter);

		/* Build arguments */
		GHashTable *device_dict = g_hash_table_new(g_str_hash, g_str_equal);
		GValue src_v = {0};
		GValue dst_v = {0};
		GValue target_v = {0};
		g_value_init(&src_v, G_TYPE_STRING);
		g_value_init(&dst_v, G_TYPE_STRING);
		g_value_init(&target_v, G_TYPE_STRING);
		g_value_set_string(&src_v, src_address);
		g_value_set_string(&dst_v, dst_address);
		g_value_set_string(&target_v, "FTP");
		g_hash_table_insert(device_dict, "Source", &src_v);
		g_hash_table_insert(device_dict, "Destination", &dst_v);
		g_hash_table_insert(device_dict, "Target", &target_v);

		OBEXClient *client = g_object_new(OBEXCLIENT_TYPE, NULL);
		OBEXAgent *agent = g_object_new(OBEXAGENT_TYPE, NULL);

		/* Create FTP session */
		gchar *session_path = obexclient_create_session(client, device_dict, &error);
		exit_if_error(error);

		OBEXClientFileTransfer *ftp_session = g_object_new(OBEXCLIENT_FILE_TRANSFER_TYPE, "DBusObjectPath", session_path, NULL);
		g_free(session_path);

		g_print("FTP session opened\n");

		while (TRUE) {
			gchar *cmd;
			/*
			cmd = readline("> ");
			if (cmd == NULL) {
				continue;
			} else {
				add_history(cmd);
			}
			*/
			gint f_argc;
			gchar **f_argv;
			/* Parsing command line */
			if (!g_shell_parse_argv(cmd, &f_argc, &f_argv, &error)) {
				g_print("%s\n", error->message);
				g_error_free(error);
				error = NULL;

				g_free(cmd);
				continue;
			}

			/* Execute commands */
			if (g_strcmp0(f_argv[0], "cd") == 0) {
				if (f_argc != 2 || strlen(f_argv[1]) == 0) {
					g_print("invalid arguments\n");
				} else {
					obexclient_file_transfer_change_folder(ftp_session, f_argv[1], &error);
					if (error) {
						g_print("%s\n", error->message);
						g_error_free(error);
						error = NULL;
					}
				}
			} else if (g_strcmp0(f_argv[0], "mkdir") == 0) {
				if (f_argc != 2 || strlen(f_argv[1]) == 0) {
					g_print("invalid arguments\n");
				} else {
					obexclient_file_transfer_create_folder(ftp_session, f_argv[1], &error);
					if (error) {
						g_print("%s\n", error->message);
						g_error_free(error);
						error = NULL;
					}
				}
			} else if (g_strcmp0(f_argv[0], "ls") == 0) {
				if (f_argc != 1) {
					g_print("invalid arguments\n");
				} else {
					GPtrArray *folders = obexclient_file_transfer_list_folder(ftp_session, &error);
					if (error) {
						g_print("%s\n", error->message);
						g_error_free(error);
						error = NULL;
					} else {
						for (int i = 0; i < folders->len; i++) {
							GHashTable *el = g_ptr_array_index(folders, i);
							g_print(
									"%s\t%llu\t%s\n",
									g_value_get_string(g_hash_table_lookup(el, "Type")),
									G_VALUE_HOLDS_UINT64(g_hash_table_lookup(el, "Size")) ?
									g_value_get_uint64(g_hash_table_lookup(el, "Size")) :
									0,
									g_value_get_string(g_hash_table_lookup(el, "Name"))
									);
						}
					}

					if (folders) g_ptr_array_unref(folders);

					/*obexclient_remove_session(client, obexclient_file_transfer_get_dbus_object_path(ftp_session), &error);
					exit_if_error(error);
					g_object_unref(ftp_session);
					session_path = obexclient_create_session(client, device_dict, &error);
					exit_if_error(error);
					ftp_session = g_object_new(OBEXCLIENT_FILE_TRANSFER_TYPE, "DBusObjectPath", session_path, NULL);
					g_free(session_path);*/

				}
			} else if (g_strcmp0(f_argv[0], "get") == 0) {
				if (f_argc != 3 || strlen(f_argv[1]) == 0 || strlen(f_argv[2]) == 0) {
					g_print("invalid arguments\n");
				} else {
					gchar *abs_dst_path = get_absolute_path(f_argv[2]);
					gchar *dir = g_path_get_dirname(abs_dst_path);
					if (!is_dir(dir, &error)) {
						g_print("%s\n", error->message);
						g_error_free(error);
						error = NULL;
					} else {
						obexclient_file_transfer_get_file(ftp_session, abs_dst_path, f_argv[1], &error);
						if (error) {
							g_print("%s\n", error->message);
							g_error_free(error);
							error = NULL;
						}
					}
					g_free(dir);
					g_free(abs_dst_path);
				}
			} else if (g_strcmp0(f_argv[0], "put") == 0) {
				if (f_argc != 3 || strlen(f_argv[1]) == 0 || strlen(f_argv[2]) == 0) {
					g_print("invalid arguments\n");
				} else {
					gchar *abs_src_path = get_absolute_path(f_argv[1]);
					if (!is_file(abs_src_path, &error)) {
						g_print("%s\n", error->message);
						g_error_free(error);
						error = NULL;
					} else {
						obexclient_file_transfer_put_file(ftp_session, abs_src_path, f_argv[2], &error);
						if (error) {
							g_print("%s\n", error->message);
							g_error_free(error);
							error = NULL;
						}
					}
					g_free(abs_src_path);
				}
			} else if (g_strcmp0(f_argv[0], "cp") == 0) {
				if (f_argc != 3 || strlen(f_argv[1]) == 0 || strlen(f_argv[2]) == 0) {
					g_print("invalid arguments\n");
				} else {
					obexclient_file_transfer_copy_file(ftp_session, f_argv[1], f_argv[2], &error);
					if (error) {
						g_print("%s\n", error->message);
						g_error_free(error);
						error = NULL;
					}
				}
			} else if (g_strcmp0(f_argv[0], "mv") == 0) {
				if (f_argc != 3 || strlen(f_argv[1]) == 0 || strlen(f_argv[2]) == 0) {
					g_print("invalid arguments\n");
				} else {
					obexclient_file_transfer_move_file(ftp_session, f_argv[1], f_argv[2], &error);
					if (error) {
						g_print("%s\n", error->message);
						g_error_free(error);
						error = NULL;
					}
				}
			} else if (g_strcmp0(f_argv[0], "rm") == 0) {
				if (f_argc != 2 || strlen(f_argv[1]) == 0) {
					g_print("invalid arguments\n");
				} else {
					obexclient_file_transfer_delete(ftp_session, f_argv[1], &error);
					if (error) {
						g_print("%s\n", error->message);
						g_error_free(error);
						error = NULL;
					}
				}
			} else if (g_strcmp0(f_argv[0], "help") == 0) {
				g_print(
						"help\t\t\tShow this message\n"
						"exit\t\t\tClose FTP session\n"
						"cd <folder>\t\tChange the current folder of the remote device\n"
						"mkdir <folder>\t\tCreate a new folder in the remote device\n"
						"ls\t\t\tList folder contents\n"
						"get <src> <dst>\t\tCopy the src file (from remote device) to the dst file (on local filesystem)\n"
						"put <src> <dst>\t\tCopy the src file (from local filesystem) to the dst file (on remote device)\n"
						"cp <src> <dst>\t\tCopy a file within the remote device from src file to dst file\n"
						"mv <src> <dst>\t\tMove a file within the remote device from src file to dst file\n"
						"rm <target>\t\tDeletes the specified file/folder\n"
						);
			} else if (g_strcmp0(f_argv[0], "exit") == 0 || g_strcmp0(f_argv[0], "quit") == 0) {
				obexclient_remove_session(client, obexclient_file_transfer_get_dbus_object_path(ftp_session), &error);
				exit_if_error(error);

				g_strfreev(f_argv);
				g_free(cmd);
				break;
			} else {
				g_print("invalid command\n");
			}

			g_strfreev(f_argv);
			g_free(cmd);
		}

		g_object_unref(agent);
		g_object_unref(client);
		g_object_unref(ftp_session);

		g_value_unset(&src_v);
		g_value_unset(&dst_v);
		g_value_unset(&target_v);
		g_hash_table_unref(device_dict);

		g_free(src_address);
		g_free(dst_address);
	}

	dbus_disconnect();

	exit(EXIT_SUCCESS);
}