tizen beta release
[profile/ivi/obexd.git] / client / agent.c
1 /*
2  *
3  *  OBEX Client
4  *
5  *  Copyright (C) 2007-2010  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <errno.h>
29
30 #include "log.h"
31 #include "agent.h"
32
33 #define AGENT_INTERFACE  "org.openobex.Agent"
34
35 struct pending_request {
36         DBusPendingCall *call;
37         DBusPendingCallNotifyFunction function;
38         void *data;
39         DBusFreeFunction destroy;
40 };
41
42 struct obc_agent {
43         DBusConnection *conn;
44         char *name;
45         char *path;
46         guint watch;
47         GFunc destroy;
48         void *data;
49         struct pending_request *pending;
50 };
51
52 static void pending_request_free(struct pending_request *req)
53 {
54         if (req->call)
55                 dbus_pending_call_unref(req->call);
56
57         if (req->destroy)
58                 req->destroy(req->data);
59
60         g_free(req);
61 }
62
63 void obc_agent_free(struct obc_agent *agent)
64 {
65         if (agent->watch)
66                 g_dbus_remove_watch(agent->conn, agent->watch);
67
68         if (agent->pending) {
69                 if (agent->pending->call)
70                         dbus_pending_call_cancel(agent->pending->call);
71                 pending_request_free(agent->pending);
72         }
73
74         dbus_connection_unref(agent->conn);
75         g_free(agent->name);
76         g_free(agent->path);
77         g_free(agent);
78 }
79
80 static void agent_disconnected(DBusConnection *connection, void *user_data)
81 {
82         struct obc_agent *agent = user_data;
83
84         agent->watch = 0;
85
86         if (agent->destroy)
87                 agent->destroy(agent, agent->data);
88
89         obc_agent_free(agent);
90 }
91
92 struct obc_agent *obc_agent_create(DBusConnection *conn, const char *name,
93                                         const char *path, GFunc destroy,
94                                         void *user_data)
95 {
96         struct obc_agent *agent;
97
98         agent = g_new0(struct obc_agent, 1);
99         agent->conn = dbus_connection_ref(conn);
100         agent->name = g_strdup(name);
101         agent->path = g_strdup(path);
102         agent->destroy = destroy;
103         agent->data = user_data;
104
105         agent->watch = g_dbus_add_disconnect_watch(conn, name,
106                                                         agent_disconnected,
107                                                         agent, NULL);
108
109         return agent;
110 }
111
112 static void agent_request_reply(DBusPendingCall *call, void *user_data)
113 {
114         struct obc_agent *agent = user_data;
115         struct pending_request *req = agent->pending;
116
117         agent->pending = NULL;
118
119         if (req->function)
120                 req->function(call, req->data);
121
122         pending_request_free(req);
123 }
124
125 int obc_agent_request(struct obc_agent *agent, const char *path,
126                                 DBusPendingCallNotifyFunction function,
127                                 void *user_data, DBusFreeFunction destroy)
128 {
129         struct pending_request *req;
130         DBusMessage *message;
131
132         if (agent->pending)
133                 return -EBUSY;
134
135         DBG("%s", path);
136
137         message = dbus_message_new_method_call(agent->name,
138                         agent->path, AGENT_INTERFACE, "Request");
139
140         dbus_message_append_args(message,
141                         DBUS_TYPE_OBJECT_PATH, &path,
142                         DBUS_TYPE_INVALID);
143
144         req = g_new0(struct pending_request, 1);
145         req->function = function;
146         req->destroy = destroy;
147         req->data = user_data;
148
149         if (!dbus_connection_send_with_reply(agent->conn, message,
150                                                 &req->call, -1)) {
151                 g_free(req);
152                 dbus_message_unref(message);
153                 return -ENOMEM;
154         }
155
156         agent->pending = req;
157
158         dbus_message_unref(message);
159
160         dbus_pending_call_set_notify(req->call, agent_request_reply,
161                                         agent, NULL);
162
163         return 0;
164 }
165
166 void obc_agent_notify_progress(struct obc_agent *agent, const char *path,
167                                                         guint64 transferred)
168 {
169         DBusMessage *message;
170
171         DBG("%s", path);
172
173         message = dbus_message_new_method_call(agent->name,
174                         agent->path, AGENT_INTERFACE, "Progress");
175         if (message == NULL)
176                 return;
177
178         dbus_message_set_no_reply(message, TRUE);
179
180         dbus_message_append_args(message,
181                         DBUS_TYPE_OBJECT_PATH, &path,
182                         DBUS_TYPE_UINT64, &transferred,
183                         DBUS_TYPE_INVALID);
184
185         g_dbus_send_message(agent->conn, message);
186 }
187
188 void obc_agent_notify_complete(struct obc_agent *agent, const char *path)
189 {
190         DBusMessage *message;
191
192         DBG("%s", path);
193
194         message = dbus_message_new_method_call(agent->name,
195                         agent->path, AGENT_INTERFACE, "Complete");
196         if (message == NULL)
197                 return;
198
199         dbus_message_set_no_reply(message, TRUE);
200
201         dbus_message_append_args(message,
202                         DBUS_TYPE_OBJECT_PATH, &path,
203                         DBUS_TYPE_INVALID);
204
205         g_dbus_send_message(agent->conn, message);
206 }
207
208 void obc_agent_notify_error(struct obc_agent *agent, const char *path,
209                                                         const char *err)
210 {
211         DBusMessage *message;
212
213         DBG("%s", path);
214
215         message = dbus_message_new_method_call(agent->name,
216                         agent->path, AGENT_INTERFACE, "Error");
217         if (message == NULL)
218                 return;
219
220         dbus_message_set_no_reply(message, TRUE);
221
222         dbus_message_append_args(message,
223                         DBUS_TYPE_OBJECT_PATH, &path,
224                         DBUS_TYPE_STRING, &err,
225                         DBUS_TYPE_INVALID);
226
227         g_dbus_send_message(agent->conn, message);
228 }
229
230 void obc_agent_release(struct obc_agent *agent)
231 {
232         DBusMessage *message;
233
234         DBG("");
235
236         message = dbus_message_new_method_call(agent->name,
237                         agent->path, AGENT_INTERFACE, "Release");
238
239         dbus_message_set_no_reply(message, TRUE);
240
241         g_dbus_send_message(agent->conn, message);
242 }
243
244 const char *obc_agent_get_name(struct obc_agent *agent)
245 {
246         return agent->name;
247 }
248
249 const char *obc_agent_get_path(struct obc_agent *agent)
250 {
251         return agent->path;
252 }