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); }
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); }
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); }
static int map_probe(struct obc_session *session) { struct map_data *map; const char *path; path = obc_session_get_path(session); DBG("%s", path); map = g_try_new0(struct map_data, 1); if (!map) return -ENOMEM; map->session = obc_session_ref(session); map->messages = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, map_msg_remove); set_notification_registration(map, true); if (!g_dbus_register_interface(conn, path, MAP_INTERFACE, map_methods, NULL, NULL, map, map_free)) { map_free(map); return -ENOMEM; } return 0; }
struct obc_transfer *obc_transfer_register(DBusConnection *conn, const char *filename, const char *name, const char *type, struct obc_transfer_params *params, void *user_data) { struct obc_session *session = user_data; struct obc_transfer *transfer; transfer = g_new0(struct obc_transfer, 1); transfer->session = obc_session_ref(session); transfer->filename = g_strdup(filename); transfer->name = g_strdup(name); transfer->type = g_strdup(type); transfer->params = params; /* for OBEX specific mime types we don't need to register a transfer */ if (type != NULL && (strncmp(type, "x-obex/", 7) == 0 || strncmp(type, "x-bt/", 5) == 0)) goto done; transfer->path = g_strdup_printf("%s/transfer%ju", TRANSFER_BASEPATH, counter++); transfer->conn = dbus_bus_get(DBUS_BUS_SESSION, NULL); if (transfer->conn == NULL) { obc_transfer_free(transfer); return NULL; } if (g_dbus_register_interface(transfer->conn, transfer->path, TRANSFER_INTERFACE, obc_transfer_methods, NULL, NULL, transfer, NULL) == FALSE) { obc_transfer_free(transfer); return NULL; } done: DBG("%p registered %s", transfer, transfer->path); obc_session_add_transfer(session, transfer); return transfer; }
static struct pending_request *pending_request_new(struct obc_session *session, struct obc_transfer *transfer, session_callback_t func, void *data) { struct pending_request *p; static guint id = 0; p = g_new0(struct pending_request, 1); p->id = ++id; p->session = obc_session_ref(session); p->transfer = transfer; p->func = func; p->data = data; return p; }
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); }
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; }
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); }
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); }
static int pbap_probe(struct obc_session *session) { struct pbap_data *pbap; const char *path; path = obc_session_get_path(session); DBG("%s", path); pbap = g_try_new0(struct pbap_data, 1); if (!pbap) return -ENOMEM; pbap->session = obc_session_ref(session); if (!g_dbus_register_interface(conn, path, PBAP_INTERFACE, pbap_methods, NULL, NULL, pbap, pbap_free)) { pbap_free(pbap); return -ENOMEM; } return 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); } }
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; }