Diff between 50d7138fe775ce5e0a38b84882fd72683c94ecd7 and 5c2632935848539a7943743c575879fc2009250f

Changed Files

File Additions Deletions Status
obexd/client/session.c +241 -79 modified

Full Patch

diff --git a/obexd/client/session.c b/obexd/client/session.c
index c61c004..d0989df 100644
--- a/obexd/client/session.c
+++ b/obexd/client/session.c
@@ -654,6 +654,68 @@ static GDBusMethodTable session_methods[] = {
 	{ }
 };
 
+static void agent_request(DBusConnection *conn, const char *agent_name,
+			const char *agent_path, const char *transfer_path)
+{
+	DBusMessage *message;
+
+	if (agent_name == NULL || agent_path == NULL)
+		return;
+
+	message = dbus_message_new_method_call(agent_name,
+			agent_path, AGENT_INTERFACE, "Request");
+
+	dbus_message_append_args(message,
+			DBUS_TYPE_OBJECT_PATH, &transfer_path,
+			DBUS_TYPE_INVALID);
+
+	g_dbus_send_message(conn, message);
+
+	/* FIXME: Reply needs be handled */
+}
+
+static void agent_notify_progress(DBusConnection *conn, const char *agent_name,
+			const char *agent_path, const char *transfer_path,
+			uint64_t transferred)
+{
+	DBusMessage *message;
+
+	if (agent_name == NULL || agent_path == NULL)
+		return;
+
+	message = dbus_message_new_method_call(agent_name,
+			agent_path, AGENT_INTERFACE, "Progress");
+
+	dbus_message_set_no_reply(message, TRUE);
+
+	dbus_message_append_args(message,
+			DBUS_TYPE_OBJECT_PATH, &transfer_path,
+			DBUS_TYPE_UINT64, &transferred,
+			DBUS_TYPE_INVALID);
+
+	g_dbus_send_message(conn, message);
+}
+
+static void agent_notify_complete(DBusConnection *conn, const char *agent_name,
+			const char *agent_path, const char *transfer_path)
+{
+	DBusMessage *message;
+
+	if (agent_name == NULL || agent_path == NULL)
+		return;
+
+	message = dbus_message_new_method_call(agent_name,
+			agent_path, AGENT_INTERFACE, "Complete");
+
+	dbus_message_set_no_reply(message, TRUE);
+
+	dbus_message_append_args(message,
+			DBUS_TYPE_OBJECT_PATH, &transfer_path,
+			DBUS_TYPE_INVALID);
+
+	g_dbus_send_message(conn, message);
+}
+
 static void append_variant(DBusMessageIter *iter, int type, void *val)
 {
 	DBusMessageIter value;
@@ -760,40 +822,170 @@ done:
 	session->msg = NULL;
 }
 
+static void get_file_callback(struct session_data *session, void *user_data)
+{
+
+}
+
 static void get_xfer_progress(GwObexXfer *xfer, gpointer user_data)
 {
 	struct callback_data *callback = user_data;
 	struct session_data *session = callback->session;
-	gint bsize, bread;
+	gint bsize, bread, err = 0;
 	gboolean ret;
 
 	/* FIXME: Check buffer overflow */
 	bsize = sizeof(session->buffer) - session->filled;
 	ret = gw_obex_xfer_read(xfer, session->buffer + session->filled,
-					bsize, &bread, NULL);
-	session->filled += bread;
-	if (ret == FALSE)
+					bsize, &bread, &err);
+
+	/* For GetFile reply on the first received stream */
+	if (session->fd > 0 && session->msg) {
+		DBusMessage *reply;
+
+		if (ret == FALSE)
+			reply = g_dbus_create_error(session->msg,
+					"org.openobex.Error.Failed",
+					OBEX_ResponseToString(err));
+		else
+			reply = dbus_message_new_method_return(session->msg);
+
+		g_dbus_send_message(session->conn, reply);
+
+		session->msg = NULL;
+	}
+
+	if (ret == FALSE) {
+		fprintf(stderr, "gw_obex_xfer_read(): %s\n",
+				OBEX_ResponseToString(err));
 		goto complete;
+	}
+
+	session->filled += bread;
+	session->transferred += bread;
+	if (session->size == 0)
+		session->size = gw_obex_xfer_object_size(xfer);
 
-	if (bread == gw_obex_xfer_object_size(xfer))
+	if (bread == session->size)
 		goto complete;
 
 	gw_obex_xfer_flush(xfer, NULL);
 
+	agent_notify_progress(session->conn, session->agent_name,
+			session->agent_path, session->transfer_path, 0);
+
 	return;
 
 complete:
+
+	agent_notify_complete(session->conn, session->agent_name,
+			session->agent_path, session->transfer_path);
+
 	gw_obex_xfer_close(xfer, NULL);
 	gw_obex_xfer_free(xfer);
 	callback->session->xfer = NULL;
 
 	callback->func(callback->session, callback->data);
 
+	if (session->fd > 0)
+		close(session->fd);
+
+	/* FIXME: Report complete */
+
 	session_unref(callback->session);
 
 	g_free(callback);
 }
 
+static char *register_transfer(DBusConnection *conn, void *user_data)
+{
+	char *path;
+
+	path = g_strdup_printf("%s/transfer%ju",
+			TRANSFER_BASEPATH, counter++);
+
+	if (g_dbus_register_interface(conn, path,
+				TRANSFER_INTERFACE,
+				transfer_methods, NULL, NULL,
+				user_data, NULL) == FALSE) {
+		g_free(path);
+		return NULL;
+	}
+
+	return path;
+}
+
+int session_get(struct session_data *session, const char *type,
+		const char *filename, const char *targetname,
+		session_callback_t func)
+{
+	struct callback_data *callback;
+	GwObexXfer *xfer;
+	int err, fd = 0;
+
+	if (session->obex == NULL)
+		return -ENOTCONN;
+
+	if (type == NULL) {
+		if (targetname == NULL)
+			targetname = filename;
+
+		fd = open(targetname, O_WRONLY | O_CREAT, 0600);
+		if (fd < 0) {
+			err = errno;
+			fprintf(stderr, "open(): %s(%d)\n", strerror(err), err);
+			return -err;
+		}
+
+		session->transfer_path = register_transfer(session->conn, session);
+		if (session->transfer_path == NULL) {
+			if (fd)
+				close(fd);
+
+			return -EIO;
+		}
+	}
+
+	session->fd = fd;
+	session->transferred = 0;
+	session->size = 0;
+	session->filename = g_strdup(filename);
+	session->name = g_strdup(targetname);
+
+	session_ref(session);
+
+	xfer = gw_obex_get_async(session->obex,
+				filename, type, NULL);
+	if (xfer == NULL) {
+		close(session->fd);
+		session_unref(session);
+		return -EIO;
+	}
+
+	callback = g_try_malloc0(sizeof(*callback));
+	if (callback == NULL) {
+		close(session->fd);
+		session_unref(session);
+		gw_obex_xfer_free(xfer);
+		return -ENOMEM;
+	}
+
+	callback->session = session;
+	callback->func = func;
+
+	gw_obex_xfer_set_callback(xfer, get_xfer_progress, callback);
+
+	session->xfer = xfer;
+
+	agent_request(session->conn, session->agent_name,
+			session->agent_path, session->transfer_path);
+
+	agent_notify_progress(session->conn, session->agent_name,
+			session->agent_path, session->transfer_path, 0);
+
+	return 0;
+}
+
 static DBusMessage *change_folder(DBusConnection *connection,
 				DBusMessage *message, void *user_data)
 {
@@ -826,45 +1018,20 @@ static DBusMessage *list_folder(DBusConnection *connection,
 				DBusMessage *message, void *user_data)
 {
 	struct session_data *session = user_data;
-	struct callback_data *callback;
-	GwObexXfer *xfer;
-	int err;
 
 	if (session->msg)
 		return g_dbus_create_error(message,
 				"org.openobex.Error.InProgress",
 				"Transfer in progress");
 
-	if (session->obex == NULL)
-		return g_dbus_create_error(message,
-				"org.openobex.Error.Failed",
-				"Not connected");
-
-	session_ref(session);
-	xfer = gw_obex_get_async(session->obex,
-			NULL, "x-obex/folder-listing", &err);
-	if (xfer == NULL) {
-		session_unref(session);
+	if (session_get(session, "x-obex/folder-listing",
+				NULL, NULL, list_folder_callback) < 0)
 		return g_dbus_create_error(message,
 				"org.openobex.Error.Failed",
-				OBEX_ResponseToString(err));
-	}
-
-	callback = g_try_malloc0(sizeof(*callback));
-	if (callback == NULL) {
-		session_unref(session);
-		gw_obex_xfer_free(xfer);
-		return NULL;
-	}
+				"Failed");
 
 	session->msg = dbus_message_ref(message);
 	session->filled = 0;
-	callback->session = session;
-	callback->func = list_folder_callback;
-
-	gw_obex_xfer_set_callback(xfer, get_xfer_progress, callback);
-
-	session->xfer = xfer;
 
 	return NULL;
 }
@@ -872,7 +1039,31 @@ static DBusMessage *list_folder(DBusConnection *connection,
 static DBusMessage *get_file(DBusConnection *connection,
 				DBusMessage *message, void *user_data)
 {
-	return dbus_message_new_method_return(message);
+	struct session_data *session = user_data;
+	const char *target_file, *source_file;
+
+	if (session->msg)
+		return g_dbus_create_error(message,
+				"org.openobex.Error.InProgress",
+				"Transfer in progress");
+
+	if (dbus_message_get_args(message, NULL,
+				DBUS_TYPE_STRING, &target_file,
+				DBUS_TYPE_STRING, &source_file,
+				DBUS_TYPE_INVALID) == FALSE)
+		return g_dbus_create_error(message,
+				"org.openobex.Error.InvalidArguments", NULL);
+
+	if (session_get(session, NULL, source_file,
+				target_file, get_file_callback) < 0)
+		return g_dbus_create_error(message,
+				"org.openobex.Error.Failed",
+				"Failed");
+
+	session->msg = dbus_message_ref(message);
+	session->filled = 0;
+
+	return NULL;
 }
 
 static DBusMessage *put_file(DBusConnection *connection,
@@ -920,7 +1111,8 @@ static GDBusMethodTable ftp_methods[] = {
 	{ "CreateFolder",	"s", "",	create_folder	},
 	{ "ListFolder",		"", "aa{sv}",	list_folder,
 						G_DBUS_METHOD_FLAG_ASYNC },
-	{ "GetFile",		"ss", "",	get_file	},
+	{ "GetFile",		"ss", "",	get_file,
+						G_DBUS_METHOD_FLAG_ASYNC },
 	{ "PutFile",		"ss", "",	put_file	},
 	{ "CopyFile",		"ss", "",	copy_file	},
 	{ "MoveFile",		"ss", "",	move_file	},
@@ -970,6 +1162,10 @@ static void put_xfer_progress(GwObexXfer *xfer, gpointer user_data)
 	return;
 
 complete:
+
+	agent_notify_complete(session->conn, session->agent_name,
+			session->agent_path, session->transfer_path);
+
 	gw_obex_xfer_close(session->xfer, NULL);
 	gw_obex_xfer_free(session->xfer);
 	session->xfer = NULL;
@@ -980,17 +1176,6 @@ complete:
 	g_free(session->name);
 	session->name = NULL;
 
-	if (session->agent_path && session->agent_name) {
-		message = dbus_message_new_method_call(session->agent_name,
-			session->agent_path, AGENT_INTERFACE, "Complete");
-
-		dbus_message_append_args(message,
-			DBUS_TYPE_OBJECT_PATH, &session->transfer_path,
-						DBUS_TYPE_INVALID);
-
-		g_dbus_send_message(session->conn, message);
-	}
-
 	if (session->pending->len > 0) {
 		gchar *filename = g_ptr_array_index(session->pending, 0);
 		gchar *basename = g_path_get_basename(filename);
@@ -1016,8 +1201,6 @@ int session_send(struct session_data *session, const char *filename,
 				const char *targetname)
 {
 	GwObexXfer *xfer;
-	DBusMessage *message;
-	guint64 transferred = 0;
 	struct stat st;
 	int fd;
 
@@ -1038,23 +1221,18 @@ int session_send(struct session_data *session, const char *filename,
 		return -EIO;
 	}
 
+	session->transfer_path = register_transfer(session->conn, session);
+	if (session->transfer_path == NULL) {
+		close(fd);
+		return -EIO;
+	}
+
 	session->fd = fd;
 	session->size = st.st_size;
 	session->transferred = 0;
 	session->filename = g_strdup(filename);
 	session->name = g_strdup(targetname);
 
-	if (session->transfer_path == NULL) {
-		session->transfer_path = g_strdup_printf("%s/transfer%ju",
-					TRANSFER_BASEPATH, counter++);
-
-		if (g_dbus_register_interface(session->conn, session->transfer_path,
-					TRANSFER_INTERFACE,
-					transfer_methods, NULL, NULL,
-						session, NULL) == FALSE)
-			return -EIO;
-	}
-
 	session_ref(session);
 
 	xfer = gw_obex_put_async(session->obex, session->name, NULL,
@@ -1066,27 +1244,11 @@ int session_send(struct session_data *session, const char *filename,
 
 	session->xfer = xfer;
 
-	if (session->agent_name == NULL || session->agent_path == NULL)
-		return 0;
-
-	message = dbus_message_new_method_call(session->agent_name,
-			session->agent_path, AGENT_INTERFACE, "Request");
-
-	dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &session->transfer_path,
-							DBUS_TYPE_INVALID);
-
-	g_dbus_send_message(session->conn, message);
-
-	message = dbus_message_new_method_call(session->agent_name,
-			session->agent_path, AGENT_INTERFACE, "Progress");
-
-	dbus_message_set_no_reply(message, TRUE);
-
-	dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &session->transfer_path,
-						DBUS_TYPE_UINT64, &transferred,
-							DBUS_TYPE_INVALID);
+	agent_request(session->conn, session->agent_name,
+			session->agent_path, session->transfer_path);
 
-	g_dbus_send_message(session->conn, message);
+	agent_notify_progress(session->conn, session->agent_name,
+			session->agent_path, session->transfer_path, 0);
 
 	return 0;
 }