summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2013-06-08 02:11:18 +0200
committerSamuel Ortiz <sameo@linux.intel.com>2013-06-08 02:23:30 +0200
commit68ec1eb2e96a92d0a814309d60856151eb0d1581 (patch)
tree5ef0f9ff6388cd3045ac42e430305a4f2ca2af25
parentb9fce4fe8622ffeb6d3d90b41f3b0a76e60b120b (diff)
downloadneard-68ec1eb2e96a92d0a814309d60856151eb0d1581.tar.gz
neard-68ec1eb2e96a92d0a814309d60856151eb0d1581.tar.bz2
neard-68ec1eb2e96a92d0a814309d60856151eb0d1581.zip
snep: Fix SNEP fragmentation
The intial request is kept through the snep_data and snep_core_process_request no longer relies on the last read frame to build an answer but only on the snep_data pointer. Without this fix, each fragment from a fragmented PUT was handled as a complete SNEP frame (header included) which caused process_request to get completely confused about how to handle fragments. Now that snep_core_read is fixed, the fragmentation SNEP unit test can be fixed as well.
-rw-r--r--include/snep.h1
-rw-r--r--plugins/snep.c3
-rw-r--r--src/snep.c49
-rw-r--r--unit/test-snep-read.c8
4 files changed, 41 insertions, 20 deletions
diff --git a/include/snep.h b/include/snep.h
index cdb9e65..ea9361a 100644
--- a/include/snep.h
+++ b/include/snep.h
@@ -72,6 +72,7 @@ struct p2p_snep_data {
uint32_t adapter_idx;
uint32_t target_idx;
gboolean respond_continue;
+ uint8_t request;
near_tag_io_cb cb;
struct p2p_snep_put_req_data *req;
};
diff --git a/plugins/snep.c b/plugins/snep.c
index 9ad6e92..5ecfc8b 100644
--- a/plugins/snep.c
+++ b/plugins/snep.c
@@ -76,6 +76,9 @@ static near_bool_t snep_default_server_req_put(int client_fd, void *data)
near_device_add_records(device, records, snep_data->cb, 0);
+ snep_data->nfc_data_length = 0;
+ snep_data->nfc_data = NULL;
+
return TRUE;
}
diff --git a/src/snep.c b/src/snep.c
index e1bbe81..1e62c00 100644
--- a/src/snep.c
+++ b/src/snep.c
@@ -382,15 +382,16 @@ static int snep_core_push_prepare_fragments(struct p2p_snep_put_req_data *req,
static near_bool_t snep_core_process_request(int client_fd,
struct p2p_snep_data *snep_data,
- struct p2p_snep_req_frame *frame,
near_server_io req_get,
near_server_io req_put)
{
near_bool_t ret;
int err;
+ DBG("request %d", snep_data->request);
+
/* Now, we process the request code */
- switch (frame->request) {
+ switch (snep_data->request) {
case NEAR_SNEP_REQ_PUT:
DBG("NEAR_SNEP_REQ_PUT");
if (req_put != NULL)
@@ -449,6 +450,12 @@ static near_bool_t snep_core_process_request(int client_fd,
* NEAR_SNEP_REQ_CONTINUE indicates that we have to send the
* remaining fragments...
*/
+
+ if (snep_data->req == NULL) {
+ ret = TRUE;
+ break;
+ }
+
DBG("NEAR_SNEP_REQ_CONTINUE");
if (snep_data->req->fragments == NULL) {
near_error("error: NEAR_SNEP_REQ_CONTINUE but no fragment");
@@ -511,11 +518,29 @@ near_bool_t near_snep_core_read(int client_fd,
{
struct p2p_snep_data *snep_data;
struct p2p_snep_req_frame frame;
- int bytes_recv;
+ int bytes_recv, ret;
uint32_t ndef_length;
DBG("");
+ /* Check previous/pending snep_data */
+ snep_data = g_hash_table_lookup(snep_client_hash,
+ GINT_TO_POINTER(client_fd));
+
+ /*
+ * If snep data is already there, and there are more bytes to read
+ * we just go ahead and read more fragments from the client.
+ */
+ if (snep_data != NULL &&
+ snep_data->nfc_data_length !=
+ snep_data->nfc_data_current_length) {
+ ret = snep_core_read_ndef(client_fd, snep_data);
+ if (ret)
+ return ret;
+
+ goto process_request;
+ }
+
/*
* We already got something from this client, we should try
* to continue reading.
@@ -541,14 +566,6 @@ near_bool_t near_snep_core_read(int client_fd,
return TRUE;
}
- /* Check previous/pending snep_data */
- snep_data = g_hash_table_lookup(snep_client_hash,
- GINT_TO_POINTER(client_fd));
-
- /* Is snep data already there, should be a CONTINUE */
- if (snep_data != NULL)
- goto jumptocontinue;
-
/* This is a new request from the client */
snep_data = g_try_malloc0(sizeof(struct p2p_snep_data));
if (snep_data == NULL)
@@ -568,6 +585,7 @@ near_bool_t near_snep_core_read(int client_fd,
snep_data->nfc_data_ptr = snep_data->nfc_data;
snep_data->adapter_idx = adapter_idx;
snep_data->target_idx = target_idx;
+ snep_data->request = frame.request;
snep_data->respond_continue = FALSE;
snep_data->cb = cb;
@@ -579,13 +597,14 @@ near_bool_t near_snep_core_read(int client_fd,
if ((frame.request == NEAR_SNEP_REQ_GET) ||
(frame.request == NEAR_SNEP_REQ_PUT)) {
/* We should read the missing bytes */
- snep_core_read_ndef(client_fd, snep_data);
+ ret = snep_core_read_ndef(client_fd, snep_data);
+ if (ret)
+ return ret;
}
}
-jumptocontinue:
-
- return snep_core_process_request(client_fd, snep_data, &frame,
+process_request:
+ return snep_core_process_request(client_fd, snep_data,
req_get, req_put);
}
diff --git a/unit/test-snep-read.c b/unit/test-snep-read.c
index cb02054..c1e5c77 100644
--- a/unit/test-snep-read.c
+++ b/unit/test-snep-read.c
@@ -368,11 +368,9 @@ static near_bool_t test_snep_read_send_fragment(size_t frag_len,
nbytes = send(sockfd[client], data, frag_len, 0);
g_assert(nbytes == frag_len);
- /*
- * TODO fragment has no SNEP header. snep_core_read will fail:
- * ret = near_snep_core_read(sockfd[server], 0, 0, NULL,
- * test_snep_dummy_req_get, test_snep_dummy_req_put);
- */
+ near_snep_core_read(sockfd[server], 0, 0, NULL,
+ test_snep_dummy_req_get, test_snep_dummy_req_put);
+
return TRUE;
}