Tizen 2.0 Release
[framework/connectivity/neard.git] / plugins / p2p.c
1 /*
2  *
3  *  neard - Near Field Communication manager
4  *
5  *  Copyright (C) 2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <unistd.h>
27 #include <stdint.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <sys/socket.h>
31
32 #include <linux/socket.h>
33
34 #include <near/nfc.h>
35 #include <near/plugin.h>
36 #include <near/log.h>
37 #include <near/types.h>
38 #include <near/tag.h>
39 #include <near/device.h>
40 #include <near/adapter.h>
41 #include <near/tlv.h>
42 #include <near/ndef.h>
43
44 #include "p2p.h"
45
46 static GSList *driver_list = NULL;
47 static GList *server_list = NULL;
48
49 struct p2p_data {
50         struct near_p2p_driver *driver;
51         uint32_t adapter_idx;
52         uint32_t target_idx;
53         near_device_io_cb cb;
54         int fd;
55         guint watch;
56
57         GList *client_list;
58 };
59
60 static gboolean p2p_client_event(GIOChannel *channel, GIOCondition condition,
61                                                         gpointer user_data)
62 {
63         struct p2p_data *client_data = user_data;
64         near_bool_t more;
65
66         DBG("condition 0x%x", condition);
67
68         if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
69                 int err;
70
71                 if (client_data->watch > 0)
72                         g_source_remove(client_data->watch);
73                 client_data->watch = 0;
74
75                 if (condition & (G_IO_NVAL | G_IO_ERR))
76                         err = -EIO;
77                 else
78                         err = 0;
79
80                 if (client_data->driver->close != NULL)
81                         client_data->driver->close(client_data->fd, err);
82
83                 near_error("%s client channel closed",
84                                         client_data->driver->name);
85
86                 return FALSE;
87         }
88
89         more = client_data->driver->read(client_data->fd,
90                                                 client_data->adapter_idx,
91                                                 client_data->target_idx,
92                                                 client_data->cb);
93
94         return more;
95 }
96
97 static void free_client_data(gpointer data)
98 {
99         struct p2p_data *client_data;
100
101         DBG("");
102
103         client_data = (struct p2p_data *) data;
104
105         if (client_data->driver->close != NULL)
106                 client_data->driver->close(client_data->fd, 0);
107
108         if (client_data->watch > 0)
109                 g_source_remove(client_data->watch);
110
111         g_free(client_data);
112 }
113
114 static void free_server_data(gpointer data)
115 {
116         struct p2p_data *server_data;
117
118         DBG("");
119
120         server_data = (struct p2p_data *)data;
121
122         if (server_data->watch > 0)
123                 g_source_remove(server_data->watch);
124         server_data->watch = 0;
125         g_list_free_full(server_data->client_list, free_client_data);
126         server_data->client_list = NULL;
127
128         DBG("Closing server socket");
129
130         close(server_data->fd);
131
132         g_free(server_data);
133 }
134
135 static gboolean p2p_listener_event(GIOChannel *channel, GIOCondition condition,
136                                                         gpointer user_data)
137 {
138         struct sockaddr_nfc_llcp client_addr;
139         socklen_t client_addr_len;
140         int server_fd, client_fd;
141         struct p2p_data *client_data, *server_data = user_data;
142         GIOChannel *client_channel;
143         struct near_p2p_driver *driver = server_data->driver;
144
145         DBG("condition 0x%x", condition);
146
147         server_fd = g_io_channel_unix_get_fd(channel);
148
149         if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
150                 if (server_data->watch > 0)
151                         g_source_remove(server_data->watch);
152                 server_data->watch = 0;
153
154                 g_list_free_full(server_data->client_list, free_client_data);
155                 server_data->client_list = NULL;
156
157                 near_error("Error with %s server channel", driver->name);
158
159                 return FALSE;
160         }
161
162         client_addr_len = sizeof(client_addr);
163         client_fd = accept(server_fd, (struct sockaddr *) &client_addr,
164                                                         &client_addr_len);
165         if (client_fd < 0) {
166                 near_error("accept failed %d", client_fd);
167
168                 return FALSE;
169         }
170
171         DBG("client dsap %d ssap %d",
172                 client_addr.dsap, client_addr.ssap);
173         DBG("target idx %d", client_addr.target_idx);
174
175         client_data = g_try_malloc0(sizeof(struct p2p_data));
176         if (client_data == NULL) {
177                 close(client_fd);
178                 return FALSE;
179         }
180
181         client_data->driver = server_data->driver;
182         client_data->adapter_idx = server_data->adapter_idx;
183         client_data->target_idx = client_addr.target_idx;
184         client_data->fd = client_fd;
185         client_data->cb = server_data->cb;
186
187         client_channel = g_io_channel_unix_new(client_fd);
188         g_io_channel_set_close_on_unref(client_channel, TRUE);
189
190         client_data->watch = g_io_add_watch(client_channel,
191                                 G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR,
192                                 p2p_client_event,
193                                 client_data);
194
195         server_data->client_list = g_list_append(server_data->client_list, client_data);
196
197         return TRUE;
198 }
199
200 static int p2p_bind(struct near_p2p_driver *driver, uint32_t adapter_idx,
201                                                         near_device_io_cb cb)
202 {
203         int err, fd;
204         struct sockaddr_nfc_llcp addr;
205         GIOChannel *channel;
206         struct p2p_data *server_data;
207
208         DBG("Binding %s", driver->name);
209
210         fd = socket(AF_NFC, SOCK_STREAM, NFC_SOCKPROTO_LLCP);
211         if (fd < 0)
212                 return -errno;
213
214         memset(&addr, 0, sizeof(struct sockaddr_nfc_llcp));
215         addr.sa_family = AF_NFC;
216         addr.dev_idx = adapter_idx;
217         addr.nfc_protocol = NFC_PROTO_NFC_DEP;
218         addr.service_name_len = strlen(driver->service_name);
219         strcpy(addr.service_name, driver->service_name);
220
221         err = bind(fd, (struct sockaddr *) &addr,
222                         sizeof(struct sockaddr_nfc_llcp));
223         if (err < 0) {
224                 if (errno == EADDRINUSE) {
225                         DBG("%s is already bound", driver->name);
226                         close(fd);
227                         return 0;
228                 }
229
230                 near_error("%s bind failed %d %d", driver->name, err, errno);
231
232                 close(fd);
233                 return err;
234         }
235
236         err = listen(fd, 10);
237         if (err < 0) {
238                 near_error("%s listen failed %d", driver->name, err);
239
240                 close(fd);
241                 return err;
242         }
243
244         server_data = g_try_malloc0(sizeof(struct p2p_data));
245         if (server_data == NULL) {
246                 close(fd);
247                 return -ENOMEM;
248         }
249
250         server_data->driver = driver;
251         server_data->adapter_idx = adapter_idx;
252         server_data->fd = fd;
253         server_data->cb = cb;
254
255         channel = g_io_channel_unix_new(fd);
256         g_io_channel_set_close_on_unref(channel, TRUE);
257
258         server_data->watch = g_io_add_watch(channel,
259                                 G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR,
260                                 p2p_listener_event,
261                                 (gpointer) server_data);
262         g_io_channel_unref(channel);
263
264         server_list = g_list_append(server_list, server_data);
265
266         return 0;
267 }
268
269 static int p2p_listen(uint32_t adapter_idx, near_device_io_cb cb)
270 {
271         int err = -1;
272         GSList *list;
273
274         for (list = driver_list; list != NULL; list = list->next) {
275                 struct near_p2p_driver *driver = list->data;
276
277                 if (p2p_bind(driver, adapter_idx, cb) == 0)
278                         err = 0;
279         }
280
281         return err;
282 }
283
284 static int p2p_connect(uint32_t adapter_idx, uint32_t target_idx,
285                         struct near_ndef_message *ndef,
286                         near_device_io_cb cb,  struct near_p2p_driver *driver)
287 {
288         int fd, err = 0;
289         struct sockaddr_nfc_llcp addr;
290
291         DBG("");
292
293         fd = socket(AF_NFC, SOCK_STREAM, NFC_SOCKPROTO_LLCP);
294         if (fd < 0)
295                 return -errno;
296
297         memset(&addr, 0, sizeof(struct sockaddr_nfc_llcp));
298         addr.sa_family = AF_NFC;
299         addr.dev_idx = adapter_idx;
300         addr.target_idx = target_idx;
301         addr.nfc_protocol = NFC_PROTO_NFC_DEP;
302         addr.service_name_len = strlen(driver->service_name);
303         strcpy(addr.service_name, driver->service_name);
304
305         err = connect(fd, (struct sockaddr *) &addr,
306                         sizeof(struct sockaddr_nfc_llcp));
307         if (err < 0) {
308                 near_error("Connect failed  %d", err);
309                 close(fd);
310
311                 return err;
312         }
313
314         return fd;
315 }
316
317 static int p2p_push(uint32_t adapter_idx, uint32_t target_idx,
318                         struct near_ndef_message *ndef, char *service_name,
319                         near_device_io_cb cb)
320 {
321         int fd;
322         GSList *list;
323
324         DBG("");
325
326         for (list = driver_list; list != NULL; list = list->next) {
327                 struct near_p2p_driver *driver = list->data;
328
329                 if (strcmp(driver->service_name, service_name) != 0)
330                         continue;
331                 /*
332                  * Because of Android's implementation, we have use SNEP for
333                  * Handover. So, on Handover session, we try to connect to
334                  * the handover service and fallback to SNEP on connect fail.
335                  */
336                 fd = p2p_connect(adapter_idx, target_idx, ndef, cb, driver);
337                 if (fd < 0)
338                         return  p2p_push(adapter_idx, target_idx, ndef,
339                                 (char *) driver->fallback_service_name, cb);
340                 else
341                         return driver->push(fd, adapter_idx, target_idx,
342                                         ndef, cb);
343         }
344
345         return -1;
346 }
347
348 static struct near_device_driver p2p_driver = {
349         .priority       = NEAR_DEVICE_PRIORITY_HIGH,
350         .listen         = p2p_listen,
351         .push           = p2p_push,
352 };
353
354
355 int near_p2p_register(struct near_p2p_driver *driver)
356 {
357         DBG("driver %p name %s", driver, driver->name);
358
359         driver_list = g_slist_prepend(driver_list, driver);
360
361         return 0;
362 }
363
364 void near_p2p_unregister(struct near_p2p_driver *driver)
365 {
366         DBG("driver %p name %s", driver, driver->name);
367
368         driver_list = g_slist_remove(driver_list, driver);
369 }
370
371 static int p2p_init(void)
372 {
373         DBG("");
374
375         npp_init();
376         snep_init();
377         handover_init();
378
379         return near_device_driver_register(&p2p_driver);
380 }
381
382 static void p2p_exit(void)
383 {
384         DBG("");
385
386         g_list_free_full(server_list, free_server_data);
387
388         snep_exit();
389         npp_exit();
390         handover_exit();
391
392         near_device_driver_unregister(&p2p_driver);
393 }
394
395 NEAR_PLUGIN_DEFINE(p2p, "NFC Forum peer to peer mode support", VERSION,
396                 NEAR_PLUGIN_PRIORITY_HIGH, p2p_init, p2p_exit)