3 * neard - Near Field Communication manager
5 * Copyright (C) 2012 Intel Corporation. All rights reserved.
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.
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.
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
30 #include <sys/socket.h>
32 #include <linux/socket.h>
34 #include <near/nfc_copy.h>
35 #include <near/plugin.h>
37 #include <near/types.h>
38 #include <near/adapter.h>
39 #include <near/device.h>
40 #include <near/ndef.h>
42 #include <near/snep.h>
46 /* Would store incoming ndefs per client */
47 static GHashTable *snep_validation_hash = NULL;
49 /* Callback: free validation data */
50 static void free_snep_validation_client(gpointer data)
52 GList *old_ndefs = data;
55 g_list_free(old_ndefs);
58 /* Validation Server REQ_PUT function
59 * The validation server shall accept PUT and GET requests. A PUT request shall
60 * cause the server to store the ndef message transmitted with the request.
62 static bool snep_validation_server_req_put(int client_fd, void *data)
64 struct p2p_snep_data *snep_data = data;
66 struct near_ndef_record *recd;
67 GList *incoming_ndefs;
71 if (!snep_data->nfc_data)
75 * We received a ndef, parse it, check if there's only
76 * 1 record (a mime type !) with an ID
78 records = near_ndef_parse_msg(snep_data->nfc_data,
79 snep_data->nfc_data_length, NULL);
81 if (g_list_length(records) != 1) {
82 DBG("records number mismatch");
93 /* Save the record but look if there are some incoming ndef stored */
94 incoming_ndefs = g_hash_table_lookup(snep_validation_hash,
95 GINT_TO_POINTER(client_fd));
97 incoming_ndefs = g_list_append(incoming_ndefs, recd);
99 /* remove existing one silently */
100 g_hash_table_steal(snep_validation_hash, GINT_TO_POINTER(client_fd));
101 /* push the new one */
102 g_hash_table_insert(snep_validation_hash, GINT_TO_POINTER(client_fd),
106 near_snep_core_response_noinfo(client_fd, NEAR_SNEP_RESP_SUCCESS);
111 near_snep_core_response_noinfo(client_fd, NEAR_SNEP_RESP_REJECT);
117 * Validation Server REQ_GET function
118 * The validation server shall accept PUT and GET requests. A GET request shall
119 * cause the server to return a previously stored NDEF message of the same NDEF
120 * message type and identifier as transmitted with the request.
122 static bool snep_validation_server_req_get(int client_fd, void *data)
124 struct p2p_snep_data *snep_data = data;
125 struct near_ndef_record *recd, *rec_store;
126 uint32_t acceptable_length;
129 GList *incoming_ndefs;
134 * We received a ndef, parse it, check if there's only
135 * 1 record (a mime type !) with an ID
137 records = near_ndef_parse_msg(snep_data->nfc_data +
138 NEAR_SNEP_ACC_LENGTH_SIZE,
139 snep_data->nfc_data_length - NEAR_SNEP_ACC_LENGTH_SIZE,
142 if (g_list_length(records) != 1) {
143 DBG("records number mismatch");
147 recd = records->data;
149 g_list_free(records);
153 /* check if the acceptable length is higher than the data_len
154 * otherwise returns a NEAR_SNEP_RESP_EXCESS
156 acceptable_length = near_get_be32(snep_data->nfc_data);
158 /* Look if there are some incoming ndef stored */
159 incoming_ndefs = g_hash_table_lookup(snep_validation_hash,
160 GINT_TO_POINTER(client_fd));
165 /* Now, loop to find the the associated record */
166 for (iter = incoming_ndefs; iter; iter = iter->next) {
168 rec_store = iter->data;
169 /* Same mime type and same id ?*/
171 if (!near_ndef_record_cmp_id(recd, rec_store))
174 if (!near_ndef_record_cmp_mime(recd, rec_store))
177 /* Found a record, check the length */
178 if (acceptable_length >= near_ndef_data_length(rec_store)) {
179 near_snep_core_response_with_info(client_fd,
180 NEAR_SNEP_RESP_SUCCESS,
181 near_ndef_data_ptr(rec_store),
182 near_ndef_data_length(rec_store));
184 incoming_ndefs = g_list_remove(incoming_ndefs,
186 /* remove existing one silently */
187 g_hash_table_steal(snep_validation_hash,
188 GINT_TO_POINTER(client_fd));
189 /* push the new one */
190 g_hash_table_insert(snep_validation_hash,
191 GINT_TO_POINTER(client_fd),
195 near_snep_core_response_noinfo(client_fd, NEAR_SNEP_RESP_EXCESS);
202 near_snep_core_response_noinfo(client_fd, NEAR_SNEP_RESP_NOT_FOUND);
207 near_snep_core_response_noinfo(client_fd, NEAR_SNEP_RESP_REJECT);
211 /* This function is a wrapper to push post processing read functions */
212 static bool snep_validation_read(int client_fd, uint32_t adapter_idx,
219 return near_snep_core_read(client_fd, adapter_idx, target_idx, cb,
220 snep_validation_server_req_get,
221 snep_validation_server_req_put,
226 static void snep_validation_close(int client_fd, int err, gpointer data)
230 g_hash_table_remove(snep_validation_hash, GINT_TO_POINTER(client_fd));
232 /* Call core server close */
233 near_snep_core_close(client_fd, err, data);
236 struct near_p2p_driver validation_snep_driver = {
237 .name = "VALIDATION_SNEP",
238 .service_name = "urn:nfc:xsn:nfc-forum.org:snep-validation",
239 .fallback_service_name = NULL,
240 .sock_type = SOCK_STREAM,
241 .read = snep_validation_read,
242 .push = near_snep_core_push,
243 .close = snep_validation_close,
246 int snep_validation_init(void)
248 /* Would store incoming ndefs per client */
249 snep_validation_hash = g_hash_table_new_full(g_direct_hash,
250 g_direct_equal, NULL,
251 free_snep_validation_client);
253 return near_p2p_register(&validation_snep_driver);
256 void snep_validation_exit(void)
258 near_p2p_unregister(&validation_snep_driver);
260 g_hash_table_destroy(snep_validation_hash);
261 snep_validation_hash = NULL;