summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClaudio Takahasi <claudio.takahasi@openbossa.org>2007-05-09 12:15:39 +0000
committerClaudio Takahasi <claudio.takahasi@openbossa.org>2007-05-09 12:15:39 +0000
commitd57f86fa59d10c46e82b1b9217387523d77d395a (patch)
tree4e3b370936e890d76e0ff2d3b6e5882f3b22759d
parent1bd19f3b6236ec87d225589108339086c0b2e8f8 (diff)
serial: added verification for pending connects
-rw-r--r--serial/manager.c81
1 files changed, 63 insertions, 18 deletions
diff --git a/serial/manager.c b/serial/manager.c
index 458a71a2..83f08884 100644
--- a/serial/manager.c
+++ b/serial/manager.c
@@ -100,6 +100,7 @@ static struct {
static DBusConnection *connection = NULL;
static GSList *connected_nodes = NULL;
+static GSList *pending_connects = NULL;
static int rfcomm_ctl = -1;
static void pending_connect_free(struct pending_connect *pc)
@@ -130,9 +131,32 @@ static void rfcomm_node_free(struct rfcomm_node *node)
g_free(node);
}
-static int node_cmp_by_name(struct rfcomm_node *node, const char *name)
+static struct rfcomm_node *find_node_by_name(const char *name)
{
- return strcmp(node->name, name);
+ GSList *l;
+
+ for (l = connected_nodes; l != NULL; l = l->next) {
+ struct rfcomm_node *node = l->data;
+ if (!strcmp(node->name, name))
+ return node;
+ }
+
+ return NULL;
+}
+
+static struct pending_connect *find_pending_connect_by_channel(const char *bda,
+ uint8_t ch)
+{
+ GSList *l;
+
+ for (l = pending_connects; l != NULL; l = l->next) {
+ struct pending_connect *pending = l->data;
+ if (!strcasecmp(bda, pending->addr) &&
+ pending->channel == ch)
+ return pending;
+ }
+
+ return NULL;
}
static uint16_t str2class(const char *pattern)
@@ -155,6 +179,15 @@ static DBusHandlerResult err_connection_failed(DBusConnection *conn,
SERIAL_ERROR_INTERFACE".ConnectionAttemptFailed", str));
}
+static DBusHandlerResult err_connection_in_progress(DBusConnection *conn,
+ DBusMessage *msg)
+{
+ return send_message_and_unref(conn,
+ dbus_message_new_error(msg,
+ SERIAL_ERROR_INTERFACE".ConnectionInProgress",
+ "Connection creation in progress"));
+}
+
static DBusHandlerResult err_does_not_exist(DBusConnection *conn,
DBusMessage *msg, const char *str)
{
@@ -301,8 +334,7 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connect *pc)
if (!dbus_bus_name_has_owner(pc->conn, owner, NULL)) {
error("Connect requestor %s exited", owner);
rfcomm_release(pc->id);
- pending_connect_free(pc);
- return FALSE;
+ goto fail;
}
snprintf(node_name, sizeof(node_name), "/dev/rfcomm%d", pc->id);
@@ -314,8 +346,7 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connect *pc)
if (++pc->ntries >= MAX_OPEN_TRIES) {
rfcomm_release(pc->id);
err_connection_failed(pc->conn, pc->msg, strerror(err));
- pending_connect_free(pc);
- return FALSE;
+ goto fail;
}
return TRUE;
}
@@ -332,7 +363,8 @@ static gboolean rfcomm_connect_cb_continue(struct pending_connect *pc)
/* Send the D-Bus signal */
send_signal(pc->conn, "ServiceConnected", node_name);
-
+fail:
+ pending_connects = g_slist_remove(pending_connects, pc);
pending_connect_free(pc);
return FALSE;
@@ -406,8 +438,9 @@ static gboolean rfcomm_connect_cb(GIOChannel *chan,
/* Send the D-Bus signal */
send_signal(pc->conn, "ServiceConnected", node_name);
fail:
+ pending_connects = g_slist_remove(pending_connects, pc);
pending_connect_free(pc);
- /* FIXME: Remote from the pending connects list */
+
return FALSE;
}
@@ -449,7 +482,8 @@ static int rfcomm_connect(struct pending_connect *pc)
debug("Connect in progress");
g_io_add_watch(io, G_IO_OUT, (GIOFunc) rfcomm_connect_cb, pc);
- /* FIXME: Control the pending connects */
+
+ pending_connects = g_slist_append(pending_connects, pc);
} else {
debug("Connect succeeded with first try");
(void) rfcomm_connect_cb(io, G_IO_OUT, pc);
@@ -461,7 +495,7 @@ fail:
static void record_reply(DBusPendingCall *call, void *data)
{
- struct pending_connect *pc = data;
+ struct pending_connect *pending, *pc = data;
DBusMessage *reply = dbus_pending_call_steal_reply(call);
sdp_record_t *rec;
const uint8_t *rec_bin;
@@ -520,7 +554,11 @@ static void record_reply(DBusPendingCall *call, void *data)
goto fail;
}
- /* FIXME: Check if there is a pending connection or if it was canceled */
+ pending = find_pending_connect_by_channel(pc->addr, ch);
+ if (pending) {
+ err_connection_in_progress(pc->conn, pc->msg);
+ goto fail;
+ }
pc->channel = ch;
err = rfcomm_connect(pc);
@@ -535,6 +573,7 @@ static void record_reply(DBusPendingCall *call, void *data)
fail:
dbus_message_unref(reply);
dbus_error_free(&derr);
+ pending_connects = g_slist_remove(pending_connects, pc);
pending_connect_free(pc);
}
@@ -610,6 +649,7 @@ static void handles_reply(DBusPendingCall *call, void *data)
fail:
dbus_message_unref(reply);
dbus_error_free(&derr);
+ pending_connects = g_slist_remove(pending_connects, pc);
pending_connect_free(pc);
}
@@ -646,7 +686,7 @@ static DBusHandlerResult connect_service(DBusConnection *conn,
{
DBusError derr;
bdaddr_t src;
- struct pending_connect *pc;
+ struct pending_connect *pending, *pc;
const char *addr, *pattern;
char *endptr;
long val;
@@ -747,11 +787,20 @@ static DBusHandlerResult connect_service(DBusConnection *conn,
"invalid RFCOMM channel");
}
+ /* FIXME: Check if it is already connected */
+
+ pending = find_pending_connect_by_channel(addr, val);
+ if (pending) {
+ pending_connect_free(pc);
+ return err_connection_in_progress(conn, msg);
+ }
+
pc->channel = val;
err = rfcomm_connect(pc);
if (err < 0) {
const char *strerr = strerror(-err);
error("RFCOMM connect failed: %s(%d)", strerr, -err);
+ pending_connect_free(pc);
err_connection_failed(conn, msg, strerr);
}
return DBUS_HANDLER_RESULT_HANDLED;
@@ -764,7 +813,6 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn,
DBusError derr;
struct rfcomm_node *node;
const char *name;
- GSList *l;
int err;
dbus_error_init(&derr);
@@ -776,13 +824,10 @@ static DBusHandlerResult disconnect_service(DBusConnection *conn,
return DBUS_HANDLER_RESULT_HANDLED;
}
- l = g_slist_find_custom(connected_nodes, name,
- (GCompareFunc) node_cmp_by_name);
- if (!l)
+ node = find_node_by_name(name);
+ if (!node)
return err_does_not_exist(conn, msg, "Invalid node");
- node = l->data;
-
if (strcmp(node->owner, dbus_message_get_sender(msg)) != 0)
return err_not_authorized(conn, msg);