Example #1
0
File: pbap.c Project: Sork007/obexd
static void pbap_free(void *data)
{
	struct pbap_data *pbap = data;

	obc_session_unref(pbap->session);
	g_free(pbap);
}
Example #2
0
static void map_free(void *data)
{
	struct map_data *map = data;

	obc_session_unref(map->session);
	g_free(map);
}
Example #3
0
static void connect_cb(GObex *obex, GError *err, GObexPacket *rsp,
							gpointer user_data)
{
	struct callback_data *callback = user_data;
	GError *gerr = NULL;
	uint8_t rsp_code;

	if (err != NULL) {
		error("connect_cb: %s", err->message);
		gerr = g_error_copy(err);
		goto done;
	}

	rsp_code = g_obex_packet_get_operation(rsp, NULL);
	if (rsp_code != G_OBEX_RSP_SUCCESS)
		gerr = g_error_new(OBEX_IO_ERROR, -EIO,
				"OBEX Connect failed with 0x%02x", rsp_code);

done:
	callback->func(callback->session, NULL, gerr, callback->data);
	if (gerr != NULL)
		g_error_free(gerr);
	obc_session_unref(callback->session);
	g_free(callback);
}
Example #4
0
static void obc_transfer_free(struct obc_transfer *transfer)
{
	struct obc_session *session = transfer->session;

	DBG("%p", transfer);

	if (transfer->xfer)
		g_obex_cancel_transfer(transfer->xfer);

	if (transfer->fd > 0)
		close(transfer->fd);

	obc_session_remove_transfer(session, transfer);

	obc_session_unref(session);

	if (transfer->params != NULL) {
		g_free(transfer->params->data);
		g_free(transfer->params);
	}

	if (transfer->conn)
		dbus_connection_unref(transfer->conn);

	g_free(transfer->callback);
	g_free(transfer->filename);
	g_free(transfer->name);
	g_free(transfer->type);
	g_free(transfer->path);
	g_free(transfer->buffer);
	g_free(transfer);
}
Example #5
0
static void adapter_reply(DBusPendingCall *call, void *user_data)
{
	DBusError err;
	DBusMessage *reply;
	struct callback_data *callback = user_data;
	struct obc_session *session = callback->session;
	struct pending_req *req = find_session_request(session, call);

	reply = dbus_pending_call_steal_reply(call);

	session->pending_calls = g_slist_remove(session->pending_calls, req);
	pending_req_finalize(req);

	dbus_error_init(&err);
	if (dbus_set_error_from_message(&err, reply)) {
		error("manager replied with an error: %s, %s",
				err.name, err.message);
		dbus_error_free(&err);

		goto failed;
	}

	if (session_connect(session, callback) < 0)
		goto failed;

	goto proceed;

failed:
	obc_session_unref(session);
	g_free(callback);

proceed:
	dbus_message_unref(reply);
}
Example #6
0
struct obc_session *obc_session_create(const char *source,
						const char *destination,
						const char *service,
						uint8_t channel,
						const char *owner,
						session_callback_t function,
						void *user_data)
{
	DBusConnection *conn;
	struct obc_session *session;
	struct obc_transport *transport;
	struct obc_driver *driver;

	if (destination == NULL)
		return NULL;

	session = session_find(source, destination, service, channel, owner);
	if (session != NULL)
		goto proceed;

	/* FIXME: Do proper transport lookup when the API supports it */
	transport = obc_transport_find("Bluetooth");
	if (transport == NULL)
		return NULL;

	driver = obc_driver_find(service);
	if (driver == NULL)
		return NULL;

	conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
	if (conn == NULL)
		return NULL;

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

	session->refcount = 1;
	session->transport = transport;
	session->driver = driver;
	session->conn = conn;
	session->source = g_strdup(source);
	session->destination = g_strdup(destination);
	session->channel = channel;
	session->queue = g_queue_new();

	if (owner)
		obc_session_set_owner(session, owner, owner_disconnected);

proceed:
	if (session_connect(session, function, user_data) < 0) {
		obc_session_unref(session);
		return NULL;
	}

	DBG("session %p transport %s driver %s", session,
			session->transport->name, session->driver->service);

	return session;
}
Example #7
0
static void session_process_queue(struct obc_session *session)
{
	struct pending_request *p;

	if (session->p != NULL)
		return;

	if (session->queue == NULL || g_queue_is_empty(session->queue))
		return;

	obc_session_ref(session);

	while ((p = g_queue_pop_head(session->queue))) {
		GError *gerr = NULL;

		DBG("Transfer(%p) started", p->transfer);

		if (obc_transfer_start(p->transfer, session->obex, &gerr)) {
			session->p = p;
			break;
		}

		if (p->func)
			p->func(session, p->transfer, gerr, p->data);

		g_clear_error(&gerr);

		pending_request_free(p);
	}

	obc_session_unref(session);
}
Example #8
0
static void session_process_queue(struct obc_session *session)
{
	struct pending_request *p;

	if (session->p != NULL)
		return;

	if (session->queue == NULL || g_queue_is_empty(session->queue))
		return;

	obc_session_ref(session);

	while ((p = g_queue_pop_head(session->queue))) {
		GError *gerr = NULL;

		if (p->process(p, &gerr) == 0)
			break;

		if (p->func)
			p->func(session, p->transfer, gerr, p->data);

		g_clear_error(&gerr);

		pending_request_free(p);
	}

	obc_session_unref(session);
}
Example #9
0
static void session_terminate_transfer(struct obc_session *session,
					struct obc_transfer *transfer,
					GError *gerr)
{
	struct pending_request *p = session->p;

	if (p == NULL || p->transfer != transfer) {
		GList *match;

		match = g_list_find_custom(session->queue->head, transfer,
						pending_transfer_cmptransfer);
		if (match == NULL)
			return;

		p = match->data;
		g_queue_delete_link(session->queue, match);
	} else
		session->p = NULL;

	obc_session_ref(session);

	if (p->func)
		p->func(session, p->transfer, gerr, p->data);

	pending_request_free(p);

	if (session->p == NULL)
		session_process_queue(session);

	obc_session_unref(session);
}
Example #10
0
static void callback_destroy(struct callback_data *callback, GError *err)
{
	struct obc_session *session = callback->session;

	callback->func(session, NULL, err, callback->data);
	g_free(callback);
	session->callback = NULL;
	obc_session_unref(session);
}
Example #11
0
static void transport_func(GIOChannel *io, GError *err, gpointer user_data)
{
    struct callback_data *callback = user_data;
    struct obc_session *session = callback->session;
    struct obc_driver *driver = session->driver;
    struct obc_transport *transport = session->transport;
    GObex *obex;
    GObexTransportType type;
    int tx_mtu = -1;
    int rx_mtu = -1;

    DBG("");

    if (err != NULL) {
        error("%s", err->message);
        goto done;
    }

    g_io_channel_set_close_on_unref(io, FALSE);

    if (transport->getpacketopt &&
            transport->getpacketopt(io, &tx_mtu, &rx_mtu) == 0)
        type = G_OBEX_TRANSPORT_PACKET;
    else
        type = G_OBEX_TRANSPORT_STREAM;

    obex = g_obex_new(io, type, tx_mtu, rx_mtu);
    if (obex == NULL)
        goto done;

    g_io_channel_set_close_on_unref(io, TRUE);

    if (driver->target != NULL)
        g_obex_connect(obex, connect_cb, callback, &err,
                       G_OBEX_HDR_TARGET, driver->target, driver->target_len,
                       G_OBEX_HDR_INVALID);
    else
        g_obex_connect(obex, connect_cb, callback, &err,
                       G_OBEX_HDR_INVALID);

    if (err != NULL) {
        error("%s", err->message);
        g_obex_unref(obex);
        goto done;
    }

    session->obex = obex;
    sessions = g_slist_prepend(sessions, session);

    g_obex_set_disconnect_function(obex, session_disconnected, session);

    return;
done:
    callback->func(callback->session, NULL, err, callback->data);
    obc_session_unref(callback->session);
    g_free(callback);
}
Example #12
0
static void unregister_session(void *data)
{
	struct obc_session *session = data;

	if (g_slist_find(sessions, session) == NULL)
		return;

	sessions = g_slist_remove(sessions, session);
	obc_session_unref(session);
}
Example #13
0
static void pending_request_free(struct pending_request *p)
{
	if (p->transfer)
		obc_transfer_unregister(p->transfer);

	if (p->session)
		obc_session_unref(p->session);

	g_free(p);
}
Example #14
0
static void map_free(void *data)
{
	struct map_data *map = data;

	set_notification_registration(map, false);

	obc_session_unref(map->session);
	g_hash_table_unref(map->messages);
	g_free(map);
}
Example #15
0
static int session_connect(struct obc_session *session,
				session_callback_t function, void *user_data)
{
	struct callback_data *callback;
	struct obc_transport *transport = session->transport;
	struct obc_driver *driver = session->driver;

	callback = g_try_malloc0(sizeof(*callback));
	if (callback == NULL)
		return -ENOMEM;

	callback->func = function;
	callback->data = user_data;
	callback->session = obc_session_ref(session);

	/* Connection completed */
	if (session->obex) {
		g_idle_add(connection_complete, callback);
		return 0;
	}

	/* Ongoing connection */
	if (session->id > 0) {
		obc_session_unref(callback->session);
		g_free(callback);
		return 0;
	}

	session->id = transport->connect(session->source, session->destination,
					driver->uuid, session->channel,
					transport_func, callback);
	if (session->id == 0) {
		obc_session_unref(callback->session);
		g_free(callback);
		return -EINVAL;
	}

	session->callback = callback;

	return 0;
}
Example #16
0
static gboolean connection_complete(gpointer data)
{
	struct callback_data *cb = data;

	cb->func(cb->session, NULL, NULL, cb->data);

	obc_session_unref(cb->session);

	g_free(cb);

	return FALSE;
}
Example #17
0
static gboolean service_callback(GIOChannel *io, GIOCondition cond,
							gpointer user_data)
{
	struct callback_data *callback = user_data;
	struct obc_session *session = callback->session;
	sdp_list_t *search, *attrid;
	uint32_t range = 0x0000ffff;
	GError *gerr = NULL;
	uuid_t uuid;

	if (cond & (G_IO_NVAL | G_IO_ERR))
		goto failed;

	if (sdp_set_notify(callback->sdp, search_callback, callback) < 0)
		goto failed;

	if (bt_string2uuid(&uuid, session->driver->uuid) < 0)
		goto failed;

	search = sdp_list_append(NULL, &uuid);
	attrid = sdp_list_append(NULL, &range);

	if (sdp_service_search_attr_async(callback->sdp,
				search, SDP_ATTR_REQ_RANGE, attrid) < 0) {
		sdp_list_free(attrid, NULL);
		sdp_list_free(search, NULL);
		goto failed;
	}

	sdp_list_free(attrid, NULL);
	sdp_list_free(search, NULL);

	g_io_add_watch(io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
						process_callback, callback);

	return FALSE;

failed:
	g_io_channel_shutdown(session->io, TRUE, NULL);
	g_io_channel_unref(session->io);
	session->io = NULL;

	g_set_error(&gerr, OBEX_IO_ERROR, -EIO,
					"Unable to find service record");
	callback->func(callback->session, gerr, callback->data);
	g_clear_error(&gerr);

	obc_session_unref(callback->session);
	g_free(callback);
	return FALSE;
}
Example #18
0
static void manager_reply(DBusPendingCall *call, void *user_data)
{
	DBusError err;
	DBusMessage *reply;
	char *adapter;
	struct callback_data *callback = user_data;
	struct obc_session *session = callback->session;
	struct pending_req *req = find_session_request(session, call);

	reply = dbus_pending_call_steal_reply(call);

	session->pending_calls = g_slist_remove(session->pending_calls, req);
	pending_req_finalize(req);

	dbus_error_init(&err);
	if (dbus_set_error_from_message(&err, reply)) {
		error("manager replied with an error: %s, %s",
				err.name, err.message);
		dbus_error_free(&err);

		goto failed;
	}

	if (dbus_message_get_args(reply, NULL,
				DBUS_TYPE_OBJECT_PATH, &adapter,
				DBUS_TYPE_INVALID)) {
		DBG("adapter path %s", adapter);

		session->adapter = g_strdup(adapter);
		req = send_method_call(session->conn_system,
					BT_BUS_NAME, adapter,
					BT_ADAPTER_IFACE, "RequestSession",
					adapter_reply, callback,
					DBUS_TYPE_INVALID);
		if (!req)
			goto failed;

		session->pending_calls = g_slist_prepend(session->pending_calls,
									req);
	} else
		goto failed;

	goto proceed;

failed:
	obc_session_unref(session);
	g_free(callback);

proceed:
	dbus_message_unref(reply);
}
Example #19
0
static void pending_request_free(struct pending_request *p)
{
	if (p->req_id > 0)
		g_obex_cancel_req(p->session->obex, p->req_id, TRUE);

	if (p->destroy)
		p->destroy(p->data);

	if (p->transfer)
		obc_transfer_unregister(p->transfer);

	if (p->session)
		obc_session_unref(p->session);

	g_free(p);
}
Example #20
0
static void disconnect_cb(GObex *obex, GError *err, GObexPacket *rsp,
							gpointer user_data)
{
	struct pending_request *p = user_data;
	struct obc_session *session = p != NULL ? p->session : NULL;

	DBG("Finalizing disconnection. ");

	pending_request_free(p);

	if (session != NULL && session->id > 0 && session->transport != NULL) {
		session->transport->disconnect(session->id);
		session->id = 0;
	}

	obc_session_unref(session);
}
Example #21
0
void obc_session_shutdown(struct obc_session *session)
{
	struct pending_request *p;
	GError *err;

	DBG("%p", session);

	obc_session_ref(session);

	/* Unregister any pending transfer */
	err = g_error_new(OBEX_IO_ERROR, OBEX_IO_DISCONNECTED,
						"Session closed by user");

	if (session->p != NULL && session->p->id != 0) {
		p = session->p;
		session->p = NULL;

		if (p->func)
			p->func(session, p->transfer, err, p->data);

		pending_request_free(p);
	}

	while ((p = g_queue_pop_head(session->queue))) {
		if (p->func)
			p->func(session, p->transfer, err, p->data);

		pending_request_free(p);
	}

	g_error_free(err);

	/* Unregister interfaces */
	if (session->path)
		session_unregistered(session);

	/* Disconnect transport */
	if (session->id > 0 && session->transport != NULL) {
		session->transport->disconnect(session->id);
		session->id = 0;
	}

	obc_session_unref(session);
}
Example #22
0
static void session_terminate_transfer(struct obc_session *session,
					struct obc_transfer *transfer,
					GError *gerr)
{
	struct session_callback *callback = session->callback;

	if (callback) {
		callback->func(session, gerr, callback->data);
		return;
	}

	obc_session_ref(session);

	obc_transfer_unregister(transfer);

	if (session->pending)
		session_request(session, session_prepare_put,
				session->pending->data);

	obc_session_unref(session);
}
Example #23
0
void obc_session_shutdown(struct obc_session *session)
{
	DBG("%p", session);

	obc_session_ref(session);

	/* Unregister any pending transfer */
	g_slist_foreach(session->pending, (GFunc) obc_transfer_unregister,
									NULL);

	/* Unregister interfaces */
	if (session->path)
		session_unregistered(session);

	/* Shutdown io */
	if (session->io) {
		int fd = g_io_channel_unix_get_fd(session->io);
		shutdown(fd, SHUT_RDWR);
	}

	obc_session_unref(session);
}
Example #24
0
static void rfcomm_callback(GIOChannel *io, GError *err, gpointer user_data)
{
	struct callback_data *callback = user_data;
	struct obc_session *session = callback->session;
	struct obc_driver *driver = session->driver;
	GwObex *obex;
	int fd;

	DBG("");

	if (err != NULL) {
		error("%s", err->message);
		goto done;
	}

	/* do not close when gw_obex is using the fd */
	g_io_channel_set_close_on_unref(session->io, FALSE);
	g_io_channel_unref(session->io);
	session->io = NULL;

	fd = g_io_channel_unix_get_fd(io);

	obex = gw_obex_setup_fd(fd, driver->target, driver->target_len,
								NULL, NULL);

	session->obex = obex;

	sessions = g_slist_prepend(sessions, session);

done:
	callback->func(callback->session, err, callback->data);

	obc_session_unref(callback->session);

	g_free(callback);
}
Example #25
0
static void search_callback(uint8_t type, uint16_t status,
			uint8_t *rsp, size_t size, void *user_data)
{
	struct callback_data *callback = user_data;
	struct obc_session *session = callback->session;
	unsigned int scanned, bytesleft = size;
	int seqlen = 0;
	uint8_t dataType, channel = 0;
	GError *gerr = NULL;

	if (status || type != SDP_SVC_SEARCH_ATTR_RSP)
		goto failed;

	scanned = sdp_extract_seqtype(rsp, bytesleft, &dataType, &seqlen);
	if (!scanned || !seqlen)
		goto failed;

	rsp += scanned;
	bytesleft -= scanned;
	do {
		sdp_record_t *rec;
		sdp_list_t *protos;
		int recsize, ch = -1;

		recsize = 0;
		rec = sdp_extract_pdu(rsp, bytesleft, &recsize);
		if (!rec)
			break;

		if (!recsize) {
			sdp_record_free(rec);
			break;
		}

		if (!sdp_get_access_protos(rec, &protos)) {
			ch = sdp_get_proto_port(protos, RFCOMM_UUID);
			sdp_list_foreach(protos,
					(sdp_list_func_t) sdp_list_free, NULL);
			sdp_list_free(protos, NULL);
			protos = NULL;
		}

		sdp_record_free(rec);

		if (ch > 0) {
			channel = ch;
			break;
		}

		scanned += recsize;
		rsp += recsize;
		bytesleft -= recsize;
	} while (scanned < size && bytesleft > 0);

	if (channel == 0)
		goto failed;

	session->channel = channel;

	g_io_channel_set_close_on_unref(session->io, FALSE);
	g_io_channel_unref(session->io);

	session->io = rfcomm_connect(&session->src, &session->dst, channel,
					rfcomm_callback, callback);
	if (session->io != NULL) {
		sdp_close(callback->sdp);
		return;
	}

failed:
	g_io_channel_shutdown(session->io, TRUE, NULL);
	g_io_channel_unref(session->io);
	session->io = NULL;

	g_set_error(&gerr, OBEX_IO_ERROR, -EIO,
					"Unable to find service record");
	callback->func(session, gerr, callback->data);
	g_clear_error(&gerr);

	obc_session_unref(callback->session);
	g_free(callback);
}
Example #26
0
struct obc_session *obc_session_create(const char *source,
						const char *destination,
						const char *service,
						uint8_t channel,
						const char *owner,
						session_callback_t function,
						void *user_data)
{
	struct obc_session *session;
	struct callback_data *callback;
	struct pending_req *req;
	struct obc_driver *driver;

	if (destination == NULL)
		return NULL;

	session = session_find(source, destination, service, channel, owner);
	if (session) {
		obc_session_ref(session);
		goto proceed;
	}

	driver = obc_driver_find(service);
	if (!driver)
		return NULL;

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

	session->refcount = 1;
	session->channel = channel;

	session->conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
	if (session->conn == NULL) {
		session_free(session);
		return NULL;
	}

	session->conn_system = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
	if (session->conn_system == NULL) {
		session_free(session);
		return NULL;
	}

	if (source == NULL)
		bacpy(&session->src, BDADDR_ANY);
	else
		str2ba(source, &session->src);

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

	DBG("driver %s", driver->service);

proceed:
	callback = g_try_malloc0(sizeof(*callback));
	if (callback == NULL) {
		obc_session_unref(session);
		return NULL;
	}

	callback->session = obc_session_ref(session);
	callback->func = function;
	callback->data = user_data;

	if (source) {
		req = send_method_call(session->conn_system,
				BT_BUS_NAME, BT_PATH,
				BT_MANAGER_IFACE, "FindAdapter",
				manager_reply, callback,
				DBUS_TYPE_STRING, &source,
				DBUS_TYPE_INVALID);
	} else {
		req = send_method_call(session->conn_system,
				BT_BUS_NAME, BT_PATH,
				BT_MANAGER_IFACE, "DefaultAdapter",
				manager_reply, callback,
				DBUS_TYPE_INVALID);
	}

	if (!req) {
		obc_session_unref(session);
		g_free(callback);
		return NULL;
	}

	session->pending_calls = g_slist_prepend(session->pending_calls, req);

	if (owner)
		obc_session_set_owner(session, owner, owner_disconnected);

	return session;
}
Example #27
0
void obc_session_shutdown(struct obc_session *session)
{
	struct pending_request *p;
	GError *err;

	DBG("%p", session);

	if (session->disconnecting == TRUE) {
		DBG("%p already disconnecting", session);
		return;
	}
	session->disconnecting = TRUE;

	obc_session_ref(session);

	/* Unregister any pending transfer */
	err = g_error_new(OBEX_IO_ERROR, OBEX_IO_DISCONNECTED,
						"Session closed by user");

	if (session->p != NULL && session->p->id != 0) {
		p = session->p;
		session->p = NULL;

		if (p->func)
			p->func(session, p->transfer, err, p->data);

		pending_request_free(p);
	}

	while ((p = g_queue_pop_head(session->queue))) {
		if (p->func)
			p->func(session, p->transfer, err, p->data);

		pending_request_free(p);
	}

	g_error_free(err);

	/* Unregister interfaces */
	if (session->path)
		session_unregistered(session);

	DBG("Checking the need for disconnect request");
	/* Send a disconnect request and wait for reply */
	if (session->id > 0 && session->transport != NULL
			&& session->obex != NULL) {
		DBG("Generating disconnect request. ");
		err = NULL;
		p = pending_request_new(session, NULL, NULL, NULL);
		p->req_id = g_obex_disconnect(session->obex, disconnect_cb,
						p, &err);
		if (err != NULL) {
			DBG("Generating disconnect request failed. ");
			disconnect_cb(session->obex, NULL, NULL, p);
		} else {
			/* Finalize when reply arrives */
			DBG("Generating disconnect request succeeded. ");
		}
	} else {
		DBG("Unreferring without disconnect request.");
		obc_session_unref(session);
	}
}
Example #28
0
static void shutdown_session(struct obc_session *session)
{
	obc_session_shutdown(session);
	obc_session_unref(session);
}