diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2013-06-08 02:11:18 +0200 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2013-06-08 02:23:30 +0200 |
commit | 68ec1eb2e96a92d0a814309d60856151eb0d1581 (patch) | |
tree | 5ef0f9ff6388cd3045ac42e430305a4f2ca2af25 | |
parent | b9fce4fe8622ffeb6d3d90b41f3b0a76e60b120b (diff) | |
download | neard-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.h | 1 | ||||
-rw-r--r-- | plugins/snep.c | 3 | ||||
-rw-r--r-- | src/snep.c | 49 | ||||
-rw-r--r-- | unit/test-snep-read.c | 8 |
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; } @@ -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; } |