Fixing repeated EH calls when client retransmits requests
authorYamin Al-Mousa <yamin.s.al-mousa@intel.com>
Thu, 8 Jan 2015 02:36:55 +0000 (18:36 -0800)
committerYamin Al-Mousa <yamin.s.al-mousa@intel.com>
Thu, 8 Jan 2015 02:36:55 +0000 (18:36 -0800)
(Bug IOT-239) When a client makes a request to a slow resource
and it does not receive an ACK for that request, it retransmits
the requests which resulted in calling the server's entity handler
several times and multilpe slow responses. When a server
detects a repeated request it should not process it. Also, when
the client receives a slow response it should stop retransmitting
requests.

Change-Id: I101ad3de9b8e0e4990fb096d4a8fe5b9dcebf4b0
Signed-off-by: Yamin Al-Mousa <yamin.s.al-mousa@intel.com>
resource/csdk/libcoap-4.1.1/net.c
resource/csdk/occoap/src/occoap.c
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/src/ocstack.c

index d36b0e2..dfc04ff 100644 (file)
@@ -814,8 +814,8 @@ coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node) {
         coap_retransmittimer_restart(context);
 #endif
 
-        debug("** retransmission #%d of transaction %d\n", node->retransmit_cnt,
-            ntohs(node->pdu->hdr->id));
+        debug("** retransmission #%d of transaction %d for coap pdu\n", node->retransmit_cnt, node->id);
+        coap_show_pdu(node->pdu);
         flag = (coap_send_flags_t)(SEND_RETX | (node->secure ? SEND_SECURE_PORT : 0));
         tid = coap_send(context, (coap_address_t *)&(node->remote),node->pdu, flag, NULL);
         return (tid == COAP_INVALID_TID)? COAP_INVALID_TID : node->id;
@@ -997,7 +997,8 @@ int coap_remove_from_queue(coap_queue_t **queue, coap_tid_t id,
 
     if (!queue || !*queue)
         return 0;
-    debug("*** looking for transaction %u == %u\n", id, (*queue)->id);
+    debug("*** looking for transaction ID %u for pdu:\n", id);
+    coap_show_pdu((*queue)->pdu);
 
     /* replace queue head if PDU's time is less than head's time */
     if (id == (*queue)->id) { /* found transaction */
@@ -1055,7 +1056,8 @@ void coap_cancel_all_messages(coap_context_t *context,
                     context->sendqueue->pdu->hdr->token_length)) {
         q = context->sendqueue;
         context->sendqueue = q->next;
-        debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id));
+        debug("**** removed transaction %d for coap pdu\n", q->id);
+        coap_show_pdu(q->pdu);
         coap_delete_node(q);
     }
 
@@ -1071,7 +1073,8 @@ void coap_cancel_all_messages(coap_context_t *context,
                 && token_match(token, token_length, q->pdu->hdr->token,
                         q->pdu->hdr->token_length)) {
             p->next = q->next;
-            debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id));
+            debug("**** removed transaction %d for coap pdu\n", q->id);
+            coap_show_pdu(q->pdu);
             coap_delete_node(q);
             q = p->next;
         } else {
@@ -1380,6 +1383,11 @@ handle_locally(coap_context_t *context __attribute__ ((unused)),
                 break;
 
             case COAP_MESSAGE_CON: /* check for unknown critical options */
+                // Receiving a response should stop retransmissions
+                if (COAP_MESSAGE_IS_RESPONSE(rcvd->pdu->hdr))
+                {
+                    coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent);
+                }
                 if (coap_option_check_critical(context, rcvd->pdu, opt_filter)
                         == 0) {
                     /* FIXME: send response only if we have received a request. Otherwise,
index 427ebf0..30881ab 100644 (file)
@@ -255,7 +255,8 @@ static void HandleCoAPRequests(struct coap_context_t *ctx,
         }
         goto exit;
     }
-    else if(requestResult == OC_STACK_SLOW_RESOURCE)
+    else if(requestResult == OC_STACK_SLOW_RESOURCE ||
+            requestResult == OC_STACK_REPEATED_REQUEST)
     {
         if(rcvdPdu->hdr->type == COAP_MESSAGE_CON)
         {
index 8be0d12..72de3c2 100644 (file)
@@ -158,6 +158,7 @@ typedef enum {
     OC_STACK_NO_RESOURCE,               /* resource not found */
     OC_STACK_RESOURCE_ERROR,            /* ex: not supported method or interface */
     OC_STACK_SLOW_RESOURCE,
+    OC_STACK_REPEATED_REQUEST,
     OC_STACK_NO_OBSERVERS,              /* resource has no registered observers */
     OC_STACK_OBSERVER_NOT_FOUND,
     #ifdef WITH_PRESENCE
index b2aec91..cdc2bf5 100644 (file)
@@ -212,30 +212,32 @@ OCStackResult HandleStackRequests(OCServerProtocolRequest * protocolRequest)
         {
             request->requestComplete = 1;
         }
-    }
-    else
-    {
-        OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request"));
-    }
 
-    if(request->requestComplete)
-    {
-        OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
-        result = DetermineResourceHandling (request, &resHandling, &resource);
-        if (result == OC_STACK_OK)
+        if(request->requestComplete)
         {
-            result = ProcessRequest(resHandling, resource, request);
+            OC_LOG(INFO, TAG, PCF("This Server Request is complete"));
+            result = DetermineResourceHandling (request, &resHandling, &resource);
+            if (result == OC_STACK_OK)
+            {
+                result = ProcessRequest(resHandling, resource, request);
+            }
+            else
+            {
+                result = OC_STACK_ERROR;
+            }
         }
         else
         {
-            result = OC_STACK_ERROR;
+            OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
+            result = OC_STACK_CONTINUE;
         }
     }
     else
     {
-        OC_LOG(INFO, TAG, PCF("This Server Request is incomplete"));
-        result = OC_STACK_CONTINUE;
+        OC_LOG(INFO, TAG, PCF("This is either a repeated Server Request or blocked Server Request"));
+        result = OC_STACK_REPEATED_REQUEST;
     }
+
     return result;
 }